X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=include%2Fllvm%2FMC%2FMCAssembler.h;h=7d8bae9f37ee89427aaa287027641ecaeea9345e;hb=62b83b62f377ac248038672015dc65970327f786;hp=892f54839db38c499932706b448fd26a5067e3ec;hpb=efbb5330b8d383a393c83d2da5d631c98b0bb3fd;p=oota-llvm.git diff --git a/include/llvm/MC/MCAssembler.h b/include/llvm/MC/MCAssembler.h index 892f54839db..7d8bae9f37e 100644 --- a/include/llvm/MC/MCAssembler.h +++ b/include/llvm/MC/MCAssembler.h @@ -10,32 +10,49 @@ #ifndef LLVM_MC_MCASSEMBLER_H #define LLVM_MC_MCASSEMBLER_H +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallPtrSet.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/MC/MCFixup.h" +#include "llvm/MC/MCInst.h" #include "llvm/Support/DataTypes.h" #include // FIXME: Shouldn't be needed. namespace llvm { class raw_ostream; +class MCAsmLayout; class MCAssembler; +class MCBinaryExpr; class MCContext; +class MCCodeEmitter; +class MCExpr; +class MCFragment; +class MCObjectWriter; class MCSection; class MCSectionData; +class MCSymbol; +class MCSymbolData; +class MCValue; +class TargetAsmBackend; class MCFragment : public ilist_node { + friend class MCAsmLayout; + MCFragment(const MCFragment&); // DO NOT IMPLEMENT void operator=(const MCFragment&); // DO NOT IMPLEMENT public: enum FragmentType { - FT_Data, FT_Align, + FT_Data, FT_Fill, + FT_Inst, FT_Org, - FT_ZeroFill + FT_Dwarf, + FT_LEB }; private: @@ -44,6 +61,11 @@ private: /// Parent - The data for the section this fragment is in. MCSectionData *Parent; + /// Atom - The atom this fragment is in, as represented by it's defining + /// symbol. Atom's are only used by backends which set + /// \see MCAsmBackend::hasReliableSymbolDifference(). + MCSymbolData *Atom; + /// @name Assembler Backend Data /// @{ // @@ -53,8 +75,8 @@ private: /// initialized. uint64_t Offset; - /// FileSize - The file size of this section. This is ~0 until initialized. - uint64_t FileSize; + /// LayoutOrder - The layout order of this fragment. + unsigned LayoutOrder; /// @} @@ -71,61 +93,124 @@ public: MCSectionData *getParent() const { return Parent; } void setParent(MCSectionData *Value) { Parent = Value; } - // FIXME: This should be abstract, fix sentinel. - virtual uint64_t getMaxFileSize() const { - assert(0 && "Invalid getMaxFileSize call!"); - return 0; - }; + MCSymbolData *getAtom() const { return Atom; } + void setAtom(MCSymbolData *Value) { Atom = Value; } + + unsigned getLayoutOrder() const { return LayoutOrder; } + void setLayoutOrder(unsigned Value) { LayoutOrder = Value; } + + static bool classof(const MCFragment *O) { return true; } + + void dump(); +}; + +class MCDataFragment : public MCFragment { + SmallString<32> Contents; - /// @name Assembler Backend Support + /// 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) {} + + /// @name Accessors /// @{ - // - // FIXME: This could all be kept private to the assembler implementation. - uint64_t getAddress() const; + SmallString<32> &getContents() { return Contents; } + const SmallString<32> &getContents() const { return Contents; } - uint64_t getFileSize() const { - assert(FileSize != ~UINT64_C(0) && "File size not set!"); - return FileSize; - } - void setFileSize(uint64_t Value) { - assert(Value <= getMaxFileSize() && "Invalid file size!"); - FileSize = Value; - } + /// @} + /// @name Fixup Access + /// @{ - uint64_t getOffset() const { - assert(Offset != ~UINT64_C(0) && "File offset not set!"); - return Offset; + void addFixup(MCFixup Fixup) { + // Enforce invariant that fixups are in offset order. + assert((Fixups.empty() || Fixup.getOffset() > Fixups.back().getOffset()) && + "Fixups must be added in order!"); + Fixups.push_back(Fixup); } - void setOffset(uint64_t Value) { Offset = Value; } + + 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 *O) { return true; } + static bool classof(const MCFragment *F) { + return F->getKind() == MCFragment::FT_Data; + } + static bool classof(const MCDataFragment *) { return true; } }; -class MCDataFragment : public MCFragment { - SmallString<32> Contents; +// FIXME: This current incarnation of MCInstFragment doesn't make much sense, as +// it is almost entirely a duplicate of MCDataFragment. If we decide to stick +// with this approach (as opposed to making MCInstFragment a very light weight +// object with just the MCInst and a code size, then we should just change +// MCDataFragment to have an optional MCInst at its end. +class MCInstFragment : public MCFragment { + /// Inst - The instruction this is a fragment for. + MCInst Inst; + + /// Code - Binary data for the currently encoded instruction. + SmallString<8> Code; + + /// Fixups - The list of fixups in this fragment. + SmallVector Fixups; public: - MCDataFragment(MCSectionData *SD = 0) : MCFragment(FT_Data, SD) {} + typedef SmallVectorImpl::const_iterator const_fixup_iterator; + typedef SmallVectorImpl::iterator fixup_iterator; + +public: + MCInstFragment(MCInst _Inst, MCSectionData *SD = 0) + : MCFragment(FT_Inst, SD), Inst(_Inst) { + } /// @name Accessors /// @{ - uint64_t getMaxFileSize() const { - return Contents.size(); - } + SmallVectorImpl &getCode() { return Code; } + const SmallVectorImpl &getCode() const { return Code; } - SmallString<32> &getContents() { return Contents; } - const SmallString<32> &getContents() const { return Contents; } + unsigned getInstSize() const { return Code.size(); } + + MCInst &getInst() { return Inst; } + const MCInst &getInst() const { return Inst; } + + void setInst(MCInst Value) { Inst = Value; } + + /// @} + /// @name Fixup Access + /// @{ + + SmallVectorImpl &getFixups() { return Fixups; } + const SmallVectorImpl &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 MCFragment *F) { + return F->getKind() == MCFragment::FT_Inst; } - static bool classof(const MCDataFragment *) { return true; } + static bool classof(const MCInstFragment *) { return true; } }; class MCAlignFragment : public MCFragment { @@ -142,190 +227,211 @@ class MCAlignFragment : public MCFragment { /// cannot be satisfied in this width then this fragment is ignored. unsigned MaxBytesToEmit; + /// Size - The current estimate of the size. + unsigned Size; + + /// 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; + public: MCAlignFragment(unsigned _Alignment, int64_t _Value, unsigned _ValueSize, unsigned _MaxBytesToEmit, MCSectionData *SD = 0) : MCFragment(FT_Align, SD), Alignment(_Alignment), Value(_Value),ValueSize(_ValueSize), - MaxBytesToEmit(_MaxBytesToEmit) {} + MaxBytesToEmit(_MaxBytesToEmit), Size(0), EmitNops(false) {} /// @name Accessors /// @{ - uint64_t getMaxFileSize() const { - return std::max(Alignment - 1, MaxBytesToEmit); - } - unsigned getAlignment() const { return Alignment; } - + int64_t getValue() const { return Value; } unsigned getValueSize() const { return ValueSize; } + unsigned getSize() const { return Size; } + + void setSize(unsigned Size_) { Size = Size_; } + 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; + static bool classof(const MCFragment *F) { + return F->getKind() == MCFragment::FT_Align; } static bool classof(const MCAlignFragment *) { return true; } }; 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. + /// ValueSize - The size (in bytes) of \arg Value to use when filling, or 0 if + /// this is a virtual fill fragment. unsigned ValueSize; - /// Count - The number of copies of \arg Value to insert. - uint64_t Count; + /// Size - The number of bytes to insert. + uint64_t Size; public: - MCFillFragment(MCValue _Value, unsigned _ValueSize, uint64_t _Count, - MCSectionData *SD = 0) + MCFillFragment(int64_t _Value, unsigned _ValueSize, uint64_t _Size, + MCSectionData *SD = 0) : MCFragment(FT_Fill, SD), - Value(_Value), ValueSize(_ValueSize), Count(_Count) {} + Value(_Value), ValueSize(_ValueSize), Size(_Size) { + assert((!ValueSize || (Size % ValueSize) == 0) && + "Fill size must be a multiple of the value size!"); + } /// @name Accessors /// @{ - uint64_t getMaxFileSize() const { - return ValueSize * Count; - } + int64_t getValue() const { return Value; } - MCValue getValue() const { return Value; } - unsigned getValueSize() const { return ValueSize; } - uint64_t getCount() const { return Count; } + uint64_t getSize() const { return Size; } /// @} - 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; } }; 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; + /// Size - The current estimate of the size. + unsigned Size; + 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), Size(0) {} /// @name Accessors /// @{ - uint64_t getMaxFileSize() const { - // FIXME: This doesn't make much sense. - return ~UINT64_C(0); - } + const MCExpr &getOffset() const { return *Offset; } - MCValue getOffset() const { return Offset; } - uint8_t getValue() const { return Value; } + unsigned getSize() const { return Size; } + + void setSize(unsigned Size_) { Size = Size_; } /// @} - 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; } }; -/// 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; +class MCLEBFragment : public MCFragment { + /// Value - The value this fragment should contain. + const MCExpr *Value; - /// Alignment - The alignment for this fragment. - unsigned Alignment; + /// IsSigned - True if this is a sleb128, false if uleb128. + bool IsSigned; + SmallString<8> Contents; public: - MCZeroFillFragment(uint64_t _Size, unsigned _Alignment, MCSectionData *SD = 0) - : MCFragment(FT_ZeroFill, SD), - Size(_Size), Alignment(_Alignment) {} + MCLEBFragment(const MCExpr &Value_, bool IsSigned_, MCSectionData *SD) + : MCFragment(FT_LEB, SD), + Value(&Value_), IsSigned(IsSigned_) { Contents.push_back(0); } /// @name Accessors /// @{ - uint64_t getMaxFileSize() const { - // FIXME: This also doesn't make much sense, this method is misnamed. - return ~UINT64_C(0); + 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; } + static bool classof(const MCLEBFragment *) { return true; } +}; - uint64_t getSize() const { return Size; } - - unsigned getAlignment() const { return Alignment; } +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, + MCSectionData *SD = 0) + : MCFragment(FT_Dwarf, SD), + 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_ZeroFill; + static bool classof(const MCFragment *F) { + return F->getKind() == MCFragment::FT_Dwarf; } - static bool classof(const MCZeroFillFragment *) { return true; } + static bool classof(const MCDwarfLineAddrFragment *) { return true; } }; // FIXME: Should this be a separate class, or just merged into MCSection? Since // we anticipate the fast path being through an MCAssembler, the only reason to // keep it out is for API abstraction. class MCSectionData : public ilist_node { + friend class MCAsmLayout; + MCSectionData(const MCSectionData&); // DO NOT IMPLEMENT 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; + FragmentListType Fragments; const MCSection *Section; + /// Ordinal - The section index in the assemblers section list. + unsigned Ordinal; + + /// LayoutOrder - The index of this section in the layout order. + unsigned LayoutOrder; + /// Alignment - The maximum alignment seen in this section. unsigned Alignment; @@ -334,26 +440,13 @@ private: // // FIXME: This could all be kept private to the assembler implementation. - /// Address - The computed address of this section. This is ~0 until - /// initialized. - uint64_t Address; - - /// Size - The content size of this section. This is ~0 until initialized. - uint64_t Size; + /// HasInstructions - Whether this section has had instructions emitted into + /// it. + unsigned HasInstructions : 1; - /// FileSize - The size of this section in the object file. This is ~0 until - /// initialized. - uint64_t FileSize; - - /// LastFixupLookup - Cache for the last looked up fixup. - mutable unsigned LastFixupLookup; - - /// 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); @@ -363,6 +456,15 @@ public: unsigned getAlignment() const { return Alignment; } void setAlignment(unsigned Value) { Alignment = Value; } + bool hasInstructions() const { return HasInstructions; } + void setHasInstructions(bool Value) { HasInstructions = Value; } + + unsigned getOrdinal() const { return Ordinal; } + void setOrdinal(unsigned Value) { Ordinal = Value; } + + unsigned getLayoutOrder() const { return LayoutOrder; } + void setLayoutOrder(unsigned Value) { LayoutOrder = Value; } + /// @name Fragment Access /// @{ @@ -375,61 +477,17 @@ 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 - /// @{ - - std::vector &getFixups() { - return Fixups; - } - - fixup_iterator fixup_begin() { - return Fixups.begin(); - } - - fixup_iterator fixup_end() { - return Fixups.end(); - } - - size_t fixup_size() const { return Fixups.size(); } - - /// @} - /// @name Assembler Backend Support - /// @{ - // - // FIXME: This could all be kept private to the assembler implementation. + reverse_iterator rbegin() { return Fragments.rbegin(); } + const_reverse_iterator rbegin() const { return Fragments.rbegin(); } - /// 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; + reverse_iterator rend() { return Fragments.rend(); } + const_reverse_iterator rend() const { return Fragments.rend(); } - uint64_t getAddress() const { - assert(Address != ~UINT64_C(0) && "Address not set!"); - return Address; - } - void setAddress(uint64_t Value) { Address = Value; } + size_t size() const { return Fragments.size(); } - uint64_t getSize() const { - assert(Size != ~UINT64_C(0) && "File size not set!"); - return Size; - } - void setSize(uint64_t Value) { Size = Value; } + bool empty() const { return Fragments.empty(); } - uint64_t getFileSize() const { - assert(FileSize != ~UINT64_C(0) && "File size not set!"); - return FileSize; - } - void setFileSize(uint64_t Value) { FileSize = Value; } + void dump(); /// @} }; @@ -445,7 +503,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; @@ -459,6 +517,10 @@ public: // common symbol can never get a definition. uint64_t CommonSize; + /// SymbolSize - An expression describing how to calculate the size of + /// a symbol. If a symbol has no size this field will be NULL. + const MCExpr *SymbolSize; + /// CommonAlign - The alignment of the symbol, if it is 'common'. // // FIXME: Pack this in with other fields? @@ -491,10 +553,10 @@ 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; } @@ -516,6 +578,15 @@ public: return CommonSize; } + void setSize(const MCExpr *SS) { + SymbolSize = SS; + } + + const MCExpr *getSize() const { + return SymbolSize; + } + + /// getCommonAlignment - Return the alignment of a 'common' symbol. unsigned getCommonAlignment() const { assert(isCommon() && "Not a 'common' symbol!"); @@ -527,14 +598,21 @@ public: /// setFlags - Set the (implementation defined) symbol flags. void setFlags(uint32_t Value) { Flags = Value; } - + + /// modifyFlags - Modify the flags via a mask + void modifyFlags(uint32_t Value, uint32_t Mask) { + Flags = (Flags & ~Mask) | 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. @@ -544,6 +622,8 @@ struct IndirectSymbolData { }; class MCAssembler { + friend class MCAsmLayout; + public: typedef iplist SectionDataListType; typedef iplist SymbolDataListType; @@ -554,6 +634,8 @@ public: typedef SymbolDataListType::const_iterator const_symbol_iterator; typedef SymbolDataListType::iterator symbol_iterator; + typedef std::vector::const_iterator + const_indirect_symbol_iterator; typedef std::vector::iterator indirect_symbol_iterator; private: @@ -562,21 +644,117 @@ private: MCContext &Context; + TargetAsmBackend &Backend; + + MCCodeEmitter &Emitter; + + MCObjectWriter &Writer; + 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; + /// The set of function symbols for which a .thumb_func directive has + /// been seen. + // + // FIXME: We really would like this in target specific code rather than + // here. Maybe when the relocation stuff moves to target specific, + // this can go with it? The streamer would need some target specific + // refactoring too. + SmallPtrSet ThumbFuncs; + + unsigned RelaxAll : 1; 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. - void LayoutSection(MCSectionData &SD); + /// Evaluate a fixup to a relocatable expression and the value which should be + /// placed into the fixup. + /// + /// \param Layout The layout to use for evaluation. + /// \param Fixup The fixup to evaluate. + /// \param DF The fragment the fixup is inside. + /// \param Target [out] On return, the relocatable expression the fixup + /// evaluates to. + /// \param Value [out] On return, the value of the fixup as currently layed + /// out. + /// \return Whether the fixup value was fully resolved. This is true if the + /// \arg Value result is fixed, otherwise the value may change due to + /// relocation. + bool EvaluateFixup(const MCAsmLayout &Layout, + const MCFixup &Fixup, const MCFragment *DF, + MCValue &Target, uint64_t &Value) const; + + /// Check whether a fixup can be satisfied, or whether it needs to be relaxed + /// (increased in size, in order to hold its value correctly). + bool FixupNeedsRelaxation(const MCFixup &Fixup, const MCFragment *DF, + const MCAsmLayout &Layout) const; + + /// Check whether the given fragment needs relaxation. + bool FragmentNeedsRelaxation(const MCInstFragment *IF, + const MCAsmLayout &Layout) const; + + /// LayoutOnce - Perform one layout iteration and return true if any offsets + /// were adjusted. + bool LayoutOnce(MCAsmLayout &Layout); + + bool LayoutSectionOnce(MCAsmLayout &Layout, MCSectionData &SD); + + bool RelaxInstruction(MCAsmLayout &Layout, MCInstFragment &IF); + + bool RelaxOrg(MCAsmLayout &Layout, MCOrgFragment &OF); + + bool RelaxLEB(MCAsmLayout &Layout, MCLEBFragment &IF); + + bool RelaxDwarfLineAddr(MCAsmLayout &Layout, MCDwarfLineAddrFragment &DF); + + bool RelaxAlignment(MCAsmLayout &Layout, MCAlignFragment &DF); + + /// FinishLayout - Finalize a layout, including fragment lowering. + void FinishLayout(MCAsmLayout &Layout); + + uint64_t HandleFixup(const MCAsmLayout &Layout, + MCFragment &F, const MCFixup &Fixup); + +public: + /// Compute the effective fragment size assuming it is layed out at the given + /// \arg SectionAddress and \arg FragmentOffset. + uint64_t ComputeFragmentSize(const MCFragment &F) const; + + /// Find the symbol which defines the atom containing the given symbol, or + /// null if there is no such symbol. + const MCSymbolData *getAtom(const MCSymbolData *Symbol) const; + + /// Check whether a particular symbol is visible to the linker and is required + /// in the symbol table, or whether it can be discarded by the assembler. This + /// also effects whether the assembler treats the label as potentially + /// defining a separate atom. + bool isSymbolLinkerVisible(const MCSymbol &SD) const; + + /// Emit the section contents using the given object writer. + void WriteSectionData(const MCSectionData *Section, + const MCAsmLayout &Layout) const; + + /// Check whether a given symbol has been flagged with .thumb_func. + bool isThumbFunc(const MCSymbol *Func) const { + return ThumbFuncs.count(Func); + } + + /// Flag a function symbol as the target of a .thumb_func directive. + void setIsThumbFunc(const MCSymbol *Func) { ThumbFuncs.insert(Func); } public: /// Construct a new assembler instance. @@ -587,12 +765,22 @@ 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(MCContext &_Context, raw_ostream &OS); + MCAssembler(MCContext &Context_, TargetAsmBackend &Backend_, + MCCodeEmitter &Emitter_, MCObjectWriter &Writer_, + raw_ostream &OS); ~MCAssembler(); MCContext &getContext() const { return Context; } + TargetAsmBackend &getBackend() const { return Backend; } + + MCCodeEmitter &getEmitter() const { return Emitter; } + + MCObjectWriter &getWriter() const { return Writer; } + /// Finish - Do final processing and write the object to the output stream. + /// \arg Writer is used for custom object writer (as the MCJIT does), + /// if not specified it is automatically created from backend. void Finish(); // FIXME: This does not belong here. @@ -603,11 +791,14 @@ public: SubsectionsViaSymbols = Value; } + bool getRelaxAll() const { return RelaxAll; } + void setRelaxAll(bool Value) { RelaxAll = 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(); } @@ -646,14 +837,60 @@ public: indirect_symbol_iterator indirect_symbol_begin() { return IndirectSymbols.begin(); } + const_indirect_symbol_iterator indirect_symbol_begin() const { + return IndirectSymbols.begin(); + } indirect_symbol_iterator indirect_symbol_end() { return IndirectSymbols.end(); } + const_indirect_symbol_iterator indirect_symbol_end() const { + return IndirectSymbols.end(); + } size_t indirect_symbol_size() const { return IndirectSymbols.size(); } /// @} + /// @name Backend Data Access + /// @{ + + MCSectionData &getSectionData(const MCSection &Section) const { + MCSectionData *Entry = SectionMap.lookup(&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) const { + MCSymbolData *Entry = SymbolMap.lookup(&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