1 | //===- MCSection.h - Machine Code Sections ----------------------*- C++ -*-===// |
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 | // |
9 | // This file declares the MCSection class. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #ifndef LLVM_MC_MCSECTION_H |
14 | #define LLVM_MC_MCSECTION_H |
15 | |
16 | #include "llvm/ADT/ArrayRef.h" |
17 | #include "llvm/ADT/DenseMap.h" |
18 | #include "llvm/ADT/SmallString.h" |
19 | #include "llvm/ADT/SmallVector.h" |
20 | #include "llvm/MC/MCFixup.h" |
21 | #include "llvm/MC/MCInst.h" |
22 | #include "llvm/MC/SectionKind.h" |
23 | #include "llvm/Support/Alignment.h" |
24 | #include "llvm/Support/Compiler.h" |
25 | #include <cassert> |
26 | #include <utility> |
27 | |
28 | namespace llvm { |
29 | |
30 | class MCAsmInfo; |
31 | class MCAssembler; |
32 | class MCContext; |
33 | class MCExpr; |
34 | class MCObjectStreamer; |
35 | class MCSymbol; |
36 | class MCSection; |
37 | class MCSubtargetInfo; |
38 | class raw_ostream; |
39 | class Triple; |
40 | |
41 | // Represents a contiguous piece of code or data within a section. Its size is |
42 | // determined by MCAssembler::layout. All subclasses (except |
43 | // MCRelaxableFragment, which stores a MCInst) must have trivial destructors. |
44 | // |
45 | // Declaration order: MCFragment, MCSection, then MCFragment's derived classes. |
46 | // This allows MCSection's inline functions to access MCFragment members and |
47 | // allows MCFragment's derived classes to access MCSection. |
48 | class MCFragment { |
49 | friend class MCAssembler; |
50 | friend class MCObjectStreamer; |
51 | friend class MCSection; |
52 | |
53 | public: |
54 | enum FragmentType : uint8_t { |
55 | FT_Align, |
56 | FT_Data, |
57 | FT_Fill, |
58 | FT_Nops, |
59 | FT_Relaxable, |
60 | FT_Org, |
61 | FT_Dwarf, |
62 | FT_DwarfFrame, |
63 | FT_LEB, |
64 | FT_BoundaryAlign, |
65 | FT_SymbolId, |
66 | FT_CVInlineLines, |
67 | FT_CVDefRange, |
68 | FT_PseudoProbe, |
69 | }; |
70 | |
71 | private: |
72 | // The next fragment within the section. |
73 | MCFragment *Next = nullptr; |
74 | |
75 | /// The data for the section this fragment is in. |
76 | MCSection *Parent = nullptr; |
77 | |
78 | /// The offset of this fragment in its section. |
79 | uint64_t Offset = 0; |
80 | |
81 | /// The layout order of this fragment. |
82 | unsigned LayoutOrder = 0; |
83 | |
84 | FragmentType Kind; |
85 | |
86 | protected: |
87 | /// Used by subclasses for better packing. |
88 | /// |
89 | /// MCEncodedFragment |
90 | bool HasInstructions : 1; |
91 | bool AlignToBundleEnd : 1; |
92 | /// MCDataFragment |
93 | bool LinkerRelaxable : 1; |
94 | /// MCRelaxableFragment: x86-specific |
95 | bool AllowAutoPadding : 1; |
96 | |
97 | LLVM_ABI MCFragment(FragmentType Kind, bool HasInstructions); |
98 | |
99 | public: |
100 | MCFragment() = delete; |
101 | MCFragment(const MCFragment &) = delete; |
102 | MCFragment &operator=(const MCFragment &) = delete; |
103 | |
104 | /// Destroys the current fragment. |
105 | /// |
106 | /// This must be used instead of delete as MCFragment is non-virtual. |
107 | /// This method will dispatch to the appropriate subclass. |
108 | LLVM_ABI void destroy(); |
109 | |
110 | MCFragment *getNext() const { return Next; } |
111 | |
112 | FragmentType getKind() const { return Kind; } |
113 | |
114 | MCSection *getParent() const { return Parent; } |
115 | void setParent(MCSection *Value) { Parent = Value; } |
116 | |
117 | LLVM_ABI const MCSymbol *getAtom() const; |
118 | |
119 | unsigned getLayoutOrder() const { return LayoutOrder; } |
120 | void setLayoutOrder(unsigned Value) { LayoutOrder = Value; } |
121 | |
122 | /// Does this fragment have instructions emitted into it? By default |
123 | /// this is false, but specific fragment types may set it to true. |
124 | bool hasInstructions() const { return HasInstructions; } |
125 | |
126 | LLVM_ABI void dump() const; |
127 | }; |
128 | |
129 | /// Instances of this class represent a uniqued identifier for a section in the |
130 | /// current translation unit. The MCContext class uniques and creates these. |
131 | class LLVM_ABI MCSection { |
132 | public: |
133 | friend MCAssembler; |
134 | friend MCObjectStreamer; |
135 | friend class MCEncodedFragment; |
136 | static constexpr unsigned NonUniqueID = ~0U; |
137 | |
138 | enum SectionVariant { |
139 | SV_COFF = 0, |
140 | SV_ELF, |
141 | SV_GOFF, |
142 | SV_MachO, |
143 | SV_Wasm, |
144 | SV_XCOFF, |
145 | SV_SPIRV, |
146 | SV_DXContainer, |
147 | }; |
148 | |
149 | /// Express the state of bundle locked groups while emitting code. |
150 | enum BundleLockStateType { |
151 | NotBundleLocked, |
152 | BundleLocked, |
153 | BundleLockedAlignToEnd |
154 | }; |
155 | |
156 | struct iterator { |
157 | MCFragment *F = nullptr; |
158 | iterator() = default; |
159 | explicit iterator(MCFragment *F) : F(F) {} |
160 | MCFragment &operator*() const { return *F; } |
161 | bool operator==(const iterator &O) const { return F == O.F; } |
162 | bool operator!=(const iterator &O) const { return F != O.F; } |
163 | iterator &operator++() { |
164 | F = F->Next; |
165 | return *this; |
166 | } |
167 | }; |
168 | |
169 | struct FragList { |
170 | MCFragment *Head = nullptr; |
171 | MCFragment *Tail = nullptr; |
172 | }; |
173 | |
174 | private: |
175 | // At parse time, this holds the fragment list of the current subsection. At |
176 | // layout time, this holds the concatenated fragment lists of all subsections. |
177 | FragList *CurFragList; |
178 | MCSymbol *Begin; |
179 | MCSymbol *End = nullptr; |
180 | /// The alignment requirement of this section. |
181 | Align Alignment; |
182 | /// The section index in the assemblers section list. |
183 | unsigned Ordinal = 0; |
184 | |
185 | /// Keeping track of bundle-locked state. |
186 | BundleLockStateType BundleLockState = NotBundleLocked; |
187 | |
188 | /// Current nesting depth of bundle_lock directives. |
189 | unsigned BundleLockNestingDepth = 0; |
190 | |
191 | /// We've seen a bundle_lock directive but not its first instruction |
192 | /// yet. |
193 | bool BundleGroupBeforeFirstInst : 1; |
194 | |
195 | /// Whether this section has had instructions emitted into it. |
196 | bool HasInstructions : 1; |
197 | |
198 | bool IsRegistered : 1; |
199 | |
200 | bool IsText : 1; |
201 | |
202 | bool IsVirtual : 1; |
203 | |
204 | /// Whether the section contains linker-relaxable fragments. If true, the |
205 | /// offset between two locations may not be fully resolved. |
206 | bool LinkerRelaxable : 1; |
207 | |
208 | // Mapping from subsection number to fragment list. At layout time, the |
209 | // subsection 0 list is replaced with concatenated fragments from all |
210 | // subsections. |
211 | SmallVector<std::pair<unsigned, FragList>, 1> Subsections; |
212 | |
213 | // Content and fixup storage for fragments |
214 | SmallVector<char, 0> ContentStorage; |
215 | SmallVector<MCFixup, 0> FixupStorage; |
216 | |
217 | protected: |
218 | // TODO Make Name private when possible. |
219 | StringRef Name; |
220 | SectionVariant Variant; |
221 | |
222 | MCSection(SectionVariant V, StringRef Name, bool IsText, bool IsVirtual, |
223 | MCSymbol *Begin); |
224 | ~MCSection(); |
225 | |
226 | public: |
227 | MCSection(const MCSection &) = delete; |
228 | MCSection &operator=(const MCSection &) = delete; |
229 | |
230 | StringRef getName() const { return Name; } |
231 | bool isText() const { return IsText; } |
232 | |
233 | SectionVariant getVariant() const { return Variant; } |
234 | |
235 | MCSymbol *getBeginSymbol() { return Begin; } |
236 | const MCSymbol *getBeginSymbol() const { |
237 | return const_cast<MCSection *>(this)->getBeginSymbol(); |
238 | } |
239 | void setBeginSymbol(MCSymbol *Sym) { |
240 | assert(!Begin); |
241 | Begin = Sym; |
242 | } |
243 | MCSymbol *getEndSymbol(MCContext &Ctx); |
244 | bool hasEnded() const; |
245 | |
246 | Align getAlign() const { return Alignment; } |
247 | void setAlignment(Align Value) { Alignment = Value; } |
248 | |
249 | /// Makes sure that Alignment is at least MinAlignment. |
250 | void ensureMinAlignment(Align MinAlignment) { |
251 | if (Alignment < MinAlignment) |
252 | Alignment = MinAlignment; |
253 | } |
254 | |
255 | unsigned getOrdinal() const { return Ordinal; } |
256 | void setOrdinal(unsigned Value) { Ordinal = Value; } |
257 | |
258 | BundleLockStateType getBundleLockState() const { return BundleLockState; } |
259 | void setBundleLockState(BundleLockStateType NewState); |
260 | bool isBundleLocked() const { return BundleLockState != NotBundleLocked; } |
261 | |
262 | bool isBundleGroupBeforeFirstInst() const { |
263 | return BundleGroupBeforeFirstInst; |
264 | } |
265 | void setBundleGroupBeforeFirstInst(bool IsFirst) { |
266 | BundleGroupBeforeFirstInst = IsFirst; |
267 | } |
268 | |
269 | bool hasInstructions() const { return HasInstructions; } |
270 | void setHasInstructions(bool Value) { HasInstructions = Value; } |
271 | |
272 | bool isRegistered() const { return IsRegistered; } |
273 | void setIsRegistered(bool Value) { IsRegistered = Value; } |
274 | |
275 | bool isLinkerRelaxable() const { return LinkerRelaxable; } |
276 | void setLinkerRelaxable() { LinkerRelaxable = true; } |
277 | |
278 | MCFragment &getDummyFragment() { return *Subsections[0].second.Head; } |
279 | |
280 | FragList *curFragList() const { return CurFragList; } |
281 | iterator begin() const { return iterator(CurFragList->Head); } |
282 | iterator end() const { return {}; } |
283 | |
284 | void dump(DenseMap<const MCFragment *, SmallVector<const MCSymbol *, 0>> |
285 | *FragToSyms = nullptr) const; |
286 | |
287 | virtual void printSwitchToSection(const MCAsmInfo &MAI, const Triple &T, |
288 | raw_ostream &OS, |
289 | uint32_t Subsection) const = 0; |
290 | |
291 | /// Return true if a .align directive should use "optimized nops" to fill |
292 | /// instead of 0s. |
293 | virtual bool useCodeAlign() const = 0; |
294 | |
295 | /// Check whether this section is "virtual", that is has no actual object |
296 | /// file contents. |
297 | bool isVirtualSection() const { return IsVirtual; } |
298 | |
299 | virtual StringRef getVirtualSectionKind() const; |
300 | }; |
301 | |
302 | /// Interface implemented by fragments that contain encoded instructions and/or |
303 | /// data. |
304 | class MCEncodedFragment : public MCFragment { |
305 | uint8_t BundlePadding = 0; |
306 | uint32_t ContentStart = 0; |
307 | uint32_t ContentEnd = 0; |
308 | uint32_t FixupStart = 0; |
309 | uint32_t FixupEnd = 0; |
310 | |
311 | protected: |
312 | MCEncodedFragment(MCFragment::FragmentType FType, bool HasInstructions) |
313 | : MCFragment(FType, HasInstructions) {} |
314 | |
315 | /// The MCSubtargetInfo in effect when the instruction was encoded. |
316 | /// It must be non-null for instructions. |
317 | const MCSubtargetInfo *STI = nullptr; |
318 | |
319 | public: |
320 | static bool classof(const MCFragment *F) { |
321 | MCFragment::FragmentType Kind = F->getKind(); |
322 | switch (Kind) { |
323 | default: |
324 | return false; |
325 | case MCFragment::FT_Relaxable: |
326 | case MCFragment::FT_Data: |
327 | case MCFragment::FT_Dwarf: |
328 | case MCFragment::FT_DwarfFrame: |
329 | case MCFragment::FT_LEB: |
330 | case MCFragment::FT_PseudoProbe: |
331 | case MCFragment::FT_CVInlineLines: |
332 | case MCFragment::FT_CVDefRange: |
333 | return true; |
334 | } |
335 | } |
336 | |
337 | /// Should this fragment be placed at the end of an aligned bundle? |
338 | bool alignToBundleEnd() const { return AlignToBundleEnd; } |
339 | void setAlignToBundleEnd(bool V) { AlignToBundleEnd = V; } |
340 | |
341 | /// Get the padding size that must be inserted before this fragment. |
342 | /// Used for bundling. By default, no padding is inserted. |
343 | /// Note that padding size is restricted to 8 bits. This is an optimization |
344 | /// to reduce the amount of space used for each fragment. In practice, larger |
345 | /// padding should never be required. |
346 | uint8_t getBundlePadding() const { return BundlePadding; } |
347 | |
348 | /// Set the padding size for this fragment. By default it's a no-op, |
349 | /// and only some fragments have a meaningful implementation. |
350 | void setBundlePadding(uint8_t N) { BundlePadding = N; } |
351 | |
352 | /// Retrieve the MCSubTargetInfo in effect when the instruction was encoded. |
353 | /// Guaranteed to be non-null if hasInstructions() == true |
354 | const MCSubtargetInfo *getSubtargetInfo() const { return STI; } |
355 | |
356 | /// Record that the fragment contains instructions with the MCSubtargetInfo in |
357 | /// effect when the instruction was encoded. |
358 | void setHasInstructions(const MCSubtargetInfo &STI) { |
359 | HasInstructions = true; |
360 | this->STI = &STI; |
361 | } |
362 | |
363 | // Content-related functions manage parent's storage using ContentStart and |
364 | // ContentSize. |
365 | void clearContents() { ContentEnd = ContentStart; } |
366 | // Get a SmallVector reference. The caller should call doneAppending to update |
367 | // `ContentEnd`. |
368 | SmallVectorImpl<char> &getContentsForAppending() { |
369 | SmallVectorImpl<char> &S = getParent()->ContentStorage; |
370 | if (LLVM_UNLIKELY(ContentEnd != S.size())) { |
371 | // Move the elements to the end. Reserve space to avoid invalidating |
372 | // S.begin()+I for `append`. |
373 | auto Size = ContentEnd - ContentStart; |
374 | auto I = std::exchange(obj&: ContentStart, new_val: S.size()); |
375 | S.reserve(N: S.size() + Size); |
376 | S.append(in_start: S.begin() + I, in_end: S.begin() + I + Size); |
377 | } |
378 | return S; |
379 | } |
380 | void doneAppending() { ContentEnd = getParent()->ContentStorage.size(); } |
381 | void appendContents(ArrayRef<char> Contents) { |
382 | getContentsForAppending().append(in_start: Contents.begin(), in_end: Contents.end()); |
383 | doneAppending(); |
384 | } |
385 | void appendContents(size_t Num, char Elt) { |
386 | getContentsForAppending().append(NumInputs: Num, Elt); |
387 | doneAppending(); |
388 | } |
389 | void setContents(ArrayRef<char> Contents); |
390 | MutableArrayRef<char> getContents() { |
391 | return MutableArrayRef(getParent()->ContentStorage) |
392 | .slice(N: ContentStart, M: ContentEnd - ContentStart); |
393 | } |
394 | ArrayRef<char> getContents() const { |
395 | return ArrayRef(getParent()->ContentStorage) |
396 | .slice(N: ContentStart, M: ContentEnd - ContentStart); |
397 | } |
398 | |
399 | // Fixup-related functions manage parent's storage using FixupStart and |
400 | // FixupSize. |
401 | void clearFixups() { FixupEnd = FixupStart; } |
402 | void addFixup(MCFixup Fixup); |
403 | void appendFixups(ArrayRef<MCFixup> Fixups); |
404 | void setFixups(ArrayRef<MCFixup> Fixups); |
405 | MutableArrayRef<MCFixup> getFixups() { |
406 | return MutableArrayRef(getParent()->FixupStorage) |
407 | .slice(N: FixupStart, M: FixupEnd - FixupStart); |
408 | } |
409 | ArrayRef<MCFixup> getFixups() const { |
410 | return ArrayRef(getParent()->FixupStorage) |
411 | .slice(N: FixupStart, M: FixupEnd - FixupStart); |
412 | } |
413 | }; |
414 | |
415 | /// Fragment for data and encoded instructions. |
416 | /// |
417 | class MCDataFragment : public MCEncodedFragment { |
418 | public: |
419 | MCDataFragment() : MCEncodedFragment(FT_Data, false) {} |
420 | |
421 | static bool classof(const MCFragment *F) { |
422 | return F->getKind() == MCFragment::FT_Data; |
423 | } |
424 | |
425 | bool isLinkerRelaxable() const { return LinkerRelaxable; } |
426 | void setLinkerRelaxable() { LinkerRelaxable = true; } |
427 | }; |
428 | |
429 | /// A relaxable fragment holds on to its MCInst, since it may need to be |
430 | /// relaxed during the assembler layout and relaxation stage. |
431 | /// |
432 | class MCRelaxableFragment : public MCEncodedFragment { |
433 | /// The instruction this is a fragment for. |
434 | MCInst Inst; |
435 | |
436 | public: |
437 | MCRelaxableFragment(const MCInst &Inst, const MCSubtargetInfo &STI) |
438 | : MCEncodedFragment(FT_Relaxable, true), Inst(Inst) { |
439 | this->STI = &STI; |
440 | } |
441 | |
442 | const MCInst &getInst() const { return Inst; } |
443 | void setInst(const MCInst &Value) { Inst = Value; } |
444 | |
445 | bool getAllowAutoPadding() const { return AllowAutoPadding; } |
446 | void setAllowAutoPadding(bool V) { AllowAutoPadding = V; } |
447 | |
448 | static bool classof(const MCFragment *F) { |
449 | return F->getKind() == MCFragment::FT_Relaxable; |
450 | } |
451 | }; |
452 | |
453 | class MCAlignFragment : public MCFragment { |
454 | /// The alignment to ensure, in bytes. |
455 | Align Alignment; |
456 | |
457 | /// Flag to indicate that (optimal) NOPs should be emitted instead |
458 | /// of using the provided value. The exact interpretation of this flag is |
459 | /// target dependent. |
460 | bool EmitNops : 1; |
461 | |
462 | /// Value to use for filling padding bytes. |
463 | int64_t Value; |
464 | |
465 | /// The size of the integer (in bytes) of \p Value. |
466 | unsigned ValueSize; |
467 | |
468 | /// The maximum number of bytes to emit; if the alignment |
469 | /// cannot be satisfied in this width then this fragment is ignored. |
470 | unsigned MaxBytesToEmit; |
471 | |
472 | /// When emitting Nops some subtargets have specific nop encodings. |
473 | const MCSubtargetInfo *STI = nullptr; |
474 | |
475 | public: |
476 | MCAlignFragment(Align Alignment, int64_t Value, unsigned ValueSize, |
477 | unsigned MaxBytesToEmit) |
478 | : MCFragment(FT_Align, false), Alignment(Alignment), EmitNops(false), |
479 | Value(Value), ValueSize(ValueSize), MaxBytesToEmit(MaxBytesToEmit) {} |
480 | |
481 | Align getAlignment() const { return Alignment; } |
482 | |
483 | int64_t getValue() const { return Value; } |
484 | |
485 | unsigned getValueSize() const { return ValueSize; } |
486 | |
487 | unsigned getMaxBytesToEmit() const { return MaxBytesToEmit; } |
488 | |
489 | bool hasEmitNops() const { return EmitNops; } |
490 | void setEmitNops(bool Value, const MCSubtargetInfo *STI) { |
491 | EmitNops = Value; |
492 | this->STI = STI; |
493 | } |
494 | |
495 | const MCSubtargetInfo *getSubtargetInfo() const { return STI; } |
496 | |
497 | static bool classof(const MCFragment *F) { |
498 | return F->getKind() == MCFragment::FT_Align; |
499 | } |
500 | }; |
501 | |
502 | class MCFillFragment : public MCFragment { |
503 | uint8_t ValueSize; |
504 | /// Value to use for filling bytes. |
505 | uint64_t Value; |
506 | /// The number of bytes to insert. |
507 | const MCExpr &NumValues; |
508 | uint64_t Size = 0; |
509 | |
510 | /// Source location of the directive that this fragment was created for. |
511 | SMLoc Loc; |
512 | |
513 | public: |
514 | MCFillFragment(uint64_t Value, uint8_t VSize, const MCExpr &NumValues, |
515 | SMLoc Loc) |
516 | : MCFragment(FT_Fill, false), ValueSize(VSize), Value(Value), |
517 | NumValues(NumValues), Loc(Loc) {} |
518 | |
519 | uint64_t getValue() const { return Value; } |
520 | uint8_t getValueSize() const { return ValueSize; } |
521 | const MCExpr &getNumValues() const { return NumValues; } |
522 | uint64_t getSize() const { return Size; } |
523 | void setSize(uint64_t Value) { Size = Value; } |
524 | |
525 | SMLoc getLoc() const { return Loc; } |
526 | |
527 | static bool classof(const MCFragment *F) { |
528 | return F->getKind() == MCFragment::FT_Fill; |
529 | } |
530 | }; |
531 | |
532 | class MCNopsFragment : public MCFragment { |
533 | /// The number of bytes to insert. |
534 | int64_t Size; |
535 | /// Maximum number of bytes allowed in each NOP instruction. |
536 | int64_t ControlledNopLength; |
537 | |
538 | /// Source location of the directive that this fragment was created for. |
539 | SMLoc Loc; |
540 | |
541 | /// When emitting Nops some subtargets have specific nop encodings. |
542 | const MCSubtargetInfo &STI; |
543 | |
544 | public: |
545 | MCNopsFragment(int64_t NumBytes, int64_t ControlledNopLength, SMLoc L, |
546 | const MCSubtargetInfo &STI) |
547 | : MCFragment(FT_Nops, false), Size(NumBytes), |
548 | ControlledNopLength(ControlledNopLength), Loc(L), STI(STI) {} |
549 | |
550 | int64_t getNumBytes() const { return Size; } |
551 | int64_t getControlledNopLength() const { return ControlledNopLength; } |
552 | |
553 | SMLoc getLoc() const { return Loc; } |
554 | |
555 | const MCSubtargetInfo *getSubtargetInfo() const { return &STI; } |
556 | |
557 | static bool classof(const MCFragment *F) { |
558 | return F->getKind() == MCFragment::FT_Nops; |
559 | } |
560 | }; |
561 | |
562 | class MCOrgFragment : public MCFragment { |
563 | /// Value to use for filling bytes. |
564 | int8_t Value; |
565 | |
566 | /// The offset this fragment should start at. |
567 | const MCExpr *Offset; |
568 | |
569 | /// Source location of the directive that this fragment was created for. |
570 | SMLoc Loc; |
571 | |
572 | public: |
573 | MCOrgFragment(const MCExpr &Offset, int8_t Value, SMLoc Loc) |
574 | : MCFragment(FT_Org, false), Value(Value), Offset(&Offset), Loc(Loc) {} |
575 | |
576 | const MCExpr &getOffset() const { return *Offset; } |
577 | |
578 | uint8_t getValue() const { return Value; } |
579 | |
580 | SMLoc getLoc() const { return Loc; } |
581 | |
582 | static bool classof(const MCFragment *F) { |
583 | return F->getKind() == MCFragment::FT_Org; |
584 | } |
585 | }; |
586 | |
587 | class MCLEBFragment final : public MCEncodedFragment { |
588 | /// True if this is a sleb128, false if uleb128. |
589 | bool IsSigned; |
590 | |
591 | /// The value this fragment should contain. |
592 | const MCExpr *Value; |
593 | |
594 | public: |
595 | MCLEBFragment(const MCExpr &Value, bool IsSigned) |
596 | : MCEncodedFragment(FT_LEB, false), IsSigned(IsSigned), Value(&Value) {} |
597 | |
598 | const MCExpr &getValue() const { return *Value; } |
599 | void setValue(const MCExpr *Expr) { Value = Expr; } |
600 | |
601 | bool isSigned() const { return IsSigned; } |
602 | |
603 | static bool classof(const MCFragment *F) { |
604 | return F->getKind() == MCFragment::FT_LEB; |
605 | } |
606 | }; |
607 | |
608 | class MCDwarfLineAddrFragment : public MCEncodedFragment { |
609 | /// The value of the difference between the two line numbers |
610 | /// between two .loc dwarf directives. |
611 | int64_t LineDelta; |
612 | |
613 | /// The expression for the difference of the two symbols that |
614 | /// make up the address delta between two .loc dwarf directives. |
615 | const MCExpr *AddrDelta; |
616 | |
617 | public: |
618 | MCDwarfLineAddrFragment(int64_t LineDelta, const MCExpr &AddrDelta) |
619 | : MCEncodedFragment(FT_Dwarf, false), LineDelta(LineDelta), |
620 | AddrDelta(&AddrDelta) {} |
621 | |
622 | int64_t getLineDelta() const { return LineDelta; } |
623 | |
624 | const MCExpr &getAddrDelta() const { return *AddrDelta; } |
625 | |
626 | static bool classof(const MCFragment *F) { |
627 | return F->getKind() == MCFragment::FT_Dwarf; |
628 | } |
629 | }; |
630 | |
631 | class MCDwarfCallFrameFragment : public MCEncodedFragment { |
632 | /// The expression for the difference of the two symbols that |
633 | /// make up the address delta between two .cfi_* dwarf directives. |
634 | const MCExpr *AddrDelta; |
635 | |
636 | public: |
637 | MCDwarfCallFrameFragment(const MCExpr &AddrDelta) |
638 | : MCEncodedFragment(FT_DwarfFrame, false), AddrDelta(&AddrDelta) {} |
639 | |
640 | const MCExpr &getAddrDelta() const { return *AddrDelta; } |
641 | void setAddrDelta(const MCExpr *E) { AddrDelta = E; } |
642 | |
643 | static bool classof(const MCFragment *F) { |
644 | return F->getKind() == MCFragment::FT_DwarfFrame; |
645 | } |
646 | }; |
647 | |
648 | /// Represents a symbol table index fragment. |
649 | class MCSymbolIdFragment : public MCFragment { |
650 | const MCSymbol *Sym; |
651 | |
652 | public: |
653 | MCSymbolIdFragment(const MCSymbol *Sym) |
654 | : MCFragment(FT_SymbolId, false), Sym(Sym) {} |
655 | |
656 | const MCSymbol *getSymbol() { return Sym; } |
657 | const MCSymbol *getSymbol() const { return Sym; } |
658 | |
659 | static bool classof(const MCFragment *F) { |
660 | return F->getKind() == MCFragment::FT_SymbolId; |
661 | } |
662 | }; |
663 | |
664 | /// Fragment representing the binary annotations produced by the |
665 | /// .cv_inline_linetable directive. |
666 | class MCCVInlineLineTableFragment : public MCEncodedFragment { |
667 | unsigned SiteFuncId; |
668 | unsigned StartFileId; |
669 | unsigned StartLineNum; |
670 | const MCSymbol *FnStartSym; |
671 | const MCSymbol *FnEndSym; |
672 | |
673 | /// CodeViewContext has the real knowledge about this format, so let it access |
674 | /// our members. |
675 | friend class CodeViewContext; |
676 | |
677 | public: |
678 | MCCVInlineLineTableFragment(unsigned SiteFuncId, unsigned StartFileId, |
679 | unsigned StartLineNum, const MCSymbol *FnStartSym, |
680 | const MCSymbol *FnEndSym) |
681 | : MCEncodedFragment(FT_CVInlineLines, false), SiteFuncId(SiteFuncId), |
682 | StartFileId(StartFileId), StartLineNum(StartLineNum), |
683 | FnStartSym(FnStartSym), FnEndSym(FnEndSym) {} |
684 | |
685 | const MCSymbol *getFnStartSym() const { return FnStartSym; } |
686 | const MCSymbol *getFnEndSym() const { return FnEndSym; } |
687 | |
688 | static bool classof(const MCFragment *F) { |
689 | return F->getKind() == MCFragment::FT_CVInlineLines; |
690 | } |
691 | }; |
692 | |
693 | /// Fragment representing the .cv_def_range directive. |
694 | class MCCVDefRangeFragment : public MCEncodedFragment { |
695 | ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges; |
696 | StringRef FixedSizePortion; |
697 | |
698 | /// CodeViewContext has the real knowledge about this format, so let it access |
699 | /// our members. |
700 | friend class CodeViewContext; |
701 | |
702 | public: |
703 | MCCVDefRangeFragment( |
704 | ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges, |
705 | StringRef FixedSizePortion) |
706 | : MCEncodedFragment(FT_CVDefRange, false), |
707 | Ranges(Ranges.begin(), Ranges.end()), |
708 | FixedSizePortion(FixedSizePortion) {} |
709 | |
710 | ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> getRanges() const { |
711 | return Ranges; |
712 | } |
713 | |
714 | StringRef getFixedSizePortion() const { return FixedSizePortion; } |
715 | |
716 | static bool classof(const MCFragment *F) { |
717 | return F->getKind() == MCFragment::FT_CVDefRange; |
718 | } |
719 | }; |
720 | |
721 | /// Represents required padding such that a particular other set of fragments |
722 | /// does not cross a particular power-of-two boundary. The other fragments must |
723 | /// follow this one within the same section. |
724 | class MCBoundaryAlignFragment : public MCFragment { |
725 | /// The alignment requirement of the branch to be aligned. |
726 | Align AlignBoundary; |
727 | /// The last fragment in the set of fragments to be aligned. |
728 | const MCFragment *LastFragment = nullptr; |
729 | /// The size of the fragment. The size is lazily set during relaxation, and |
730 | /// is not meaningful before that. |
731 | uint64_t Size = 0; |
732 | |
733 | /// When emitting Nops some subtargets have specific nop encodings. |
734 | const MCSubtargetInfo &STI; |
735 | |
736 | public: |
737 | MCBoundaryAlignFragment(Align AlignBoundary, const MCSubtargetInfo &STI) |
738 | : MCFragment(FT_BoundaryAlign, false), AlignBoundary(AlignBoundary), |
739 | STI(STI) {} |
740 | |
741 | uint64_t getSize() const { return Size; } |
742 | void setSize(uint64_t Value) { Size = Value; } |
743 | |
744 | Align getAlignment() const { return AlignBoundary; } |
745 | void setAlignment(Align Value) { AlignBoundary = Value; } |
746 | |
747 | const MCFragment *getLastFragment() const { return LastFragment; } |
748 | void setLastFragment(const MCFragment *F) { |
749 | assert(!F || getParent() == F->getParent()); |
750 | LastFragment = F; |
751 | } |
752 | |
753 | const MCSubtargetInfo *getSubtargetInfo() const { return &STI; } |
754 | |
755 | static bool classof(const MCFragment *F) { |
756 | return F->getKind() == MCFragment::FT_BoundaryAlign; |
757 | } |
758 | }; |
759 | |
760 | class MCPseudoProbeAddrFragment : public MCEncodedFragment { |
761 | /// The expression for the difference of the two symbols that |
762 | /// make up the address delta between two .pseudoprobe directives. |
763 | const MCExpr *AddrDelta; |
764 | |
765 | public: |
766 | MCPseudoProbeAddrFragment(const MCExpr *AddrDelta) |
767 | : MCEncodedFragment(FT_PseudoProbe, false), AddrDelta(AddrDelta) {} |
768 | |
769 | const MCExpr &getAddrDelta() const { return *AddrDelta; } |
770 | |
771 | static bool classof(const MCFragment *F) { |
772 | return F->getKind() == MCFragment::FT_PseudoProbe; |
773 | } |
774 | }; |
775 | |
776 | } // end namespace llvm |
777 | |
778 | #endif // LLVM_MC_MCSECTION_H |
779 | |