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 // FIXME: On most platforms, `Target`'s component symbols are labels from
132 // having been simplified during evaluation, but on Mach-O they can be
133 // variables due to PR19203. This, and the line below for `B` can be
134 // restored to call `getLabelOffset` when PR19203 is fixed.
135 if (!getSymbolOffsetImpl(Layout
, A
->getSymbol(), ReportError
, ValA
))
140 const MCSymbolRefExpr
*B
= Target
.getSymB();
143 if (!getSymbolOffsetImpl(Layout
, B
->getSymbol(), ReportError
, ValB
))
152 bool MCAsmLayout::getSymbolOffset(const MCSymbol
&S
, uint64_t &Val
) const {
153 return getSymbolOffsetImpl(*this, S
, false, Val
);
156 uint64_t MCAsmLayout::getSymbolOffset(const MCSymbol
&S
) const {
158 getSymbolOffsetImpl(*this, S
, true, Val
);
162 const MCSymbol
*MCAsmLayout::getBaseSymbol(const MCSymbol
&Symbol
) const {
163 if (!Symbol
.isVariable())
166 const MCExpr
*Expr
= Symbol
.getVariableValue();
168 if (!Expr
->evaluateAsValue(Value
, *this)) {
169 Assembler
.getContext().reportError(
170 Expr
->getLoc(), "expression could not be evaluated");
174 const MCSymbolRefExpr
*RefB
= Value
.getSymB();
176 Assembler
.getContext().reportError(
177 Expr
->getLoc(), Twine("symbol '") + RefB
->getSymbol().getName() +
178 "' could not be evaluated in a subtraction expression");
182 const MCSymbolRefExpr
*A
= Value
.getSymA();
186 const MCSymbol
&ASym
= A
->getSymbol();
187 const MCAssembler
&Asm
= getAssembler();
188 if (ASym
.isCommon()) {
189 Asm
.getContext().reportError(Expr
->getLoc(),
190 "Common symbol '" + ASym
.getName() +
191 "' cannot be used in assignment expr");
198 uint64_t MCAsmLayout::getSectionAddressSize(const MCSection
*Sec
) const {
199 // The size is the last fragment's end offset.
200 const MCFragment
&F
= Sec
->getFragmentList().back();
201 return getFragmentOffset(&F
) + getAssembler().computeFragmentSize(*this, F
);
204 uint64_t MCAsmLayout::getSectionFileSize(const MCSection
*Sec
) const {
205 // Virtual sections have no file size.
206 if (Sec
->isVirtualSection())
209 // Otherwise, the file size is the same as the address space size.
210 return getSectionAddressSize(Sec
);
213 uint64_t llvm::computeBundlePadding(const MCAssembler
&Assembler
,
214 const MCEncodedFragment
*F
,
215 uint64_t FOffset
, uint64_t FSize
) {
216 uint64_t BundleSize
= Assembler
.getBundleAlignSize();
217 assert(BundleSize
> 0 &&
218 "computeBundlePadding should only be called if bundling is enabled");
219 uint64_t BundleMask
= BundleSize
- 1;
220 uint64_t OffsetInBundle
= FOffset
& BundleMask
;
221 uint64_t EndOfFragment
= OffsetInBundle
+ FSize
;
223 // There are two kinds of bundling restrictions:
225 // 1) For alignToBundleEnd(), add padding to ensure that the fragment will
226 // *end* on a bundle boundary.
227 // 2) Otherwise, check if the fragment would cross a bundle boundary. If it
228 // would, add padding until the end of the bundle so that the fragment
229 // will start in a new one.
230 if (F
->alignToBundleEnd()) {
231 // Three possibilities here:
233 // A) The fragment just happens to end at a bundle boundary, so we're good.
234 // B) The fragment ends before the current bundle boundary: pad it just
235 // enough to reach the boundary.
236 // C) The fragment ends after the current bundle boundary: pad it until it
237 // reaches the end of the next bundle boundary.
239 // Note: this code could be made shorter with some modulo trickery, but it's
240 // intentionally kept in its more explicit form for simplicity.
241 if (EndOfFragment
== BundleSize
)
243 else if (EndOfFragment
< BundleSize
)
244 return BundleSize
- EndOfFragment
;
245 else { // EndOfFragment > BundleSize
246 return 2 * BundleSize
- EndOfFragment
;
248 } else if (OffsetInBundle
> 0 && EndOfFragment
> BundleSize
)
249 return BundleSize
- OffsetInBundle
;
256 void ilist_alloc_traits
<MCFragment
>::deleteNode(MCFragment
*V
) { V
->destroy(); }
258 MCFragment::MCFragment(FragmentType Kind
, bool HasInstructions
,
260 : Parent(Parent
), Atom(nullptr), Offset(~UINT64_C(0)), LayoutOrder(0),
261 Kind(Kind
), IsBeingLaidOut(false), HasInstructions(HasInstructions
) {
262 if (Parent
&& !isa
<MCDummyFragment
>(*this))
263 Parent
->getFragmentList().push_back(this);
266 void MCFragment::destroy() {
267 // First check if we are the sentinel.
268 if (Kind
== FragmentType(~0)) {
275 delete cast
<MCAlignFragment
>(this);
278 delete cast
<MCDataFragment
>(this);
280 case FT_CompactEncodedInst
:
281 delete cast
<MCCompactEncodedInstFragment
>(this);
284 delete cast
<MCFillFragment
>(this);
287 delete cast
<MCNopsFragment
>(this);
290 delete cast
<MCRelaxableFragment
>(this);
293 delete cast
<MCOrgFragment
>(this);
296 delete cast
<MCDwarfLineAddrFragment
>(this);
299 delete cast
<MCDwarfCallFrameFragment
>(this);
302 delete cast
<MCLEBFragment
>(this);
304 case FT_BoundaryAlign
:
305 delete cast
<MCBoundaryAlignFragment
>(this);
308 delete cast
<MCSymbolIdFragment
>(this);
310 case FT_CVInlineLines
:
311 delete cast
<MCCVInlineLineTableFragment
>(this);
314 delete cast
<MCCVDefRangeFragment
>(this);
317 delete cast
<MCPseudoProbeAddrFragment
>(this);
320 delete cast
<MCDummyFragment
>(this);
329 raw_ostream
&operator<<(raw_ostream
&OS
, const MCFixup
&AF
) {
330 OS
<< "<MCFixup" << " Offset:" << AF
.getOffset()
331 << " Value:" << *AF
.getValue()
332 << " Kind:" << AF
.getKind() << ">";
336 } // end namespace llvm
338 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
339 LLVM_DUMP_METHOD
void MCFragment::dump() const {
340 raw_ostream
&OS
= errs();
344 case MCFragment::FT_Align
: OS
<< "MCAlignFragment"; break;
345 case MCFragment::FT_Data
: OS
<< "MCDataFragment"; break;
346 case MCFragment::FT_CompactEncodedInst
:
347 OS
<< "MCCompactEncodedInstFragment"; break;
348 case MCFragment::FT_Fill
: OS
<< "MCFillFragment"; break;
349 case MCFragment::FT_Nops
:
350 OS
<< "MCFNopsFragment";
352 case MCFragment::FT_Relaxable
: OS
<< "MCRelaxableFragment"; break;
353 case MCFragment::FT_Org
: OS
<< "MCOrgFragment"; break;
354 case MCFragment::FT_Dwarf
: OS
<< "MCDwarfFragment"; break;
355 case MCFragment::FT_DwarfFrame
: OS
<< "MCDwarfCallFrameFragment"; break;
356 case MCFragment::FT_LEB
: OS
<< "MCLEBFragment"; break;
357 case MCFragment::FT_BoundaryAlign
: OS
<<"MCBoundaryAlignFragment"; break;
358 case MCFragment::FT_SymbolId
: OS
<< "MCSymbolIdFragment"; break;
359 case MCFragment::FT_CVInlineLines
: OS
<< "MCCVInlineLineTableFragment"; break;
360 case MCFragment::FT_CVDefRange
: OS
<< "MCCVDefRangeTableFragment"; break;
361 case MCFragment::FT_PseudoProbe
:
362 OS
<< "MCPseudoProbe";
364 case MCFragment::FT_Dummy
: OS
<< "MCDummyFragment"; break;
367 OS
<< "<MCFragment " << (const void *)this << " LayoutOrder:" << LayoutOrder
368 << " Offset:" << Offset
<< " HasInstructions:" << hasInstructions();
369 if (const auto *EF
= dyn_cast
<MCEncodedFragment
>(this))
370 OS
<< " BundlePadding:" << static_cast<unsigned>(EF
->getBundlePadding());
374 case MCFragment::FT_Align
: {
375 const auto *AF
= cast
<MCAlignFragment
>(this);
376 if (AF
->hasEmitNops())
377 OS
<< " (emit nops)";
379 OS
<< " Alignment:" << AF
->getAlignment().value()
380 << " Value:" << AF
->getValue() << " ValueSize:" << AF
->getValueSize()
381 << " MaxBytesToEmit:" << AF
->getMaxBytesToEmit() << ">";
384 case MCFragment::FT_Data
: {
385 const auto *DF
= cast
<MCDataFragment
>(this);
388 const SmallVectorImpl
<char> &Contents
= DF
->getContents();
389 for (unsigned i
= 0, e
= Contents
.size(); i
!= e
; ++i
) {
391 OS
<< hexdigit((Contents
[i
] >> 4) & 0xF) << hexdigit(Contents
[i
] & 0xF);
393 OS
<< "] (" << Contents
.size() << " bytes)";
395 if (DF
->fixup_begin() != DF
->fixup_end()) {
398 for (MCDataFragment::const_fixup_iterator it
= DF
->fixup_begin(),
399 ie
= DF
->fixup_end(); it
!= ie
; ++it
) {
400 if (it
!= DF
->fixup_begin()) OS
<< ",\n ";
407 case MCFragment::FT_CompactEncodedInst
: {
409 cast
<MCCompactEncodedInstFragment
>(this);
412 const SmallVectorImpl
<char> &Contents
= CEIF
->getContents();
413 for (unsigned i
= 0, e
= Contents
.size(); i
!= e
; ++i
) {
415 OS
<< hexdigit((Contents
[i
] >> 4) & 0xF) << hexdigit(Contents
[i
] & 0xF);
417 OS
<< "] (" << Contents
.size() << " bytes)";
420 case MCFragment::FT_Fill
: {
421 const auto *FF
= cast
<MCFillFragment
>(this);
422 OS
<< " Value:" << static_cast<unsigned>(FF
->getValue())
423 << " ValueSize:" << static_cast<unsigned>(FF
->getValueSize())
424 << " NumValues:" << FF
->getNumValues();
427 case MCFragment::FT_Nops
: {
428 const auto *NF
= cast
<MCNopsFragment
>(this);
429 OS
<< " NumBytes:" << NF
->getNumBytes()
430 << " ControlledNopLength:" << NF
->getControlledNopLength();
433 case MCFragment::FT_Relaxable
: {
434 const auto *F
= cast
<MCRelaxableFragment
>(this);
437 F
->getInst().dump_pretty(OS
);
438 OS
<< " (" << F
->getContents().size() << " bytes)";
441 case MCFragment::FT_Org
: {
442 const auto *OF
= cast
<MCOrgFragment
>(this);
444 OS
<< " Offset:" << OF
->getOffset()
445 << " Value:" << static_cast<unsigned>(OF
->getValue());
448 case MCFragment::FT_Dwarf
: {
449 const auto *OF
= cast
<MCDwarfLineAddrFragment
>(this);
451 OS
<< " AddrDelta:" << OF
->getAddrDelta()
452 << " LineDelta:" << OF
->getLineDelta();
455 case MCFragment::FT_DwarfFrame
: {
456 const auto *CF
= cast
<MCDwarfCallFrameFragment
>(this);
458 OS
<< " AddrDelta:" << CF
->getAddrDelta();
461 case MCFragment::FT_LEB
: {
462 const auto *LF
= cast
<MCLEBFragment
>(this);
464 OS
<< " Value:" << LF
->getValue() << " Signed:" << LF
->isSigned();
467 case MCFragment::FT_BoundaryAlign
: {
468 const auto *BF
= cast
<MCBoundaryAlignFragment
>(this);
470 OS
<< " BoundarySize:" << BF
->getAlignment().value()
471 << " LastFragment:" << BF
->getLastFragment()
472 << " Size:" << BF
->getSize();
475 case MCFragment::FT_SymbolId
: {
476 const auto *F
= cast
<MCSymbolIdFragment
>(this);
478 OS
<< " Sym:" << F
->getSymbol();
481 case MCFragment::FT_CVInlineLines
: {
482 const auto *F
= cast
<MCCVInlineLineTableFragment
>(this);
484 OS
<< " Sym:" << *F
->getFnStartSym();
487 case MCFragment::FT_CVDefRange
: {
488 const auto *F
= cast
<MCCVDefRangeFragment
>(this);
490 for (std::pair
<const MCSymbol
*, const MCSymbol
*> RangeStartEnd
:
492 OS
<< " RangeStart:" << RangeStartEnd
.first
;
493 OS
<< " RangeEnd:" << RangeStartEnd
.second
;
497 case MCFragment::FT_PseudoProbe
: {
498 const auto *OF
= cast
<MCPseudoProbeAddrFragment
>(this);
500 OS
<< " AddrDelta:" << OF
->getAddrDelta();
503 case MCFragment::FT_Dummy
: