xref: /freebsd/contrib/llvm-project/llvm/include/llvm/MC/MCFragment.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- MCFragment.h - Fragment type hierarchy -------------------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #ifndef LLVM_MC_MCFRAGMENT_H
100b57cec5SDimitry Andric #define LLVM_MC_MCFRAGMENT_H
110b57cec5SDimitry Andric 
120b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h"
130b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h"
140b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
150b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
160b57cec5SDimitry Andric #include "llvm/ADT/ilist_node.h"
170b57cec5SDimitry Andric #include "llvm/MC/MCFixup.h"
180b57cec5SDimitry Andric #include "llvm/MC/MCInst.h"
19480093f4SDimitry Andric #include "llvm/Support/Alignment.h"
200b57cec5SDimitry Andric #include "llvm/Support/SMLoc.h"
210b57cec5SDimitry Andric #include <cstdint>
220b57cec5SDimitry Andric #include <utility>
230b57cec5SDimitry Andric 
240b57cec5SDimitry Andric namespace llvm {
250b57cec5SDimitry Andric 
26*0fca6ea1SDimitry Andric class MCAssembler;
27*0fca6ea1SDimitry Andric class MCObjectStreamer;
280b57cec5SDimitry Andric class MCSection;
290b57cec5SDimitry Andric class MCSubtargetInfo;
300b57cec5SDimitry Andric class MCSymbol;
310b57cec5SDimitry Andric 
32*0fca6ea1SDimitry Andric class MCFragment {
33*0fca6ea1SDimitry Andric   friend class MCAssembler;
34*0fca6ea1SDimitry Andric   friend class MCObjectStreamer;
35*0fca6ea1SDimitry Andric   friend class MCSection;
360b57cec5SDimitry Andric 
370b57cec5SDimitry Andric public:
380b57cec5SDimitry Andric   enum FragmentType : uint8_t {
390b57cec5SDimitry Andric     FT_Align,
400b57cec5SDimitry Andric     FT_Data,
410b57cec5SDimitry Andric     FT_CompactEncodedInst,
420b57cec5SDimitry Andric     FT_Fill,
43e8d8bef9SDimitry Andric     FT_Nops,
440b57cec5SDimitry Andric     FT_Relaxable,
450b57cec5SDimitry Andric     FT_Org,
460b57cec5SDimitry Andric     FT_Dwarf,
470b57cec5SDimitry Andric     FT_DwarfFrame,
480b57cec5SDimitry Andric     FT_LEB,
49480093f4SDimitry Andric     FT_BoundaryAlign,
500b57cec5SDimitry Andric     FT_SymbolId,
510b57cec5SDimitry Andric     FT_CVInlineLines,
520b57cec5SDimitry Andric     FT_CVDefRange,
53e8d8bef9SDimitry Andric     FT_PseudoProbe,
540b57cec5SDimitry Andric     FT_Dummy
550b57cec5SDimitry Andric   };
560b57cec5SDimitry Andric 
570b57cec5SDimitry Andric private:
58*0fca6ea1SDimitry Andric   // The next fragment within the section.
59*0fca6ea1SDimitry Andric   MCFragment *Next = nullptr;
60*0fca6ea1SDimitry Andric 
61480093f4SDimitry Andric   /// The data for the section this fragment is in.
62*0fca6ea1SDimitry Andric   MCSection *Parent = nullptr;
63480093f4SDimitry Andric 
64*0fca6ea1SDimitry Andric   /// The offset of this fragment in its section.
65*0fca6ea1SDimitry Andric   uint64_t Offset = 0;
66480093f4SDimitry Andric 
67480093f4SDimitry Andric   /// The layout order of this fragment.
68*0fca6ea1SDimitry Andric   unsigned LayoutOrder = 0;
69e8d8bef9SDimitry Andric 
700b57cec5SDimitry Andric   FragmentType Kind;
710b57cec5SDimitry Andric 
720b57cec5SDimitry Andric protected:
73*0fca6ea1SDimitry Andric   bool HasInstructions : 1;
74*0fca6ea1SDimitry Andric   bool LinkerRelaxable : 1;
750b57cec5SDimitry Andric 
76*0fca6ea1SDimitry Andric   MCFragment(FragmentType Kind, bool HasInstructions);
770b57cec5SDimitry Andric 
780b57cec5SDimitry Andric public:
790b57cec5SDimitry Andric   MCFragment() = delete;
800b57cec5SDimitry Andric   MCFragment(const MCFragment &) = delete;
810b57cec5SDimitry Andric   MCFragment &operator=(const MCFragment &) = delete;
820b57cec5SDimitry Andric 
830b57cec5SDimitry Andric   /// Destroys the current fragment.
840b57cec5SDimitry Andric   ///
850b57cec5SDimitry Andric   /// This must be used instead of delete as MCFragment is non-virtual.
860b57cec5SDimitry Andric   /// This method will dispatch to the appropriate subclass.
870b57cec5SDimitry Andric   void destroy();
880b57cec5SDimitry Andric 
getNext()89*0fca6ea1SDimitry Andric   MCFragment *getNext() const { return Next; }
90*0fca6ea1SDimitry Andric 
getKind()910b57cec5SDimitry Andric   FragmentType getKind() const { return Kind; }
920b57cec5SDimitry Andric 
getParent()930b57cec5SDimitry Andric   MCSection *getParent() const { return Parent; }
setParent(MCSection * Value)940b57cec5SDimitry Andric   void setParent(MCSection *Value) { Parent = Value; }
950b57cec5SDimitry Andric 
96*0fca6ea1SDimitry Andric   const MCSymbol *getAtom() const;
970b57cec5SDimitry Andric 
getLayoutOrder()980b57cec5SDimitry Andric   unsigned getLayoutOrder() const { return LayoutOrder; }
setLayoutOrder(unsigned Value)990b57cec5SDimitry Andric   void setLayoutOrder(unsigned Value) { LayoutOrder = Value; }
1000b57cec5SDimitry Andric 
1010b57cec5SDimitry Andric   /// Does this fragment have instructions emitted into it? By default
1020b57cec5SDimitry Andric   /// this is false, but specific fragment types may set it to true.
hasInstructions()1030b57cec5SDimitry Andric   bool hasInstructions() const { return HasInstructions; }
1040b57cec5SDimitry Andric 
1050b57cec5SDimitry Andric   void dump() const;
1060b57cec5SDimitry Andric };
1070b57cec5SDimitry Andric 
1080b57cec5SDimitry Andric class MCDummyFragment : public MCFragment {
1090b57cec5SDimitry Andric public:
MCDummyFragment()110*0fca6ea1SDimitry Andric   explicit MCDummyFragment() : MCFragment(FT_Dummy, false) {}
1110b57cec5SDimitry Andric 
classof(const MCFragment * F)1120b57cec5SDimitry Andric   static bool classof(const MCFragment *F) { return F->getKind() == FT_Dummy; }
1130b57cec5SDimitry Andric };
1140b57cec5SDimitry Andric 
1150b57cec5SDimitry Andric /// Interface implemented by fragments that contain encoded instructions and/or
1160b57cec5SDimitry Andric /// data.
1170b57cec5SDimitry Andric ///
1180b57cec5SDimitry Andric class MCEncodedFragment : public MCFragment {
1190b57cec5SDimitry Andric   /// Should this fragment be aligned to the end of a bundle?
1200b57cec5SDimitry Andric   bool AlignToBundleEnd = false;
1210b57cec5SDimitry Andric 
1220b57cec5SDimitry Andric   uint8_t BundlePadding = 0;
1230b57cec5SDimitry Andric 
1240b57cec5SDimitry Andric protected:
MCEncodedFragment(MCFragment::FragmentType FType,bool HasInstructions)125*0fca6ea1SDimitry Andric   MCEncodedFragment(MCFragment::FragmentType FType, bool HasInstructions)
126*0fca6ea1SDimitry Andric       : MCFragment(FType, HasInstructions) {}
1270b57cec5SDimitry Andric 
128480093f4SDimitry Andric   /// The MCSubtargetInfo in effect when the instruction was encoded.
129480093f4SDimitry Andric   /// It must be non-null for instructions.
1300b57cec5SDimitry Andric   const MCSubtargetInfo *STI = nullptr;
1310b57cec5SDimitry Andric 
1320b57cec5SDimitry Andric public:
classof(const MCFragment * F)1330b57cec5SDimitry Andric   static bool classof(const MCFragment *F) {
1340b57cec5SDimitry Andric     MCFragment::FragmentType Kind = F->getKind();
1350b57cec5SDimitry Andric     switch (Kind) {
1360b57cec5SDimitry Andric     default:
1370b57cec5SDimitry Andric       return false;
1380b57cec5SDimitry Andric     case MCFragment::FT_Relaxable:
1390b57cec5SDimitry Andric     case MCFragment::FT_CompactEncodedInst:
1400b57cec5SDimitry Andric     case MCFragment::FT_Data:
1410b57cec5SDimitry Andric     case MCFragment::FT_Dwarf:
1420b57cec5SDimitry Andric     case MCFragment::FT_DwarfFrame:
143e8d8bef9SDimitry Andric     case MCFragment::FT_PseudoProbe:
1440b57cec5SDimitry Andric       return true;
1450b57cec5SDimitry Andric     }
1460b57cec5SDimitry Andric   }
1470b57cec5SDimitry Andric 
1480b57cec5SDimitry Andric   /// Should this fragment be placed at the end of an aligned bundle?
alignToBundleEnd()1490b57cec5SDimitry Andric   bool alignToBundleEnd() const { return AlignToBundleEnd; }
setAlignToBundleEnd(bool V)1500b57cec5SDimitry Andric   void setAlignToBundleEnd(bool V) { AlignToBundleEnd = V; }
1510b57cec5SDimitry Andric 
1520b57cec5SDimitry Andric   /// Get the padding size that must be inserted before this fragment.
1530b57cec5SDimitry Andric   /// Used for bundling. By default, no padding is inserted.
1540b57cec5SDimitry Andric   /// Note that padding size is restricted to 8 bits. This is an optimization
1550b57cec5SDimitry Andric   /// to reduce the amount of space used for each fragment. In practice, larger
1560b57cec5SDimitry Andric   /// padding should never be required.
getBundlePadding()1570b57cec5SDimitry Andric   uint8_t getBundlePadding() const { return BundlePadding; }
1580b57cec5SDimitry Andric 
1590b57cec5SDimitry Andric   /// Set the padding size for this fragment. By default it's a no-op,
1600b57cec5SDimitry Andric   /// and only some fragments have a meaningful implementation.
setBundlePadding(uint8_t N)1610b57cec5SDimitry Andric   void setBundlePadding(uint8_t N) { BundlePadding = N; }
1620b57cec5SDimitry Andric 
1630b57cec5SDimitry Andric   /// Retrieve the MCSubTargetInfo in effect when the instruction was encoded.
1640b57cec5SDimitry Andric   /// Guaranteed to be non-null if hasInstructions() == true
getSubtargetInfo()1650b57cec5SDimitry Andric   const MCSubtargetInfo *getSubtargetInfo() const { return STI; }
1660b57cec5SDimitry Andric 
1670b57cec5SDimitry Andric   /// Record that the fragment contains instructions with the MCSubtargetInfo in
1680b57cec5SDimitry Andric   /// effect when the instruction was encoded.
setHasInstructions(const MCSubtargetInfo & STI)1690b57cec5SDimitry Andric   void setHasInstructions(const MCSubtargetInfo &STI) {
1700b57cec5SDimitry Andric     HasInstructions = true;
1710b57cec5SDimitry Andric     this->STI = &STI;
1720b57cec5SDimitry Andric   }
1730b57cec5SDimitry Andric };
1740b57cec5SDimitry Andric 
1750b57cec5SDimitry Andric /// Interface implemented by fragments that contain encoded instructions and/or
1760b57cec5SDimitry Andric /// data.
1770b57cec5SDimitry Andric ///
1780b57cec5SDimitry Andric template<unsigned ContentsSize>
1790b57cec5SDimitry Andric class MCEncodedFragmentWithContents : public MCEncodedFragment {
1800b57cec5SDimitry Andric   SmallVector<char, ContentsSize> Contents;
1810b57cec5SDimitry Andric 
1820b57cec5SDimitry Andric protected:
MCEncodedFragmentWithContents(MCFragment::FragmentType FType,bool HasInstructions)1830b57cec5SDimitry Andric   MCEncodedFragmentWithContents(MCFragment::FragmentType FType,
184*0fca6ea1SDimitry Andric                                 bool HasInstructions)
185*0fca6ea1SDimitry Andric       : MCEncodedFragment(FType, HasInstructions) {}
1860b57cec5SDimitry Andric 
1870b57cec5SDimitry Andric public:
getContents()1880b57cec5SDimitry Andric   SmallVectorImpl<char> &getContents() { return Contents; }
getContents()1890b57cec5SDimitry Andric   const SmallVectorImpl<char> &getContents() const { return Contents; }
1900b57cec5SDimitry Andric };
1910b57cec5SDimitry Andric 
1920b57cec5SDimitry Andric /// Interface implemented by fragments that contain encoded instructions and/or
1930b57cec5SDimitry Andric /// data and also have fixups registered.
1940b57cec5SDimitry Andric ///
1950b57cec5SDimitry Andric template<unsigned ContentsSize, unsigned FixupsSize>
1960b57cec5SDimitry Andric class MCEncodedFragmentWithFixups :
1970b57cec5SDimitry Andric   public MCEncodedFragmentWithContents<ContentsSize> {
1980b57cec5SDimitry Andric 
199480093f4SDimitry Andric   /// The list of fixups in this fragment.
2000b57cec5SDimitry Andric   SmallVector<MCFixup, FixupsSize> Fixups;
2010b57cec5SDimitry Andric 
2020b57cec5SDimitry Andric protected:
MCEncodedFragmentWithFixups(MCFragment::FragmentType FType,bool HasInstructions)2030b57cec5SDimitry Andric   MCEncodedFragmentWithFixups(MCFragment::FragmentType FType,
204*0fca6ea1SDimitry Andric                               bool HasInstructions)
205*0fca6ea1SDimitry Andric       : MCEncodedFragmentWithContents<ContentsSize>(FType, HasInstructions) {}
2060b57cec5SDimitry Andric 
2070b57cec5SDimitry Andric public:
2080b57cec5SDimitry Andric 
2090b57cec5SDimitry Andric   using const_fixup_iterator = SmallVectorImpl<MCFixup>::const_iterator;
2100b57cec5SDimitry Andric   using fixup_iterator = SmallVectorImpl<MCFixup>::iterator;
2110b57cec5SDimitry Andric 
getFixups()2120b57cec5SDimitry Andric   SmallVectorImpl<MCFixup> &getFixups() { return Fixups; }
getFixups()2130b57cec5SDimitry Andric   const SmallVectorImpl<MCFixup> &getFixups() const { return Fixups; }
2140b57cec5SDimitry Andric 
fixup_begin()2150b57cec5SDimitry Andric   fixup_iterator fixup_begin() { return Fixups.begin(); }
fixup_begin()2160b57cec5SDimitry Andric   const_fixup_iterator fixup_begin() const { return Fixups.begin(); }
2170b57cec5SDimitry Andric 
fixup_end()2180b57cec5SDimitry Andric   fixup_iterator fixup_end() { return Fixups.end(); }
fixup_end()2190b57cec5SDimitry Andric   const_fixup_iterator fixup_end() const { return Fixups.end(); }
2200b57cec5SDimitry Andric 
classof(const MCFragment * F)2210b57cec5SDimitry Andric   static bool classof(const MCFragment *F) {
2220b57cec5SDimitry Andric     MCFragment::FragmentType Kind = F->getKind();
2230b57cec5SDimitry Andric     return Kind == MCFragment::FT_Relaxable || Kind == MCFragment::FT_Data ||
2240b57cec5SDimitry Andric            Kind == MCFragment::FT_CVDefRange || Kind == MCFragment::FT_Dwarf ||
2250b57cec5SDimitry Andric            Kind == MCFragment::FT_DwarfFrame;
2260b57cec5SDimitry Andric   }
2270b57cec5SDimitry Andric };
2280b57cec5SDimitry Andric 
2290b57cec5SDimitry Andric /// Fragment for data and encoded instructions.
2300b57cec5SDimitry Andric ///
2310b57cec5SDimitry Andric class MCDataFragment : public MCEncodedFragmentWithFixups<32, 4> {
2320b57cec5SDimitry Andric public:
MCDataFragment()233*0fca6ea1SDimitry Andric   MCDataFragment() : MCEncodedFragmentWithFixups<32, 4>(FT_Data, false) {}
2340b57cec5SDimitry Andric 
classof(const MCFragment * F)2350b57cec5SDimitry Andric   static bool classof(const MCFragment *F) {
2360b57cec5SDimitry Andric     return F->getKind() == MCFragment::FT_Data;
2370b57cec5SDimitry Andric   }
23806c3fb27SDimitry Andric 
isLinkerRelaxable()23906c3fb27SDimitry Andric   bool isLinkerRelaxable() const { return LinkerRelaxable; }
setLinkerRelaxable()24006c3fb27SDimitry Andric   void setLinkerRelaxable() { LinkerRelaxable = true; }
2410b57cec5SDimitry Andric };
2420b57cec5SDimitry Andric 
2430b57cec5SDimitry Andric /// This is a compact (memory-size-wise) fragment for holding an encoded
2440b57cec5SDimitry Andric /// instruction (non-relaxable) that has no fixups registered. When applicable,
2450b57cec5SDimitry Andric /// it can be used instead of MCDataFragment and lead to lower memory
2460b57cec5SDimitry Andric /// consumption.
2470b57cec5SDimitry Andric ///
2480b57cec5SDimitry Andric class MCCompactEncodedInstFragment : public MCEncodedFragmentWithContents<4> {
2490b57cec5SDimitry Andric public:
MCCompactEncodedInstFragment()250*0fca6ea1SDimitry Andric   MCCompactEncodedInstFragment()
251*0fca6ea1SDimitry Andric       : MCEncodedFragmentWithContents(FT_CompactEncodedInst, true) {}
2520b57cec5SDimitry Andric 
classof(const MCFragment * F)2530b57cec5SDimitry Andric   static bool classof(const MCFragment *F) {
2540b57cec5SDimitry Andric     return F->getKind() == MCFragment::FT_CompactEncodedInst;
2550b57cec5SDimitry Andric   }
2560b57cec5SDimitry Andric };
2570b57cec5SDimitry Andric 
2580b57cec5SDimitry Andric /// A relaxable fragment holds on to its MCInst, since it may need to be
2590b57cec5SDimitry Andric /// relaxed during the assembler layout and relaxation stage.
2600b57cec5SDimitry Andric ///
2610b57cec5SDimitry Andric class MCRelaxableFragment : public MCEncodedFragmentWithFixups<8, 1> {
2620b57cec5SDimitry Andric 
263480093f4SDimitry Andric   /// The instruction this is a fragment for.
2640b57cec5SDimitry Andric   MCInst Inst;
2655ffd83dbSDimitry Andric   /// Can we auto pad the instruction?
2665ffd83dbSDimitry Andric   bool AllowAutoPadding = false;
2670b57cec5SDimitry Andric 
2680b57cec5SDimitry Andric public:
MCRelaxableFragment(const MCInst & Inst,const MCSubtargetInfo & STI)269*0fca6ea1SDimitry Andric   MCRelaxableFragment(const MCInst &Inst, const MCSubtargetInfo &STI)
270*0fca6ea1SDimitry Andric       : MCEncodedFragmentWithFixups(FT_Relaxable, true), Inst(Inst) {
271*0fca6ea1SDimitry Andric     this->STI = &STI;
272*0fca6ea1SDimitry Andric   }
2730b57cec5SDimitry Andric 
getInst()2740b57cec5SDimitry Andric   const MCInst &getInst() const { return Inst; }
setInst(const MCInst & Value)2750b57cec5SDimitry Andric   void setInst(const MCInst &Value) { Inst = Value; }
2760b57cec5SDimitry Andric 
getAllowAutoPadding()2775ffd83dbSDimitry Andric   bool getAllowAutoPadding() const { return AllowAutoPadding; }
setAllowAutoPadding(bool V)2785ffd83dbSDimitry Andric   void setAllowAutoPadding(bool V) { AllowAutoPadding = V; }
2795ffd83dbSDimitry Andric 
classof(const MCFragment * F)2800b57cec5SDimitry Andric   static bool classof(const MCFragment *F) {
2810b57cec5SDimitry Andric     return F->getKind() == MCFragment::FT_Relaxable;
2820b57cec5SDimitry Andric   }
2830b57cec5SDimitry Andric };
2840b57cec5SDimitry Andric 
2850b57cec5SDimitry Andric class MCAlignFragment : public MCFragment {
286480093f4SDimitry Andric   /// The alignment to ensure, in bytes.
28781ad6265SDimitry Andric   Align Alignment;
2880b57cec5SDimitry Andric 
289480093f4SDimitry Andric   /// Flag to indicate that (optimal) NOPs should be emitted instead
2900b57cec5SDimitry Andric   /// of using the provided value. The exact interpretation of this flag is
2910b57cec5SDimitry Andric   /// target dependent.
2920b57cec5SDimitry Andric   bool EmitNops : 1;
2930b57cec5SDimitry Andric 
294480093f4SDimitry Andric   /// Value to use for filling padding bytes.
2950b57cec5SDimitry Andric   int64_t Value;
2960b57cec5SDimitry Andric 
297480093f4SDimitry Andric   /// The size of the integer (in bytes) of \p Value.
2980b57cec5SDimitry Andric   unsigned ValueSize;
2990b57cec5SDimitry Andric 
300480093f4SDimitry Andric   /// The maximum number of bytes to emit; if the alignment
3010b57cec5SDimitry Andric   /// cannot be satisfied in this width then this fragment is ignored.
3020b57cec5SDimitry Andric   unsigned MaxBytesToEmit;
3030b57cec5SDimitry Andric 
304349cc55cSDimitry Andric   /// When emitting Nops some subtargets have specific nop encodings.
30506c3fb27SDimitry Andric   const MCSubtargetInfo *STI = nullptr;
306349cc55cSDimitry Andric 
3070b57cec5SDimitry Andric public:
MCAlignFragment(Align Alignment,int64_t Value,unsigned ValueSize,unsigned MaxBytesToEmit)30881ad6265SDimitry Andric   MCAlignFragment(Align Alignment, int64_t Value, unsigned ValueSize,
309*0fca6ea1SDimitry Andric                   unsigned MaxBytesToEmit)
310*0fca6ea1SDimitry Andric       : MCFragment(FT_Align, false), Alignment(Alignment), EmitNops(false),
3110b57cec5SDimitry Andric         Value(Value), ValueSize(ValueSize), MaxBytesToEmit(MaxBytesToEmit) {}
3120b57cec5SDimitry Andric 
getAlignment()31381ad6265SDimitry Andric   Align getAlignment() const { return Alignment; }
3140b57cec5SDimitry Andric 
getValue()3150b57cec5SDimitry Andric   int64_t getValue() const { return Value; }
3160b57cec5SDimitry Andric 
getValueSize()3170b57cec5SDimitry Andric   unsigned getValueSize() const { return ValueSize; }
3180b57cec5SDimitry Andric 
getMaxBytesToEmit()3190b57cec5SDimitry Andric   unsigned getMaxBytesToEmit() const { return MaxBytesToEmit; }
3200b57cec5SDimitry Andric 
hasEmitNops()3210b57cec5SDimitry Andric   bool hasEmitNops() const { return EmitNops; }
setEmitNops(bool Value,const MCSubtargetInfo * STI)322349cc55cSDimitry Andric   void setEmitNops(bool Value, const MCSubtargetInfo *STI) {
323349cc55cSDimitry Andric     EmitNops = Value;
324349cc55cSDimitry Andric     this->STI = STI;
325349cc55cSDimitry Andric   }
326349cc55cSDimitry Andric 
getSubtargetInfo()327349cc55cSDimitry Andric   const MCSubtargetInfo *getSubtargetInfo() const { return STI; }
3280b57cec5SDimitry Andric 
classof(const MCFragment * F)3290b57cec5SDimitry Andric   static bool classof(const MCFragment *F) {
3300b57cec5SDimitry Andric     return F->getKind() == MCFragment::FT_Align;
3310b57cec5SDimitry Andric   }
3320b57cec5SDimitry Andric };
3330b57cec5SDimitry Andric 
3340b57cec5SDimitry Andric class MCFillFragment : public MCFragment {
335480093f4SDimitry Andric   uint8_t ValueSize;
3360b57cec5SDimitry Andric   /// Value to use for filling bytes.
3370b57cec5SDimitry Andric   uint64_t Value;
3380b57cec5SDimitry Andric   /// The number of bytes to insert.
3390b57cec5SDimitry Andric   const MCExpr &NumValues;
3400b57cec5SDimitry Andric 
3410b57cec5SDimitry Andric   /// Source location of the directive that this fragment was created for.
3420b57cec5SDimitry Andric   SMLoc Loc;
3430b57cec5SDimitry Andric 
3440b57cec5SDimitry Andric public:
MCFillFragment(uint64_t Value,uint8_t VSize,const MCExpr & NumValues,SMLoc Loc)3450b57cec5SDimitry Andric   MCFillFragment(uint64_t Value, uint8_t VSize, const MCExpr &NumValues,
346*0fca6ea1SDimitry Andric                  SMLoc Loc)
347*0fca6ea1SDimitry Andric       : MCFragment(FT_Fill, false), ValueSize(VSize), Value(Value),
3480b57cec5SDimitry Andric         NumValues(NumValues), Loc(Loc) {}
3490b57cec5SDimitry Andric 
getValue()3500b57cec5SDimitry Andric   uint64_t getValue() const { return Value; }
getValueSize()3510b57cec5SDimitry Andric   uint8_t getValueSize() const { return ValueSize; }
getNumValues()3520b57cec5SDimitry Andric   const MCExpr &getNumValues() const { return NumValues; }
3530b57cec5SDimitry Andric 
getLoc()3540b57cec5SDimitry Andric   SMLoc getLoc() const { return Loc; }
3550b57cec5SDimitry Andric 
classof(const MCFragment * F)3560b57cec5SDimitry Andric   static bool classof(const MCFragment *F) {
3570b57cec5SDimitry Andric     return F->getKind() == MCFragment::FT_Fill;
3580b57cec5SDimitry Andric   }
3590b57cec5SDimitry Andric };
3600b57cec5SDimitry Andric 
361e8d8bef9SDimitry Andric class MCNopsFragment : public MCFragment {
362e8d8bef9SDimitry Andric   /// The number of bytes to insert.
363e8d8bef9SDimitry Andric   int64_t Size;
364e8d8bef9SDimitry Andric   /// Maximum number of bytes allowed in each NOP instruction.
365e8d8bef9SDimitry Andric   int64_t ControlledNopLength;
366e8d8bef9SDimitry Andric 
367e8d8bef9SDimitry Andric   /// Source location of the directive that this fragment was created for.
368e8d8bef9SDimitry Andric   SMLoc Loc;
369e8d8bef9SDimitry Andric 
370349cc55cSDimitry Andric   /// When emitting Nops some subtargets have specific nop encodings.
371349cc55cSDimitry Andric   const MCSubtargetInfo &STI;
372349cc55cSDimitry Andric 
373e8d8bef9SDimitry Andric public:
MCNopsFragment(int64_t NumBytes,int64_t ControlledNopLength,SMLoc L,const MCSubtargetInfo & STI)374e8d8bef9SDimitry Andric   MCNopsFragment(int64_t NumBytes, int64_t ControlledNopLength, SMLoc L,
375*0fca6ea1SDimitry Andric                  const MCSubtargetInfo &STI)
376*0fca6ea1SDimitry Andric       : MCFragment(FT_Nops, false), Size(NumBytes),
377349cc55cSDimitry Andric         ControlledNopLength(ControlledNopLength), Loc(L), STI(STI) {}
378e8d8bef9SDimitry Andric 
getNumBytes()379e8d8bef9SDimitry Andric   int64_t getNumBytes() const { return Size; }
getControlledNopLength()380e8d8bef9SDimitry Andric   int64_t getControlledNopLength() const { return ControlledNopLength; }
381e8d8bef9SDimitry Andric 
getLoc()382e8d8bef9SDimitry Andric   SMLoc getLoc() const { return Loc; }
383e8d8bef9SDimitry Andric 
getSubtargetInfo()384349cc55cSDimitry Andric   const MCSubtargetInfo *getSubtargetInfo() const { return &STI; }
385349cc55cSDimitry Andric 
classof(const MCFragment * F)386e8d8bef9SDimitry Andric   static bool classof(const MCFragment *F) {
387e8d8bef9SDimitry Andric     return F->getKind() == MCFragment::FT_Nops;
388e8d8bef9SDimitry Andric   }
389e8d8bef9SDimitry Andric };
390e8d8bef9SDimitry Andric 
3910b57cec5SDimitry Andric class MCOrgFragment : public MCFragment {
3920b57cec5SDimitry Andric   /// Value to use for filling bytes.
3930b57cec5SDimitry Andric   int8_t Value;
3940b57cec5SDimitry Andric 
395480093f4SDimitry Andric   /// The offset this fragment should start at.
396480093f4SDimitry Andric   const MCExpr *Offset;
397480093f4SDimitry Andric 
3980b57cec5SDimitry Andric   /// Source location of the directive that this fragment was created for.
3990b57cec5SDimitry Andric   SMLoc Loc;
4000b57cec5SDimitry Andric 
4010b57cec5SDimitry Andric public:
MCOrgFragment(const MCExpr & Offset,int8_t Value,SMLoc Loc)402*0fca6ea1SDimitry Andric   MCOrgFragment(const MCExpr &Offset, int8_t Value, SMLoc Loc)
403*0fca6ea1SDimitry Andric       : MCFragment(FT_Org, false), Value(Value), Offset(&Offset), Loc(Loc) {}
4040b57cec5SDimitry Andric 
getOffset()4050b57cec5SDimitry Andric   const MCExpr &getOffset() const { return *Offset; }
4060b57cec5SDimitry Andric 
getValue()4070b57cec5SDimitry Andric   uint8_t getValue() const { return Value; }
4080b57cec5SDimitry Andric 
getLoc()4090b57cec5SDimitry Andric   SMLoc getLoc() const { return Loc; }
4100b57cec5SDimitry Andric 
classof(const MCFragment * F)4110b57cec5SDimitry Andric   static bool classof(const MCFragment *F) {
4120b57cec5SDimitry Andric     return F->getKind() == MCFragment::FT_Org;
4130b57cec5SDimitry Andric   }
4140b57cec5SDimitry Andric };
4150b57cec5SDimitry Andric 
4165f757f3fSDimitry Andric class MCLEBFragment final : public MCEncodedFragmentWithFixups<8, 0> {
417480093f4SDimitry Andric   /// True if this is a sleb128, false if uleb128.
4180b57cec5SDimitry Andric   bool IsSigned;
4190b57cec5SDimitry Andric 
420480093f4SDimitry Andric   /// The value this fragment should contain.
421480093f4SDimitry Andric   const MCExpr *Value;
422480093f4SDimitry Andric 
4230b57cec5SDimitry Andric public:
MCLEBFragment(const MCExpr & Value,bool IsSigned)424*0fca6ea1SDimitry Andric   MCLEBFragment(const MCExpr &Value, bool IsSigned)
425*0fca6ea1SDimitry Andric       : MCEncodedFragmentWithFixups<8, 0>(FT_LEB, false), IsSigned(IsSigned),
426*0fca6ea1SDimitry Andric         Value(&Value) {
4275f757f3fSDimitry Andric     getContents().push_back(0);
4280b57cec5SDimitry Andric   }
4290b57cec5SDimitry Andric 
getValue()4300b57cec5SDimitry Andric   const MCExpr &getValue() const { return *Value; }
setValue(const MCExpr * Expr)4315f757f3fSDimitry Andric   void setValue(const MCExpr *Expr) { Value = Expr; }
4320b57cec5SDimitry Andric 
isSigned()4330b57cec5SDimitry Andric   bool isSigned() const { return IsSigned; }
4340b57cec5SDimitry Andric 
4350b57cec5SDimitry Andric   /// @}
4360b57cec5SDimitry Andric 
classof(const MCFragment * F)4370b57cec5SDimitry Andric   static bool classof(const MCFragment *F) {
4380b57cec5SDimitry Andric     return F->getKind() == MCFragment::FT_LEB;
4390b57cec5SDimitry Andric   }
4400b57cec5SDimitry Andric };
4410b57cec5SDimitry Andric 
4420b57cec5SDimitry Andric class MCDwarfLineAddrFragment : public MCEncodedFragmentWithFixups<8, 1> {
443480093f4SDimitry Andric   /// The value of the difference between the two line numbers
4440b57cec5SDimitry Andric   /// between two .loc dwarf directives.
4450b57cec5SDimitry Andric   int64_t LineDelta;
4460b57cec5SDimitry Andric 
447480093f4SDimitry Andric   /// The expression for the difference of the two symbols that
4480b57cec5SDimitry Andric   /// make up the address delta between two .loc dwarf directives.
4490b57cec5SDimitry Andric   const MCExpr *AddrDelta;
4500b57cec5SDimitry Andric 
4510b57cec5SDimitry Andric public:
MCDwarfLineAddrFragment(int64_t LineDelta,const MCExpr & AddrDelta)452*0fca6ea1SDimitry Andric   MCDwarfLineAddrFragment(int64_t LineDelta, const MCExpr &AddrDelta)
453*0fca6ea1SDimitry Andric       : MCEncodedFragmentWithFixups<8, 1>(FT_Dwarf, false),
4540b57cec5SDimitry Andric         LineDelta(LineDelta), AddrDelta(&AddrDelta) {}
4550b57cec5SDimitry Andric 
getLineDelta()4560b57cec5SDimitry Andric   int64_t getLineDelta() const { return LineDelta; }
4570b57cec5SDimitry Andric 
getAddrDelta()4580b57cec5SDimitry Andric   const MCExpr &getAddrDelta() const { return *AddrDelta; }
4590b57cec5SDimitry Andric 
classof(const MCFragment * F)4600b57cec5SDimitry Andric   static bool classof(const MCFragment *F) {
4610b57cec5SDimitry Andric     return F->getKind() == MCFragment::FT_Dwarf;
4620b57cec5SDimitry Andric   }
4630b57cec5SDimitry Andric };
4640b57cec5SDimitry Andric 
4650b57cec5SDimitry Andric class MCDwarfCallFrameFragment : public MCEncodedFragmentWithFixups<8, 1> {
466480093f4SDimitry Andric   /// The expression for the difference of the two symbols that
4670b57cec5SDimitry Andric   /// make up the address delta between two .cfi_* dwarf directives.
4680b57cec5SDimitry Andric   const MCExpr *AddrDelta;
4690b57cec5SDimitry Andric 
4700b57cec5SDimitry Andric public:
MCDwarfCallFrameFragment(const MCExpr & AddrDelta)471*0fca6ea1SDimitry Andric   MCDwarfCallFrameFragment(const MCExpr &AddrDelta)
472*0fca6ea1SDimitry Andric       : MCEncodedFragmentWithFixups<8, 1>(FT_DwarfFrame, false),
4730b57cec5SDimitry Andric         AddrDelta(&AddrDelta) {}
4740b57cec5SDimitry Andric 
getAddrDelta()4750b57cec5SDimitry Andric   const MCExpr &getAddrDelta() const { return *AddrDelta; }
setAddrDelta(const MCExpr * E)47606c3fb27SDimitry Andric   void setAddrDelta(const MCExpr *E) { AddrDelta = E; }
4770b57cec5SDimitry Andric 
classof(const MCFragment * F)4780b57cec5SDimitry Andric   static bool classof(const MCFragment *F) {
4790b57cec5SDimitry Andric     return F->getKind() == MCFragment::FT_DwarfFrame;
4800b57cec5SDimitry Andric   }
4810b57cec5SDimitry Andric };
4820b57cec5SDimitry Andric 
4830b57cec5SDimitry Andric /// Represents a symbol table index fragment.
4840b57cec5SDimitry Andric class MCSymbolIdFragment : public MCFragment {
4850b57cec5SDimitry Andric   const MCSymbol *Sym;
4860b57cec5SDimitry Andric 
4870b57cec5SDimitry Andric public:
MCSymbolIdFragment(const MCSymbol * Sym)488*0fca6ea1SDimitry Andric   MCSymbolIdFragment(const MCSymbol *Sym)
489*0fca6ea1SDimitry Andric       : MCFragment(FT_SymbolId, false), Sym(Sym) {}
4900b57cec5SDimitry Andric 
getSymbol()4910b57cec5SDimitry Andric   const MCSymbol *getSymbol() { return Sym; }
getSymbol()4920b57cec5SDimitry Andric   const MCSymbol *getSymbol() const { return Sym; }
4930b57cec5SDimitry Andric 
classof(const MCFragment * F)4940b57cec5SDimitry Andric   static bool classof(const MCFragment *F) {
4950b57cec5SDimitry Andric     return F->getKind() == MCFragment::FT_SymbolId;
4960b57cec5SDimitry Andric   }
4970b57cec5SDimitry Andric };
4980b57cec5SDimitry Andric 
4990b57cec5SDimitry Andric /// Fragment representing the binary annotations produced by the
5000b57cec5SDimitry Andric /// .cv_inline_linetable directive.
5010b57cec5SDimitry Andric class MCCVInlineLineTableFragment : public MCFragment {
5020b57cec5SDimitry Andric   unsigned SiteFuncId;
5030b57cec5SDimitry Andric   unsigned StartFileId;
5040b57cec5SDimitry Andric   unsigned StartLineNum;
5050b57cec5SDimitry Andric   const MCSymbol *FnStartSym;
5060b57cec5SDimitry Andric   const MCSymbol *FnEndSym;
5070b57cec5SDimitry Andric   SmallString<8> Contents;
5080b57cec5SDimitry Andric 
5090b57cec5SDimitry Andric   /// CodeViewContext has the real knowledge about this format, so let it access
5100b57cec5SDimitry Andric   /// our members.
5110b57cec5SDimitry Andric   friend class CodeViewContext;
5120b57cec5SDimitry Andric 
5130b57cec5SDimitry Andric public:
MCCVInlineLineTableFragment(unsigned SiteFuncId,unsigned StartFileId,unsigned StartLineNum,const MCSymbol * FnStartSym,const MCSymbol * FnEndSym)5140b57cec5SDimitry Andric   MCCVInlineLineTableFragment(unsigned SiteFuncId, unsigned StartFileId,
5150b57cec5SDimitry Andric                               unsigned StartLineNum, const MCSymbol *FnStartSym,
516*0fca6ea1SDimitry Andric                               const MCSymbol *FnEndSym)
517*0fca6ea1SDimitry Andric       : MCFragment(FT_CVInlineLines, false), SiteFuncId(SiteFuncId),
5180b57cec5SDimitry Andric         StartFileId(StartFileId), StartLineNum(StartLineNum),
5190b57cec5SDimitry Andric         FnStartSym(FnStartSym), FnEndSym(FnEndSym) {}
5200b57cec5SDimitry Andric 
getFnStartSym()5210b57cec5SDimitry Andric   const MCSymbol *getFnStartSym() const { return FnStartSym; }
getFnEndSym()5220b57cec5SDimitry Andric   const MCSymbol *getFnEndSym() const { return FnEndSym; }
5230b57cec5SDimitry Andric 
getContents()5240b57cec5SDimitry Andric   SmallString<8> &getContents() { return Contents; }
getContents()5250b57cec5SDimitry Andric   const SmallString<8> &getContents() const { return Contents; }
5260b57cec5SDimitry Andric 
classof(const MCFragment * F)5270b57cec5SDimitry Andric   static bool classof(const MCFragment *F) {
5280b57cec5SDimitry Andric     return F->getKind() == MCFragment::FT_CVInlineLines;
5290b57cec5SDimitry Andric   }
5300b57cec5SDimitry Andric };
5310b57cec5SDimitry Andric 
5320b57cec5SDimitry Andric /// Fragment representing the .cv_def_range directive.
5330b57cec5SDimitry Andric class MCCVDefRangeFragment : public MCEncodedFragmentWithFixups<32, 4> {
5340b57cec5SDimitry Andric   SmallVector<std::pair<const MCSymbol *, const MCSymbol *>, 2> Ranges;
5350b57cec5SDimitry Andric   SmallString<32> FixedSizePortion;
5360b57cec5SDimitry Andric 
5370b57cec5SDimitry Andric   /// CodeViewContext has the real knowledge about this format, so let it access
5380b57cec5SDimitry Andric   /// our members.
5390b57cec5SDimitry Andric   friend class CodeViewContext;
5400b57cec5SDimitry Andric 
5410b57cec5SDimitry Andric public:
MCCVDefRangeFragment(ArrayRef<std::pair<const MCSymbol *,const MCSymbol * >> Ranges,StringRef FixedSizePortion)5420b57cec5SDimitry Andric   MCCVDefRangeFragment(
5430b57cec5SDimitry Andric       ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
544*0fca6ea1SDimitry Andric       StringRef FixedSizePortion)
545*0fca6ea1SDimitry Andric       : MCEncodedFragmentWithFixups<32, 4>(FT_CVDefRange, false),
5460b57cec5SDimitry Andric         Ranges(Ranges.begin(), Ranges.end()),
5470b57cec5SDimitry Andric         FixedSizePortion(FixedSizePortion) {}
5480b57cec5SDimitry Andric 
getRanges()5490b57cec5SDimitry Andric   ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> getRanges() const {
5500b57cec5SDimitry Andric     return Ranges;
5510b57cec5SDimitry Andric   }
5520b57cec5SDimitry Andric 
getFixedSizePortion()553fe6060f1SDimitry Andric   StringRef getFixedSizePortion() const { return FixedSizePortion.str(); }
5540b57cec5SDimitry Andric 
classof(const MCFragment * F)5550b57cec5SDimitry Andric   static bool classof(const MCFragment *F) {
5560b57cec5SDimitry Andric     return F->getKind() == MCFragment::FT_CVDefRange;
5570b57cec5SDimitry Andric   }
5580b57cec5SDimitry Andric };
5590b57cec5SDimitry Andric 
560480093f4SDimitry Andric /// Represents required padding such that a particular other set of fragments
561480093f4SDimitry Andric /// does not cross a particular power-of-two boundary. The other fragments must
562480093f4SDimitry Andric /// follow this one within the same section.
563480093f4SDimitry Andric class MCBoundaryAlignFragment : public MCFragment {
564480093f4SDimitry Andric   /// The alignment requirement of the branch to be aligned.
565480093f4SDimitry Andric   Align AlignBoundary;
5665ffd83dbSDimitry Andric   /// The last fragment in the set of fragments to be aligned.
5675ffd83dbSDimitry Andric   const MCFragment *LastFragment = nullptr;
568480093f4SDimitry Andric   /// The size of the fragment.  The size is lazily set during relaxation, and
569480093f4SDimitry Andric   /// is not meaningful before that.
570480093f4SDimitry Andric   uint64_t Size = 0;
571480093f4SDimitry Andric 
572349cc55cSDimitry Andric   /// When emitting Nops some subtargets have specific nop encodings.
573349cc55cSDimitry Andric   const MCSubtargetInfo &STI;
574349cc55cSDimitry Andric 
575480093f4SDimitry Andric public:
MCBoundaryAlignFragment(Align AlignBoundary,const MCSubtargetInfo & STI)576*0fca6ea1SDimitry Andric   MCBoundaryAlignFragment(Align AlignBoundary, const MCSubtargetInfo &STI)
577*0fca6ea1SDimitry Andric       : MCFragment(FT_BoundaryAlign, false), AlignBoundary(AlignBoundary),
578349cc55cSDimitry Andric         STI(STI) {}
579480093f4SDimitry Andric 
getSize()580480093f4SDimitry Andric   uint64_t getSize() const { return Size; }
setSize(uint64_t Value)581480093f4SDimitry Andric   void setSize(uint64_t Value) { Size = Value; }
582480093f4SDimitry Andric 
getAlignment()583480093f4SDimitry Andric   Align getAlignment() const { return AlignBoundary; }
setAlignment(Align Value)5845ffd83dbSDimitry Andric   void setAlignment(Align Value) { AlignBoundary = Value; }
585480093f4SDimitry Andric 
getLastFragment()5865ffd83dbSDimitry Andric   const MCFragment *getLastFragment() const { return LastFragment; }
setLastFragment(const MCFragment * F)5875ffd83dbSDimitry Andric   void setLastFragment(const MCFragment *F) {
5885ffd83dbSDimitry Andric     assert(!F || getParent() == F->getParent());
5895ffd83dbSDimitry Andric     LastFragment = F;
5905ffd83dbSDimitry Andric   }
591480093f4SDimitry Andric 
getSubtargetInfo()592349cc55cSDimitry Andric   const MCSubtargetInfo *getSubtargetInfo() const { return &STI; }
593349cc55cSDimitry Andric 
classof(const MCFragment * F)594480093f4SDimitry Andric   static bool classof(const MCFragment *F) {
595480093f4SDimitry Andric     return F->getKind() == MCFragment::FT_BoundaryAlign;
596480093f4SDimitry Andric   }
597480093f4SDimitry Andric };
598e8d8bef9SDimitry Andric 
599e8d8bef9SDimitry Andric class MCPseudoProbeAddrFragment : public MCEncodedFragmentWithFixups<8, 1> {
600e8d8bef9SDimitry Andric   /// The expression for the difference of the two symbols that
601e8d8bef9SDimitry Andric   /// make up the address delta between two .pseudoprobe directives.
602e8d8bef9SDimitry Andric   const MCExpr *AddrDelta;
603e8d8bef9SDimitry Andric 
604e8d8bef9SDimitry Andric public:
MCPseudoProbeAddrFragment(const MCExpr * AddrDelta)605*0fca6ea1SDimitry Andric   MCPseudoProbeAddrFragment(const MCExpr *AddrDelta)
606*0fca6ea1SDimitry Andric       : MCEncodedFragmentWithFixups<8, 1>(FT_PseudoProbe, false),
607e8d8bef9SDimitry Andric         AddrDelta(AddrDelta) {}
608e8d8bef9SDimitry Andric 
getAddrDelta()609e8d8bef9SDimitry Andric   const MCExpr &getAddrDelta() const { return *AddrDelta; }
610e8d8bef9SDimitry Andric 
classof(const MCFragment * F)611e8d8bef9SDimitry Andric   static bool classof(const MCFragment *F) {
612e8d8bef9SDimitry Andric     return F->getKind() == MCFragment::FT_PseudoProbe;
613e8d8bef9SDimitry Andric   }
614e8d8bef9SDimitry Andric };
6150b57cec5SDimitry Andric } // end namespace llvm
6160b57cec5SDimitry Andric 
6170b57cec5SDimitry Andric #endif // LLVM_MC_MCFRAGMENT_H
618