diff options
Diffstat (limited to 'include/llvm/MC/MCAssembler.h')
-rw-r--r-- | include/llvm/MC/MCAssembler.h | 512 |
1 files changed, 21 insertions, 491 deletions
diff --git a/include/llvm/MC/MCAssembler.h b/include/llvm/MC/MCAssembler.h index 0642af837e7e..c0bd12875839 100644 --- a/include/llvm/MC/MCAssembler.h +++ b/include/llvm/MC/MCAssembler.h @@ -10,23 +10,18 @@ #ifndef LLVM_MC_MCASSEMBLER_H #define LLVM_MC_MCASSEMBLER_H -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/SmallPtrSet.h" -#include "llvm/ADT/SmallString.h" #include "llvm/ADT/ilist.h" #include "llvm/ADT/ilist_node.h" #include "llvm/ADT/iterator.h" #include "llvm/MC/MCDirectives.h" +#include "llvm/MC/MCDwarf.h" #include "llvm/MC/MCFixup.h" +#include "llvm/MC/MCFragment.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCLinkerOptimizationHint.h" -#include "llvm/MC/MCSection.h" #include "llvm/MC/MCSubtargetInfo.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/DataTypes.h" -#include <algorithm> -#include <vector> // FIXME: Shouldn't be needed. +#include "llvm/MC/MCSymbol.h" namespace llvm { class raw_ostream; @@ -42,476 +37,6 @@ class MCSubtargetInfo; class MCValue; class MCAsmBackend; -class MCFragment : public ilist_node<MCFragment> { - friend class MCAsmLayout; - - MCFragment(const MCFragment &) = delete; - void operator=(const MCFragment &) = delete; - -public: - enum FragmentType : uint8_t { - FT_Align, - FT_Data, - FT_CompactEncodedInst, - FT_Fill, - FT_Relaxable, - FT_Org, - FT_Dwarf, - FT_DwarfFrame, - FT_LEB, - FT_SafeSEH - }; - -private: - FragmentType Kind; - -protected: - bool HasInstructions; - -private: - /// \brief Should this fragment be aligned to the end of a bundle? - bool AlignToBundleEnd; - - uint8_t BundlePadding; - - /// LayoutOrder - The layout order of this fragment. - unsigned LayoutOrder; - - /// The data for the section this fragment is in. - MCSection *Parent; - - /// Atom - The atom this fragment is in, as represented by it's defining - /// symbol. - const MCSymbol *Atom; - - /// \name Assembler Backend Data - /// @{ - // - // FIXME: This could all be kept private to the assembler implementation. - - /// Offset - The offset of this fragment in its section. This is ~0 until - /// initialized. - uint64_t Offset; - - /// @} - -protected: - MCFragment(FragmentType Kind, bool HasInstructions, - uint8_t BundlePadding, MCSection *Parent = nullptr); - - ~MCFragment(); -private: - - // This is a friend so that the sentinal can be created. - friend struct ilist_sentinel_traits<MCFragment>; - MCFragment(); - -public: - /// Destroys the current fragment. - /// - /// This must be used instead of delete as MCFragment is non-virtual. - /// This method will dispatch to the appropriate subclass. - void destroy(); - - FragmentType getKind() const { return Kind; } - - MCSection *getParent() const { return Parent; } - void setParent(MCSection *Value) { Parent = Value; } - - const MCSymbol *getAtom() const { return Atom; } - void setAtom(const MCSymbol *Value) { Atom = Value; } - - unsigned getLayoutOrder() const { return LayoutOrder; } - void setLayoutOrder(unsigned Value) { LayoutOrder = Value; } - - /// \brief Does this fragment have instructions emitted into it? By default - /// this is false, but specific fragment types may set it to true. - bool hasInstructions() const { return HasInstructions; } - - /// \brief Should this fragment be placed at the end of an aligned bundle? - bool alignToBundleEnd() const { return AlignToBundleEnd; } - void setAlignToBundleEnd(bool V) { AlignToBundleEnd = V; } - - /// \brief Get the padding size that must be inserted before this fragment. - /// Used for bundling. By default, no padding is inserted. - /// Note that padding size is restricted to 8 bits. This is an optimization - /// to reduce the amount of space used for each fragment. In practice, larger - /// padding should never be required. - uint8_t getBundlePadding() const { return BundlePadding; } - - /// \brief Set the padding size for this fragment. By default it's a no-op, - /// and only some fragments have a meaningful implementation. - void setBundlePadding(uint8_t N) { BundlePadding = N; } - - void dump(); -}; - -/// Interface implemented by fragments that contain encoded instructions and/or -/// data. -/// -class MCEncodedFragment : public MCFragment { -protected: - MCEncodedFragment(MCFragment::FragmentType FType, bool HasInstructions, - MCSection *Sec) - : MCFragment(FType, HasInstructions, 0, Sec) {} - -public: - static bool classof(const MCFragment *F) { - MCFragment::FragmentType Kind = F->getKind(); - switch (Kind) { - default: - return false; - case MCFragment::FT_Relaxable: - case MCFragment::FT_CompactEncodedInst: - case MCFragment::FT_Data: - return true; - } - } -}; - -/// Interface implemented by fragments that contain encoded instructions and/or -/// data. -/// -template<unsigned ContentsSize> -class MCEncodedFragmentWithContents : public MCEncodedFragment { - SmallVector<char, ContentsSize> Contents; - -protected: - MCEncodedFragmentWithContents(MCFragment::FragmentType FType, - bool HasInstructions, - MCSection *Sec) - : MCEncodedFragment(FType, HasInstructions, Sec) {} - -public: - SmallVectorImpl<char> &getContents() { return Contents; } - const SmallVectorImpl<char> &getContents() const { return Contents; } -}; - -/// Interface implemented by fragments that contain encoded instructions and/or -/// data and also have fixups registered. -/// -template<unsigned ContentsSize, unsigned FixupsSize> -class MCEncodedFragmentWithFixups : - public MCEncodedFragmentWithContents<ContentsSize> { - - /// Fixups - The list of fixups in this fragment. - SmallVector<MCFixup, FixupsSize> Fixups; - -protected: - MCEncodedFragmentWithFixups(MCFragment::FragmentType FType, - bool HasInstructions, - MCSection *Sec) - : MCEncodedFragmentWithContents<ContentsSize>(FType, HasInstructions, - Sec) {} - -public: - typedef SmallVectorImpl<MCFixup>::const_iterator const_fixup_iterator; - typedef SmallVectorImpl<MCFixup>::iterator fixup_iterator; - - SmallVectorImpl<MCFixup> &getFixups() { return Fixups; } - const SmallVectorImpl<MCFixup> &getFixups() const { return Fixups; } - - fixup_iterator fixup_begin() { return Fixups.begin(); } - const_fixup_iterator fixup_begin() const { return Fixups.begin(); } - - fixup_iterator fixup_end() { return Fixups.end(); } - const_fixup_iterator fixup_end() const { return Fixups.end(); } - - static bool classof(const MCFragment *F) { - MCFragment::FragmentType Kind = F->getKind(); - return Kind == MCFragment::FT_Relaxable || Kind == MCFragment::FT_Data; - } -}; - -/// Fragment for data and encoded instructions. -/// -class MCDataFragment : public MCEncodedFragmentWithFixups<32, 4> { -public: - MCDataFragment(MCSection *Sec = nullptr) - : MCEncodedFragmentWithFixups<32, 4>(FT_Data, false, Sec) {} - - void setHasInstructions(bool V) { HasInstructions = V; } - - static bool classof(const MCFragment *F) { - return F->getKind() == MCFragment::FT_Data; - } -}; - -/// This is a compact (memory-size-wise) fragment for holding an encoded -/// instruction (non-relaxable) that has no fixups registered. When applicable, -/// it can be used instead of MCDataFragment and lead to lower memory -/// consumption. -/// -class MCCompactEncodedInstFragment : public MCEncodedFragmentWithContents<4> { -public: - MCCompactEncodedInstFragment(MCSection *Sec = nullptr) - : MCEncodedFragmentWithContents(FT_CompactEncodedInst, true, Sec) { - } - - static bool classof(const MCFragment *F) { - return F->getKind() == MCFragment::FT_CompactEncodedInst; - } -}; - -/// A relaxable fragment holds on to its MCInst, since it may need to be -/// relaxed during the assembler layout and relaxation stage. -/// -class MCRelaxableFragment : public MCEncodedFragmentWithFixups<8, 1> { - - /// Inst - The instruction this is a fragment for. - MCInst Inst; - - /// STI - The MCSubtargetInfo in effect when the instruction was encoded. - /// Keep a copy instead of a reference to make sure that updates to STI - /// in the assembler are not seen here. - const MCSubtargetInfo STI; - -public: - MCRelaxableFragment(const MCInst &Inst, const MCSubtargetInfo &STI, - MCSection *Sec = nullptr) - : MCEncodedFragmentWithFixups(FT_Relaxable, true, Sec), - Inst(Inst), STI(STI) {} - - const MCInst &getInst() const { return Inst; } - void setInst(const MCInst &Value) { Inst = Value; } - - const MCSubtargetInfo &getSubtargetInfo() { return STI; } - - static bool classof(const MCFragment *F) { - return F->getKind() == MCFragment::FT_Relaxable; - } -}; - -class MCAlignFragment : public MCFragment { - - /// Alignment - The alignment to ensure, in bytes. - unsigned Alignment; - - /// EmitNops - Flag to indicate that (optimal) NOPs should be emitted instead - /// of using the provided value. The exact interpretation of this flag is - /// target dependent. - bool EmitNops : 1; - - /// Value - Value to use for filling padding bytes. - int64_t Value; - - /// ValueSize - The size of the integer (in bytes) of \p Value. - unsigned ValueSize; - - /// MaxBytesToEmit - The maximum number of bytes to emit; if the alignment - /// cannot be satisfied in this width then this fragment is ignored. - unsigned MaxBytesToEmit; - -public: - MCAlignFragment(unsigned Alignment, int64_t Value, unsigned ValueSize, - unsigned MaxBytesToEmit, MCSection *Sec = nullptr) - : MCFragment(FT_Align, false, 0, Sec), Alignment(Alignment), - EmitNops(false), Value(Value), - ValueSize(ValueSize), MaxBytesToEmit(MaxBytesToEmit) {} - - /// \name Accessors - /// @{ - - unsigned getAlignment() const { return Alignment; } - - int64_t getValue() const { return Value; } - - unsigned getValueSize() const { return ValueSize; } - - unsigned getMaxBytesToEmit() const { return MaxBytesToEmit; } - - bool hasEmitNops() const { return EmitNops; } - void setEmitNops(bool Value) { EmitNops = Value; } - - /// @} - - static bool classof(const MCFragment *F) { - return F->getKind() == MCFragment::FT_Align; - } -}; - -class MCFillFragment : public MCFragment { - - /// Value - Value to use for filling bytes. - int64_t Value; - - /// ValueSize - The size (in bytes) of \p Value to use when filling, or 0 if - /// this is a virtual fill fragment. - unsigned ValueSize; - - /// Size - The number of bytes to insert. - uint64_t Size; - -public: - MCFillFragment(int64_t Value, unsigned ValueSize, uint64_t Size, - MCSection *Sec = nullptr) - : MCFragment(FT_Fill, false, 0, Sec), Value(Value), ValueSize(ValueSize), - Size(Size) { - assert((!ValueSize || (Size % ValueSize) == 0) && - "Fill size must be a multiple of the value size!"); - } - - /// \name Accessors - /// @{ - - int64_t getValue() const { return Value; } - - unsigned getValueSize() const { return ValueSize; } - - uint64_t getSize() const { return Size; } - - /// @} - - static bool classof(const MCFragment *F) { - return F->getKind() == MCFragment::FT_Fill; - } -}; - -class MCOrgFragment : public MCFragment { - - /// Offset - The offset this fragment should start at. - const MCExpr *Offset; - - /// Value - Value to use for filling bytes. - int8_t Value; - -public: - MCOrgFragment(const MCExpr &Offset, int8_t Value, MCSection *Sec = nullptr) - : MCFragment(FT_Org, false, 0, Sec), Offset(&Offset), Value(Value) {} - - /// \name Accessors - /// @{ - - const MCExpr &getOffset() const { return *Offset; } - - uint8_t getValue() const { return Value; } - - /// @} - - static bool classof(const MCFragment *F) { - return F->getKind() == MCFragment::FT_Org; - } -}; - -class MCLEBFragment : public MCFragment { - - /// Value - The value this fragment should contain. - const MCExpr *Value; - - /// IsSigned - True if this is a sleb128, false if uleb128. - bool IsSigned; - - SmallString<8> Contents; - -public: - MCLEBFragment(const MCExpr &Value_, bool IsSigned_, MCSection *Sec = nullptr) - : MCFragment(FT_LEB, false, 0, Sec), Value(&Value_), IsSigned(IsSigned_) { - Contents.push_back(0); - } - - /// \name Accessors - /// @{ - - const MCExpr &getValue() const { return *Value; } - - bool isSigned() const { return IsSigned; } - - SmallString<8> &getContents() { return Contents; } - const SmallString<8> &getContents() const { return Contents; } - - /// @} - - static bool classof(const MCFragment *F) { - return F->getKind() == MCFragment::FT_LEB; - } -}; - -class MCDwarfLineAddrFragment : public MCFragment { - - /// LineDelta - the value of the difference between the two line numbers - /// between two .loc dwarf directives. - int64_t LineDelta; - - /// AddrDelta - The expression for the difference of the two symbols that - /// make up the address delta between two .loc dwarf directives. - const MCExpr *AddrDelta; - - SmallString<8> Contents; - -public: - MCDwarfLineAddrFragment(int64_t LineDelta, const MCExpr &AddrDelta, - MCSection *Sec = nullptr) - : MCFragment(FT_Dwarf, false, 0, Sec), LineDelta(LineDelta), - AddrDelta(&AddrDelta) { - Contents.push_back(0); - } - - /// \name Accessors - /// @{ - - int64_t getLineDelta() const { return LineDelta; } - - const MCExpr &getAddrDelta() const { return *AddrDelta; } - - SmallString<8> &getContents() { return Contents; } - const SmallString<8> &getContents() const { return Contents; } - - /// @} - - static bool classof(const MCFragment *F) { - return F->getKind() == MCFragment::FT_Dwarf; - } -}; - -class MCDwarfCallFrameFragment : public MCFragment { - - /// AddrDelta - The expression for the difference of the two symbols that - /// make up the address delta between two .cfi_* dwarf directives. - const MCExpr *AddrDelta; - - SmallString<8> Contents; - -public: - MCDwarfCallFrameFragment(const MCExpr &AddrDelta, MCSection *Sec = nullptr) - : MCFragment(FT_DwarfFrame, false, 0, Sec), AddrDelta(&AddrDelta) { - Contents.push_back(0); - } - - /// \name Accessors - /// @{ - - const MCExpr &getAddrDelta() const { return *AddrDelta; } - - SmallString<8> &getContents() { return Contents; } - const SmallString<8> &getContents() const { return Contents; } - - /// @} - - static bool classof(const MCFragment *F) { - return F->getKind() == MCFragment::FT_DwarfFrame; - } -}; - -class MCSafeSEHFragment : public MCFragment { - const MCSymbol *Sym; - -public: - MCSafeSEHFragment(const MCSymbol *Sym, MCSection *Sec = nullptr) - : MCFragment(FT_SafeSEH, false, 0, Sec), Sym(Sym) {} - - /// \name Accessors - /// @{ - - const MCSymbol *getSymbol() { return Sym; } - const MCSymbol *getSymbol() const { return Sym; } - - /// @} - - static bool classof(const MCFragment *F) { - return F->getKind() == MCFragment::FT_SafeSEH; - } -}; - // FIXME: This really doesn't belong here. See comments below. struct IndirectSymbolData { MCSymbol *Symbol; @@ -575,8 +100,6 @@ private: MCObjectWriter &Writer; - raw_ostream &OS; - SectionListType Sections; SymbolDataListType Symbols; @@ -591,6 +114,8 @@ private: /// List of declared file names std::vector<std::string> FileNames; + MCDwarfLineTableParams LTParams; + /// The set of function symbols for which a .thumb_func directive has /// been seen. // @@ -607,6 +132,7 @@ private: unsigned RelaxAll : 1; unsigned SubsectionsViaSymbols : 1; + unsigned IncrementalLinkerCompatible : 1; /// ELF specific e_header flags // It would be good if there were an MCELFAssembler class to hold this. @@ -712,16 +238,13 @@ public: public: /// Construct a new assembler instance. - /// - /// \param OS The stream to output to. // // FIXME: How are we going to parameterize this? Two obvious options are stay // concrete and require clients to pass in a target like object. The other // option is to make this abstract, and have targets provide concrete // implementations as we do with AsmParser. MCAssembler(MCContext &Context_, MCAsmBackend &Backend_, - MCCodeEmitter &Emitter_, MCObjectWriter &Writer_, - raw_ostream &OS); + MCCodeEmitter &Emitter_, MCObjectWriter &Writer_); ~MCAssembler(); /// Reuse an assembler instance @@ -736,15 +259,28 @@ public: MCObjectWriter &getWriter() const { return Writer; } + MCDwarfLineTableParams getDWARFLinetableParams() const { return LTParams; } + void setDWARFLinetableParams(MCDwarfLineTableParams P) { LTParams = P; } + /// Finish - Do final processing and write the object to the output stream. /// \p Writer is used for custom object writer (as the MCJIT does), /// if not specified it is automatically created from backend. void Finish(); + // Layout all section and prepare them for emission. + void layout(MCAsmLayout &Layout); + // FIXME: This does not belong here. bool getSubsectionsViaSymbols() const { return SubsectionsViaSymbols; } void setSubsectionsViaSymbols(bool Value) { SubsectionsViaSymbols = Value; } + bool isIncrementalLinkerCompatible() const { + return IncrementalLinkerCompatible; + } + void setIncrementalLinkerCompatible(bool Value) { + IncrementalLinkerCompatible = Value; + } + bool getRelaxAll() const { return RelaxAll; } void setRelaxAll(bool Value) { RelaxAll = Value; } @@ -856,13 +392,7 @@ public: /// \name Backend Data Access /// @{ - bool registerSection(MCSection &Section) { - if (Section.isRegistered()) - return false; - Sections.push_back(&Section); - Section.setIsRegistered(true); - return true; - } + bool registerSection(MCSection &Section); void registerSymbol(const MCSymbol &Symbol, bool *Created = nullptr); |