xref: /freebsd/contrib/llvm-project/llvm/include/llvm/MC/MCFragment.h (revision 480093f4440d54b30b3025afeac24b48f2ba7a2e)
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"
19*480093f4SDimitry Andric #include "llvm/Support/Alignment.h"
200b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
210b57cec5SDimitry Andric #include "llvm/Support/SMLoc.h"
220b57cec5SDimitry Andric #include <cstdint>
230b57cec5SDimitry Andric #include <utility>
240b57cec5SDimitry Andric 
250b57cec5SDimitry Andric namespace llvm {
260b57cec5SDimitry Andric 
270b57cec5SDimitry Andric class MCSection;
280b57cec5SDimitry Andric class MCSubtargetInfo;
290b57cec5SDimitry Andric class MCSymbol;
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric class MCFragment : public ilist_node_with_parent<MCFragment, MCSection> {
320b57cec5SDimitry Andric   friend class MCAsmLayout;
330b57cec5SDimitry Andric 
340b57cec5SDimitry Andric public:
350b57cec5SDimitry Andric   enum FragmentType : uint8_t {
360b57cec5SDimitry Andric     FT_Align,
370b57cec5SDimitry Andric     FT_Data,
380b57cec5SDimitry Andric     FT_CompactEncodedInst,
390b57cec5SDimitry Andric     FT_Fill,
400b57cec5SDimitry Andric     FT_Relaxable,
410b57cec5SDimitry Andric     FT_Org,
420b57cec5SDimitry Andric     FT_Dwarf,
430b57cec5SDimitry Andric     FT_DwarfFrame,
440b57cec5SDimitry Andric     FT_LEB,
45*480093f4SDimitry Andric     FT_BoundaryAlign,
460b57cec5SDimitry Andric     FT_SymbolId,
470b57cec5SDimitry Andric     FT_CVInlineLines,
480b57cec5SDimitry Andric     FT_CVDefRange,
490b57cec5SDimitry Andric     FT_Dummy
500b57cec5SDimitry Andric   };
510b57cec5SDimitry Andric 
520b57cec5SDimitry Andric private:
53*480093f4SDimitry Andric   /// The data for the section this fragment is in.
54*480093f4SDimitry Andric   MCSection *Parent;
55*480093f4SDimitry Andric 
56*480093f4SDimitry Andric   /// The atom this fragment is in, as represented by its defining symbol.
57*480093f4SDimitry Andric   const MCSymbol *Atom;
58*480093f4SDimitry Andric 
59*480093f4SDimitry Andric   /// The offset of this fragment in its section. This is ~0 until
60*480093f4SDimitry Andric   /// initialized.
61*480093f4SDimitry Andric   uint64_t Offset;
62*480093f4SDimitry Andric 
63*480093f4SDimitry Andric   /// The layout order of this fragment.
64*480093f4SDimitry Andric   unsigned LayoutOrder;
65*480093f4SDimitry Andric 
660b57cec5SDimitry Andric   FragmentType Kind;
670b57cec5SDimitry Andric 
680b57cec5SDimitry Andric protected:
690b57cec5SDimitry Andric   bool HasInstructions;
700b57cec5SDimitry Andric 
710b57cec5SDimitry Andric   MCFragment(FragmentType Kind, bool HasInstructions,
720b57cec5SDimitry Andric              MCSection *Parent = nullptr);
730b57cec5SDimitry Andric 
740b57cec5SDimitry Andric public:
750b57cec5SDimitry Andric   MCFragment() = delete;
760b57cec5SDimitry Andric   MCFragment(const MCFragment &) = delete;
770b57cec5SDimitry Andric   MCFragment &operator=(const MCFragment &) = delete;
780b57cec5SDimitry Andric 
790b57cec5SDimitry Andric   /// Destroys the current fragment.
800b57cec5SDimitry Andric   ///
810b57cec5SDimitry Andric   /// This must be used instead of delete as MCFragment is non-virtual.
820b57cec5SDimitry Andric   /// This method will dispatch to the appropriate subclass.
830b57cec5SDimitry Andric   void destroy();
840b57cec5SDimitry Andric 
850b57cec5SDimitry Andric   FragmentType getKind() const { return Kind; }
860b57cec5SDimitry Andric 
870b57cec5SDimitry Andric   MCSection *getParent() const { return Parent; }
880b57cec5SDimitry Andric   void setParent(MCSection *Value) { Parent = Value; }
890b57cec5SDimitry Andric 
900b57cec5SDimitry Andric   const MCSymbol *getAtom() const { return Atom; }
910b57cec5SDimitry Andric   void setAtom(const MCSymbol *Value) { Atom = Value; }
920b57cec5SDimitry Andric 
930b57cec5SDimitry Andric   unsigned getLayoutOrder() const { return LayoutOrder; }
940b57cec5SDimitry Andric   void setLayoutOrder(unsigned Value) { LayoutOrder = Value; }
950b57cec5SDimitry Andric 
960b57cec5SDimitry Andric   /// Does this fragment have instructions emitted into it? By default
970b57cec5SDimitry Andric   /// this is false, but specific fragment types may set it to true.
980b57cec5SDimitry Andric   bool hasInstructions() const { return HasInstructions; }
990b57cec5SDimitry Andric 
1000b57cec5SDimitry Andric   void dump() const;
1010b57cec5SDimitry Andric };
1020b57cec5SDimitry Andric 
1030b57cec5SDimitry Andric class MCDummyFragment : public MCFragment {
1040b57cec5SDimitry Andric public:
1050b57cec5SDimitry Andric   explicit MCDummyFragment(MCSection *Sec) : MCFragment(FT_Dummy, false, Sec) {}
1060b57cec5SDimitry Andric 
1070b57cec5SDimitry Andric   static bool classof(const MCFragment *F) { return F->getKind() == FT_Dummy; }
1080b57cec5SDimitry Andric };
1090b57cec5SDimitry Andric 
1100b57cec5SDimitry Andric /// Interface implemented by fragments that contain encoded instructions and/or
1110b57cec5SDimitry Andric /// data.
1120b57cec5SDimitry Andric ///
1130b57cec5SDimitry Andric class MCEncodedFragment : public MCFragment {
1140b57cec5SDimitry Andric   /// Should this fragment be aligned to the end of a bundle?
1150b57cec5SDimitry Andric   bool AlignToBundleEnd = false;
1160b57cec5SDimitry Andric 
1170b57cec5SDimitry Andric   uint8_t BundlePadding = 0;
1180b57cec5SDimitry Andric 
1190b57cec5SDimitry Andric protected:
1200b57cec5SDimitry Andric   MCEncodedFragment(MCFragment::FragmentType FType, bool HasInstructions,
1210b57cec5SDimitry Andric                     MCSection *Sec)
1220b57cec5SDimitry Andric       : MCFragment(FType, HasInstructions, Sec) {}
1230b57cec5SDimitry Andric 
124*480093f4SDimitry Andric   /// The MCSubtargetInfo in effect when the instruction was encoded.
125*480093f4SDimitry Andric   /// It must be non-null for instructions.
1260b57cec5SDimitry Andric   const MCSubtargetInfo *STI = nullptr;
1270b57cec5SDimitry Andric 
1280b57cec5SDimitry Andric public:
1290b57cec5SDimitry Andric   static bool classof(const MCFragment *F) {
1300b57cec5SDimitry Andric     MCFragment::FragmentType Kind = F->getKind();
1310b57cec5SDimitry Andric     switch (Kind) {
1320b57cec5SDimitry Andric     default:
1330b57cec5SDimitry Andric       return false;
1340b57cec5SDimitry Andric     case MCFragment::FT_Relaxable:
1350b57cec5SDimitry Andric     case MCFragment::FT_CompactEncodedInst:
1360b57cec5SDimitry Andric     case MCFragment::FT_Data:
1370b57cec5SDimitry Andric     case MCFragment::FT_Dwarf:
1380b57cec5SDimitry Andric     case MCFragment::FT_DwarfFrame:
1390b57cec5SDimitry Andric       return true;
1400b57cec5SDimitry Andric     }
1410b57cec5SDimitry Andric   }
1420b57cec5SDimitry Andric 
1430b57cec5SDimitry Andric   /// Should this fragment be placed at the end of an aligned bundle?
1440b57cec5SDimitry Andric   bool alignToBundleEnd() const { return AlignToBundleEnd; }
1450b57cec5SDimitry Andric   void setAlignToBundleEnd(bool V) { AlignToBundleEnd = V; }
1460b57cec5SDimitry Andric 
1470b57cec5SDimitry Andric   /// Get the padding size that must be inserted before this fragment.
1480b57cec5SDimitry Andric   /// Used for bundling. By default, no padding is inserted.
1490b57cec5SDimitry Andric   /// Note that padding size is restricted to 8 bits. This is an optimization
1500b57cec5SDimitry Andric   /// to reduce the amount of space used for each fragment. In practice, larger
1510b57cec5SDimitry Andric   /// padding should never be required.
1520b57cec5SDimitry Andric   uint8_t getBundlePadding() const { return BundlePadding; }
1530b57cec5SDimitry Andric 
1540b57cec5SDimitry Andric   /// Set the padding size for this fragment. By default it's a no-op,
1550b57cec5SDimitry Andric   /// and only some fragments have a meaningful implementation.
1560b57cec5SDimitry Andric   void setBundlePadding(uint8_t N) { BundlePadding = N; }
1570b57cec5SDimitry Andric 
1580b57cec5SDimitry Andric   /// Retrieve the MCSubTargetInfo in effect when the instruction was encoded.
1590b57cec5SDimitry Andric   /// Guaranteed to be non-null if hasInstructions() == true
1600b57cec5SDimitry Andric   const MCSubtargetInfo *getSubtargetInfo() const { return STI; }
1610b57cec5SDimitry Andric 
1620b57cec5SDimitry Andric   /// Record that the fragment contains instructions with the MCSubtargetInfo in
1630b57cec5SDimitry Andric   /// effect when the instruction was encoded.
1640b57cec5SDimitry Andric   void setHasInstructions(const MCSubtargetInfo &STI) {
1650b57cec5SDimitry Andric     HasInstructions = true;
1660b57cec5SDimitry Andric     this->STI = &STI;
1670b57cec5SDimitry Andric   }
1680b57cec5SDimitry Andric };
1690b57cec5SDimitry Andric 
1700b57cec5SDimitry Andric /// Interface implemented by fragments that contain encoded instructions and/or
1710b57cec5SDimitry Andric /// data.
1720b57cec5SDimitry Andric ///
1730b57cec5SDimitry Andric template<unsigned ContentsSize>
1740b57cec5SDimitry Andric class MCEncodedFragmentWithContents : public MCEncodedFragment {
1750b57cec5SDimitry Andric   SmallVector<char, ContentsSize> Contents;
1760b57cec5SDimitry Andric 
1770b57cec5SDimitry Andric protected:
1780b57cec5SDimitry Andric   MCEncodedFragmentWithContents(MCFragment::FragmentType FType,
1790b57cec5SDimitry Andric                                 bool HasInstructions,
1800b57cec5SDimitry Andric                                 MCSection *Sec)
1810b57cec5SDimitry Andric       : MCEncodedFragment(FType, HasInstructions, Sec) {}
1820b57cec5SDimitry Andric 
1830b57cec5SDimitry Andric public:
1840b57cec5SDimitry Andric   SmallVectorImpl<char> &getContents() { return Contents; }
1850b57cec5SDimitry Andric   const SmallVectorImpl<char> &getContents() const { return Contents; }
1860b57cec5SDimitry Andric };
1870b57cec5SDimitry Andric 
1880b57cec5SDimitry Andric /// Interface implemented by fragments that contain encoded instructions and/or
1890b57cec5SDimitry Andric /// data and also have fixups registered.
1900b57cec5SDimitry Andric ///
1910b57cec5SDimitry Andric template<unsigned ContentsSize, unsigned FixupsSize>
1920b57cec5SDimitry Andric class MCEncodedFragmentWithFixups :
1930b57cec5SDimitry Andric   public MCEncodedFragmentWithContents<ContentsSize> {
1940b57cec5SDimitry Andric 
195*480093f4SDimitry Andric   /// The list of fixups in this fragment.
1960b57cec5SDimitry Andric   SmallVector<MCFixup, FixupsSize> Fixups;
1970b57cec5SDimitry Andric 
1980b57cec5SDimitry Andric protected:
1990b57cec5SDimitry Andric   MCEncodedFragmentWithFixups(MCFragment::FragmentType FType,
2000b57cec5SDimitry Andric                               bool HasInstructions,
2010b57cec5SDimitry Andric                               MCSection *Sec)
2020b57cec5SDimitry Andric       : MCEncodedFragmentWithContents<ContentsSize>(FType, HasInstructions,
2030b57cec5SDimitry Andric                                                     Sec) {}
2040b57cec5SDimitry Andric 
2050b57cec5SDimitry Andric public:
2060b57cec5SDimitry Andric 
2070b57cec5SDimitry Andric   using const_fixup_iterator = SmallVectorImpl<MCFixup>::const_iterator;
2080b57cec5SDimitry Andric   using fixup_iterator = SmallVectorImpl<MCFixup>::iterator;
2090b57cec5SDimitry Andric 
2100b57cec5SDimitry Andric   SmallVectorImpl<MCFixup> &getFixups() { return Fixups; }
2110b57cec5SDimitry Andric   const SmallVectorImpl<MCFixup> &getFixups() const { return Fixups; }
2120b57cec5SDimitry Andric 
2130b57cec5SDimitry Andric   fixup_iterator fixup_begin() { return Fixups.begin(); }
2140b57cec5SDimitry Andric   const_fixup_iterator fixup_begin() const { return Fixups.begin(); }
2150b57cec5SDimitry Andric 
2160b57cec5SDimitry Andric   fixup_iterator fixup_end() { return Fixups.end(); }
2170b57cec5SDimitry Andric   const_fixup_iterator fixup_end() const { return Fixups.end(); }
2180b57cec5SDimitry Andric 
2190b57cec5SDimitry Andric   static bool classof(const MCFragment *F) {
2200b57cec5SDimitry Andric     MCFragment::FragmentType Kind = F->getKind();
2210b57cec5SDimitry Andric     return Kind == MCFragment::FT_Relaxable || Kind == MCFragment::FT_Data ||
2220b57cec5SDimitry Andric            Kind == MCFragment::FT_CVDefRange || Kind == MCFragment::FT_Dwarf ||
2230b57cec5SDimitry Andric            Kind == MCFragment::FT_DwarfFrame;
2240b57cec5SDimitry Andric   }
2250b57cec5SDimitry Andric };
2260b57cec5SDimitry Andric 
2270b57cec5SDimitry Andric /// Fragment for data and encoded instructions.
2280b57cec5SDimitry Andric ///
2290b57cec5SDimitry Andric class MCDataFragment : public MCEncodedFragmentWithFixups<32, 4> {
2300b57cec5SDimitry Andric public:
2310b57cec5SDimitry Andric   MCDataFragment(MCSection *Sec = nullptr)
2320b57cec5SDimitry Andric       : MCEncodedFragmentWithFixups<32, 4>(FT_Data, false, Sec) {}
2330b57cec5SDimitry Andric 
2340b57cec5SDimitry Andric   static bool classof(const MCFragment *F) {
2350b57cec5SDimitry Andric     return F->getKind() == MCFragment::FT_Data;
2360b57cec5SDimitry Andric   }
2370b57cec5SDimitry Andric };
2380b57cec5SDimitry Andric 
2390b57cec5SDimitry Andric /// This is a compact (memory-size-wise) fragment for holding an encoded
2400b57cec5SDimitry Andric /// instruction (non-relaxable) that has no fixups registered. When applicable,
2410b57cec5SDimitry Andric /// it can be used instead of MCDataFragment and lead to lower memory
2420b57cec5SDimitry Andric /// consumption.
2430b57cec5SDimitry Andric ///
2440b57cec5SDimitry Andric class MCCompactEncodedInstFragment : public MCEncodedFragmentWithContents<4> {
2450b57cec5SDimitry Andric public:
2460b57cec5SDimitry Andric   MCCompactEncodedInstFragment(MCSection *Sec = nullptr)
2470b57cec5SDimitry Andric       : MCEncodedFragmentWithContents(FT_CompactEncodedInst, true, Sec) {
2480b57cec5SDimitry Andric   }
2490b57cec5SDimitry Andric 
2500b57cec5SDimitry Andric   static bool classof(const MCFragment *F) {
2510b57cec5SDimitry Andric     return F->getKind() == MCFragment::FT_CompactEncodedInst;
2520b57cec5SDimitry Andric   }
2530b57cec5SDimitry Andric };
2540b57cec5SDimitry Andric 
2550b57cec5SDimitry Andric /// A relaxable fragment holds on to its MCInst, since it may need to be
2560b57cec5SDimitry Andric /// relaxed during the assembler layout and relaxation stage.
2570b57cec5SDimitry Andric ///
2580b57cec5SDimitry Andric class MCRelaxableFragment : public MCEncodedFragmentWithFixups<8, 1> {
2590b57cec5SDimitry Andric 
260*480093f4SDimitry Andric   /// The instruction this is a fragment for.
2610b57cec5SDimitry Andric   MCInst Inst;
2620b57cec5SDimitry Andric 
2630b57cec5SDimitry Andric public:
2640b57cec5SDimitry Andric   MCRelaxableFragment(const MCInst &Inst, const MCSubtargetInfo &STI,
2650b57cec5SDimitry Andric                       MCSection *Sec = nullptr)
2660b57cec5SDimitry Andric       : MCEncodedFragmentWithFixups(FT_Relaxable, true, Sec),
2670b57cec5SDimitry Andric         Inst(Inst) { this->STI = &STI; }
2680b57cec5SDimitry Andric 
2690b57cec5SDimitry Andric   const MCInst &getInst() const { return Inst; }
2700b57cec5SDimitry Andric   void setInst(const MCInst &Value) { Inst = Value; }
2710b57cec5SDimitry Andric 
2720b57cec5SDimitry Andric   static bool classof(const MCFragment *F) {
2730b57cec5SDimitry Andric     return F->getKind() == MCFragment::FT_Relaxable;
2740b57cec5SDimitry Andric   }
2750b57cec5SDimitry Andric };
2760b57cec5SDimitry Andric 
2770b57cec5SDimitry Andric class MCAlignFragment : public MCFragment {
278*480093f4SDimitry Andric   /// The alignment to ensure, in bytes.
2790b57cec5SDimitry Andric   unsigned Alignment;
2800b57cec5SDimitry Andric 
281*480093f4SDimitry Andric   /// Flag to indicate that (optimal) NOPs should be emitted instead
2820b57cec5SDimitry Andric   /// of using the provided value. The exact interpretation of this flag is
2830b57cec5SDimitry Andric   /// target dependent.
2840b57cec5SDimitry Andric   bool EmitNops : 1;
2850b57cec5SDimitry Andric 
286*480093f4SDimitry Andric   /// Value to use for filling padding bytes.
2870b57cec5SDimitry Andric   int64_t Value;
2880b57cec5SDimitry Andric 
289*480093f4SDimitry Andric   /// The size of the integer (in bytes) of \p Value.
2900b57cec5SDimitry Andric   unsigned ValueSize;
2910b57cec5SDimitry Andric 
292*480093f4SDimitry Andric   /// The maximum number of bytes to emit; if the alignment
2930b57cec5SDimitry Andric   /// cannot be satisfied in this width then this fragment is ignored.
2940b57cec5SDimitry Andric   unsigned MaxBytesToEmit;
2950b57cec5SDimitry Andric 
2960b57cec5SDimitry Andric public:
2970b57cec5SDimitry Andric   MCAlignFragment(unsigned Alignment, int64_t Value, unsigned ValueSize,
2980b57cec5SDimitry Andric                   unsigned MaxBytesToEmit, MCSection *Sec = nullptr)
2990b57cec5SDimitry Andric       : MCFragment(FT_Align, false, Sec), Alignment(Alignment), EmitNops(false),
3000b57cec5SDimitry Andric         Value(Value), ValueSize(ValueSize), MaxBytesToEmit(MaxBytesToEmit) {}
3010b57cec5SDimitry Andric 
3020b57cec5SDimitry Andric   unsigned getAlignment() const { return Alignment; }
3030b57cec5SDimitry Andric 
3040b57cec5SDimitry Andric   int64_t getValue() const { return Value; }
3050b57cec5SDimitry Andric 
3060b57cec5SDimitry Andric   unsigned getValueSize() const { return ValueSize; }
3070b57cec5SDimitry Andric 
3080b57cec5SDimitry Andric   unsigned getMaxBytesToEmit() const { return MaxBytesToEmit; }
3090b57cec5SDimitry Andric 
3100b57cec5SDimitry Andric   bool hasEmitNops() const { return EmitNops; }
3110b57cec5SDimitry Andric   void setEmitNops(bool Value) { EmitNops = Value; }
3120b57cec5SDimitry Andric 
3130b57cec5SDimitry Andric   static bool classof(const MCFragment *F) {
3140b57cec5SDimitry Andric     return F->getKind() == MCFragment::FT_Align;
3150b57cec5SDimitry Andric   }
3160b57cec5SDimitry Andric };
3170b57cec5SDimitry Andric 
3180b57cec5SDimitry Andric class MCFillFragment : public MCFragment {
319*480093f4SDimitry Andric   uint8_t ValueSize;
3200b57cec5SDimitry Andric   /// Value to use for filling bytes.
3210b57cec5SDimitry Andric   uint64_t Value;
3220b57cec5SDimitry Andric   /// The number of bytes to insert.
3230b57cec5SDimitry Andric   const MCExpr &NumValues;
3240b57cec5SDimitry Andric 
3250b57cec5SDimitry Andric   /// Source location of the directive that this fragment was created for.
3260b57cec5SDimitry Andric   SMLoc Loc;
3270b57cec5SDimitry Andric 
3280b57cec5SDimitry Andric public:
3290b57cec5SDimitry Andric   MCFillFragment(uint64_t Value, uint8_t VSize, const MCExpr &NumValues,
3300b57cec5SDimitry Andric                  SMLoc Loc, MCSection *Sec = nullptr)
331*480093f4SDimitry Andric       : MCFragment(FT_Fill, false, Sec), ValueSize(VSize), Value(Value),
3320b57cec5SDimitry Andric         NumValues(NumValues), Loc(Loc) {}
3330b57cec5SDimitry Andric 
3340b57cec5SDimitry Andric   uint64_t getValue() const { return Value; }
3350b57cec5SDimitry Andric   uint8_t getValueSize() const { return ValueSize; }
3360b57cec5SDimitry Andric   const MCExpr &getNumValues() const { return NumValues; }
3370b57cec5SDimitry Andric 
3380b57cec5SDimitry Andric   SMLoc getLoc() const { return Loc; }
3390b57cec5SDimitry Andric 
3400b57cec5SDimitry Andric   static bool classof(const MCFragment *F) {
3410b57cec5SDimitry Andric     return F->getKind() == MCFragment::FT_Fill;
3420b57cec5SDimitry Andric   }
3430b57cec5SDimitry Andric };
3440b57cec5SDimitry Andric 
3450b57cec5SDimitry Andric class MCOrgFragment : public MCFragment {
3460b57cec5SDimitry Andric   /// Value to use for filling bytes.
3470b57cec5SDimitry Andric   int8_t Value;
3480b57cec5SDimitry Andric 
349*480093f4SDimitry Andric   /// The offset this fragment should start at.
350*480093f4SDimitry Andric   const MCExpr *Offset;
351*480093f4SDimitry Andric 
3520b57cec5SDimitry Andric   /// Source location of the directive that this fragment was created for.
3530b57cec5SDimitry Andric   SMLoc Loc;
3540b57cec5SDimitry Andric 
3550b57cec5SDimitry Andric public:
3560b57cec5SDimitry Andric   MCOrgFragment(const MCExpr &Offset, int8_t Value, SMLoc Loc,
3570b57cec5SDimitry Andric                 MCSection *Sec = nullptr)
358*480093f4SDimitry Andric       : MCFragment(FT_Org, false, Sec), Value(Value), Offset(&Offset),
359*480093f4SDimitry Andric         Loc(Loc) {}
3600b57cec5SDimitry Andric 
3610b57cec5SDimitry Andric   const MCExpr &getOffset() const { return *Offset; }
3620b57cec5SDimitry Andric 
3630b57cec5SDimitry Andric   uint8_t getValue() const { return Value; }
3640b57cec5SDimitry Andric 
3650b57cec5SDimitry Andric   SMLoc getLoc() const { return Loc; }
3660b57cec5SDimitry Andric 
3670b57cec5SDimitry Andric   static bool classof(const MCFragment *F) {
3680b57cec5SDimitry Andric     return F->getKind() == MCFragment::FT_Org;
3690b57cec5SDimitry Andric   }
3700b57cec5SDimitry Andric };
3710b57cec5SDimitry Andric 
3720b57cec5SDimitry Andric class MCLEBFragment : public MCFragment {
373*480093f4SDimitry Andric   /// True if this is a sleb128, false if uleb128.
3740b57cec5SDimitry Andric   bool IsSigned;
3750b57cec5SDimitry Andric 
376*480093f4SDimitry Andric   /// The value this fragment should contain.
377*480093f4SDimitry Andric   const MCExpr *Value;
378*480093f4SDimitry Andric 
3790b57cec5SDimitry Andric   SmallString<8> Contents;
3800b57cec5SDimitry Andric 
3810b57cec5SDimitry Andric public:
3820b57cec5SDimitry Andric   MCLEBFragment(const MCExpr &Value_, bool IsSigned_, MCSection *Sec = nullptr)
383*480093f4SDimitry Andric       : MCFragment(FT_LEB, false, Sec), IsSigned(IsSigned_), Value(&Value_) {
3840b57cec5SDimitry Andric     Contents.push_back(0);
3850b57cec5SDimitry Andric   }
3860b57cec5SDimitry Andric 
3870b57cec5SDimitry Andric   const MCExpr &getValue() const { return *Value; }
3880b57cec5SDimitry Andric 
3890b57cec5SDimitry Andric   bool isSigned() const { return IsSigned; }
3900b57cec5SDimitry Andric 
3910b57cec5SDimitry Andric   SmallString<8> &getContents() { return Contents; }
3920b57cec5SDimitry Andric   const SmallString<8> &getContents() const { return Contents; }
3930b57cec5SDimitry Andric 
3940b57cec5SDimitry Andric   /// @}
3950b57cec5SDimitry Andric 
3960b57cec5SDimitry Andric   static bool classof(const MCFragment *F) {
3970b57cec5SDimitry Andric     return F->getKind() == MCFragment::FT_LEB;
3980b57cec5SDimitry Andric   }
3990b57cec5SDimitry Andric };
4000b57cec5SDimitry Andric 
4010b57cec5SDimitry Andric class MCDwarfLineAddrFragment : public MCEncodedFragmentWithFixups<8, 1> {
402*480093f4SDimitry Andric   /// The value of the difference between the two line numbers
4030b57cec5SDimitry Andric   /// between two .loc dwarf directives.
4040b57cec5SDimitry Andric   int64_t LineDelta;
4050b57cec5SDimitry Andric 
406*480093f4SDimitry Andric   /// The expression for the difference of the two symbols that
4070b57cec5SDimitry Andric   /// make up the address delta between two .loc dwarf directives.
4080b57cec5SDimitry Andric   const MCExpr *AddrDelta;
4090b57cec5SDimitry Andric 
4100b57cec5SDimitry Andric public:
4110b57cec5SDimitry Andric   MCDwarfLineAddrFragment(int64_t LineDelta, const MCExpr &AddrDelta,
4120b57cec5SDimitry Andric                           MCSection *Sec = nullptr)
4130b57cec5SDimitry Andric       : MCEncodedFragmentWithFixups<8, 1>(FT_Dwarf, false, Sec),
4140b57cec5SDimitry Andric         LineDelta(LineDelta), AddrDelta(&AddrDelta) {}
4150b57cec5SDimitry Andric 
4160b57cec5SDimitry Andric   int64_t getLineDelta() const { return LineDelta; }
4170b57cec5SDimitry Andric 
4180b57cec5SDimitry Andric   const MCExpr &getAddrDelta() const { return *AddrDelta; }
4190b57cec5SDimitry Andric 
4200b57cec5SDimitry Andric   static bool classof(const MCFragment *F) {
4210b57cec5SDimitry Andric     return F->getKind() == MCFragment::FT_Dwarf;
4220b57cec5SDimitry Andric   }
4230b57cec5SDimitry Andric };
4240b57cec5SDimitry Andric 
4250b57cec5SDimitry Andric class MCDwarfCallFrameFragment : public MCEncodedFragmentWithFixups<8, 1> {
426*480093f4SDimitry Andric   /// The expression for the difference of the two symbols that
4270b57cec5SDimitry Andric   /// make up the address delta between two .cfi_* dwarf directives.
4280b57cec5SDimitry Andric   const MCExpr *AddrDelta;
4290b57cec5SDimitry Andric 
4300b57cec5SDimitry Andric public:
4310b57cec5SDimitry Andric   MCDwarfCallFrameFragment(const MCExpr &AddrDelta, MCSection *Sec = nullptr)
4320b57cec5SDimitry Andric       : MCEncodedFragmentWithFixups<8, 1>(FT_DwarfFrame, false, Sec),
4330b57cec5SDimitry Andric         AddrDelta(&AddrDelta) {}
4340b57cec5SDimitry Andric 
4350b57cec5SDimitry Andric   const MCExpr &getAddrDelta() const { return *AddrDelta; }
4360b57cec5SDimitry Andric 
4370b57cec5SDimitry Andric   static bool classof(const MCFragment *F) {
4380b57cec5SDimitry Andric     return F->getKind() == MCFragment::FT_DwarfFrame;
4390b57cec5SDimitry Andric   }
4400b57cec5SDimitry Andric };
4410b57cec5SDimitry Andric 
4420b57cec5SDimitry Andric /// Represents a symbol table index fragment.
4430b57cec5SDimitry Andric class MCSymbolIdFragment : public MCFragment {
4440b57cec5SDimitry Andric   const MCSymbol *Sym;
4450b57cec5SDimitry Andric 
4460b57cec5SDimitry Andric public:
4470b57cec5SDimitry Andric   MCSymbolIdFragment(const MCSymbol *Sym, MCSection *Sec = nullptr)
4480b57cec5SDimitry Andric       : MCFragment(FT_SymbolId, false, Sec), Sym(Sym) {}
4490b57cec5SDimitry Andric 
4500b57cec5SDimitry Andric   const MCSymbol *getSymbol() { return Sym; }
4510b57cec5SDimitry Andric   const MCSymbol *getSymbol() const { return Sym; }
4520b57cec5SDimitry Andric 
4530b57cec5SDimitry Andric   static bool classof(const MCFragment *F) {
4540b57cec5SDimitry Andric     return F->getKind() == MCFragment::FT_SymbolId;
4550b57cec5SDimitry Andric   }
4560b57cec5SDimitry Andric };
4570b57cec5SDimitry Andric 
4580b57cec5SDimitry Andric /// Fragment representing the binary annotations produced by the
4590b57cec5SDimitry Andric /// .cv_inline_linetable directive.
4600b57cec5SDimitry Andric class MCCVInlineLineTableFragment : public MCFragment {
4610b57cec5SDimitry Andric   unsigned SiteFuncId;
4620b57cec5SDimitry Andric   unsigned StartFileId;
4630b57cec5SDimitry Andric   unsigned StartLineNum;
4640b57cec5SDimitry Andric   const MCSymbol *FnStartSym;
4650b57cec5SDimitry Andric   const MCSymbol *FnEndSym;
4660b57cec5SDimitry Andric   SmallString<8> Contents;
4670b57cec5SDimitry Andric 
4680b57cec5SDimitry Andric   /// CodeViewContext has the real knowledge about this format, so let it access
4690b57cec5SDimitry Andric   /// our members.
4700b57cec5SDimitry Andric   friend class CodeViewContext;
4710b57cec5SDimitry Andric 
4720b57cec5SDimitry Andric public:
4730b57cec5SDimitry Andric   MCCVInlineLineTableFragment(unsigned SiteFuncId, unsigned StartFileId,
4740b57cec5SDimitry Andric                               unsigned StartLineNum, const MCSymbol *FnStartSym,
4750b57cec5SDimitry Andric                               const MCSymbol *FnEndSym,
4760b57cec5SDimitry Andric                               MCSection *Sec = nullptr)
4770b57cec5SDimitry Andric       : MCFragment(FT_CVInlineLines, false, Sec), SiteFuncId(SiteFuncId),
4780b57cec5SDimitry Andric         StartFileId(StartFileId), StartLineNum(StartLineNum),
4790b57cec5SDimitry Andric         FnStartSym(FnStartSym), FnEndSym(FnEndSym) {}
4800b57cec5SDimitry Andric 
4810b57cec5SDimitry Andric   const MCSymbol *getFnStartSym() const { return FnStartSym; }
4820b57cec5SDimitry Andric   const MCSymbol *getFnEndSym() const { return FnEndSym; }
4830b57cec5SDimitry Andric 
4840b57cec5SDimitry Andric   SmallString<8> &getContents() { return Contents; }
4850b57cec5SDimitry Andric   const SmallString<8> &getContents() const { return Contents; }
4860b57cec5SDimitry Andric 
4870b57cec5SDimitry Andric   static bool classof(const MCFragment *F) {
4880b57cec5SDimitry Andric     return F->getKind() == MCFragment::FT_CVInlineLines;
4890b57cec5SDimitry Andric   }
4900b57cec5SDimitry Andric };
4910b57cec5SDimitry Andric 
4920b57cec5SDimitry Andric /// Fragment representing the .cv_def_range directive.
4930b57cec5SDimitry Andric class MCCVDefRangeFragment : public MCEncodedFragmentWithFixups<32, 4> {
4940b57cec5SDimitry Andric   SmallVector<std::pair<const MCSymbol *, const MCSymbol *>, 2> Ranges;
4950b57cec5SDimitry Andric   SmallString<32> FixedSizePortion;
4960b57cec5SDimitry Andric 
4970b57cec5SDimitry Andric   /// CodeViewContext has the real knowledge about this format, so let it access
4980b57cec5SDimitry Andric   /// our members.
4990b57cec5SDimitry Andric   friend class CodeViewContext;
5000b57cec5SDimitry Andric 
5010b57cec5SDimitry Andric public:
5020b57cec5SDimitry Andric   MCCVDefRangeFragment(
5030b57cec5SDimitry Andric       ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
5040b57cec5SDimitry Andric       StringRef FixedSizePortion, MCSection *Sec = nullptr)
5050b57cec5SDimitry Andric       : MCEncodedFragmentWithFixups<32, 4>(FT_CVDefRange, false, Sec),
5060b57cec5SDimitry Andric         Ranges(Ranges.begin(), Ranges.end()),
5070b57cec5SDimitry Andric         FixedSizePortion(FixedSizePortion) {}
5080b57cec5SDimitry Andric 
5090b57cec5SDimitry Andric   ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> getRanges() const {
5100b57cec5SDimitry Andric     return Ranges;
5110b57cec5SDimitry Andric   }
5120b57cec5SDimitry Andric 
5130b57cec5SDimitry Andric   StringRef getFixedSizePortion() const { return FixedSizePortion; }
5140b57cec5SDimitry Andric 
5150b57cec5SDimitry Andric   static bool classof(const MCFragment *F) {
5160b57cec5SDimitry Andric     return F->getKind() == MCFragment::FT_CVDefRange;
5170b57cec5SDimitry Andric   }
5180b57cec5SDimitry Andric };
5190b57cec5SDimitry Andric 
520*480093f4SDimitry Andric /// Represents required padding such that a particular other set of fragments
521*480093f4SDimitry Andric /// does not cross a particular power-of-two boundary. The other fragments must
522*480093f4SDimitry Andric /// follow this one within the same section.
523*480093f4SDimitry Andric class MCBoundaryAlignFragment : public MCFragment {
524*480093f4SDimitry Andric   /// The alignment requirement of the branch to be aligned.
525*480093f4SDimitry Andric   Align AlignBoundary;
526*480093f4SDimitry Andric   /// Flag to indicate whether the branch is fused.  Use in determining the
527*480093f4SDimitry Andric   /// region of fragments being aligned.
528*480093f4SDimitry Andric   bool Fused : 1;
529*480093f4SDimitry Andric   /// Flag to indicate whether NOPs should be emitted.
530*480093f4SDimitry Andric   bool EmitNops : 1;
531*480093f4SDimitry Andric   /// The size of the fragment.  The size is lazily set during relaxation, and
532*480093f4SDimitry Andric   /// is not meaningful before that.
533*480093f4SDimitry Andric   uint64_t Size = 0;
534*480093f4SDimitry Andric 
535*480093f4SDimitry Andric public:
536*480093f4SDimitry Andric   MCBoundaryAlignFragment(Align AlignBoundary, bool Fused = false,
537*480093f4SDimitry Andric                           bool EmitNops = false, MCSection *Sec = nullptr)
538*480093f4SDimitry Andric       : MCFragment(FT_BoundaryAlign, false, Sec), AlignBoundary(AlignBoundary),
539*480093f4SDimitry Andric         Fused(Fused), EmitNops(EmitNops) {}
540*480093f4SDimitry Andric 
541*480093f4SDimitry Andric   uint64_t getSize() const { return Size; }
542*480093f4SDimitry Andric   void setSize(uint64_t Value) { Size = Value; }
543*480093f4SDimitry Andric 
544*480093f4SDimitry Andric   Align getAlignment() const { return AlignBoundary; }
545*480093f4SDimitry Andric 
546*480093f4SDimitry Andric   bool isFused() const { return Fused; }
547*480093f4SDimitry Andric   void setFused(bool Value) { Fused = Value; }
548*480093f4SDimitry Andric 
549*480093f4SDimitry Andric   bool canEmitNops() const { return EmitNops; }
550*480093f4SDimitry Andric   void setEmitNops(bool Value) { EmitNops = Value; }
551*480093f4SDimitry Andric 
552*480093f4SDimitry Andric   static bool classof(const MCFragment *F) {
553*480093f4SDimitry Andric     return F->getKind() == MCFragment::FT_BoundaryAlign;
554*480093f4SDimitry Andric   }
555*480093f4SDimitry Andric };
5560b57cec5SDimitry Andric } // end namespace llvm
5570b57cec5SDimitry Andric 
5580b57cec5SDimitry Andric #endif // LLVM_MC_MCFRAGMENT_H
559