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
28namespace llvm {
29
30class MCAsmInfo;
31class MCAssembler;
32class MCContext;
33class MCExpr;
34class MCObjectStreamer;
35class MCSymbol;
36class MCSection;
37class MCSubtargetInfo;
38class raw_ostream;
39class 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.
48class MCFragment {
49 friend class MCAssembler;
50 friend class MCObjectStreamer;
51 friend class MCSection;
52
53public:
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
71private:
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
86protected:
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
99public:
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.
131class LLVM_ABI MCSection {
132public:
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
174private:
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
217protected:
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
226public:
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.
304class 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
311protected:
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
319public:
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///
417class MCDataFragment : public MCEncodedFragment {
418public:
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///
432class MCRelaxableFragment : public MCEncodedFragment {
433 /// The instruction this is a fragment for.
434 MCInst Inst;
435
436public:
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
453class 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
475public:
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
502class 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
513public:
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
532class 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
544public:
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
562class 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
572public:
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
587class 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
594public:
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
608class 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
617public:
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
631class 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
636public:
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.
649class MCSymbolIdFragment : public MCFragment {
650 const MCSymbol *Sym;
651
652public:
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.
666class 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
677public:
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.
694class 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
702public:
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.
724class 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
736public:
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
760class 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
765public:
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