Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:44:13

0001 //===- MCFragment.h - Fragment type hierarchy -------------------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 
0009 #ifndef LLVM_MC_MCFRAGMENT_H
0010 #define LLVM_MC_MCFRAGMENT_H
0011 
0012 #include "llvm/ADT/ArrayRef.h"
0013 #include "llvm/ADT/SmallString.h"
0014 #include "llvm/ADT/SmallVector.h"
0015 #include "llvm/ADT/StringRef.h"
0016 #include "llvm/ADT/ilist_node.h"
0017 #include "llvm/MC/MCFixup.h"
0018 #include "llvm/MC/MCInst.h"
0019 #include "llvm/Support/Alignment.h"
0020 #include "llvm/Support/SMLoc.h"
0021 #include <cstdint>
0022 #include <utility>
0023 
0024 namespace llvm {
0025 
0026 class MCAssembler;
0027 class MCObjectStreamer;
0028 class MCSection;
0029 class MCSubtargetInfo;
0030 class MCSymbol;
0031 
0032 class MCFragment {
0033   friend class MCAssembler;
0034   friend class MCObjectStreamer;
0035   friend class MCSection;
0036 
0037 public:
0038   enum FragmentType : uint8_t {
0039     FT_Align,
0040     FT_Data,
0041     FT_Fill,
0042     FT_Nops,
0043     FT_Relaxable,
0044     FT_Org,
0045     FT_Dwarf,
0046     FT_DwarfFrame,
0047     FT_LEB,
0048     FT_BoundaryAlign,
0049     FT_SymbolId,
0050     FT_CVInlineLines,
0051     FT_CVDefRange,
0052     FT_PseudoProbe,
0053     FT_Dummy
0054   };
0055 
0056 private:
0057   // The next fragment within the section.
0058   MCFragment *Next = nullptr;
0059 
0060   /// The data for the section this fragment is in.
0061   MCSection *Parent = nullptr;
0062 
0063   /// The offset of this fragment in its section.
0064   uint64_t Offset = 0;
0065 
0066   /// The layout order of this fragment.
0067   unsigned LayoutOrder = 0;
0068 
0069   FragmentType Kind;
0070 
0071 protected:
0072   /// Used by subclasses for better packing.
0073   ///
0074   /// MCEncodedFragment
0075   bool HasInstructions : 1;
0076   bool AlignToBundleEnd : 1;
0077   /// MCDataFragment
0078   bool LinkerRelaxable : 1;
0079   /// MCRelaxableFragment: x86-specific
0080   bool AllowAutoPadding : 1;
0081 
0082   MCFragment(FragmentType Kind, bool HasInstructions);
0083 
0084 public:
0085   MCFragment() = delete;
0086   MCFragment(const MCFragment &) = delete;
0087   MCFragment &operator=(const MCFragment &) = delete;
0088 
0089   /// Destroys the current fragment.
0090   ///
0091   /// This must be used instead of delete as MCFragment is non-virtual.
0092   /// This method will dispatch to the appropriate subclass.
0093   void destroy();
0094 
0095   MCFragment *getNext() const { return Next; }
0096 
0097   FragmentType getKind() const { return Kind; }
0098 
0099   MCSection *getParent() const { return Parent; }
0100   void setParent(MCSection *Value) { Parent = Value; }
0101 
0102   const MCSymbol *getAtom() const;
0103 
0104   unsigned getLayoutOrder() const { return LayoutOrder; }
0105   void setLayoutOrder(unsigned Value) { LayoutOrder = Value; }
0106 
0107   /// Does this fragment have instructions emitted into it? By default
0108   /// this is false, but specific fragment types may set it to true.
0109   bool hasInstructions() const { return HasInstructions; }
0110 
0111   void dump() const;
0112 };
0113 
0114 class MCDummyFragment : public MCFragment {
0115 public:
0116   explicit MCDummyFragment() : MCFragment(FT_Dummy, false) {}
0117 
0118   static bool classof(const MCFragment *F) { return F->getKind() == FT_Dummy; }
0119 };
0120 
0121 /// Interface implemented by fragments that contain encoded instructions and/or
0122 /// data.
0123 ///
0124 class MCEncodedFragment : public MCFragment {
0125   uint8_t BundlePadding = 0;
0126 
0127 protected:
0128   MCEncodedFragment(MCFragment::FragmentType FType, bool HasInstructions)
0129       : MCFragment(FType, HasInstructions) {}
0130 
0131   /// The MCSubtargetInfo in effect when the instruction was encoded.
0132   /// It must be non-null for instructions.
0133   const MCSubtargetInfo *STI = nullptr;
0134 
0135 public:
0136   static bool classof(const MCFragment *F) {
0137     MCFragment::FragmentType Kind = F->getKind();
0138     switch (Kind) {
0139     default:
0140       return false;
0141     case MCFragment::FT_Relaxable:
0142     case MCFragment::FT_Data:
0143     case MCFragment::FT_Dwarf:
0144     case MCFragment::FT_DwarfFrame:
0145     case MCFragment::FT_PseudoProbe:
0146       return true;
0147     }
0148   }
0149 
0150   /// Should this fragment be placed at the end of an aligned bundle?
0151   bool alignToBundleEnd() const { return AlignToBundleEnd; }
0152   void setAlignToBundleEnd(bool V) { AlignToBundleEnd = V; }
0153 
0154   /// Get the padding size that must be inserted before this fragment.
0155   /// Used for bundling. By default, no padding is inserted.
0156   /// Note that padding size is restricted to 8 bits. This is an optimization
0157   /// to reduce the amount of space used for each fragment. In practice, larger
0158   /// padding should never be required.
0159   uint8_t getBundlePadding() const { return BundlePadding; }
0160 
0161   /// Set the padding size for this fragment. By default it's a no-op,
0162   /// and only some fragments have a meaningful implementation.
0163   void setBundlePadding(uint8_t N) { BundlePadding = N; }
0164 
0165   /// Retrieve the MCSubTargetInfo in effect when the instruction was encoded.
0166   /// Guaranteed to be non-null if hasInstructions() == true
0167   const MCSubtargetInfo *getSubtargetInfo() const { return STI; }
0168 
0169   /// Record that the fragment contains instructions with the MCSubtargetInfo in
0170   /// effect when the instruction was encoded.
0171   void setHasInstructions(const MCSubtargetInfo &STI) {
0172     HasInstructions = true;
0173     this->STI = &STI;
0174   }
0175 };
0176 
0177 /// Interface implemented by fragments that contain encoded instructions and/or
0178 /// data and also have fixups registered.
0179 ///
0180 template <unsigned ContentsSize, unsigned FixupsSize>
0181 class MCEncodedFragmentWithFixups : public MCEncodedFragment {
0182   SmallVector<char, ContentsSize> Contents;
0183 
0184   /// The list of fixups in this fragment.
0185   SmallVector<MCFixup, FixupsSize> Fixups;
0186 
0187 protected:
0188   MCEncodedFragmentWithFixups(MCFragment::FragmentType FType,
0189                               bool HasInstructions)
0190       : MCEncodedFragment(FType, HasInstructions) {}
0191 
0192 public:
0193   SmallVectorImpl<char> &getContents() { return Contents; }
0194   const SmallVectorImpl<char> &getContents() const { return Contents; }
0195 
0196   void appendContents(ArrayRef<char> C) { Contents.append(C.begin(), C.end()); }
0197   void appendContents(size_t Num, char Elt) { Contents.append(Num, Elt); }
0198   void setContents(ArrayRef<char> C) { Contents.assign(C.begin(), C.end()); }
0199 
0200   SmallVectorImpl<MCFixup> &getFixups() { return Fixups; }
0201   const SmallVectorImpl<MCFixup> &getFixups() const { return Fixups; }
0202 
0203   static bool classof(const MCFragment *F) {
0204     MCFragment::FragmentType Kind = F->getKind();
0205     return Kind == MCFragment::FT_Relaxable || Kind == MCFragment::FT_Data ||
0206            Kind == MCFragment::FT_CVDefRange || Kind == MCFragment::FT_Dwarf ||
0207            Kind == MCFragment::FT_DwarfFrame;
0208   }
0209 };
0210 
0211 /// Fragment for data and encoded instructions.
0212 ///
0213 class MCDataFragment : public MCEncodedFragmentWithFixups<32, 4> {
0214 public:
0215   MCDataFragment() : MCEncodedFragmentWithFixups<32, 4>(FT_Data, false) {}
0216 
0217   static bool classof(const MCFragment *F) {
0218     return F->getKind() == MCFragment::FT_Data;
0219   }
0220 
0221   bool isLinkerRelaxable() const { return LinkerRelaxable; }
0222   void setLinkerRelaxable() { LinkerRelaxable = true; }
0223 };
0224 
0225 /// A relaxable fragment holds on to its MCInst, since it may need to be
0226 /// relaxed during the assembler layout and relaxation stage.
0227 ///
0228 class MCRelaxableFragment : public MCEncodedFragmentWithFixups<8, 1> {
0229   /// The instruction this is a fragment for.
0230   MCInst Inst;
0231 
0232 public:
0233   MCRelaxableFragment(const MCInst &Inst, const MCSubtargetInfo &STI)
0234       : MCEncodedFragmentWithFixups(FT_Relaxable, true), Inst(Inst) {
0235     this->STI = &STI;
0236   }
0237 
0238   const MCInst &getInst() const { return Inst; }
0239   void setInst(const MCInst &Value) { Inst = Value; }
0240 
0241   bool getAllowAutoPadding() const { return AllowAutoPadding; }
0242   void setAllowAutoPadding(bool V) { AllowAutoPadding = V; }
0243 
0244   static bool classof(const MCFragment *F) {
0245     return F->getKind() == MCFragment::FT_Relaxable;
0246   }
0247 };
0248 
0249 class MCAlignFragment : public MCFragment {
0250   /// The alignment to ensure, in bytes.
0251   Align Alignment;
0252 
0253   /// Flag to indicate that (optimal) NOPs should be emitted instead
0254   /// of using the provided value. The exact interpretation of this flag is
0255   /// target dependent.
0256   bool EmitNops : 1;
0257 
0258   /// Value to use for filling padding bytes.
0259   int64_t Value;
0260 
0261   /// The size of the integer (in bytes) of \p Value.
0262   unsigned ValueSize;
0263 
0264   /// The maximum number of bytes to emit; if the alignment
0265   /// cannot be satisfied in this width then this fragment is ignored.
0266   unsigned MaxBytesToEmit;
0267 
0268   /// When emitting Nops some subtargets have specific nop encodings.
0269   const MCSubtargetInfo *STI = nullptr;
0270 
0271 public:
0272   MCAlignFragment(Align Alignment, int64_t Value, unsigned ValueSize,
0273                   unsigned MaxBytesToEmit)
0274       : MCFragment(FT_Align, false), Alignment(Alignment), EmitNops(false),
0275         Value(Value), ValueSize(ValueSize), MaxBytesToEmit(MaxBytesToEmit) {}
0276 
0277   Align getAlignment() const { return Alignment; }
0278 
0279   int64_t getValue() const { return Value; }
0280 
0281   unsigned getValueSize() const { return ValueSize; }
0282 
0283   unsigned getMaxBytesToEmit() const { return MaxBytesToEmit; }
0284 
0285   bool hasEmitNops() const { return EmitNops; }
0286   void setEmitNops(bool Value, const MCSubtargetInfo *STI) {
0287     EmitNops = Value;
0288     this->STI = STI;
0289   }
0290 
0291   const MCSubtargetInfo *getSubtargetInfo() const { return STI; }
0292 
0293   static bool classof(const MCFragment *F) {
0294     return F->getKind() == MCFragment::FT_Align;
0295   }
0296 };
0297 
0298 class MCFillFragment : public MCFragment {
0299   uint8_t ValueSize;
0300   /// Value to use for filling bytes.
0301   uint64_t Value;
0302   /// The number of bytes to insert.
0303   const MCExpr &NumValues;
0304 
0305   /// Source location of the directive that this fragment was created for.
0306   SMLoc Loc;
0307 
0308 public:
0309   MCFillFragment(uint64_t Value, uint8_t VSize, const MCExpr &NumValues,
0310                  SMLoc Loc)
0311       : MCFragment(FT_Fill, false), ValueSize(VSize), Value(Value),
0312         NumValues(NumValues), Loc(Loc) {}
0313 
0314   uint64_t getValue() const { return Value; }
0315   uint8_t getValueSize() const { return ValueSize; }
0316   const MCExpr &getNumValues() const { return NumValues; }
0317 
0318   SMLoc getLoc() const { return Loc; }
0319 
0320   static bool classof(const MCFragment *F) {
0321     return F->getKind() == MCFragment::FT_Fill;
0322   }
0323 };
0324 
0325 class MCNopsFragment : public MCFragment {
0326   /// The number of bytes to insert.
0327   int64_t Size;
0328   /// Maximum number of bytes allowed in each NOP instruction.
0329   int64_t ControlledNopLength;
0330 
0331   /// Source location of the directive that this fragment was created for.
0332   SMLoc Loc;
0333 
0334   /// When emitting Nops some subtargets have specific nop encodings.
0335   const MCSubtargetInfo &STI;
0336 
0337 public:
0338   MCNopsFragment(int64_t NumBytes, int64_t ControlledNopLength, SMLoc L,
0339                  const MCSubtargetInfo &STI)
0340       : MCFragment(FT_Nops, false), Size(NumBytes),
0341         ControlledNopLength(ControlledNopLength), Loc(L), STI(STI) {}
0342 
0343   int64_t getNumBytes() const { return Size; }
0344   int64_t getControlledNopLength() const { return ControlledNopLength; }
0345 
0346   SMLoc getLoc() const { return Loc; }
0347 
0348   const MCSubtargetInfo *getSubtargetInfo() const { return &STI; }
0349 
0350   static bool classof(const MCFragment *F) {
0351     return F->getKind() == MCFragment::FT_Nops;
0352   }
0353 };
0354 
0355 class MCOrgFragment : public MCFragment {
0356   /// Value to use for filling bytes.
0357   int8_t Value;
0358 
0359   /// The offset this fragment should start at.
0360   const MCExpr *Offset;
0361 
0362   /// Source location of the directive that this fragment was created for.
0363   SMLoc Loc;
0364 
0365 public:
0366   MCOrgFragment(const MCExpr &Offset, int8_t Value, SMLoc Loc)
0367       : MCFragment(FT_Org, false), Value(Value), Offset(&Offset), Loc(Loc) {}
0368 
0369   const MCExpr &getOffset() const { return *Offset; }
0370 
0371   uint8_t getValue() const { return Value; }
0372 
0373   SMLoc getLoc() const { return Loc; }
0374 
0375   static bool classof(const MCFragment *F) {
0376     return F->getKind() == MCFragment::FT_Org;
0377   }
0378 };
0379 
0380 class MCLEBFragment final : public MCEncodedFragmentWithFixups<8, 0> {
0381   /// True if this is a sleb128, false if uleb128.
0382   bool IsSigned;
0383 
0384   /// The value this fragment should contain.
0385   const MCExpr *Value;
0386 
0387 public:
0388   MCLEBFragment(const MCExpr &Value, bool IsSigned)
0389       : MCEncodedFragmentWithFixups<8, 0>(FT_LEB, false), IsSigned(IsSigned),
0390         Value(&Value) {
0391     getContents().push_back(0);
0392   }
0393 
0394   const MCExpr &getValue() const { return *Value; }
0395   void setValue(const MCExpr *Expr) { Value = Expr; }
0396 
0397   bool isSigned() const { return IsSigned; }
0398 
0399   /// @}
0400 
0401   static bool classof(const MCFragment *F) {
0402     return F->getKind() == MCFragment::FT_LEB;
0403   }
0404 };
0405 
0406 class MCDwarfLineAddrFragment : public MCEncodedFragmentWithFixups<8, 1> {
0407   /// The value of the difference between the two line numbers
0408   /// between two .loc dwarf directives.
0409   int64_t LineDelta;
0410 
0411   /// The expression for the difference of the two symbols that
0412   /// make up the address delta between two .loc dwarf directives.
0413   const MCExpr *AddrDelta;
0414 
0415 public:
0416   MCDwarfLineAddrFragment(int64_t LineDelta, const MCExpr &AddrDelta)
0417       : MCEncodedFragmentWithFixups<8, 1>(FT_Dwarf, false),
0418         LineDelta(LineDelta), AddrDelta(&AddrDelta) {}
0419 
0420   int64_t getLineDelta() const { return LineDelta; }
0421 
0422   const MCExpr &getAddrDelta() const { return *AddrDelta; }
0423 
0424   static bool classof(const MCFragment *F) {
0425     return F->getKind() == MCFragment::FT_Dwarf;
0426   }
0427 };
0428 
0429 class MCDwarfCallFrameFragment : public MCEncodedFragmentWithFixups<8, 1> {
0430   /// The expression for the difference of the two symbols that
0431   /// make up the address delta between two .cfi_* dwarf directives.
0432   const MCExpr *AddrDelta;
0433 
0434 public:
0435   MCDwarfCallFrameFragment(const MCExpr &AddrDelta)
0436       : MCEncodedFragmentWithFixups<8, 1>(FT_DwarfFrame, false),
0437         AddrDelta(&AddrDelta) {}
0438 
0439   const MCExpr &getAddrDelta() const { return *AddrDelta; }
0440   void setAddrDelta(const MCExpr *E) { AddrDelta = E; }
0441 
0442   static bool classof(const MCFragment *F) {
0443     return F->getKind() == MCFragment::FT_DwarfFrame;
0444   }
0445 };
0446 
0447 /// Represents a symbol table index fragment.
0448 class MCSymbolIdFragment : public MCFragment {
0449   const MCSymbol *Sym;
0450 
0451 public:
0452   MCSymbolIdFragment(const MCSymbol *Sym)
0453       : MCFragment(FT_SymbolId, false), Sym(Sym) {}
0454 
0455   const MCSymbol *getSymbol() { return Sym; }
0456   const MCSymbol *getSymbol() const { return Sym; }
0457 
0458   static bool classof(const MCFragment *F) {
0459     return F->getKind() == MCFragment::FT_SymbolId;
0460   }
0461 };
0462 
0463 /// Fragment representing the binary annotations produced by the
0464 /// .cv_inline_linetable directive.
0465 class MCCVInlineLineTableFragment : public MCFragment {
0466   unsigned SiteFuncId;
0467   unsigned StartFileId;
0468   unsigned StartLineNum;
0469   const MCSymbol *FnStartSym;
0470   const MCSymbol *FnEndSym;
0471   SmallString<8> Contents;
0472 
0473   /// CodeViewContext has the real knowledge about this format, so let it access
0474   /// our members.
0475   friend class CodeViewContext;
0476 
0477 public:
0478   MCCVInlineLineTableFragment(unsigned SiteFuncId, unsigned StartFileId,
0479                               unsigned StartLineNum, const MCSymbol *FnStartSym,
0480                               const MCSymbol *FnEndSym)
0481       : MCFragment(FT_CVInlineLines, false), SiteFuncId(SiteFuncId),
0482         StartFileId(StartFileId), StartLineNum(StartLineNum),
0483         FnStartSym(FnStartSym), FnEndSym(FnEndSym) {}
0484 
0485   const MCSymbol *getFnStartSym() const { return FnStartSym; }
0486   const MCSymbol *getFnEndSym() const { return FnEndSym; }
0487 
0488   SmallString<8> &getContents() { return Contents; }
0489   const SmallString<8> &getContents() const { return Contents; }
0490 
0491   static bool classof(const MCFragment *F) {
0492     return F->getKind() == MCFragment::FT_CVInlineLines;
0493   }
0494 };
0495 
0496 /// Fragment representing the .cv_def_range directive.
0497 class MCCVDefRangeFragment : public MCEncodedFragmentWithFixups<32, 4> {
0498   SmallVector<std::pair<const MCSymbol *, const MCSymbol *>, 2> Ranges;
0499   SmallString<32> FixedSizePortion;
0500 
0501   /// CodeViewContext has the real knowledge about this format, so let it access
0502   /// our members.
0503   friend class CodeViewContext;
0504 
0505 public:
0506   MCCVDefRangeFragment(
0507       ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
0508       StringRef FixedSizePortion)
0509       : MCEncodedFragmentWithFixups<32, 4>(FT_CVDefRange, false),
0510         Ranges(Ranges), FixedSizePortion(FixedSizePortion) {}
0511 
0512   ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> getRanges() const {
0513     return Ranges;
0514   }
0515 
0516   StringRef getFixedSizePortion() const { return FixedSizePortion.str(); }
0517 
0518   static bool classof(const MCFragment *F) {
0519     return F->getKind() == MCFragment::FT_CVDefRange;
0520   }
0521 };
0522 
0523 /// Represents required padding such that a particular other set of fragments
0524 /// does not cross a particular power-of-two boundary. The other fragments must
0525 /// follow this one within the same section.
0526 class MCBoundaryAlignFragment : public MCFragment {
0527   /// The alignment requirement of the branch to be aligned.
0528   Align AlignBoundary;
0529   /// The last fragment in the set of fragments to be aligned.
0530   const MCFragment *LastFragment = nullptr;
0531   /// The size of the fragment.  The size is lazily set during relaxation, and
0532   /// is not meaningful before that.
0533   uint64_t Size = 0;
0534 
0535   /// When emitting Nops some subtargets have specific nop encodings.
0536   const MCSubtargetInfo &STI;
0537 
0538 public:
0539   MCBoundaryAlignFragment(Align AlignBoundary, const MCSubtargetInfo &STI)
0540       : MCFragment(FT_BoundaryAlign, false), AlignBoundary(AlignBoundary),
0541         STI(STI) {}
0542 
0543   uint64_t getSize() const { return Size; }
0544   void setSize(uint64_t Value) { Size = Value; }
0545 
0546   Align getAlignment() const { return AlignBoundary; }
0547   void setAlignment(Align Value) { AlignBoundary = Value; }
0548 
0549   const MCFragment *getLastFragment() const { return LastFragment; }
0550   void setLastFragment(const MCFragment *F) {
0551     assert(!F || getParent() == F->getParent());
0552     LastFragment = F;
0553   }
0554 
0555   const MCSubtargetInfo *getSubtargetInfo() const { return &STI; }
0556 
0557   static bool classof(const MCFragment *F) {
0558     return F->getKind() == MCFragment::FT_BoundaryAlign;
0559   }
0560 };
0561 
0562 class MCPseudoProbeAddrFragment : public MCEncodedFragmentWithFixups<8, 1> {
0563   /// The expression for the difference of the two symbols that
0564   /// make up the address delta between two .pseudoprobe directives.
0565   const MCExpr *AddrDelta;
0566 
0567 public:
0568   MCPseudoProbeAddrFragment(const MCExpr *AddrDelta)
0569       : MCEncodedFragmentWithFixups<8, 1>(FT_PseudoProbe, false),
0570         AddrDelta(AddrDelta) {}
0571 
0572   const MCExpr &getAddrDelta() const { return *AddrDelta; }
0573 
0574   static bool classof(const MCFragment *F) {
0575     return F->getKind() == MCFragment::FT_PseudoProbe;
0576   }
0577 };
0578 } // end namespace llvm
0579 
0580 #endif // LLVM_MC_MCFRAGMENT_H