1 //===- lib/MC/MCFragment.cpp - Assembler Fragment Implementation ----------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "llvm/MC/MCFragment.h"
10 #include "llvm/ADT/SmallVector.h"
11 #include "llvm/ADT/StringExtras.h"
12 #include "llvm/ADT/Twine.h"
13 #include "llvm/Config/llvm-config.h"
14 #include "llvm/MC/MCAsmLayout.h"
15 #include "llvm/MC/MCAssembler.h"
16 #include "llvm/MC/MCContext.h"
17 #include "llvm/MC/MCExpr.h"
18 #include "llvm/MC/MCFixup.h"
19 #include "llvm/MC/MCSection.h"
20 #include "llvm/MC/MCSymbol.h"
21 #include "llvm/MC/MCValue.h"
22 #include "llvm/Support/Casting.h"
23 #include "llvm/Support/Compiler.h"
24 #include "llvm/Support/ErrorHandling.h"
25 #include "llvm/Support/raw_ostream.h"
32 MCAsmLayout::MCAsmLayout(MCAssembler
&Asm
) : Assembler(Asm
) {
33 // Compute the section layout order. Virtual sections must go last.
34 for (MCSection
&Sec
: Asm
)
35 if (!Sec
.isVirtualSection())
36 SectionOrder
.push_back(&Sec
);
37 for (MCSection
&Sec
: Asm
)
38 if (Sec
.isVirtualSection())
39 SectionOrder
.push_back(&Sec
);
42 bool MCAsmLayout::isFragmentValid(const MCFragment
*F
) const {
43 const MCSection
*Sec
= F
->getParent();
44 const MCFragment
*LastValid
= LastValidFragment
.lookup(Sec
);
47 assert(LastValid
->getParent() == Sec
);
48 return F
->getLayoutOrder() <= LastValid
->getLayoutOrder();
51 bool MCAsmLayout::canGetFragmentOffset(const MCFragment
*F
) const {
52 MCSection
*Sec
= F
->getParent();
53 MCSection::iterator I
;
54 if (MCFragment
*LastValid
= LastValidFragment
[Sec
]) {
55 // Fragment already valid, offset is available.
56 if (F
->getLayoutOrder() <= LastValid
->getLayoutOrder())
58 I
= ++MCSection::iterator(LastValid
);
62 // A fragment ordered before F is currently being laid out.
63 const MCFragment
*FirstInvalidFragment
= &*I
;
64 if (FirstInvalidFragment
->IsBeingLaidOut
)
70 void MCAsmLayout::invalidateFragmentsFrom(MCFragment
*F
) {
71 // If this fragment wasn't already valid, we don't need to do anything.
72 if (!isFragmentValid(F
))
75 // Otherwise, reset the last valid fragment to the previous fragment
76 // (if this is the first fragment, it will be NULL).
77 LastValidFragment
[F
->getParent()] = F
->getPrevNode();
80 void MCAsmLayout::ensureValid(const MCFragment
*F
) const {
81 MCSection
*Sec
= F
->getParent();
82 MCSection::iterator I
;
83 if (MCFragment
*Cur
= LastValidFragment
[Sec
])
84 I
= ++MCSection::iterator(Cur
);
88 // Advance the layout position until the fragment is valid.
89 while (!isFragmentValid(F
)) {
90 assert(I
!= Sec
->end() && "Layout bookkeeping error");
91 const_cast<MCAsmLayout
*>(this)->layoutFragment(&*I
);
96 uint64_t MCAsmLayout::getFragmentOffset(const MCFragment
*F
) const {
98 assert(F
->Offset
!= ~UINT64_C(0) && "Address not set!");
102 // Simple getSymbolOffset helper for the non-variable case.
103 static bool getLabelOffset(const MCAsmLayout
&Layout
, const MCSymbol
&S
,
104 bool ReportError
, uint64_t &Val
) {
105 if (!S
.getFragment()) {
107 report_fatal_error("unable to evaluate offset to undefined symbol '" +
111 Val
= Layout
.getFragmentOffset(S
.getFragment()) + S
.getOffset();
115 static bool getSymbolOffsetImpl(const MCAsmLayout
&Layout
, const MCSymbol
&S
,
116 bool ReportError
, uint64_t &Val
) {
118 return getLabelOffset(Layout
, S
, ReportError
, Val
);
120 // If SD is a variable, evaluate it.
122 if (!S
.getVariableValue()->evaluateAsValue(Target
, Layout
))
123 report_fatal_error("unable to evaluate offset for variable '" +
126 uint64_t Offset
= Target
.getConstant();
128 const MCSymbolRefExpr
*A
= Target
.getSymA();
131 if (!getLabelOffset(Layout
, A
->getSymbol(), ReportError
, ValA
))
136 const MCSymbolRefExpr
*B
= Target
.getSymB();
139 if (!getLabelOffset(Layout
, B
->getSymbol(), ReportError
, ValB
))
148 bool MCAsmLayout::getSymbolOffset(const MCSymbol
&S
, uint64_t &Val
) const {
149 return getSymbolOffsetImpl(*this, S
, false, Val
);
152 uint64_t MCAsmLayout::getSymbolOffset(const MCSymbol
&S
) const {
154 getSymbolOffsetImpl(*this, S
, true, Val
);
158 const MCSymbol
*MCAsmLayout::getBaseSymbol(const MCSymbol
&Symbol
) const {
159 if (!Symbol
.isVariable())
162 const MCExpr
*Expr
= Symbol
.getVariableValue();
164 if (!Expr
->evaluateAsValue(Value
, *this)) {
165 Assembler
.getContext().reportError(
166 Expr
->getLoc(), "expression could not be evaluated");
170 const MCSymbolRefExpr
*RefB
= Value
.getSymB();
172 Assembler
.getContext().reportError(
173 Expr
->getLoc(), Twine("symbol '") + RefB
->getSymbol().getName() +
174 "' could not be evaluated in a subtraction expression");
178 const MCSymbolRefExpr
*A
= Value
.getSymA();
182 const MCSymbol
&ASym
= A
->getSymbol();
183 const MCAssembler
&Asm
= getAssembler();
184 if (ASym
.isCommon()) {
185 Asm
.getContext().reportError(Expr
->getLoc(),
186 "Common symbol '" + ASym
.getName() +
187 "' cannot be used in assignment expr");
194 uint64_t MCAsmLayout::getSectionAddressSize(const MCSection
*Sec
) const {
195 // The size is the last fragment's end offset.
196 const MCFragment
&F
= Sec
->getFragmentList().back();
197 return getFragmentOffset(&F
) + getAssembler().computeFragmentSize(*this, F
);
200 uint64_t MCAsmLayout::getSectionFileSize(const MCSection
*Sec
) const {
201 // Virtual sections have no file size.
202 if (Sec
->isVirtualSection())
205 // Otherwise, the file size is the same as the address space size.
206 return getSectionAddressSize(Sec
);
209 uint64_t llvm::computeBundlePadding(const MCAssembler
&Assembler
,
210 const MCEncodedFragment
*F
,
211 uint64_t FOffset
, uint64_t FSize
) {
212 uint64_t BundleSize
= Assembler
.getBundleAlignSize();
213 assert(BundleSize
> 0 &&
214 "computeBundlePadding should only be called if bundling is enabled");
215 uint64_t BundleMask
= BundleSize
- 1;
216 uint64_t OffsetInBundle
= FOffset
& BundleMask
;
217 uint64_t EndOfFragment
= OffsetInBundle
+ FSize
;
219 // There are two kinds of bundling restrictions:
221 // 1) For alignToBundleEnd(), add padding to ensure that the fragment will
222 // *end* on a bundle boundary.
223 // 2) Otherwise, check if the fragment would cross a bundle boundary. If it
224 // would, add padding until the end of the bundle so that the fragment
225 // will start in a new one.
226 if (F
->alignToBundleEnd()) {
227 // Three possibilities here:
229 // A) The fragment just happens to end at a bundle boundary, so we're good.
230 // B) The fragment ends before the current bundle boundary: pad it just
231 // enough to reach the boundary.
232 // C) The fragment ends after the current bundle boundary: pad it until it
233 // reaches the end of the next bundle boundary.
235 // Note: this code could be made shorter with some modulo trickery, but it's
236 // intentionally kept in its more explicit form for simplicity.
237 if (EndOfFragment
== BundleSize
)
239 else if (EndOfFragment
< BundleSize
)
240 return BundleSize
- EndOfFragment
;
241 else { // EndOfFragment > BundleSize
242 return 2 * BundleSize
- EndOfFragment
;
244 } else if (OffsetInBundle
> 0 && EndOfFragment
> BundleSize
)
245 return BundleSize
- OffsetInBundle
;
252 void ilist_alloc_traits
<MCFragment
>::deleteNode(MCFragment
*V
) { V
->destroy(); }
254 MCFragment::MCFragment(FragmentType Kind
, bool HasInstructions
,
256 : Parent(Parent
), Atom(nullptr), Offset(~UINT64_C(0)), LayoutOrder(0),
257 Kind(Kind
), IsBeingLaidOut(false), HasInstructions(HasInstructions
) {
258 if (Parent
&& !isa
<MCDummyFragment
>(*this))
259 Parent
->getFragmentList().push_back(this);
262 void MCFragment::destroy() {
263 // First check if we are the sentinal.
264 if (Kind
== FragmentType(~0)) {
271 delete cast
<MCAlignFragment
>(this);
274 delete cast
<MCDataFragment
>(this);
276 case FT_CompactEncodedInst
:
277 delete cast
<MCCompactEncodedInstFragment
>(this);
280 delete cast
<MCFillFragment
>(this);
283 delete cast
<MCNopsFragment
>(this);
286 delete cast
<MCRelaxableFragment
>(this);
289 delete cast
<MCOrgFragment
>(this);
292 delete cast
<MCDwarfLineAddrFragment
>(this);
295 delete cast
<MCDwarfCallFrameFragment
>(this);
298 delete cast
<MCLEBFragment
>(this);
300 case FT_BoundaryAlign
:
301 delete cast
<MCBoundaryAlignFragment
>(this);
304 delete cast
<MCSymbolIdFragment
>(this);
306 case FT_CVInlineLines
:
307 delete cast
<MCCVInlineLineTableFragment
>(this);
310 delete cast
<MCCVDefRangeFragment
>(this);
313 delete cast
<MCPseudoProbeAddrFragment
>(this);
316 delete cast
<MCDummyFragment
>(this);
325 raw_ostream
&operator<<(raw_ostream
&OS
, const MCFixup
&AF
) {
326 OS
<< "<MCFixup" << " Offset:" << AF
.getOffset()
327 << " Value:" << *AF
.getValue()
328 << " Kind:" << AF
.getKind() << ">";
332 } // end namespace llvm
334 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
335 LLVM_DUMP_METHOD
void MCFragment::dump() const {
336 raw_ostream
&OS
= errs();
340 case MCFragment::FT_Align
: OS
<< "MCAlignFragment"; break;
341 case MCFragment::FT_Data
: OS
<< "MCDataFragment"; break;
342 case MCFragment::FT_CompactEncodedInst
:
343 OS
<< "MCCompactEncodedInstFragment"; break;
344 case MCFragment::FT_Fill
: OS
<< "MCFillFragment"; break;
345 case MCFragment::FT_Nops
:
346 OS
<< "MCFNopsFragment";
348 case MCFragment::FT_Relaxable
: OS
<< "MCRelaxableFragment"; break;
349 case MCFragment::FT_Org
: OS
<< "MCOrgFragment"; break;
350 case MCFragment::FT_Dwarf
: OS
<< "MCDwarfFragment"; break;
351 case MCFragment::FT_DwarfFrame
: OS
<< "MCDwarfCallFrameFragment"; break;
352 case MCFragment::FT_LEB
: OS
<< "MCLEBFragment"; break;
353 case MCFragment::FT_BoundaryAlign
: OS
<<"MCBoundaryAlignFragment"; break;
354 case MCFragment::FT_SymbolId
: OS
<< "MCSymbolIdFragment"; break;
355 case MCFragment::FT_CVInlineLines
: OS
<< "MCCVInlineLineTableFragment"; break;
356 case MCFragment::FT_CVDefRange
: OS
<< "MCCVDefRangeTableFragment"; break;
357 case MCFragment::FT_PseudoProbe
:
358 OS
<< "MCPseudoProbe";
360 case MCFragment::FT_Dummy
: OS
<< "MCDummyFragment"; break;
363 OS
<< "<MCFragment " << (const void *)this << " LayoutOrder:" << LayoutOrder
364 << " Offset:" << Offset
<< " HasInstructions:" << hasInstructions();
365 if (const auto *EF
= dyn_cast
<MCEncodedFragment
>(this))
366 OS
<< " BundlePadding:" << static_cast<unsigned>(EF
->getBundlePadding());
370 case MCFragment::FT_Align
: {
371 const auto *AF
= cast
<MCAlignFragment
>(this);
372 if (AF
->hasEmitNops())
373 OS
<< " (emit nops)";
375 OS
<< " Alignment:" << AF
->getAlignment()
376 << " Value:" << AF
->getValue() << " ValueSize:" << AF
->getValueSize()
377 << " MaxBytesToEmit:" << AF
->getMaxBytesToEmit() << ">";
380 case MCFragment::FT_Data
: {
381 const auto *DF
= cast
<MCDataFragment
>(this);
384 const SmallVectorImpl
<char> &Contents
= DF
->getContents();
385 for (unsigned i
= 0, e
= Contents
.size(); i
!= e
; ++i
) {
387 OS
<< hexdigit((Contents
[i
] >> 4) & 0xF) << hexdigit(Contents
[i
] & 0xF);
389 OS
<< "] (" << Contents
.size() << " bytes)";
391 if (DF
->fixup_begin() != DF
->fixup_end()) {
394 for (MCDataFragment::const_fixup_iterator it
= DF
->fixup_begin(),
395 ie
= DF
->fixup_end(); it
!= ie
; ++it
) {
396 if (it
!= DF
->fixup_begin()) OS
<< ",\n ";
403 case MCFragment::FT_CompactEncodedInst
: {
405 cast
<MCCompactEncodedInstFragment
>(this);
408 const SmallVectorImpl
<char> &Contents
= CEIF
->getContents();
409 for (unsigned i
= 0, e
= Contents
.size(); i
!= e
; ++i
) {
411 OS
<< hexdigit((Contents
[i
] >> 4) & 0xF) << hexdigit(Contents
[i
] & 0xF);
413 OS
<< "] (" << Contents
.size() << " bytes)";
416 case MCFragment::FT_Fill
: {
417 const auto *FF
= cast
<MCFillFragment
>(this);
418 OS
<< " Value:" << static_cast<unsigned>(FF
->getValue())
419 << " ValueSize:" << static_cast<unsigned>(FF
->getValueSize())
420 << " NumValues:" << FF
->getNumValues();
423 case MCFragment::FT_Nops
: {
424 const auto *NF
= cast
<MCNopsFragment
>(this);
425 OS
<< " NumBytes:" << NF
->getNumBytes()
426 << " ControlledNopLength:" << NF
->getControlledNopLength();
429 case MCFragment::FT_Relaxable
: {
430 const auto *F
= cast
<MCRelaxableFragment
>(this);
433 F
->getInst().dump_pretty(OS
);
434 OS
<< " (" << F
->getContents().size() << " bytes)";
437 case MCFragment::FT_Org
: {
438 const auto *OF
= cast
<MCOrgFragment
>(this);
440 OS
<< " Offset:" << OF
->getOffset()
441 << " Value:" << static_cast<unsigned>(OF
->getValue());
444 case MCFragment::FT_Dwarf
: {
445 const auto *OF
= cast
<MCDwarfLineAddrFragment
>(this);
447 OS
<< " AddrDelta:" << OF
->getAddrDelta()
448 << " LineDelta:" << OF
->getLineDelta();
451 case MCFragment::FT_DwarfFrame
: {
452 const auto *CF
= cast
<MCDwarfCallFrameFragment
>(this);
454 OS
<< " AddrDelta:" << CF
->getAddrDelta();
457 case MCFragment::FT_LEB
: {
458 const auto *LF
= cast
<MCLEBFragment
>(this);
460 OS
<< " Value:" << LF
->getValue() << " Signed:" << LF
->isSigned();
463 case MCFragment::FT_BoundaryAlign
: {
464 const auto *BF
= cast
<MCBoundaryAlignFragment
>(this);
466 OS
<< " BoundarySize:" << BF
->getAlignment().value()
467 << " LastFragment:" << BF
->getLastFragment()
468 << " Size:" << BF
->getSize();
471 case MCFragment::FT_SymbolId
: {
472 const auto *F
= cast
<MCSymbolIdFragment
>(this);
474 OS
<< " Sym:" << F
->getSymbol();
477 case MCFragment::FT_CVInlineLines
: {
478 const auto *F
= cast
<MCCVInlineLineTableFragment
>(this);
480 OS
<< " Sym:" << *F
->getFnStartSym();
483 case MCFragment::FT_CVDefRange
: {
484 const auto *F
= cast
<MCCVDefRangeFragment
>(this);
486 for (std::pair
<const MCSymbol
*, const MCSymbol
*> RangeStartEnd
:
488 OS
<< " RangeStart:" << RangeStartEnd
.first
;
489 OS
<< " RangeEnd:" << RangeStartEnd
.second
;
493 case MCFragment::FT_PseudoProbe
: {
494 const auto *OF
= cast
<MCPseudoProbeAddrFragment
>(this);
496 OS
<< " AddrDelta:" << OF
->getAddrDelta();
499 case MCFragment::FT_Dummy
: