aboutsummaryrefslogtreecommitdiff
path: root/include/llvm/MC/MCAssembler.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/llvm/MC/MCAssembler.h')
-rw-r--r--include/llvm/MC/MCAssembler.h214
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);