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