diff options
-rw-r--r-- | include/llvm/MC/MCAssembler.h | 105 | ||||
-rw-r--r-- | lib/MC/MCAssembler.cpp | 36 | ||||
-rw-r--r-- | lib/MC/MCELFStreamer.cpp | 14 |
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) { |