aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/llvm/MC/MCAssembler.h105
-rw-r--r--lib/MC/MCAssembler.cpp36
-rw-r--r--lib/MC/MCELFStreamer.cpp14
3 files changed, 135 insertions, 20 deletions
diff --git a/include/llvm/MC/MCAssembler.h b/include/llvm/MC/MCAssembler.h
index 57aa08a2d0..8269f08c44 100644
--- a/include/llvm/MC/MCAssembler.h
+++ b/include/llvm/MC/MCAssembler.h
@@ -47,6 +47,7 @@ public:
enum FragmentType {
FT_Align,
FT_Data,
+ FT_CompactEncodedInst,
FT_Fill,
FT_Relaxable,
FT_Org,
@@ -105,6 +106,7 @@ public:
/// \brief Should this fragment be placed at the end of an aligned bundle?
virtual bool alignToBundleEnd() const { return false; }
+ virtual void setAlignToBundleEnd(bool V) { }
/// \brief Get the padding size that must be inserted before this fragment.
/// Used for bundling. By default, no padding is inserted.
@@ -120,9 +122,16 @@ public:
virtual void setBundlePadding(uint8_t N) {
}
+ virtual bool hasFixups() const {
+ return false;
+ }
+
void dump();
};
+/// Interface implemented by fragments that contain encoded instructions and/or
+/// data.
+///
class MCEncodedFragment : public MCFragment {
virtual void anchor();
@@ -134,20 +143,9 @@ public:
}
virtual ~MCEncodedFragment();
- 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;
- virtual SmallVectorImpl<MCFixup> &getFixups() = 0;
- virtual const SmallVectorImpl<MCFixup> &getFixups() const = 0;
-
- 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;
-
virtual uint8_t getBundlePadding() const {
return BundlePadding;
}
@@ -158,13 +156,55 @@ public:
static bool classof(const MCFragment *F) {
MCFragment::FragmentType Kind = F->getKind();
- return Kind == MCFragment::FT_Relaxable || Kind == MCFragment::FT_Data;
+ switch (Kind) {
+ default:
+ return false;
+ case MCFragment::FT_Relaxable:
+ case MCFragment::FT_CompactEncodedInst:
+ case MCFragment::FT_Data:
+ return true;
+ }
+ }
+};
+
+/// Interface implemented by fragments that contain encoded instructions and/or
+/// data and also have fixups registered.
+///
+class MCEncodedFragmentWithFixups : public MCEncodedFragment {
+ virtual void anchor();
+
+public:
+ MCEncodedFragmentWithFixups(MCFragment::FragmentType FType,
+ MCSectionData *SD = 0)
+ : MCEncodedFragment(FType, SD)
+ {
+ }
+
+ virtual ~MCEncodedFragmentWithFixups();
+
+ virtual bool hasFixups() const {
+ return true;
+ }
+
+ typedef SmallVectorImpl<MCFixup>::const_iterator const_fixup_iterator;
+ typedef SmallVectorImpl<MCFixup>::iterator fixup_iterator;
+
+ virtual SmallVectorImpl<MCFixup> &getFixups() = 0;
+ virtual const SmallVectorImpl<MCFixup> &getFixups() const = 0;
+
+ 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;
+
+ static bool classof(const MCFragment *F) {
+ return isa<MCEncodedFragment>(F) && F->hasFixups();
}
};
/// Fragment for data and encoded instructions.
///
-class MCDataFragment : public MCEncodedFragment {
+class MCDataFragment : public MCEncodedFragmentWithFixups {
virtual void anchor();
/// \brief Does this fragment contain encoded instructions anywhere in it?
@@ -179,7 +219,7 @@ class MCDataFragment : public MCEncodedFragment {
SmallVector<MCFixup, 4> Fixups;
public:
MCDataFragment(MCSectionData *SD = 0)
- : MCEncodedFragment(FT_Data, SD),
+ : MCEncodedFragmentWithFixups(FT_Data, SD),
HasInstructions(false), AlignToBundleEnd(false)
{
}
@@ -212,10 +252,43 @@ public:
}
};
+/// This is a compact (memory-size-wise) fragment for holding an encoded
+/// instruction (non-relaxable) that has no fixups registered. When applicable,
+/// it can be used instead of MCDataFragment and lead to lower memory
+/// consumption.
+///
+class MCCompactEncodedInstFragment : public MCEncodedFragment {
+ virtual void anchor();
+
+ /// \brief Should this fragment be aligned to the end of a bundle?
+ bool AlignToBundleEnd;
+
+ SmallVector<char, 4> Contents;
+public:
+ MCCompactEncodedInstFragment(MCSectionData *SD = 0)
+ : MCEncodedFragment(FT_CompactEncodedInst, SD), AlignToBundleEnd(false)
+ {
+ }
+
+ virtual bool hasInstructions() const {
+ return true;
+ }
+
+ virtual SmallVectorImpl<char> &getContents() { return Contents; }
+ virtual const SmallVectorImpl<char> &getContents() const { return Contents; }
+
+ virtual bool alignToBundleEnd() const { return AlignToBundleEnd; }
+ virtual void setAlignToBundleEnd(bool V) { AlignToBundleEnd = V; }
+
+ static bool classof(const MCFragment *F) {
+ return F->getKind() == MCFragment::FT_CompactEncodedInst;
+ }
+};
+
/// A relaxable fragment holds on to its MCInst, since it may need to be
/// relaxed during the assembler layout and relaxation stage.
///
-class MCRelaxableFragment : public MCEncodedFragment {
+class MCRelaxableFragment : public MCEncodedFragmentWithFixups {
virtual void anchor();
/// Inst - The instruction this is a fragment for.
@@ -229,7 +302,7 @@ class MCRelaxableFragment : public MCEncodedFragment {
public:
MCRelaxableFragment(const MCInst &_Inst, MCSectionData *SD = 0)
- : MCEncodedFragment(FT_Relaxable, SD), Inst(_Inst) {
+ : MCEncodedFragmentWithFixups(FT_Relaxable, SD), Inst(_Inst) {
}
virtual SmallVectorImpl<char> &getContents() { return Contents; }
diff --git a/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp
index 5fdc57ad30..c51ddc800e 100644
--- a/lib/MC/MCAssembler.cpp
+++ b/lib/MC/MCAssembler.cpp
@@ -38,6 +38,8 @@ STATISTIC(EmittedRelaxableFragments,
"Number of emitted assembler fragments - relaxable");
STATISTIC(EmittedDataFragments,
"Number of emitted assembler fragments - data");
+STATISTIC(EmittedCompactEncodedInstFragments,
+ "Number of emitted assembler fragments - compact encoded inst");
STATISTIC(EmittedAlignFragments,
"Number of emitted assembler fragments - align");
STATISTIC(EmittedFillFragments,
@@ -222,6 +224,11 @@ MCEncodedFragment::~MCEncodedFragment() {
/* *** */
+MCEncodedFragmentWithFixups::~MCEncodedFragmentWithFixups() {
+}
+
+/* *** */
+
MCSectionData::MCSectionData() : Section(0) {}
MCSectionData::MCSectionData(const MCSection &_Section, MCAssembler *A)
@@ -388,6 +395,7 @@ uint64_t MCAssembler::computeFragmentSize(const MCAsmLayout &Layout,
switch (F.getKind()) {
case MCFragment::FT_Data:
case MCFragment::FT_Relaxable:
+ case MCFragment::FT_CompactEncodedInst:
return cast<MCEncodedFragment>(F).getContents().size();
case MCFragment::FT_Fill:
return cast<MCFillFragment>(F).getSize();
@@ -570,6 +578,11 @@ static void writeFragment(const MCAssembler &Asm, const MCAsmLayout &Layout,
writeFragmentContents(F, OW);
break;
+ case MCFragment::FT_CompactEncodedInst:
+ ++stats::EmittedCompactEncodedInstFragments;
+ writeFragmentContents(F, OW);
+ break;
+
case MCFragment::FT_Fill: {
++stats::EmittedFillFragments;
MCFillFragment &FF = cast<MCFillFragment>(F);
@@ -742,9 +755,10 @@ void MCAssembler::Finish() {
for (MCAssembler::iterator it = begin(), ie = end(); it != ie; ++it) {
for (MCSectionData::iterator it2 = it->begin(),
ie2 = it->end(); it2 != ie2; ++it2) {
- MCEncodedFragment *F = dyn_cast<MCEncodedFragment>(it2);
+ MCEncodedFragmentWithFixups *F =
+ dyn_cast<MCEncodedFragmentWithFixups>(it2);
if (F) {
- for (MCEncodedFragment::fixup_iterator it3 = F->fixup_begin(),
+ for (MCEncodedFragmentWithFixups::fixup_iterator it3 = F->fixup_begin(),
ie3 = F->fixup_end(); it3 != ie3; ++it3) {
MCFixup &Fixup = *it3;
uint64_t FixedValue = handleFixup(Layout, *F, Fixup);
@@ -954,6 +968,8 @@ void MCFragment::dump() {
switch (getKind()) {
case MCFragment::FT_Align: OS << "MCAlignFragment"; break;
case MCFragment::FT_Data: OS << "MCDataFragment"; break;
+ case MCFragment::FT_CompactEncodedInst:
+ OS << "MCCompactEncodedInstFragment"; break;
case MCFragment::FT_Fill: OS << "MCFillFragment"; break;
case MCFragment::FT_Relaxable: OS << "MCRelaxableFragment"; break;
case MCFragment::FT_Org: OS << "MCOrgFragment"; break;
@@ -1001,6 +1017,19 @@ void MCFragment::dump() {
}
break;
}
+ case MCFragment::FT_CompactEncodedInst: {
+ const MCCompactEncodedInstFragment *CEIF =
+ cast<MCCompactEncodedInstFragment>(this);
+ OS << "\n ";
+ OS << " Contents:[";
+ const SmallVectorImpl<char> &Contents = CEIF->getContents();
+ for (unsigned i = 0, e = Contents.size(); i != e; ++i) {
+ if (i) OS << ",";
+ OS << hexdigit((Contents[i] >> 4) & 0xF) << hexdigit(Contents[i] & 0xF);
+ }
+ OS << "] (" << Contents.size() << " bytes)";
+ break;
+ }
case MCFragment::FT_Fill: {
const MCFillFragment *FF = cast<MCFillFragment>(this);
OS << " Value:" << FF->getValue() << " ValueSize:" << FF->getValueSize()
@@ -1094,7 +1123,9 @@ void MCAssembler::dump() {
// anchors for MC*Fragment vtables
void MCEncodedFragment::anchor() { }
+void MCEncodedFragmentWithFixups::anchor() { }
void MCDataFragment::anchor() { }
+void MCCompactEncodedInstFragment::anchor() { }
void MCRelaxableFragment::anchor() { }
void MCAlignFragment::anchor() { }
void MCFillFragment::anchor() { }
@@ -1102,3 +1133,4 @@ void MCOrgFragment::anchor() { }
void MCLEBFragment::anchor() { }
void MCDwarfLineAddrFragment::anchor() { }
void MCDwarfCallFrameFragment::anchor() { }
+
diff --git a/lib/MC/MCELFStreamer.cpp b/lib/MC/MCELFStreamer.cpp
index cae73be298..e5b749e28b 100644
--- a/lib/MC/MCELFStreamer.cpp
+++ b/lib/MC/MCELFStreamer.cpp
@@ -371,8 +371,10 @@ void MCELFStreamer::EmitInstToData(const MCInst &Inst) {
// data fragment).
//
// If bundling is enabled:
- // - If we're not in a bundle-locked group, emit the instruction into a data
- // fragment of its own.
+ // - If we're not in a bundle-locked group, emit the instruction into a
+ // fragment of its own. If there are no fixups registered for the
+ // instruction, emit a MCCompactEncodedInstFragment. Otherwise, emit a
+ // MCDataFragment.
// - If we're in a bundle-locked group, append the instruction to the current
// data fragment because we want all the instructions in a group to get into
// the same fragment. Be careful not to do that for the first instruction in
@@ -383,6 +385,14 @@ void MCELFStreamer::EmitInstToData(const MCInst &Inst) {
MCSectionData *SD = getCurrentSectionData();
if (SD->isBundleLocked() && !SD->isBundleGroupBeforeFirstInst())
DF = getOrCreateDataFragment();
+ else if (!SD->isBundleLocked() && Fixups.size() == 0) {
+ // Optimize memory usage by emitting the instruction to a
+ // MCCompactEncodedInstFragment when not in a bundle-locked group and
+ // there are no fixups registered.
+ MCCompactEncodedInstFragment *CEIF = new MCCompactEncodedInstFragment(SD);
+ CEIF->getContents().append(Code.begin(), Code.end());
+ return;
+ }
else {
DF = new MCDataFragment(SD);
if (SD->getBundleLockState() == MCSectionData::BundleLockedAlignToEnd) {