LLVM 19.0.0git
MCFragment.cpp
Go to the documentation of this file.
1//===- lib/MC/MCFragment.cpp - Assembler Fragment Implementation ----------===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8
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"
21#include "llvm/MC/MCSymbol.h"
22#include "llvm/MC/MCValue.h"
27#include <cassert>
28#include <cstdint>
29#include <utility>
30
31using namespace llvm;
32
33MCAsmLayout::MCAsmLayout(MCAssembler &Asm) : Assembler(Asm) {
34 // Compute the section layout order. Virtual sections must go last.
35 for (MCSection &Sec : Asm)
36 if (!Sec.isVirtualSection())
37 SectionOrder.push_back(&Sec);
38 for (MCSection &Sec : Asm)
39 if (Sec.isVirtualSection())
40 SectionOrder.push_back(&Sec);
41}
42
44 F->getParent()->setHasLayout(false);
45}
46
47// Simple getSymbolOffset helper for the non-variable case.
48static bool getLabelOffset(const MCAsmLayout &Layout, const MCSymbol &S,
49 bool ReportError, uint64_t &Val) {
50 if (!S.getFragment()) {
51 if (ReportError)
52 report_fatal_error("unable to evaluate offset to undefined symbol '" +
53 S.getName() + "'");
54 return false;
55 }
56 Val = Layout.getFragmentOffset(S.getFragment()) + S.getOffset();
57 return true;
58}
59
60static bool getSymbolOffsetImpl(const MCAsmLayout &Layout, const MCSymbol &S,
61 bool ReportError, uint64_t &Val) {
62 if (!S.isVariable())
63 return getLabelOffset(Layout, S, ReportError, Val);
64
65 // If SD is a variable, evaluate it.
67 if (!S.getVariableValue()->evaluateAsValue(Target, Layout))
68 report_fatal_error("unable to evaluate offset for variable '" +
69 S.getName() + "'");
70
71 uint64_t Offset = Target.getConstant();
72
73 const MCSymbolRefExpr *A = Target.getSymA();
74 if (A) {
75 uint64_t ValA;
76 // FIXME: On most platforms, `Target`'s component symbols are labels from
77 // having been simplified during evaluation, but on Mach-O they can be
78 // variables due to PR19203. This, and the line below for `B` can be
79 // restored to call `getLabelOffset` when PR19203 is fixed.
80 if (!getSymbolOffsetImpl(Layout, A->getSymbol(), ReportError, ValA))
81 return false;
82 Offset += ValA;
83 }
84
85 const MCSymbolRefExpr *B = Target.getSymB();
86 if (B) {
87 uint64_t ValB;
88 if (!getSymbolOffsetImpl(Layout, B->getSymbol(), ReportError, ValB))
89 return false;
90 Offset -= ValB;
91 }
92
93 Val = Offset;
94 return true;
95}
96
98 return getSymbolOffsetImpl(*this, S, false, Val);
99}
100
102 uint64_t Val;
103 getSymbolOffsetImpl(*this, S, true, Val);
104 return Val;
105}
106
107const MCSymbol *MCAsmLayout::getBaseSymbol(const MCSymbol &Symbol) const {
108 if (!Symbol.isVariable())
109 return &Symbol;
110
111 const MCExpr *Expr = Symbol.getVariableValue();
113 if (!Expr->evaluateAsValue(Value, *this)) {
114 Assembler.getContext().reportError(
115 Expr->getLoc(), "expression could not be evaluated");
116 return nullptr;
117 }
118
119 const MCSymbolRefExpr *RefB = Value.getSymB();
120 if (RefB) {
121 Assembler.getContext().reportError(
122 Expr->getLoc(), Twine("symbol '") + RefB->getSymbol().getName() +
123 "' could not be evaluated in a subtraction expression");
124 return nullptr;
125 }
126
127 const MCSymbolRefExpr *A = Value.getSymA();
128 if (!A)
129 return nullptr;
130
131 const MCSymbol &ASym = A->getSymbol();
132 const MCAssembler &Asm = getAssembler();
133 if (ASym.isCommon()) {
134 Asm.getContext().reportError(Expr->getLoc(),
135 "Common symbol '" + ASym.getName() +
136 "' cannot be used in assignment expr");
137 return nullptr;
138 }
139
140 return &ASym;
141}
142
144 // The size is the last fragment's end offset.
145 const MCFragment &F = *Sec->curFragList()->Tail;
147}
148
150 // Virtual sections have no file size.
151 if (Sec->isVirtualSection())
152 return 0;
153
154 // Otherwise, the file size is the same as the address space size.
155 return getSectionAddressSize(Sec);
156}
157
158/* *** */
159
160MCFragment::MCFragment(FragmentType Kind, bool HasInstructions)
161 : Kind(Kind), HasInstructions(HasInstructions), LinkerRelaxable(false) {}
162
164 switch (Kind) {
165 case FT_Align:
166 cast<MCAlignFragment>(this)->~MCAlignFragment();
167 return;
168 case FT_Data:
169 cast<MCDataFragment>(this)->~MCDataFragment();
170 return;
172 cast<MCCompactEncodedInstFragment>(this)->~MCCompactEncodedInstFragment();
173 return;
174 case FT_Fill:
175 cast<MCFillFragment>(this)->~MCFillFragment();
176 return;
177 case FT_Nops:
178 cast<MCNopsFragment>(this)->~MCNopsFragment();
179 return;
180 case FT_Relaxable:
181 cast<MCRelaxableFragment>(this)->~MCRelaxableFragment();
182 return;
183 case FT_Org:
184 cast<MCOrgFragment>(this)->~MCOrgFragment();
185 return;
186 case FT_Dwarf:
187 cast<MCDwarfLineAddrFragment>(this)->~MCDwarfLineAddrFragment();
188 return;
189 case FT_DwarfFrame:
190 cast<MCDwarfCallFrameFragment>(this)->~MCDwarfCallFrameFragment();
191 return;
192 case FT_LEB:
193 cast<MCLEBFragment>(this)->~MCLEBFragment();
194 return;
195 case FT_BoundaryAlign:
196 cast<MCBoundaryAlignFragment>(this)->~MCBoundaryAlignFragment();
197 return;
198 case FT_SymbolId:
199 cast<MCSymbolIdFragment>(this)->~MCSymbolIdFragment();
200 return;
201 case FT_CVInlineLines:
202 cast<MCCVInlineLineTableFragment>(this)->~MCCVInlineLineTableFragment();
203 return;
204 case FT_CVDefRange:
205 cast<MCCVDefRangeFragment>(this)->~MCCVDefRangeFragment();
206 return;
207 case FT_PseudoProbe:
208 cast<MCPseudoProbeAddrFragment>(this)->~MCPseudoProbeAddrFragment();
209 return;
210 case FT_Dummy:
211 cast<MCDummyFragment>(this)->~MCDummyFragment();
212 return;
213 }
214}
215
217 return cast<MCSectionMachO>(Parent)->getAtom(LayoutOrder);
218}
219
220// Debugging methods
221
222namespace llvm {
223
225 OS << "<MCFixup" << " Offset:" << AF.getOffset()
226 << " Value:" << *AF.getValue()
227 << " Kind:" << AF.getKind() << ">";
228 return OS;
229}
230
231} // end namespace llvm
232
233#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
235 raw_ostream &OS = errs();
236
237 OS << "<";
238 switch (getKind()) {
239 case MCFragment::FT_Align: OS << "MCAlignFragment"; break;
240 case MCFragment::FT_Data: OS << "MCDataFragment"; break;
242 OS << "MCCompactEncodedInstFragment"; break;
243 case MCFragment::FT_Fill: OS << "MCFillFragment"; break;
245 OS << "MCFNopsFragment";
246 break;
247 case MCFragment::FT_Relaxable: OS << "MCRelaxableFragment"; break;
248 case MCFragment::FT_Org: OS << "MCOrgFragment"; break;
249 case MCFragment::FT_Dwarf: OS << "MCDwarfFragment"; break;
250 case MCFragment::FT_DwarfFrame: OS << "MCDwarfCallFrameFragment"; break;
251 case MCFragment::FT_LEB: OS << "MCLEBFragment"; break;
252 case MCFragment::FT_BoundaryAlign: OS<<"MCBoundaryAlignFragment"; break;
253 case MCFragment::FT_SymbolId: OS << "MCSymbolIdFragment"; break;
254 case MCFragment::FT_CVInlineLines: OS << "MCCVInlineLineTableFragment"; break;
255 case MCFragment::FT_CVDefRange: OS << "MCCVDefRangeTableFragment"; break;
257 OS << "MCPseudoProbe";
258 break;
259 case MCFragment::FT_Dummy: OS << "MCDummyFragment"; break;
260 }
261
262 OS << "<MCFragment " << (const void *)this << " LayoutOrder:" << LayoutOrder
263 << " Offset:" << Offset << " HasInstructions:" << hasInstructions();
264 if (const auto *EF = dyn_cast<MCEncodedFragment>(this))
265 OS << " BundlePadding:" << static_cast<unsigned>(EF->getBundlePadding());
266 OS << ">";
267
268 switch (getKind()) {
270 const auto *AF = cast<MCAlignFragment>(this);
271 if (AF->hasEmitNops())
272 OS << " (emit nops)";
273 OS << "\n ";
274 OS << " Alignment:" << AF->getAlignment().value()
275 << " Value:" << AF->getValue() << " ValueSize:" << AF->getValueSize()
276 << " MaxBytesToEmit:" << AF->getMaxBytesToEmit() << ">";
277 break;
278 }
279 case MCFragment::FT_Data: {
280 const auto *DF = cast<MCDataFragment>(this);
281 OS << "\n ";
282 OS << " Contents:[";
283 const SmallVectorImpl<char> &Contents = DF->getContents();
284 for (unsigned i = 0, e = Contents.size(); i != e; ++i) {
285 if (i) OS << ",";
286 OS << hexdigit((Contents[i] >> 4) & 0xF) << hexdigit(Contents[i] & 0xF);
287 }
288 OS << "] (" << Contents.size() << " bytes)";
289
290 if (DF->fixup_begin() != DF->fixup_end()) {
291 OS << ",\n ";
292 OS << " Fixups:[";
293 for (MCDataFragment::const_fixup_iterator it = DF->fixup_begin(),
294 ie = DF->fixup_end(); it != ie; ++it) {
295 if (it != DF->fixup_begin()) OS << ",\n ";
296 OS << *it;
297 }
298 OS << "]";
299 }
300 break;
301 }
303 const auto *CEIF =
304 cast<MCCompactEncodedInstFragment>(this);
305 OS << "\n ";
306 OS << " Contents:[";
307 const SmallVectorImpl<char> &Contents = CEIF->getContents();
308 for (unsigned i = 0, e = Contents.size(); i != e; ++i) {
309 if (i) OS << ",";
310 OS << hexdigit((Contents[i] >> 4) & 0xF) << hexdigit(Contents[i] & 0xF);
311 }
312 OS << "] (" << Contents.size() << " bytes)";
313 break;
314 }
315 case MCFragment::FT_Fill: {
316 const auto *FF = cast<MCFillFragment>(this);
317 OS << " Value:" << static_cast<unsigned>(FF->getValue())
318 << " ValueSize:" << static_cast<unsigned>(FF->getValueSize())
319 << " NumValues:" << FF->getNumValues();
320 break;
321 }
322 case MCFragment::FT_Nops: {
323 const auto *NF = cast<MCNopsFragment>(this);
324 OS << " NumBytes:" << NF->getNumBytes()
325 << " ControlledNopLength:" << NF->getControlledNopLength();
326 break;
327 }
329 const auto *F = cast<MCRelaxableFragment>(this);
330 OS << "\n ";
331 OS << " Inst:";
332 F->getInst().dump_pretty(OS);
333 OS << " (" << F->getContents().size() << " bytes)";
334 break;
335 }
336 case MCFragment::FT_Org: {
337 const auto *OF = cast<MCOrgFragment>(this);
338 OS << "\n ";
339 OS << " Offset:" << OF->getOffset()
340 << " Value:" << static_cast<unsigned>(OF->getValue());
341 break;
342 }
344 const auto *OF = cast<MCDwarfLineAddrFragment>(this);
345 OS << "\n ";
346 OS << " AddrDelta:" << OF->getAddrDelta()
347 << " LineDelta:" << OF->getLineDelta();
348 break;
349 }
351 const auto *CF = cast<MCDwarfCallFrameFragment>(this);
352 OS << "\n ";
353 OS << " AddrDelta:" << CF->getAddrDelta();
354 break;
355 }
356 case MCFragment::FT_LEB: {
357 const auto *LF = cast<MCLEBFragment>(this);
358 OS << "\n ";
359 OS << " Value:" << LF->getValue() << " Signed:" << LF->isSigned();
360 break;
361 }
363 const auto *BF = cast<MCBoundaryAlignFragment>(this);
364 OS << "\n ";
365 OS << " BoundarySize:" << BF->getAlignment().value()
366 << " LastFragment:" << BF->getLastFragment()
367 << " Size:" << BF->getSize();
368 break;
369 }
371 const auto *F = cast<MCSymbolIdFragment>(this);
372 OS << "\n ";
373 OS << " Sym:" << F->getSymbol();
374 break;
375 }
377 const auto *F = cast<MCCVInlineLineTableFragment>(this);
378 OS << "\n ";
379 OS << " Sym:" << *F->getFnStartSym();
380 break;
381 }
383 const auto *F = cast<MCCVDefRangeFragment>(this);
384 OS << "\n ";
385 for (std::pair<const MCSymbol *, const MCSymbol *> RangeStartEnd :
386 F->getRanges()) {
387 OS << " RangeStart:" << RangeStartEnd.first;
388 OS << " RangeEnd:" << RangeStartEnd.second;
389 }
390 break;
391 }
393 const auto *OF = cast<MCPseudoProbeAddrFragment>(this);
394 OS << "\n ";
395 OS << " AddrDelta:" << OF->getAddrDelta();
396 break;
397 }
399 break;
400 }
401 OS << ">";
402}
403#endif
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
Definition: Compiler.h:537
static RegisterPass< DebugifyFunctionPass > DF("debugify-function", "Attach debug info to a function")
static bool getSymbolOffsetImpl(const MCAsmLayout &Layout, const MCSymbol &S, bool ReportError, uint64_t &Val)
Definition: MCFragment.cpp:60
static bool getLabelOffset(const MCAsmLayout &Layout, const MCSymbol &S, bool ReportError, uint64_t &Val)
Definition: MCFragment.cpp:48
#define F(x, y, z)
Definition: MD5.cpp:55
raw_pwrite_stream & OS
This file defines the SmallVector class.
This file contains some functions that are useful when dealing with strings.
Encapsulates the layout of an assembly file at a particular point in time.
Definition: MCAsmLayout.h:28
void invalidateFragmentsFrom(MCFragment *F)
Invalidate the fragments starting with F because it has been resized.
Definition: MCFragment.cpp:43
const MCSymbol * getBaseSymbol(const MCSymbol &Symbol) const
If this symbol is equivalent to A + Constant, return A.
Definition: MCFragment.cpp:107
uint64_t getSectionAddressSize(const MCSection *Sec) const
Get the address space size of the given section, as it effects layout.
Definition: MCFragment.cpp:143
uint64_t getSectionFileSize(const MCSection *Sec) const
Get the data size of the given section, as emitted to the object file.
Definition: MCFragment.cpp:149
bool getSymbolOffset(const MCSymbol &S, uint64_t &Val) const
Get the offset of the given symbol, as computed in the current layout.
Definition: MCFragment.cpp:97
MCAsmLayout(MCAssembler &Assembler)
Definition: MCFragment.cpp:33
uint64_t getFragmentOffset(const MCFragment *F) const
Get the offset of the given fragment inside its containing section.
MCAssembler & getAssembler() const
Get the assembler object this is a layout for.
Definition: MCAsmLayout.h:41
MCContext & getContext() const
Definition: MCAssembler.h:322
uint64_t computeFragmentSize(const MCAsmLayout &Layout, const MCFragment &F) const
Compute the effective fragment size assuming it is laid out at the given SectionAddress and FragmentO...
void reportError(SMLoc L, const Twine &Msg)
Definition: MCContext.cpp:1070
SmallVectorImpl< MCFixup >::const_iterator const_fixup_iterator
Definition: MCFragment.h:210
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:35
bool evaluateAsValue(MCValue &Res, const MCAsmLayout &Layout) const
Try to evaluate the expression to the form (a - b + constant) where neither a nor b are variables.
Definition: MCExpr.cpp:811
SMLoc getLoc() const
Definition: MCExpr.h:82
Encode information on a single operation to perform on a byte sequence (e.g., an encoded instruction)...
Definition: MCFixup.h:71
const MCExpr * getValue() const
Definition: MCFixup.h:105
uint32_t getOffset() const
Definition: MCFixup.h:102
MCFixupKind getKind() const
Definition: MCFixup.h:98
FragmentType getKind() const
Definition: MCFragment.h:92
MCFragment()=delete
const MCSymbol * getAtom() const
Definition: MCFragment.cpp:216
void destroy()
Destroys the current fragment.
Definition: MCFragment.cpp:163
void dump() const
Definition: MCFragment.cpp:234
bool hasInstructions() const
Does this fragment have instructions emitted into it? By default this is false, but specific fragment...
Definition: MCFragment.h:104
Instances of this class represent a uniqued identifier for a section in the current translation unit.
Definition: MCSection.h:36
bool isVirtualSection() const
Check whether this section is "virtual", that is has no actual object file contents.
Definition: MCSection.h:225
FragList * curFragList() const
Definition: MCSection.h:196
Represent a reference to a symbol from inside an expression.
Definition: MCExpr.h:192
const MCSymbol & getSymbol() const
Definition: MCExpr.h:410
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:41
const MCExpr * getVariableValue(bool SetUsed=true) const
getVariableValue - Get the value for variable symbols.
Definition: MCSymbol.h:305
bool isCommon() const
Is this a 'common' symbol.
Definition: MCSymbol.h:387
StringRef getName() const
getName - Get the symbol name.
Definition: MCSymbol.h:205
bool isVariable() const
isVariable - Check if this is a variable symbol.
Definition: MCSymbol.h:300
uint64_t getOffset() const
Definition: MCSymbol.h:327
MCFragment * getFragment(bool SetUsed=true) const
Definition: MCSymbol.h:397
This represents an "assembler immediate".
Definition: MCValue.h:36
size_t size() const
Definition: SmallVector.h:91
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:586
Target - Wrapper for Target specific information.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
LLVM Value Representation.
Definition: Value.h:74
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:480
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:167
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
Definition: APFixedPoint.h:293