X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=include%2Fllvm%2FMC%2FMCAssembler.h;h=83c01ec5b98f2de2cd274f20e22a754928d24d96;hb=34aadd63346b5f9b98749a306b71fcb00ee6996f;hp=c371f1dd008a5df33a32ba838e865632ba5950e7;hpb=f08fde41f34d739c157b1d75dadbb864e7957cab;p=oota-llvm.git diff --git a/include/llvm/MC/MCAssembler.h b/include/llvm/MC/MCAssembler.h index c371f1dd008..83c01ec5b98 100644 --- a/include/llvm/MC/MCAssembler.h +++ b/include/llvm/MC/MCAssembler.h @@ -10,13 +10,15 @@ #ifndef LLVM_MC_MCASSEMBLER_H #define LLVM_MC_MCASSEMBLER_H +#include "llvm/MC/MCFixup.h" +#include "llvm/MC/MCInst.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/Support/Casting.h" -#include "llvm/MC/MCFixup.h" -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include // FIXME: Shouldn't be needed. namespace llvm { @@ -24,48 +26,33 @@ class raw_ostream; class MCAsmLayout; class MCAssembler; class MCContext; +class MCCodeEmitter; class MCExpr; class MCFragment; +class MCObjectWriter; class MCSection; class MCSectionData; class MCSymbol; +class MCSymbolData; class MCValue; -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 MCAsmBackend; class MCFragment : public ilist_node { - MCFragment(const MCFragment&); // DO NOT IMPLEMENT - void operator=(const MCFragment&); // DO NOT IMPLEMENT + friend class MCAsmLayout; + + MCFragment(const MCFragment&) LLVM_DELETED_FUNCTION; + void operator=(const MCFragment&) LLVM_DELETED_FUNCTION; public: enum FragmentType { - FT_Data, FT_Align, + FT_Data, FT_Fill, + FT_Inst, FT_Org, - FT_ZeroFill + FT_Dwarf, + FT_DwarfFrame, + FT_LEB }; private: @@ -74,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 /// @{ // @@ -83,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; /// @} @@ -101,50 +93,27 @@ 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; - } - - /// @name Assembler Backend Support - /// @{ - // - // FIXME: This could all be kept private to the assembler implementation. - - uint64_t getAddress() const; - - 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; - } - - uint64_t getOffset() const { - assert(Offset != ~UINT64_C(0) && "File offset not set!"); - return Offset; - } - void setOffset(uint64_t Value) { Offset = Value; } + 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; } - virtual void dump(); + void dump(); }; class MCDataFragment : public MCFragment { + virtual void anchor(); SmallString<32> Contents; /// Fixups - The list of fixups in this fragment. - std::vector Fixups; + std::vector Fixups; public: - typedef std::vector::const_iterator const_fixup_iterator; - typedef std::vector::iterator fixup_iterator; + typedef std::vector::const_iterator const_fixup_iterator; + typedef std::vector::iterator fixup_iterator; public: MCDataFragment(MCSectionData *SD = 0) : MCFragment(FT_Data, SD) {} @@ -152,27 +121,22 @@ public: /// @name Accessors /// @{ - uint64_t getMaxFileSize() const { - return Contents.size(); - } - SmallString<32> &getContents() { return Contents; } const SmallString<32> &getContents() const { return Contents; } /// @} - /// @name Fixup Access /// @{ - void addFixup(MCAsmFixup Fixup) { + void addFixup(MCFixup Fixup) { // Enforce invariant that fixups are in offset order. - assert(Fixups.empty() || Fixup.Offset > Fixups.back().Offset && + assert((Fixups.empty() || Fixup.getOffset() >= Fixups.back().getOffset()) && "Fixups must be added in order!"); Fixups.push_back(Fixup); } - std::vector &getFixups() { return Fixups; } - const std::vector &getFixups() const { return Fixups; } + 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(); } @@ -188,43 +152,101 @@ public: return F->getKind() == MCFragment::FT_Data; } static bool classof(const MCDataFragment *) { return true; } +}; + +// 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 { + virtual void anchor(); + + /// 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: + typedef SmallVectorImpl::const_iterator const_fixup_iterator; + typedef SmallVectorImpl::iterator fixup_iterator; - virtual void dump(); +public: + MCInstFragment(const MCInst &_Inst, MCSectionData *SD = 0) + : MCFragment(FT_Inst, SD), Inst(_Inst) { + } + + /// @name Accessors + /// @{ + + SmallVectorImpl &getCode() { return Code; } + const SmallVectorImpl &getCode() const { return Code; } + + unsigned getInstSize() const { return Code.size(); } + + MCInst &getInst() { return Inst; } + const MCInst &getInst() const { return Inst; } + + void setInst(const 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_Inst; + } + static bool classof(const MCInstFragment *) { return true; } }; class MCAlignFragment : public MCFragment { + virtual void anchor(); + /// Alignment - The alignment to ensure, in bytes. unsigned Alignment; /// Value - Value to use for filling padding bytes. int64_t Value; - /// ValueSize - The size of the integer (in bytes) of \arg 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; - /// EmitNops - true when aligning code and optimal nops to be used for - /// filling. - bool EmitNops; + /// 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, bool _EmitNops, - MCSectionData *SD = 0) + unsigned _MaxBytesToEmit, MCSectionData *SD = 0) : MCFragment(FT_Align, SD), Alignment(_Alignment), Value(_Value),ValueSize(_ValueSize), - MaxBytesToEmit(_MaxBytesToEmit), EmitNops(_EmitNops) {} + MaxBytesToEmit(_MaxBytesToEmit), 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; } @@ -233,7 +255,8 @@ public: unsigned getMaxBytesToEmit() const { return MaxBytesToEmit; } - unsigned getEmitNops() const { return EmitNops; } + bool hasEmitNops() const { return EmitNops; } + void setEmitNops(bool Value) { EmitNops = Value; } /// @} @@ -241,38 +264,38 @@ public: return F->getKind() == MCFragment::FT_Align; } static bool classof(const MCAlignFragment *) { return true; } - - virtual void dump(); }; class MCFillFragment : public MCFragment { + virtual void anchor(); + /// Value - Value to use for filling bytes. int64_t Value; - /// ValueSize - The size (in bytes) of \arg Value to use when filling. + /// ValueSize - The size (in bytes) of \p 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(int64_t _Value, unsigned _ValueSize, uint64_t _Count, + 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; } unsigned getValueSize() const { return ValueSize; } - uint64_t getCount() const { return Count; } + uint64_t getSize() const { return Size; } /// @} @@ -280,11 +303,11 @@ public: return F->getKind() == MCFragment::FT_Fill; } static bool classof(const MCFillFragment *) { return true; } - - virtual void dump(); }; class MCOrgFragment : public MCFragment { + virtual void anchor(); + /// Offset - The offset this fragment should start at. const MCExpr *Offset; @@ -299,11 +322,6 @@ public: /// @name Accessors /// @{ - uint64_t getMaxFileSize() const { - // FIXME: This doesn't make much sense. - return ~UINT64_C(0); - } - const MCExpr &getOffset() const { return *Offset; } uint8_t getValue() const { return Value; } @@ -314,52 +332,116 @@ public: 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; +class MCLEBFragment : public MCFragment { + virtual void anchor(); - /// Alignment - The alignment for this fragment. - unsigned Alignment; + /// 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: - 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; } +class MCDwarfLineAddrFragment : public MCFragment { + virtual void anchor(); - unsigned getAlignment() const { return Alignment; } + /// 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) + : 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; + return F->getKind() == MCFragment::FT_Dwarf; } - static bool classof(const MCZeroFillFragment *) { return true; } + static bool classof(const MCDwarfLineAddrFragment *) { return true; } +}; - virtual void dump(); +class MCDwarfCallFrameFragment : public MCFragment { + virtual void anchor(); + + /// 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, MCSectionData *SD) + : MCFragment(FT_DwarfFrame, SD), + 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; + } + static bool classof(const MCDwarfCallFrameFragment *) { 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 { - MCSectionData(const MCSectionData&); // DO NOT IMPLEMENT - void operator=(const MCSectionData&); // DO NOT IMPLEMENT + friend class MCAsmLayout; + + MCSectionData(const MCSectionData&) LLVM_DELETED_FUNCTION; + void operator=(const MCSectionData&) LLVM_DELETED_FUNCTION; public: typedef iplist FragmentListType; @@ -371,9 +453,15 @@ public: 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; @@ -382,17 +470,6 @@ 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; - - /// FileSize - The size of this section in the object file. This is ~0 until - /// initialized. - uint64_t FileSize; - /// HasInstructions - Whether this section has had instructions emitted into /// it. unsigned HasInstructions : 1; @@ -409,6 +486,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 /// @{ @@ -431,36 +517,9 @@ public: bool empty() const { return Fragments.empty(); } - /// @} - /// @name Assembler Backend Support - /// @{ - // - // FIXME: This could all be kept private to the assembler implementation. - - 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 { - assert(Size != ~UINT64_C(0) && "File size not set!"); - return Size; - } - void setSize(uint64_t Value) { Size = Value; } - - uint64_t getFileSize() const { - assert(FileSize != ~UINT64_C(0) && "File size not set!"); - return FileSize; - } - void setFileSize(uint64_t Value) { FileSize = Value; } - - bool hasInstructions() const { return HasInstructions; } - void setHasInstructions(bool Value) { HasInstructions = Value; } + void dump(); /// @} - - void dump(); }; // FIXME: Same concerns as with SectionData. @@ -488,6 +547,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? @@ -517,11 +580,6 @@ public: uint64_t getOffset() const { return Offset; } void setOffset(uint64_t Value) { Offset = Value; } - uint64_t getAddress() const { - assert(getFragment() && "Invalid getAddress() on undefined symbol!"); - return getFragment()->getAddress() + getOffset(); - } - /// @} /// @name Symbol Attributes /// @{ @@ -550,6 +608,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!"); @@ -562,6 +629,11 @@ 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; } @@ -579,7 +651,19 @@ struct IndirectSymbolData { MCSectionData *SectionData; }; +// FIXME: Ditto this. Purely so the Streamer and the ObjectWriter can talk +// to one another. +struct DataRegionData { + // This enum should be kept in sync w/ the mach-o definition in + // llvm/Object/MachOFormat.h. + enum KindTy { Data = 1, JumpTable8, JumpTable16, JumpTable32 } Kind; + MCSymbol *Start; + MCSymbol *End; +}; + class MCAssembler { + friend class MCAsmLayout; + public: typedef iplist SectionDataListType; typedef iplist SymbolDataListType; @@ -590,15 +674,25 @@ 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; + typedef std::vector::const_iterator + const_data_region_iterator; + typedef std::vector::iterator data_region_iterator; + private: - MCAssembler(const MCAssembler&); // DO NOT IMPLEMENT - void operator=(const MCAssembler&); // DO NOT IMPLEMENT + MCAssembler(const MCAssembler&) LLVM_DELETED_FUNCTION; + void operator=(const MCAssembler&) LLVM_DELETED_FUNCTION; MCContext &Context; - TargetAsmBackend &Backend; + MCAsmBackend &Backend; + + MCCodeEmitter &Emitter; + + MCObjectWriter &Writer; raw_ostream &OS; @@ -618,24 +712,21 @@ private: std::vector IndirectSymbols; + std::vector DataRegions; + /// 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 NoExecStack : 1; unsigned SubsectionsViaSymbols : 1; private: - /// 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(MCAsmFixup &Fixup, MCDataFragment *DF); - - /// 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); - - /// LayoutOnce - Perform one layout iteration and return true if any offsets - /// were adjusted. - bool LayoutOnce(); - - // FIXME: Make protected once we factor out object writer classes. -public: /// Evaluate a fixup to a relocatable expression and the value which should be /// placed into the fixup. /// @@ -644,32 +735,97 @@ public: /// \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 + /// \param Value [out] On return, the value of the fixup as currently laid /// 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 + /// \p Value result is fixed, otherwise the value may change due to /// relocation. - bool EvaluateFixup(const MCAsmLayout &Layout, - MCAsmFixup &Fixup, MCDataFragment *DF, + 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 MCInstFragment *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 relaxLEB(MCAsmLayout &Layout, MCLEBFragment &IF); + + bool relaxDwarfLineAddr(MCAsmLayout &Layout, MCDwarfLineAddrFragment &DF); + bool relaxDwarfCallFrameFragment(MCAsmLayout &Layout, + MCDwarfCallFrameFragment &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 laid out at the given + /// \p SectionAddress and \p FragmentOffset. + uint64_t computeFragmentSize(const MCAsmLayout &Layout, + 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. /// - /// \arg OS - The stream to output to. + /// \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, TargetAsmBackend &_Backend, raw_ostream &OS); + MCAssembler(MCContext &Context_, MCAsmBackend &Backend_, + MCCodeEmitter &Emitter_, MCObjectWriter &Writer_, + raw_ostream &OS); ~MCAssembler(); MCContext &getContext() const { return Context; } - TargetAsmBackend &getBackend() const { return Backend; } + MCAsmBackend &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. + /// \p 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. @@ -680,6 +836,12 @@ public: SubsectionsViaSymbols = Value; } + bool getRelaxAll() const { return RelaxAll; } + void setRelaxAll(bool Value) { RelaxAll = Value; } + + bool getNoExecStack() const { return NoExecStack; } + void setNoExecStack(bool Value) { NoExecStack = Value; } + /// @name Section List Access /// @{ @@ -723,13 +885,46 @@ 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 Data Region List Access + /// @{ + + // FIXME: This is a total hack, this should not be here. Once things are + // factored so that the streamer has direct access to the .o writer, it can + // disappear. + std::vector &getDataRegions() { + return DataRegions; + } + + data_region_iterator data_region_begin() { + return DataRegions.begin(); + } + const_data_region_iterator data_region_begin() const { + return DataRegions.begin(); + } + + data_region_iterator data_region_end() { + return DataRegions.end(); + } + const_data_region_iterator data_region_end() const { + return DataRegions.end(); + } + + size_t data_region_size() const { return DataRegions.size(); } + /// @} /// @name Backend Data Access /// @{