X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=include%2Fllvm%2FMC%2FMCAssembler.h;h=83c01ec5b98f2de2cd274f20e22a754928d24d96;hb=34aadd63346b5f9b98749a306b71fcb00ee6996f;hp=e0e009526dd0700b88eba7a736e972460411a92e;hpb=1c15413ebc8f4a35545a381a789a718627396d03;p=oota-llvm.git diff --git a/include/llvm/MC/MCAssembler.h b/include/llvm/MC/MCAssembler.h index e0e009526dd..83c01ec5b98 100644 --- a/include/llvm/MC/MCAssembler.h +++ b/include/llvm/MC/MCAssembler.h @@ -10,14 +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/MC/MCInst.h" -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include // FIXME: Shouldn't be needed. namespace llvm { @@ -34,34 +35,13 @@ 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. -// -// FIXME: This should probably just be merged with MCFixup. -class MCAsmFixup { -public: - /// 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; - -public: - MCAsmFixup(uint64_t _Offset, const MCExpr &_Value, MCFixupKind _Kind) - : Offset(_Offset), Value(&_Value), Kind(_Kind) {} -}; +class MCAsmBackend; class MCFragment : public ilist_node { friend class MCAsmLayout; - MCFragment(const MCFragment&); // DO NOT IMPLEMENT - void operator=(const MCFragment&); // DO NOT IMPLEMENT + MCFragment(const MCFragment&) LLVM_DELETED_FUNCTION; + void operator=(const MCFragment&) LLVM_DELETED_FUNCTION; public: enum FragmentType { @@ -69,7 +49,10 @@ public: FT_Data, FT_Fill, FT_Inst, - FT_Org + FT_Org, + FT_Dwarf, + FT_DwarfFrame, + FT_LEB }; private: @@ -92,13 +75,8 @@ private: /// initialized. uint64_t Offset; - /// EffectiveSize - The compute size of this section. This is ~0 until - /// initialized. - uint64_t EffectiveSize; - - /// Ordinal - The global index of this fragment. This is the index across all - /// sections, not just the parent section. - unsigned Ordinal; + /// LayoutOrder - The layout order of this fragment. + unsigned LayoutOrder; /// @} @@ -118,23 +96,24 @@ public: MCSymbolData *getAtom() const { return Atom; } void setAtom(MCSymbolData *Value) { Atom = Value; } - unsigned getOrdinal() const { return Ordinal; } - void setOrdinal(unsigned Value) { Ordinal = 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) {} @@ -149,15 +128,15 @@ public: /// @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(); } @@ -173,8 +152,6 @@ public: return F->getKind() == MCFragment::FT_Data; } static bool classof(const MCDataFragment *) { return true; } - - virtual void dump(); }; // FIXME: This current incarnation of MCInstFragment doesn't make much sense, as @@ -183,21 +160,23 @@ public: // 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; - /// InstSize - The size of the currently encoded instruction. + /// Code - Binary data for the currently encoded instruction. SmallString<8> Code; /// Fixups - The list of fixups in this fragment. - SmallVector Fixups; + SmallVector Fixups; public: - typedef SmallVectorImpl::const_iterator const_fixup_iterator; - typedef SmallVectorImpl::iterator fixup_iterator; + typedef SmallVectorImpl::const_iterator const_fixup_iterator; + typedef SmallVectorImpl::iterator fixup_iterator; public: - MCInstFragment(MCInst _Inst, MCSectionData *SD = 0) + MCInstFragment(const MCInst &_Inst, MCSectionData *SD = 0) : MCFragment(FT_Inst, SD), Inst(_Inst) { } @@ -212,14 +191,14 @@ public: MCInst &getInst() { return Inst; } const MCInst &getInst() const { return Inst; } - void setInst(MCInst Value) { Inst = Value; } + void setInst(const MCInst& Value) { Inst = Value; } /// @} /// @name Fixup Access /// @{ - SmallVectorImpl &getFixups() { return Fixups; } - const SmallVectorImpl &getFixups() const { return Fixups; } + 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(); } @@ -235,18 +214,18 @@ public: return F->getKind() == MCFragment::FT_Inst; } static bool classof(const MCInstFragment *) { return true; } - - virtual void dump(); }; 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 @@ -285,15 +264,15 @@ 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, or 0 if + /// ValueSize - The size (in bytes) of \p Value to use when filling, or 0 if /// this is a virtual fill fragment. unsigned ValueSize; @@ -324,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; @@ -353,8 +332,106 @@ public: return F->getKind() == MCFragment::FT_Org; } static bool classof(const MCOrgFragment *) { return true; } +}; + +class MCLEBFragment : public MCFragment { + virtual void anchor(); + + /// 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_, MCSectionData *SD) + : MCFragment(FT_LEB, SD), + 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; + } + static bool classof(const MCLEBFragment *) { return true; } +}; + +class MCDwarfLineAddrFragment : public MCFragment { + virtual void anchor(); + + /// 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_Dwarf; + } + static bool classof(const MCDwarfLineAddrFragment *) { return true; } +}; + +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; } - virtual void dump(); + /// @} + + 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 @@ -363,8 +440,8 @@ public: class MCSectionData : public ilist_node { friend class MCAsmLayout; - MCSectionData(const MCSectionData&); // DO NOT IMPLEMENT - void operator=(const MCSectionData&); // DO NOT IMPLEMENT + MCSectionData(const MCSectionData&) LLVM_DELETED_FUNCTION; + void operator=(const MCSectionData&) LLVM_DELETED_FUNCTION; public: typedef iplist FragmentListType; @@ -376,12 +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; @@ -390,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; @@ -423,6 +492,9 @@ public: 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 /// @{ @@ -475,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? @@ -532,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!"); @@ -566,6 +651,16 @@ 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; @@ -583,16 +678,22 @@ public: 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; iplist Sections; @@ -611,7 +712,18 @@ 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: @@ -623,79 +735,97 @@ private: /// \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, - const MCAsmFixup &Fixup, const MCFragment *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 MCAsmFixup &Fixup, const MCFragment *DF, + bool fixupNeedsRelaxation(const MCFixup &Fixup, const MCInstFragment *DF, const MCAsmLayout &Layout) const; /// Check whether the given fragment needs relaxation. - bool FragmentNeedsRelaxation(const MCInstFragment *IF, + bool fragmentNeedsRelaxation(const MCInstFragment *IF, const MCAsmLayout &Layout) const; - /// LayoutFragment - Performs layout of the given \arg Fragment; assuming that - /// the previous fragment has already been layed out correctly, and the parent - /// section has been initialized. - void LayoutFragment(MCAsmLayout &Layout, MCFragment &Fragment); + /// layoutOnce - Perform one layout iteration and return true if any offsets + /// were adjusted. + bool layoutOnce(MCAsmLayout &Layout); - /// LayoutSection - Performs layout of the section referenced by the given - /// \arg SectionOrderIndex. The layout assumes that the previous section has - /// already been layed out correctly. - void LayoutSection(MCAsmLayout &Layout, unsigned SectionOrderIndex); + bool layoutSectionOnce(MCAsmLayout &Layout, MCSectionData &SD); - /// LayoutOnce - Perform one layout iteration and return true if any offsets - /// were adjusted. - bool LayoutOnce(MCAsmLayout &Layout); + 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); + /// 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 MCAsmLayout &Layout, - const MCSymbolData *Symbol) const; + 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 MCSymbolData *SD) const; + bool isSymbolLinkerVisible(const MCSymbol &SD) const; /// Emit the section contents using the given object writer. - // - // FIXME: Should MCAssembler always have a reference to the object writer? - void WriteSectionData(const MCSectionData *Section, const MCAsmLayout &Layout, - MCObjectWriter *OW) const; + 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, - MCCodeEmitter &_Emitter, 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. @@ -709,6 +839,9 @@ public: 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 /// @{ @@ -765,6 +898,33 @@ public: 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 /// @{