Home | History | Annotate | Line # | Download | only in MC
      1 //===- MCFragment.h - Fragment type hierarchy -------------------*- 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 #ifndef LLVM_MC_MCFRAGMENT_H
     10 #define LLVM_MC_MCFRAGMENT_H
     11 
     12 #include "llvm/ADT/ArrayRef.h"
     13 #include "llvm/ADT/SmallString.h"
     14 #include "llvm/ADT/SmallVector.h"
     15 #include "llvm/ADT/StringRef.h"
     16 #include "llvm/ADT/ilist_node.h"
     17 #include "llvm/MC/MCFixup.h"
     18 #include "llvm/MC/MCInst.h"
     19 #include "llvm/Support/Alignment.h"
     20 #include "llvm/Support/Casting.h"
     21 #include "llvm/Support/SMLoc.h"
     22 #include <cstdint>
     23 #include <utility>
     24 
     25 namespace llvm {
     26 
     27 class MCSection;
     28 class MCSubtargetInfo;
     29 class MCSymbol;
     30 
     31 class MCFragment : public ilist_node_with_parent<MCFragment, MCSection> {
     32   friend class MCAsmLayout;
     33 
     34 public:
     35   enum FragmentType : uint8_t {
     36     FT_Align,
     37     FT_Data,
     38     FT_CompactEncodedInst,
     39     FT_Fill,
     40     FT_Nops,
     41     FT_Relaxable,
     42     FT_Org,
     43     FT_Dwarf,
     44     FT_DwarfFrame,
     45     FT_LEB,
     46     FT_BoundaryAlign,
     47     FT_SymbolId,
     48     FT_CVInlineLines,
     49     FT_CVDefRange,
     50     FT_PseudoProbe,
     51     FT_Dummy
     52   };
     53 
     54 private:
     55   /// The data for the section this fragment is in.
     56   MCSection *Parent;
     57 
     58   /// The atom this fragment is in, as represented by its defining symbol.
     59   const MCSymbol *Atom;
     60 
     61   /// The offset of this fragment in its section. This is ~0 until
     62   /// initialized.
     63   uint64_t Offset;
     64 
     65   /// The layout order of this fragment.
     66   unsigned LayoutOrder;
     67 
     68   /// The subsection this fragment belongs to. This is 0 if the fragment is not
     69   // in any subsection.
     70   unsigned SubsectionNumber = 0;
     71 
     72   FragmentType Kind;
     73 
     74   /// Whether fragment is being laid out.
     75   bool IsBeingLaidOut;
     76 
     77 protected:
     78   bool HasInstructions;
     79 
     80   MCFragment(FragmentType Kind, bool HasInstructions,
     81              MCSection *Parent = nullptr);
     82 
     83 public:
     84   MCFragment() = delete;
     85   MCFragment(const MCFragment &) = delete;
     86   MCFragment &operator=(const MCFragment &) = delete;
     87 
     88   /// Destroys the current fragment.
     89   ///
     90   /// This must be used instead of delete as MCFragment is non-virtual.
     91   /// This method will dispatch to the appropriate subclass.
     92   void destroy();
     93 
     94   FragmentType getKind() const { return Kind; }
     95 
     96   MCSection *getParent() const { return Parent; }
     97   void setParent(MCSection *Value) { Parent = Value; }
     98 
     99   const MCSymbol *getAtom() const { return Atom; }
    100   void setAtom(const MCSymbol *Value) { Atom = Value; }
    101 
    102   unsigned getLayoutOrder() const { return LayoutOrder; }
    103   void setLayoutOrder(unsigned Value) { LayoutOrder = Value; }
    104 
    105   /// Does this fragment have instructions emitted into it? By default
    106   /// this is false, but specific fragment types may set it to true.
    107   bool hasInstructions() const { return HasInstructions; }
    108 
    109   void dump() const;
    110 
    111   void setSubsectionNumber(unsigned Value) { SubsectionNumber = Value; }
    112   unsigned getSubsectionNumber() const { return SubsectionNumber; }
    113 };
    114 
    115 class MCDummyFragment : public MCFragment {
    116 public:
    117   explicit MCDummyFragment(MCSection *Sec) : MCFragment(FT_Dummy, false, Sec) {}
    118 
    119   static bool classof(const MCFragment *F) { return F->getKind() == FT_Dummy; }
    120 };
    121 
    122 /// Interface implemented by fragments that contain encoded instructions and/or
    123 /// data.
    124 ///
    125 class MCEncodedFragment : public MCFragment {
    126   /// Should this fragment be aligned to the end of a bundle?
    127   bool AlignToBundleEnd = false;
    128 
    129   uint8_t BundlePadding = 0;
    130 
    131 protected:
    132   MCEncodedFragment(MCFragment::FragmentType FType, bool HasInstructions,
    133                     MCSection *Sec)
    134       : MCFragment(FType, HasInstructions, Sec) {}
    135 
    136   /// The MCSubtargetInfo in effect when the instruction was encoded.
    137   /// It must be non-null for instructions.
    138   const MCSubtargetInfo *STI = nullptr;
    139 
    140 public:
    141   static bool classof(const MCFragment *F) {
    142     MCFragment::FragmentType Kind = F->getKind();
    143     switch (Kind) {
    144     default:
    145       return false;
    146     case MCFragment::FT_Relaxable:
    147     case MCFragment::FT_CompactEncodedInst:
    148     case MCFragment::FT_Data:
    149     case MCFragment::FT_Dwarf:
    150     case MCFragment::FT_DwarfFrame:
    151     case MCFragment::FT_PseudoProbe:
    152       return true;
    153     }
    154   }
    155 
    156   /// Should this fragment be placed at the end of an aligned bundle?
    157   bool alignToBundleEnd() const { return AlignToBundleEnd; }
    158   void setAlignToBundleEnd(bool V) { AlignToBundleEnd = V; }
    159 
    160   /// Get the padding size that must be inserted before this fragment.
    161   /// Used for bundling. By default, no padding is inserted.
    162   /// Note that padding size is restricted to 8 bits. This is an optimization
    163   /// to reduce the amount of space used for each fragment. In practice, larger
    164   /// padding should never be required.
    165   uint8_t getBundlePadding() const { return BundlePadding; }
    166 
    167   /// Set the padding size for this fragment. By default it's a no-op,
    168   /// and only some fragments have a meaningful implementation.
    169   void setBundlePadding(uint8_t N) { BundlePadding = N; }
    170 
    171   /// Retrieve the MCSubTargetInfo in effect when the instruction was encoded.
    172   /// Guaranteed to be non-null if hasInstructions() == true
    173   const MCSubtargetInfo *getSubtargetInfo() const { return STI; }
    174 
    175   /// Record that the fragment contains instructions with the MCSubtargetInfo in
    176   /// effect when the instruction was encoded.
    177   void setHasInstructions(const MCSubtargetInfo &STI) {
    178     HasInstructions = true;
    179     this->STI = &STI;
    180   }
    181 };
    182 
    183 /// Interface implemented by fragments that contain encoded instructions and/or
    184 /// data.
    185 ///
    186 template<unsigned ContentsSize>
    187 class MCEncodedFragmentWithContents : public MCEncodedFragment {
    188   SmallVector<char, ContentsSize> Contents;
    189 
    190 protected:
    191   MCEncodedFragmentWithContents(MCFragment::FragmentType FType,
    192                                 bool HasInstructions,
    193                                 MCSection *Sec)
    194       : MCEncodedFragment(FType, HasInstructions, Sec) {}
    195 
    196 public:
    197   SmallVectorImpl<char> &getContents() { return Contents; }
    198   const SmallVectorImpl<char> &getContents() const { return Contents; }
    199 };
    200 
    201 /// Interface implemented by fragments that contain encoded instructions and/or
    202 /// data and also have fixups registered.
    203 ///
    204 template<unsigned ContentsSize, unsigned FixupsSize>
    205 class MCEncodedFragmentWithFixups :
    206   public MCEncodedFragmentWithContents<ContentsSize> {
    207 
    208   /// The list of fixups in this fragment.
    209   SmallVector<MCFixup, FixupsSize> Fixups;
    210 
    211 protected:
    212   MCEncodedFragmentWithFixups(MCFragment::FragmentType FType,
    213                               bool HasInstructions,
    214                               MCSection *Sec)
    215       : MCEncodedFragmentWithContents<ContentsSize>(FType, HasInstructions,
    216                                                     Sec) {}
    217 
    218 public:
    219 
    220   using const_fixup_iterator = SmallVectorImpl<MCFixup>::const_iterator;
    221   using fixup_iterator = SmallVectorImpl<MCFixup>::iterator;
    222 
    223   SmallVectorImpl<MCFixup> &getFixups() { return Fixups; }
    224   const SmallVectorImpl<MCFixup> &getFixups() const { return Fixups; }
    225 
    226   fixup_iterator fixup_begin() { return Fixups.begin(); }
    227   const_fixup_iterator fixup_begin() const { return Fixups.begin(); }
    228 
    229   fixup_iterator fixup_end() { return Fixups.end(); }
    230   const_fixup_iterator fixup_end() const { return Fixups.end(); }
    231 
    232   static bool classof(const MCFragment *F) {
    233     MCFragment::FragmentType Kind = F->getKind();
    234     return Kind == MCFragment::FT_Relaxable || Kind == MCFragment::FT_Data ||
    235            Kind == MCFragment::FT_CVDefRange || Kind == MCFragment::FT_Dwarf ||
    236            Kind == MCFragment::FT_DwarfFrame;
    237   }
    238 };
    239 
    240 /// Fragment for data and encoded instructions.
    241 ///
    242 class MCDataFragment : public MCEncodedFragmentWithFixups<32, 4> {
    243 public:
    244   MCDataFragment(MCSection *Sec = nullptr)
    245       : MCEncodedFragmentWithFixups<32, 4>(FT_Data, false, Sec) {}
    246 
    247   static bool classof(const MCFragment *F) {
    248     return F->getKind() == MCFragment::FT_Data;
    249   }
    250 };
    251 
    252 /// This is a compact (memory-size-wise) fragment for holding an encoded
    253 /// instruction (non-relaxable) that has no fixups registered. When applicable,
    254 /// it can be used instead of MCDataFragment and lead to lower memory
    255 /// consumption.
    256 ///
    257 class MCCompactEncodedInstFragment : public MCEncodedFragmentWithContents<4> {
    258 public:
    259   MCCompactEncodedInstFragment(MCSection *Sec = nullptr)
    260       : MCEncodedFragmentWithContents(FT_CompactEncodedInst, true, Sec) {
    261   }
    262 
    263   static bool classof(const MCFragment *F) {
    264     return F->getKind() == MCFragment::FT_CompactEncodedInst;
    265   }
    266 };
    267 
    268 /// A relaxable fragment holds on to its MCInst, since it may need to be
    269 /// relaxed during the assembler layout and relaxation stage.
    270 ///
    271 class MCRelaxableFragment : public MCEncodedFragmentWithFixups<8, 1> {
    272 
    273   /// The instruction this is a fragment for.
    274   MCInst Inst;
    275   /// Can we auto pad the instruction?
    276   bool AllowAutoPadding = false;
    277 
    278 public:
    279   MCRelaxableFragment(const MCInst &Inst, const MCSubtargetInfo &STI,
    280                       MCSection *Sec = nullptr)
    281       : MCEncodedFragmentWithFixups(FT_Relaxable, true, Sec),
    282         Inst(Inst) { this->STI = &STI; }
    283 
    284   const MCInst &getInst() const { return Inst; }
    285   void setInst(const MCInst &Value) { Inst = Value; }
    286 
    287   bool getAllowAutoPadding() const { return AllowAutoPadding; }
    288   void setAllowAutoPadding(bool V) { AllowAutoPadding = V; }
    289 
    290   static bool classof(const MCFragment *F) {
    291     return F->getKind() == MCFragment::FT_Relaxable;
    292   }
    293 };
    294 
    295 class MCAlignFragment : public MCFragment {
    296   /// The alignment to ensure, in bytes.
    297   unsigned Alignment;
    298 
    299   /// Flag to indicate that (optimal) NOPs should be emitted instead
    300   /// of using the provided value. The exact interpretation of this flag is
    301   /// target dependent.
    302   bool EmitNops : 1;
    303 
    304   /// Value to use for filling padding bytes.
    305   int64_t Value;
    306 
    307   /// The size of the integer (in bytes) of \p Value.
    308   unsigned ValueSize;
    309 
    310   /// The maximum number of bytes to emit; if the alignment
    311   /// cannot be satisfied in this width then this fragment is ignored.
    312   unsigned MaxBytesToEmit;
    313 
    314 public:
    315   MCAlignFragment(unsigned Alignment, int64_t Value, unsigned ValueSize,
    316                   unsigned MaxBytesToEmit, MCSection *Sec = nullptr)
    317       : MCFragment(FT_Align, false, Sec), Alignment(Alignment), EmitNops(false),
    318         Value(Value), ValueSize(ValueSize), MaxBytesToEmit(MaxBytesToEmit) {}
    319 
    320   unsigned getAlignment() const { return Alignment; }
    321 
    322   int64_t getValue() const { return Value; }
    323 
    324   unsigned getValueSize() const { return ValueSize; }
    325 
    326   unsigned getMaxBytesToEmit() const { return MaxBytesToEmit; }
    327 
    328   bool hasEmitNops() const { return EmitNops; }
    329   void setEmitNops(bool Value) { EmitNops = Value; }
    330 
    331   static bool classof(const MCFragment *F) {
    332     return F->getKind() == MCFragment::FT_Align;
    333   }
    334 };
    335 
    336 class MCFillFragment : public MCFragment {
    337   uint8_t ValueSize;
    338   /// Value to use for filling bytes.
    339   uint64_t Value;
    340   /// The number of bytes to insert.
    341   const MCExpr &NumValues;
    342 
    343   /// Source location of the directive that this fragment was created for.
    344   SMLoc Loc;
    345 
    346 public:
    347   MCFillFragment(uint64_t Value, uint8_t VSize, const MCExpr &NumValues,
    348                  SMLoc Loc, MCSection *Sec = nullptr)
    349       : MCFragment(FT_Fill, false, Sec), ValueSize(VSize), Value(Value),
    350         NumValues(NumValues), Loc(Loc) {}
    351 
    352   uint64_t getValue() const { return Value; }
    353   uint8_t getValueSize() const { return ValueSize; }
    354   const MCExpr &getNumValues() const { return NumValues; }
    355 
    356   SMLoc getLoc() const { return Loc; }
    357 
    358   static bool classof(const MCFragment *F) {
    359     return F->getKind() == MCFragment::FT_Fill;
    360   }
    361 };
    362 
    363 class MCNopsFragment : public MCFragment {
    364   /// The number of bytes to insert.
    365   int64_t Size;
    366   /// Maximum number of bytes allowed in each NOP instruction.
    367   int64_t ControlledNopLength;
    368 
    369   /// Source location of the directive that this fragment was created for.
    370   SMLoc Loc;
    371 
    372 public:
    373   MCNopsFragment(int64_t NumBytes, int64_t ControlledNopLength, SMLoc L,
    374                  MCSection *Sec = nullptr)
    375       : MCFragment(FT_Nops, false, Sec), Size(NumBytes),
    376         ControlledNopLength(ControlledNopLength), Loc(L) {}
    377 
    378   int64_t getNumBytes() const { return Size; }
    379   int64_t getControlledNopLength() const { return ControlledNopLength; }
    380 
    381   SMLoc getLoc() const { return Loc; }
    382 
    383   static bool classof(const MCFragment *F) {
    384     return F->getKind() == MCFragment::FT_Nops;
    385   }
    386 };
    387 
    388 class MCOrgFragment : public MCFragment {
    389   /// Value to use for filling bytes.
    390   int8_t Value;
    391 
    392   /// The offset this fragment should start at.
    393   const MCExpr *Offset;
    394 
    395   /// Source location of the directive that this fragment was created for.
    396   SMLoc Loc;
    397 
    398 public:
    399   MCOrgFragment(const MCExpr &Offset, int8_t Value, SMLoc Loc,
    400                 MCSection *Sec = nullptr)
    401       : MCFragment(FT_Org, false, Sec), Value(Value), Offset(&Offset),
    402         Loc(Loc) {}
    403 
    404   const MCExpr &getOffset() const { return *Offset; }
    405 
    406   uint8_t getValue() const { return Value; }
    407 
    408   SMLoc getLoc() const { return Loc; }
    409 
    410   static bool classof(const MCFragment *F) {
    411     return F->getKind() == MCFragment::FT_Org;
    412   }
    413 };
    414 
    415 class MCLEBFragment : public MCFragment {
    416   /// True if this is a sleb128, false if uleb128.
    417   bool IsSigned;
    418 
    419   /// The value this fragment should contain.
    420   const MCExpr *Value;
    421 
    422   SmallString<8> Contents;
    423 
    424 public:
    425   MCLEBFragment(const MCExpr &Value_, bool IsSigned_, MCSection *Sec = nullptr)
    426       : MCFragment(FT_LEB, false, Sec), IsSigned(IsSigned_), Value(&Value_) {
    427     Contents.push_back(0);
    428   }
    429 
    430   const MCExpr &getValue() const { return *Value; }
    431 
    432   bool isSigned() const { return IsSigned; }
    433 
    434   SmallString<8> &getContents() { return Contents; }
    435   const SmallString<8> &getContents() const { return Contents; }
    436 
    437   /// @}
    438 
    439   static bool classof(const MCFragment *F) {
    440     return F->getKind() == MCFragment::FT_LEB;
    441   }
    442 };
    443 
    444 class MCDwarfLineAddrFragment : public MCEncodedFragmentWithFixups<8, 1> {
    445   /// The value of the difference between the two line numbers
    446   /// between two .loc dwarf directives.
    447   int64_t LineDelta;
    448 
    449   /// The expression for the difference of the two symbols that
    450   /// make up the address delta between two .loc dwarf directives.
    451   const MCExpr *AddrDelta;
    452 
    453 public:
    454   MCDwarfLineAddrFragment(int64_t LineDelta, const MCExpr &AddrDelta,
    455                           MCSection *Sec = nullptr)
    456       : MCEncodedFragmentWithFixups<8, 1>(FT_Dwarf, false, Sec),
    457         LineDelta(LineDelta), AddrDelta(&AddrDelta) {}
    458 
    459   int64_t getLineDelta() const { return LineDelta; }
    460 
    461   const MCExpr &getAddrDelta() const { return *AddrDelta; }
    462 
    463   static bool classof(const MCFragment *F) {
    464     return F->getKind() == MCFragment::FT_Dwarf;
    465   }
    466 };
    467 
    468 class MCDwarfCallFrameFragment : public MCEncodedFragmentWithFixups<8, 1> {
    469   /// The expression for the difference of the two symbols that
    470   /// make up the address delta between two .cfi_* dwarf directives.
    471   const MCExpr *AddrDelta;
    472 
    473 public:
    474   MCDwarfCallFrameFragment(const MCExpr &AddrDelta, MCSection *Sec = nullptr)
    475       : MCEncodedFragmentWithFixups<8, 1>(FT_DwarfFrame, false, Sec),
    476         AddrDelta(&AddrDelta) {}
    477 
    478   const MCExpr &getAddrDelta() const { return *AddrDelta; }
    479 
    480   static bool classof(const MCFragment *F) {
    481     return F->getKind() == MCFragment::FT_DwarfFrame;
    482   }
    483 };
    484 
    485 /// Represents a symbol table index fragment.
    486 class MCSymbolIdFragment : public MCFragment {
    487   const MCSymbol *Sym;
    488 
    489 public:
    490   MCSymbolIdFragment(const MCSymbol *Sym, MCSection *Sec = nullptr)
    491       : MCFragment(FT_SymbolId, false, Sec), Sym(Sym) {}
    492 
    493   const MCSymbol *getSymbol() { return Sym; }
    494   const MCSymbol *getSymbol() const { return Sym; }
    495 
    496   static bool classof(const MCFragment *F) {
    497     return F->getKind() == MCFragment::FT_SymbolId;
    498   }
    499 };
    500 
    501 /// Fragment representing the binary annotations produced by the
    502 /// .cv_inline_linetable directive.
    503 class MCCVInlineLineTableFragment : public MCFragment {
    504   unsigned SiteFuncId;
    505   unsigned StartFileId;
    506   unsigned StartLineNum;
    507   const MCSymbol *FnStartSym;
    508   const MCSymbol *FnEndSym;
    509   SmallString<8> Contents;
    510 
    511   /// CodeViewContext has the real knowledge about this format, so let it access
    512   /// our members.
    513   friend class CodeViewContext;
    514 
    515 public:
    516   MCCVInlineLineTableFragment(unsigned SiteFuncId, unsigned StartFileId,
    517                               unsigned StartLineNum, const MCSymbol *FnStartSym,
    518                               const MCSymbol *FnEndSym,
    519                               MCSection *Sec = nullptr)
    520       : MCFragment(FT_CVInlineLines, false, Sec), SiteFuncId(SiteFuncId),
    521         StartFileId(StartFileId), StartLineNum(StartLineNum),
    522         FnStartSym(FnStartSym), FnEndSym(FnEndSym) {}
    523 
    524   const MCSymbol *getFnStartSym() const { return FnStartSym; }
    525   const MCSymbol *getFnEndSym() const { return FnEndSym; }
    526 
    527   SmallString<8> &getContents() { return Contents; }
    528   const SmallString<8> &getContents() const { return Contents; }
    529 
    530   static bool classof(const MCFragment *F) {
    531     return F->getKind() == MCFragment::FT_CVInlineLines;
    532   }
    533 };
    534 
    535 /// Fragment representing the .cv_def_range directive.
    536 class MCCVDefRangeFragment : public MCEncodedFragmentWithFixups<32, 4> {
    537   SmallVector<std::pair<const MCSymbol *, const MCSymbol *>, 2> Ranges;
    538   SmallString<32> FixedSizePortion;
    539 
    540   /// CodeViewContext has the real knowledge about this format, so let it access
    541   /// our members.
    542   friend class CodeViewContext;
    543 
    544 public:
    545   MCCVDefRangeFragment(
    546       ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
    547       StringRef FixedSizePortion, MCSection *Sec = nullptr)
    548       : MCEncodedFragmentWithFixups<32, 4>(FT_CVDefRange, false, Sec),
    549         Ranges(Ranges.begin(), Ranges.end()),
    550         FixedSizePortion(FixedSizePortion) {}
    551 
    552   ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> getRanges() const {
    553     return Ranges;
    554   }
    555 
    556   StringRef getFixedSizePortion() const { return FixedSizePortion; }
    557 
    558   static bool classof(const MCFragment *F) {
    559     return F->getKind() == MCFragment::FT_CVDefRange;
    560   }
    561 };
    562 
    563 /// Represents required padding such that a particular other set of fragments
    564 /// does not cross a particular power-of-two boundary. The other fragments must
    565 /// follow this one within the same section.
    566 class MCBoundaryAlignFragment : public MCFragment {
    567   /// The alignment requirement of the branch to be aligned.
    568   Align AlignBoundary;
    569   /// The last fragment in the set of fragments to be aligned.
    570   const MCFragment *LastFragment = nullptr;
    571   /// The size of the fragment.  The size is lazily set during relaxation, and
    572   /// is not meaningful before that.
    573   uint64_t Size = 0;
    574 
    575 public:
    576   MCBoundaryAlignFragment(Align AlignBoundary, MCSection *Sec = nullptr)
    577       : MCFragment(FT_BoundaryAlign, false, Sec), AlignBoundary(AlignBoundary) {
    578   }
    579 
    580   uint64_t getSize() const { return Size; }
    581   void setSize(uint64_t Value) { Size = Value; }
    582 
    583   Align getAlignment() const { return AlignBoundary; }
    584   void setAlignment(Align Value) { AlignBoundary = Value; }
    585 
    586   const MCFragment *getLastFragment() const { return LastFragment; }
    587   void setLastFragment(const MCFragment *F) {
    588     assert(!F || getParent() == F->getParent());
    589     LastFragment = F;
    590   }
    591 
    592   static bool classof(const MCFragment *F) {
    593     return F->getKind() == MCFragment::FT_BoundaryAlign;
    594   }
    595 };
    596 
    597 class MCPseudoProbeAddrFragment : public MCEncodedFragmentWithFixups<8, 1> {
    598   /// The expression for the difference of the two symbols that
    599   /// make up the address delta between two .pseudoprobe directives.
    600   const MCExpr *AddrDelta;
    601 
    602 public:
    603   MCPseudoProbeAddrFragment(const MCExpr *AddrDelta, MCSection *Sec = nullptr)
    604       : MCEncodedFragmentWithFixups<8, 1>(FT_PseudoProbe, false, Sec),
    605         AddrDelta(AddrDelta) {}
    606 
    607   const MCExpr &getAddrDelta() const { return *AddrDelta; }
    608 
    609   static bool classof(const MCFragment *F) {
    610     return F->getKind() == MCFragment::FT_PseudoProbe;
    611   }
    612 };
    613 } // end namespace llvm
    614 
    615 #endif // LLVM_MC_MCFRAGMENT_H
    616