X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=include%2Fllvm%2FMC%2FMCAssembler.h;h=5771415c81cc42b6c962e9cdcce071bcd7b2fee6;hb=2128aaebd850edc0415ab8f37b907077651d4399;hp=8a5009ffc4269babc6273da2fda5f3dc95e1c9e9;hpb=85f2ecc697a8ca6c8cf08093054cbbb9d2060ccf;p=oota-llvm.git diff --git a/include/llvm/MC/MCAssembler.h b/include/llvm/MC/MCAssembler.h index 8a5009ffc42..5771415c81c 100644 --- a/include/llvm/MC/MCAssembler.h +++ b/include/llvm/MC/MCAssembler.h @@ -10,13 +10,14 @@ #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/Support/DataTypes.h" #include // FIXME: Shouldn't be needed. @@ -24,7 +25,6 @@ namespace llvm { class raw_ostream; class MCAsmLayout; class MCAssembler; -class MCBinaryExpr; class MCContext; class MCCodeEmitter; class MCExpr; @@ -35,13 +35,13 @@ class MCSectionData; class MCSymbol; class MCSymbolData; class MCValue; -class TargetAsmBackend; +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 { @@ -51,6 +51,7 @@ public: FT_Inst, FT_Org, FT_Dwarf, + FT_DwarfFrame, FT_LEB }; @@ -74,12 +75,7 @@ private: /// initialized. uint64_t Offset; - /// EffectiveSize - The compute size of this section. This is ~0 until - /// initialized. - uint64_t EffectiveSize; - - /// LayoutOrder - The global layout order of this fragment. This is the index - /// across all fragments in the file, not just within the section. + /// LayoutOrder - The layout order of this fragment. unsigned LayoutOrder; /// @} @@ -103,12 +99,11 @@ public: 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 { + virtual void anchor(); SmallString<32> Contents; /// Fixups - The list of fixups in this fragment. @@ -133,7 +128,7 @@ public: void addFixup(MCFixup Fixup) { // Enforce invariant that fixups are in offset order. - assert((Fixups.empty() || Fixup.getOffset() > Fixups.back().getOffset()) && + assert((Fixups.empty() || Fixup.getOffset() >= Fixups.back().getOffset()) && "Fixups must be added in order!"); Fixups.push_back(Fixup); } @@ -154,7 +149,6 @@ public: static bool classof(const MCFragment *F) { 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 @@ -163,6 +157,8 @@ 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; @@ -177,7 +173,7 @@ public: 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) { } @@ -192,7 +188,7 @@ 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 @@ -214,17 +210,18 @@ public: 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 @@ -262,14 +259,15 @@ public: static bool classof(const MCFragment *F) { return F->getKind() == MCFragment::FT_Align; } - static bool classof(const MCAlignFragment *) { return true; } }; 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; @@ -299,23 +297,21 @@ public: static bool classof(const MCFragment *F) { return F->getKind() == MCFragment::FT_Fill; } - static bool classof(const MCFillFragment *) { return true; } }; class MCOrgFragment : public MCFragment { + virtual void anchor(); + /// Offset - The offset this fragment should start at. const MCExpr *Offset; /// Value - Value to use for filling bytes. int8_t Value; - /// Size - The current estimate of the size. - unsigned Size; - public: MCOrgFragment(const MCExpr &_Offset, int8_t _Value, MCSectionData *SD = 0) : MCFragment(FT_Org, SD), - Offset(&_Offset), Value(_Value), Size(0) {} + Offset(&_Offset), Value(_Value) {} /// @name Accessors /// @{ @@ -324,18 +320,16 @@ public: 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 MCOrgFragment *) { return true; } }; class MCLEBFragment : public MCFragment { + virtual void anchor(); + /// Value - The value this fragment should contain. const MCExpr *Value; @@ -363,10 +357,11 @@ public: 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; @@ -379,7 +374,7 @@ class MCDwarfLineAddrFragment : public MCFragment { public: MCDwarfLineAddrFragment(int64_t _LineDelta, const MCExpr &_AddrDelta, - MCSectionData *SD = 0) + MCSectionData *SD) : MCFragment(FT_Dwarf, SD), LineDelta(_LineDelta), AddrDelta(&_AddrDelta) { Contents.push_back(0); } @@ -398,7 +393,35 @@ public: 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; } + + /// @} + + static bool classof(const MCFragment *F) { + return F->getKind() == MCFragment::FT_DwarfFrame; + } }; // FIXME: Should this be a separate class, or just merged into MCSection? Since @@ -407,8 +430,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; @@ -618,6 +641,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; @@ -635,16 +668,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; @@ -663,7 +702,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: @@ -675,54 +725,50 @@ 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 MCObjectWriter &Writer, const MCAsmLayout &Layout, + 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 MCObjectWriter &Writer, - const MCFixup &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 MCObjectWriter &Writer, - const MCInstFragment *IF, + bool fragmentNeedsRelaxation(const MCInstFragment *IF, const MCAsmLayout &Layout) const; - /// Compute the effective fragment size assuming it is layed out at the given - /// \arg SectionAddress and \arg FragmentOffset. - uint64_t ComputeFragmentSize(const MCFragment &F, - uint64_t FragmentOffset) const; - - /// LayoutOnce - Perform one layout iteration and return true if any offsets + /// layoutOnce - Perform one layout iteration and return true if any offsets /// were adjusted. - bool LayoutOnce(const MCObjectWriter &Writer, MCAsmLayout &Layout); + bool layoutOnce(MCAsmLayout &Layout); - bool RelaxInstruction(const MCObjectWriter &Writer, MCAsmLayout &Layout, - MCInstFragment &IF); + bool layoutSectionOnce(MCAsmLayout &Layout, MCSectionData &SD); - bool RelaxOrg(const MCObjectWriter &Writer, MCAsmLayout &Layout, - MCOrgFragment &OF); + bool relaxInstruction(MCAsmLayout &Layout, MCInstFragment &IF); - bool RelaxLEB(const MCObjectWriter &Writer, MCAsmLayout &Layout, - MCLEBFragment &IF); + bool relaxLEB(MCAsmLayout &Layout, MCLEBFragment &IF); - bool RelaxDwarfLineAddr(const MCObjectWriter &Writer, MCAsmLayout &Layout, - MCDwarfLineAddrFragment &DF); + 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(MCObjectWriter &Writer, const 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; @@ -734,34 +780,43 @@ public: 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. - /// \arg Writer is used for custom object writer (as the MCJIT does), + /// \p Writer is used for custom object writer (as the MCJIT does), /// if not specified it is automatically created from backend. - void Finish(MCObjectWriter *Writer = 0); + void Finish(); // FIXME: This does not belong here. bool getSubsectionsViaSymbols() const { @@ -774,6 +829,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 /// @{ @@ -830,6 +888,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 /// @{