X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=include%2Fllvm%2FMC%2FMCAssembler.h;h=ffd77c51eb4298d5f0b8a458760d794fa391c98a;hb=1f3e445184e5ca2aa4295c2a77f2a4e0b957fea1;hp=dc3f5c0f5892c80e05f53dc85835e3bb56661f8e;hpb=3f6a960f9c9ad27f2ac573020df414e8b8cdda04;p=oota-llvm.git diff --git a/include/llvm/MC/MCAssembler.h b/include/llvm/MC/MCAssembler.h index dc3f5c0f589..ffd77c51eb4 100644 --- a/include/llvm/MC/MCAssembler.h +++ b/include/llvm/MC/MCAssembler.h @@ -10,19 +10,48 @@ #ifndef LLVM_MC_MCASSEMBLER_H #define LLVM_MC_MCASSEMBLER_H +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/ilist.h" #include "llvm/ADT/ilist_node.h" -#include "llvm/MC/MCValue.h" #include "llvm/Support/Casting.h" -#include "llvm/Support/DataTypes.h" +#include "llvm/MC/MCFixup.h" +#include "llvm/System/DataTypes.h" #include // FIXME: Shouldn't be needed. namespace llvm { class raw_ostream; class MCAssembler; +class MCContext; +class MCExpr; +class MCFragment; class MCSection; class MCSectionData; +class MCSymbol; +class TargetAsmBackend; + +/// MCAsmFixup - Represent a fixed size region of bytes inside some fragment +/// which needs to be rewritten. This region will either be rewritten by the +/// assembler or cause a relocation entry to be generated. +struct MCAsmFixup { + /// Offset - The offset inside the fragment which needs to be rewritten. + uint64_t Offset; + + /// Value - The expression to eventually write into the fragment. + const MCExpr *Value; + + /// Kind - The fixup kind. + MCFixupKind Kind; + + /// FixedValue - The value to replace the fix up by. + // + // FIXME: This should not be here. + uint64_t FixedValue; + +public: + MCAsmFixup(uint64_t _Offset, const MCExpr &_Value, MCFixupKind _Kind) + : Offset(_Offset), Value(&_Value), Kind(_Kind), FixedValue(0) {} +}; class MCFragment : public ilist_node { MCFragment(const MCFragment&); // DO NOT IMPLEMENT @@ -33,7 +62,8 @@ public: FT_Data, FT_Align, FT_Fill, - FT_Org + FT_Org, + FT_ZeroFill }; private: @@ -73,7 +103,7 @@ public: virtual uint64_t getMaxFileSize() const { assert(0 && "Invalid getMaxFileSize call!"); return 0; - }; + } /// @name Assembler Backend Support /// @{ @@ -82,7 +112,7 @@ public: uint64_t getAddress() const; - uint64_t getFileSize() const { + uint64_t getFileSize() const { assert(FileSize != ~UINT64_C(0) && "File size not set!"); return FileSize; } @@ -100,11 +130,20 @@ public: /// @} static bool classof(const MCFragment *O) { return true; } + + virtual void dump(); }; class MCDataFragment : public MCFragment { SmallString<32> Contents; + /// Fixups - The list of fixups in this fragment. + std::vector Fixups; + +public: + typedef std::vector::const_iterator const_fixup_iterator; + typedef std::vector::iterator fixup_iterator; + public: MCDataFragment(MCSectionData *SD = 0) : MCFragment(FT_Data, SD) {} @@ -120,10 +159,28 @@ public: /// @} - static bool classof(const MCFragment *F) { - return F->getKind() == MCFragment::FT_Data; + /// @name Fixup Access + /// @{ + + std::vector &getFixups() { return Fixups; } + const std::vector &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();} + + size_t fixup_size() const { return Fixups.size(); } + + /// @} + + static bool classof(const MCFragment *F) { + return F->getKind() == MCFragment::FT_Data; } static bool classof(const MCDataFragment *) { return true; } + + virtual void dump(); }; class MCAlignFragment : public MCFragment { @@ -140,12 +197,16 @@ class MCAlignFragment : public MCFragment { /// cannot be satisfied in this width then this fragment is ignored. unsigned MaxBytesToEmit; + /// EmitNops - true when aligning code and optimal nops to be used for filling + bool EmitNops; + public: MCAlignFragment(unsigned _Alignment, int64_t _Value, unsigned _ValueSize, - unsigned _MaxBytesToEmit, MCSectionData *SD = 0) + unsigned _MaxBytesToEmit, bool _EmitNops, + MCSectionData *SD = 0) : MCFragment(FT_Align, SD), Alignment(_Alignment), Value(_Value),ValueSize(_ValueSize), - MaxBytesToEmit(_MaxBytesToEmit) {} + MaxBytesToEmit(_MaxBytesToEmit), EmitNops(_EmitNops) {} /// @name Accessors /// @{ @@ -155,24 +216,28 @@ public: } unsigned getAlignment() const { return Alignment; } - + int64_t getValue() const { return Value; } unsigned getValueSize() const { return ValueSize; } unsigned getMaxBytesToEmit() const { return MaxBytesToEmit; } + unsigned getEmitNops() const { return EmitNops; } + /// @} - static bool classof(const MCFragment *F) { - return F->getKind() == MCFragment::FT_Align; + static bool classof(const MCFragment *F) { + return F->getKind() == MCFragment::FT_Align; } static bool classof(const MCAlignFragment *) { return true; } + + virtual void dump(); }; class MCFillFragment : public MCFragment { /// Value - Value to use for filling bytes. - MCValue Value; + int64_t Value; /// ValueSize - The size (in bytes) of \arg Value to use when filling. unsigned ValueSize; @@ -181,8 +246,8 @@ class MCFillFragment : public MCFragment { uint64_t Count; public: - MCFillFragment(MCValue _Value, unsigned _ValueSize, uint64_t _Count, - MCSectionData *SD = 0) + MCFillFragment(int64_t _Value, unsigned _ValueSize, uint64_t _Count, + MCSectionData *SD = 0) : MCFragment(FT_Fill, SD), Value(_Value), ValueSize(_ValueSize), Count(_Count) {} @@ -193,31 +258,34 @@ public: return ValueSize * Count; } - MCValue getValue() const { return Value; } - + int64_t getValue() const { return Value; } + unsigned getValueSize() const { return ValueSize; } uint64_t getCount() const { return Count; } /// @} - static bool classof(const MCFragment *F) { - return F->getKind() == MCFragment::FT_Fill; + static bool classof(const MCFragment *F) { + return F->getKind() == MCFragment::FT_Fill; } static bool classof(const MCFillFragment *) { return true; } + + virtual void dump(); }; class MCOrgFragment : public MCFragment { /// Offset - The offset this fragment should start at. - MCValue Offset; + const MCExpr *Offset; - /// Value - Value to use for filling bytes. + /// Value - Value to use for filling bytes. int8_t Value; public: - MCOrgFragment(MCValue _Offset, int8_t _Value, MCSectionData *SD = 0) + MCOrgFragment(const MCExpr &_Offset, int8_t _Value, MCSectionData *SD = 0) : MCFragment(FT_Org, SD), - Offset(_Offset), Value(_Value) {} + Offset(&_Offset), Value(_Value) {} + /// @name Accessors /// @{ @@ -226,16 +294,54 @@ public: return ~UINT64_C(0); } - MCValue getOffset() const { return Offset; } - + const MCExpr &getOffset() const { return *Offset; } + uint8_t getValue() const { return Value; } /// @} - static bool classof(const MCFragment *F) { - return F->getKind() == MCFragment::FT_Org; + static bool classof(const MCFragment *F) { + return F->getKind() == MCFragment::FT_Org; } static bool classof(const MCOrgFragment *) { return true; } + + virtual void dump(); +}; + +/// MCZeroFillFragment - Represent data which has a fixed size and alignment, +/// but requires no physical space in the object file. +class MCZeroFillFragment : public MCFragment { + /// Size - The size of this fragment. + uint64_t Size; + + /// Alignment - The alignment for this fragment. + unsigned Alignment; + +public: + MCZeroFillFragment(uint64_t _Size, unsigned _Alignment, MCSectionData *SD = 0) + : MCFragment(FT_ZeroFill, SD), + Size(_Size), Alignment(_Alignment) {} + + /// @name Accessors + /// @{ + + uint64_t getMaxFileSize() const { + // FIXME: This also doesn't make much sense, this method is misnamed. + return ~UINT64_C(0); + } + + uint64_t getSize() const { return Size; } + + unsigned getAlignment() const { return Alignment; } + + /// @} + + static bool classof(const MCFragment *F) { + return F->getKind() == MCFragment::FT_ZeroFill; + } + static bool classof(const MCZeroFillFragment *) { return true; } + + virtual void dump(); }; // FIXME: Should this be a separate class, or just merged into MCSection? Since @@ -246,48 +352,17 @@ class MCSectionData : public ilist_node { void operator=(const MCSectionData&); // DO NOT IMPLEMENT public: - /// Fixup - Represent a fixed size region of bytes inside some fragment which - /// needs to be rewritten. This region will either be rewritten by the - /// assembler or cause a relocation entry to be generated. - struct Fixup { - /// Fragment - The fragment containing the fixup. - MCFragment *Fragment; - - /// Offset - The offset inside the fragment which needs to be rewritten. - uint64_t Offset; - - /// Value - The expression to eventually write into the fragment. - // - // FIXME: We could probably get away with requiring the client to pass in an - // owned reference whose lifetime extends past that of the fixup. - MCValue Value; - - /// Size - The fixup size. - unsigned Size; - - /// FixedValue - The value to replace the fix up by. - // - // FIXME: This should not be here. - uint64_t FixedValue; - - public: - Fixup(MCFragment &_Fragment, uint64_t _Offset, const MCValue &_Value, - unsigned _Size) - : Fragment(&_Fragment), Offset(_Offset), Value(_Value), Size(_Size), - FixedValue(0) {} - }; - typedef iplist FragmentListType; typedef FragmentListType::const_iterator const_iterator; typedef FragmentListType::iterator iterator; - typedef std::vector::const_iterator const_fixup_iterator; - typedef std::vector::iterator fixup_iterator; + typedef FragmentListType::const_reverse_iterator const_reverse_iterator; + typedef FragmentListType::reverse_iterator reverse_iterator; private: iplist Fragments; - const MCSection &Section; + const MCSection *Section; /// Alignment - The maximum alignment seen in this section. unsigned Alignment; @@ -308,20 +383,18 @@ private: /// initialized. uint64_t FileSize; - /// LastFixupLookup - Cache for the last looked up fixup. - mutable unsigned LastFixupLookup; + /// HasInstructions - Whether this section has had instructions emitted into + /// it. + unsigned HasInstructions : 1; - /// Fixups - The list of fixups in this section. - std::vector Fixups; - /// @} -public: +public: // Only for use as sentinel. MCSectionData(); MCSectionData(const MCSection &Section, MCAssembler *A = 0); - const MCSection &getSection() const { return Section; } + const MCSection &getSection() const { return *Section; } unsigned getAlignment() const { return Alignment; } void setAlignment(unsigned Value) { Alignment = Value; } @@ -338,27 +411,15 @@ public: iterator end() { return Fragments.end(); } const_iterator end() const { return Fragments.end(); } - size_t size() const { return Fragments.size(); } - - bool empty() const { return Fragments.empty(); } - - /// @} - /// @name Fixup Access - /// @{ + reverse_iterator rbegin() { return Fragments.rbegin(); } + const_reverse_iterator rbegin() const { return Fragments.rbegin(); } - std::vector &getFixups() { - return Fixups; - } + reverse_iterator rend() { return Fragments.rend(); } + const_reverse_iterator rend() const { return Fragments.rend(); } - fixup_iterator fixup_begin() { - return Fixups.begin(); - } - - fixup_iterator fixup_end() { - return Fixups.end(); - } + size_t size() const { return Fragments.size(); } - size_t fixup_size() const { return Fixups.size(); } + bool empty() const { return Fragments.empty(); } /// @} /// @name Assembler Backend Support @@ -366,41 +427,36 @@ public: // // FIXME: This could all be kept private to the assembler implementation. - /// LookupFixup - Look up the fixup for the given \arg Fragment and \arg - /// Offset. - /// - /// If multiple fixups exist for the same fragment and offset it is undefined - /// which one is returned. - // - // FIXME: This isn't horribly slow in practice, but there are much nicer - // solutions to applying the fixups. - const Fixup *LookupFixup(const MCFragment *Fragment, uint64_t Offset) const; - - uint64_t getAddress() const { + uint64_t getAddress() const { assert(Address != ~UINT64_C(0) && "Address not set!"); return Address; } void setAddress(uint64_t Value) { Address = Value; } - uint64_t getSize() const { + uint64_t getSize() const { assert(Size != ~UINT64_C(0) && "File size not set!"); return Size; } void setSize(uint64_t Value) { Size = Value; } - uint64_t getFileSize() const { + uint64_t getFileSize() const { assert(FileSize != ~UINT64_C(0) && "File size not set!"); return FileSize; } - void setFileSize(uint64_t Value) { FileSize = Value; } + void setFileSize(uint64_t Value) { FileSize = Value; } + + bool hasInstructions() const { return HasInstructions; } + void setHasInstructions(bool Value) { HasInstructions = Value; } /// @} + + void dump(); }; // FIXME: Same concerns as with SectionData. class MCSymbolData : public ilist_node { public: - MCSymbol &Symbol; + const MCSymbol *Symbol; /// Fragment - The fragment this symbol's value is relative to, if any. MCFragment *Fragment; @@ -408,7 +464,7 @@ public: /// Offset - The offset to apply to the fragment address to form this symbol's /// value. uint64_t Offset; - + /// IsExternal - True if this symbol is visible outside this translation /// unit. unsigned IsExternal : 1; @@ -416,6 +472,17 @@ public: /// IsPrivateExtern - True if this symbol is private extern. unsigned IsPrivateExtern : 1; + /// CommonSize - The size of the symbol, if it is 'common', or 0. + // + // FIXME: Pack this in with other fields? We could put it in offset, since a + // common symbol can never get a definition. + uint64_t CommonSize; + + /// CommonAlign - The alignment of the symbol, if it is 'common'. + // + // FIXME: Pack this in with other fields? + unsigned CommonAlign; + /// Flags - The Flags field is used by object file implementations to store /// additional per symbol information which is not easily classified. uint32_t Flags; @@ -426,13 +493,13 @@ public: public: // Only for use as sentinel. MCSymbolData(); - MCSymbolData(MCSymbol &_Symbol, MCFragment *_Fragment, uint64_t _Offset, + MCSymbolData(const MCSymbol &_Symbol, MCFragment *_Fragment, uint64_t _Offset, MCAssembler *A = 0); /// @name Accessors /// @{ - MCSymbol &getSymbol() const { return Symbol; } + const MCSymbol &getSymbol() const { return *Symbol; } MCFragment *getFragment() const { return Fragment; } void setFragment(MCFragment *Value) { Fragment = Value; } @@ -443,26 +510,52 @@ public: /// @} /// @name Symbol Attributes /// @{ - + bool isExternal() const { return IsExternal; } void setExternal(bool Value) { IsExternal = Value; } - + bool isPrivateExtern() const { return IsPrivateExtern; } void setPrivateExtern(bool Value) { IsPrivateExtern = Value; } - + + /// isCommon - Is this a 'common' symbol. + bool isCommon() const { return CommonSize != 0; } + + /// setCommon - Mark this symbol as being 'common'. + /// + /// \param Size - The size of the symbol. + /// \param Align - The alignment of the symbol. + void setCommon(uint64_t Size, unsigned Align) { + CommonSize = Size; + CommonAlign = Align; + } + + /// getCommonSize - Return the size of a 'common' symbol. + uint64_t getCommonSize() const { + assert(isCommon() && "Not a 'common' symbol!"); + return CommonSize; + } + + /// getCommonAlignment - Return the alignment of a 'common' symbol. + unsigned getCommonAlignment() const { + assert(isCommon() && "Not a 'common' symbol!"); + return CommonAlign; + } + /// getFlags - Get the (implementation defined) symbol flags. uint32_t getFlags() const { return Flags; } /// setFlags - Set the (implementation defined) symbol flags. void setFlags(uint32_t Value) { Flags = Value; } - + /// getIndex - Get the (implementation defined) index. uint64_t getIndex() const { return Index; } /// setIndex - Set the (implementation defined) index. void setIndex(uint64_t Value) { Index = Value; } - - /// @} + + /// @} + + void dump(); }; // FIXME: This really doesn't belong here. See comments below. @@ -488,23 +581,35 @@ private: MCAssembler(const MCAssembler&); // DO NOT IMPLEMENT void operator=(const MCAssembler&); // DO NOT IMPLEMENT + MCContext &Context; + + TargetAsmBackend &Backend; + raw_ostream &OS; - + iplist Sections; iplist Symbols; + /// The map of sections to their associated assembler backend data. + // + // FIXME: Avoid this indirection? + DenseMap SectionMap; + + /// The map of symbols to their associated assembler backend data. + // + // FIXME: Avoid this indirection? + DenseMap SymbolMap; + std::vector IndirectSymbols; + unsigned SubsectionsViaSymbols : 1; + private: /// LayoutSection - Assign offsets and sizes to the fragments in the section /// \arg SD, and update the section size. The section file offset should /// already have been computed. - /// - /// \param NextAlign - The alignment for the section end address, which may - /// add padding bytes to the section (these are included in the section "file" - /// size, but not its regular size). - void LayoutSection(MCSectionData &SD, unsigned NextAlign); + void LayoutSection(MCSectionData &SD); public: /// Construct a new assembler instance. @@ -515,17 +620,27 @@ public: // 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(raw_ostream &OS); + MCAssembler(MCContext &_Context, TargetAsmBackend &_Backend, raw_ostream &OS); ~MCAssembler(); + MCContext &getContext() const { return Context; } + /// Finish - Do final processing and write the object to the output stream. void Finish(); + // FIXME: This does not belong here. + bool getSubsectionsViaSymbols() const { + return SubsectionsViaSymbols; + } + void setSubsectionsViaSymbols(bool Value) { + SubsectionsViaSymbols = Value; + } + /// @name Section List Access /// @{ const SectionDataListType &getSectionList() const { return Sections; } - SectionDataListType &getSectionList() { return Sections; } + SectionDataListType &getSectionList() { return Sections; } iterator begin() { return Sections.begin(); } const_iterator begin() const { return Sections.begin(); } @@ -572,6 +687,46 @@ public: size_t indirect_symbol_size() const { return IndirectSymbols.size(); } /// @} + /// @name Backend Data Access + /// @{ + + MCSectionData &getSectionData(const MCSection &Section) { + MCSectionData *&Entry = SectionMap[&Section]; + assert(Entry && "Missing section data!"); + return *Entry; + } + + MCSectionData &getOrCreateSectionData(const MCSection &Section, + bool *Created = 0) { + MCSectionData *&Entry = SectionMap[&Section]; + + if (Created) *Created = !Entry; + if (!Entry) + Entry = new MCSectionData(Section, this); + + return *Entry; + } + + MCSymbolData &getSymbolData(const MCSymbol &Symbol) { + MCSymbolData *&Entry = SymbolMap[&Symbol]; + assert(Entry && "Missing symbol data!"); + return *Entry; + } + + MCSymbolData &getOrCreateSymbolData(const MCSymbol &Symbol, + bool *Created = 0) { + MCSymbolData *&Entry = SymbolMap[&Symbol]; + + if (Created) *Created = !Entry; + if (!Entry) + Entry = new MCSymbolData(Symbol, 0, 0, this); + + return *Entry; + } + + /// @} + + void dump(); }; } // end namespace llvm