diff options
Diffstat (limited to 'include/llvm/MC/MCAssembler.h')
-rw-r--r-- | include/llvm/MC/MCAssembler.h | 214 |
1 files changed, 158 insertions, 56 deletions
diff --git a/include/llvm/MC/MCAssembler.h b/include/llvm/MC/MCAssembler.h index 0ecb66c734..949e99b50b 100644 --- a/include/llvm/MC/MCAssembler.h +++ b/include/llvm/MC/MCAssembler.h @@ -10,13 +10,13 @@ #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/MC/MCFixup.h" -#include "llvm/MC/MCInst.h" #include "llvm/Support/Casting.h" #include "llvm/Support/DataTypes.h" #include <vector> // FIXME: Shouldn't be needed. @@ -52,11 +52,39 @@ public: FT_Org, FT_Dwarf, FT_DwarfFrame, - FT_LEB + FT_LEB, + FT_Tiny // @LOCALMOD }; + // @LOCALMOD-BEGIN + enum BundleAlignType { + BundleAlignNone = 0, + BundleAlignStart = 1, + BundleAlignEnd = 2 + }; + // @LOCALMOD-END + private: - FragmentType Kind; + // @LOCALMOD-BEGIN + // Try to compress the layout of MCFragment by: + // 1) Making Kind, the bundling flags, and BundlePadding fit in 32 bits. + // 2) Move LayoutOrder to fit in the hole left by aligning for 64 bits. + + FragmentType Kind : 4; + + BundleAlignType BundleAlign : 2; + bool BundleGroupStart : 1; + bool BundleGroupEnd : 1; + + /// BundlePadding - The computed padding for this fragment. This is ~0 + /// until initialized. + uint8_t BundlePadding; + + /// LayoutOrder - The layout order of this fragment. + unsigned LayoutOrder; + + // @LOCALMOD-END + /// Parent - The data for the section this fragment is in. MCSectionData *Parent; @@ -75,9 +103,6 @@ private: /// initialized. uint64_t Offset; - /// LayoutOrder - The layout order of this fragment. - unsigned LayoutOrder; - /// @} protected: @@ -99,102 +124,135 @@ public: unsigned getLayoutOrder() const { return LayoutOrder; } void setLayoutOrder(unsigned Value) { LayoutOrder = Value; } + // @LOCALMOD-BEGIN + bool isBundleGroupStart() const { return BundleGroupStart; } + void setBundleGroupStart(bool Value) { BundleGroupStart = Value; } + + bool isBundleGroupEnd() const { return BundleGroupEnd; } + void setBundleGroupEnd(bool Value) { BundleGroupEnd = Value; } + + BundleAlignType getBundleAlign() const { return BundleAlign; } + void setBundleAlign(BundleAlignType Value) { BundleAlign = Value; } + // @LOCALMOD-END + void dump(); }; -class MCEncodedFragment : public MCFragment { - virtual void anchor(); -public: - MCEncodedFragment(MCFragment::FragmentType FType, MCSectionData *SD = 0) - : MCFragment(FType, SD) { - } - virtual ~MCEncodedFragment(); +// @LOCALMOD-BEGIN +// This is just a tiny data fragment with no fixups. +// (To help with memory usage) +class MCTinyFragment : public MCFragment { + private: + SmallString<6> Contents; - typedef SmallVectorImpl<MCFixup>::const_iterator const_fixup_iterator; - typedef SmallVectorImpl<MCFixup>::iterator fixup_iterator; - - virtual SmallVectorImpl<char> &getContents() = 0; - virtual const SmallVectorImpl<char> &getContents() const = 0; + public: - virtual SmallVectorImpl<MCFixup> &getFixups() = 0; - virtual const SmallVectorImpl<MCFixup> &getFixups() const = 0; + MCTinyFragment(MCSectionData *SD = 0) : MCFragment(FT_Tiny, SD) {} - virtual fixup_iterator fixup_begin() = 0; - virtual const_fixup_iterator fixup_begin() const = 0; - virtual fixup_iterator fixup_end() = 0; - virtual const_fixup_iterator fixup_end() const = 0; + SmallString<6> &getContents() { return Contents; } + const SmallString<6> &getContents() const { return Contents; } static bool classof(const MCFragment *F) { - MCFragment::FragmentType Kind = F->getKind(); - return Kind == MCFragment::FT_Inst || Kind == MCFragment::FT_Data; + return F->getKind() == MCFragment::FT_Tiny; } + static bool classof(const MCTinyFragment *) { return true; } }; +// @LOCALMOD-END -class MCDataFragment : public MCEncodedFragment { +class MCDataFragment : public MCFragment { virtual void anchor(); - SmallVector<char, 32> Contents; + SmallString<6> Contents; // @LOCALMOD: Memory efficiency /// Fixups - The list of fixups in this fragment. - SmallVector<MCFixup, 4> Fixups; + std::vector<MCFixup> Fixups; public: - MCDataFragment(MCSectionData *SD = 0) - : MCEncodedFragment(FT_Data, SD) { - } + typedef std::vector<MCFixup>::const_iterator const_fixup_iterator; + typedef std::vector<MCFixup>::iterator fixup_iterator; - virtual SmallVectorImpl<char> &getContents() { return Contents; } - virtual const SmallVectorImpl<char> &getContents() const { return Contents; } +public: + MCDataFragment(MCSectionData *SD = 0) : MCFragment(FT_Data, SD) {} - SmallVectorImpl<MCFixup> &getFixups() { - return Fixups; - } + /// @name Accessors + /// @{ - const SmallVectorImpl<MCFixup> &getFixups() const { - return Fixups; + SmallString<6> &getContents() { return Contents; } // @LOCALMOD + const SmallString<6> &getContents() const { return Contents; } // @LOCALMOD + + /// @} + /// @name Fixup Access + /// @{ + + 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); } + std::vector<MCFixup> &getFixups() { return Fixups; } + const std::vector<MCFixup> &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; } }; -class MCInstFragment : public MCEncodedFragment { +// 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; - /// Contents - Binary data for the currently encoded instruction. - SmallVector<char, 8> Contents; + /// Code - Binary data for the currently encoded instruction. + SmallString<8> Code; /// Fixups - The list of fixups in this fragment. SmallVector<MCFixup, 1> Fixups; public: + typedef SmallVectorImpl<MCFixup>::const_iterator const_fixup_iterator; + typedef SmallVectorImpl<MCFixup>::iterator fixup_iterator; + +public: MCInstFragment(const MCInst &_Inst, MCSectionData *SD = 0) - : MCEncodedFragment(FT_Inst, SD), Inst(_Inst) { + : MCFragment(FT_Inst, SD), Inst(_Inst) { } - virtual SmallVectorImpl<char> &getContents() { return Contents; } - virtual const SmallVectorImpl<char> &getContents() const { return Contents; } + /// @name Accessors + /// @{ + + SmallVectorImpl<char> &getCode() { return Code; } + const SmallVectorImpl<char> &getCode() const { return Code; } + + unsigned getInstSize() const { return Code.size(); } - unsigned getInstSize() const { return Contents.size(); } + MCInst &getInst() { return Inst; } const MCInst &getInst() const { return Inst; } + void setInst(const MCInst& Value) { Inst = Value; } - SmallVectorImpl<MCFixup> &getFixups() { - return Fixups; - } + /// @} + /// @name Fixup Access + /// @{ - const SmallVectorImpl<MCFixup> &getFixups() const { - return Fixups; - } + SmallVectorImpl<MCFixup> &getFixups() { return Fixups; } + const SmallVectorImpl<MCFixup> &getFixups() const { return Fixups; } fixup_iterator fixup_begin() { return Fixups.begin(); } const_fixup_iterator fixup_begin() const { return Fixups.begin(); } @@ -202,6 +260,10 @@ public: 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; } @@ -459,6 +521,29 @@ private: /// it. unsigned HasInstructions : 1; + // @LOCALMOD-BEGIN + bool BundlingEnabled : 1; + bool BundleLocked : 1; + + // Because ".bundle_lock" occurs before the fragment it applies to exists, + // we need to keep this flag around so we know to mark the next fragment + // as the start of a bundle group. A similar flag is not necessary for the + // last fragment, because when a .bundle_unlock occurs, the last fragment + // in the group already exists and can be marked directly. + bool BundleGroupFirstFrag : 1; + + typedef MCFragment::BundleAlignType BundleAlignType; + BundleAlignType BundleAlignNext : 2; + + // Optimization to reduce the number of fragments generated (for memory + // savings). Keep track of when we know the offset of the next point to + // emit an instruction. If we know the offset from a known alignment point, + // we can just append to the previous fragment. + bool BundleOffsetKnown : 1; + unsigned BundleSize; + unsigned BundleOffset; + // @LOCALMOD-END + /// @} public: @@ -480,6 +565,25 @@ public: unsigned getLayoutOrder() const { return LayoutOrder; } void setLayoutOrder(unsigned Value) { LayoutOrder = Value; } + // @LOCALMOD-BEGIN + bool isBundlingEnabled() const { return BundlingEnabled; } + + bool isBundleLocked() const { return BundleLocked; } + void setBundleLocked(bool Value) { BundleLocked = Value; } + + bool isBundleGroupFirstFrag() const { return BundleGroupFirstFrag; } + void setBundleGroupFirstFrag(bool Value) { BundleGroupFirstFrag = Value; } + + + BundleAlignType getBundleAlignNext() const { return BundleAlignNext; } + void setBundleAlignNext(BundleAlignType Value) { BundleAlignNext = Value; } + + void MarkBundleOffsetUnknown(); + bool ShouldCreateNewFragment(size_t Size); + void UpdateBundleOffset(size_t Size); + void AlignBundleOffsetTo(size_t AlignBase); + // @LOCALMOD-END + /// @name Fragment Access /// @{ @@ -738,12 +842,10 @@ private: bool fragmentNeedsRelaxation(const MCInstFragment *IF, const MCAsmLayout &Layout) const; - /// \brief 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(MCAsmLayout &Layout); - /// \brief Perform one layout iteration of the given section and return true - /// if any offsets were adjusted. bool layoutSectionOnce(MCAsmLayout &Layout, MCSectionData &SD); bool relaxInstruction(MCAsmLayout &Layout, MCInstFragment &IF); |