From 3f4dcd92daef80f87919507b6baf2a97d4bfaa2e Mon Sep 17 00:00:00 2001 From: Daniel Dunbar Date: Mon, 22 Mar 2010 23:16:48 +0000 Subject: [PATCH] MC: Add MCInstFragment, not used yet. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@99229 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/MC/MCAssembler.h | 43 +++++++++++++++++- lib/MC/MCAssembler.cpp | 84 +++++++++++++++++++++++++++++++++-- lib/MC/MCMachOStreamer.cpp | 3 ++ 3 files changed, 124 insertions(+), 6 deletions(-) diff --git a/include/llvm/MC/MCAssembler.h b/include/llvm/MC/MCAssembler.h index 8a7a7853c6d..ff32eb26fc0 100644 --- a/include/llvm/MC/MCAssembler.h +++ b/include/llvm/MC/MCAssembler.h @@ -16,6 +16,7 @@ #include "llvm/ADT/ilist_node.h" #include "llvm/Support/Casting.h" #include "llvm/MC/MCFixup.h" +#include "llvm/MC/MCInst.h" #include "llvm/System/DataTypes.h" #include // FIXME: Shouldn't be needed. @@ -37,6 +38,8 @@ class TargetAsmBackend; /// MCAsmFixup - Represent a fixed size region of bytes inside some fragment /// which needs to be rewritten. This region will either be rewritten by the /// assembler or cause a relocation entry to be generated. +// +// FIXME: This should probably just be merged with MCFixup. class MCAsmFixup { public: /// Offset - The offset inside the fragment which needs to be rewritten. @@ -59,9 +62,10 @@ class MCFragment : public ilist_node { public: enum FragmentType { - FT_Data, FT_Align, + FT_Data, FT_Fill, + FT_Inst, FT_Org, FT_ZeroFill }; @@ -145,7 +149,6 @@ public: const SmallString<32> &getContents() const { return Contents; } /// @} - /// @name Fixup Access /// @{ @@ -177,6 +180,39 @@ public: virtual void dump(); }; +class MCInstFragment : public MCFragment { + /// Inst - The instruction this is a fragment for. + MCInst Inst; + + /// InstSize - The size of the currently encoded instruction. + unsigned InstSize; + +public: + MCInstFragment(MCInst _Inst, unsigned _InstSize, MCSectionData *SD = 0) + : MCFragment(FT_Inst, SD), Inst(_Inst), InstSize(_InstSize) {} + + /// @name Accessors + /// @{ + + unsigned getInstSize() const { return InstSize; } + + const MCInst &getInst() const { return Inst; } + + void setInst(MCInst Inst, unsigned InstSize) { + this->Inst = Inst; + this->InstSize = InstSize; + } + + /// @} + + static bool classof(const MCFragment *F) { + return F->getKind() == MCFragment::FT_Inst; + } + static bool classof(const MCInstFragment *) { return true; } + + virtual void dump(); +}; + class MCAlignFragment : public MCFragment { /// Alignment - The alignment to ensure, in bytes. unsigned Alignment; @@ -623,6 +659,9 @@ private: /// were adjusted. bool LayoutOnce(MCAsmLayout &Layout); + /// FinishLayout - Finalize a layout, including fragment lowering. + void FinishLayout(MCAsmLayout &Layout); + public: /// Find the symbol which defines the atom containing given address, inside /// the given section, or null if there is no such symbol. diff --git a/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp index 8cb72706fec..ba2e5de73e5 100644 --- a/lib/MC/MCAssembler.cpp +++ b/lib/MC/MCAssembler.cpp @@ -327,6 +327,10 @@ void MCAssembler::LayoutSection(MCSectionData &SD, break; } + case MCFragment::FT_Inst: + F.setFileSize(cast(F).getInstSize()); + break; + case MCFragment::FT_Org: { MCOrgFragment &OF = cast(F); @@ -471,7 +475,9 @@ static void WriteFragmentData(const MCFragment &F, MCObjectWriter *OW) { } case MCFragment::FT_Data: { - OW->WriteBytes(cast(F).getContents().str()); + MCDataFragment &DF = cast(F); + assert(DF.getFileSize() == DF.getContents().size() && "Invalid size!"); + OW->WriteBytes(DF.getContents().str()); break; } @@ -490,6 +496,10 @@ static void WriteFragmentData(const MCFragment &F, MCObjectWriter *OW) { break; } + case MCFragment::FT_Inst: + llvm_unreachable("unexpected inst fragment after lowering"); + break; + case MCFragment::FT_Org: { MCOrgFragment &OF = cast(F); @@ -541,7 +551,14 @@ void MCAssembler::Finish() { continue; DEBUG_WITH_TYPE("mc-dump", { - llvm::errs() << "assembler backend - post-layout\n--\n"; + llvm::errs() << "assembler backend - post-relaxation\n--\n"; + dump(); }); + + // Finalize the layout, including fragment lowering. + FinishLayout(Layout); + + DEBUG_WITH_TYPE("mc-dump", { + llvm::errs() << "assembler backend - final-layout\n--\n"; dump(); }); llvm::OwningPtr Writer(getBackend().createObjectWriter(OS)); @@ -722,8 +739,8 @@ bool MCAssembler::LayoutOnce(MCAsmLayout &Layout) { // Restart layout. // - // FIXME: This is O(N^2), but will be eliminated once we have a smart - // MCAsmLayout object. + // FIXME-PERF: This is O(N^2), but will be eliminated once we have a + // smart MCAsmLayout object. return true; } } @@ -732,6 +749,54 @@ bool MCAssembler::LayoutOnce(MCAsmLayout &Layout) { return false; } +void MCAssembler::FinishLayout(MCAsmLayout &Layout) { + // Lower out any instruction fragments, to simplify the fixup application and + // output. + // + // FIXME-PERF: We don't have to do this, but the assumption is that it is + // cheap (we will mostly end up eliminating fragments and appending on to data + // fragments), so the extra complexity downstream isn't worth it. Evaluate + // this assumption. + for (iterator it = begin(), ie = end(); it != ie; ++it) { + MCSectionData &SD = *it; + + for (MCSectionData::iterator it2 = SD.begin(), + ie2 = SD.end(); it2 != ie2; ++it2) { + MCInstFragment *IF = dyn_cast(it2); + if (!IF) + continue; + + // Create a new data fragment for the instruction. + // + // FIXME: Reuse previous data fragment if possible. + MCDataFragment *DF = new MCDataFragment(); + SD.getFragmentList().insert(it2, DF); + + // Update the data fragments layout data. + DF->setOffset(IF->getOffset()); + DF->setFileSize(IF->getInstSize()); + + // Encode the final instruction. + SmallVector Fixups; + raw_svector_ostream VecOS(DF->getContents()); + getEmitter().EncodeInstruction(IF->getInst(), VecOS, Fixups); + + // Copy over the fixups. + // + // FIXME-PERF: Encode fixups directly into the data fragment as well. + for (unsigned i = 0, e = Fixups.size(); i != e; ++i) { + MCFixup &F = Fixups[i]; + DF->addFixup(MCAsmFixup(DF->getContents().size()+F.getOffset(), + *F.getValue(), F.getKind())); + } + + // Delete the instruction fragment and update the iterator. + SD.getFragmentList().erase(IF); + it2 = DF; + } + } +} + // Debugging methods namespace llvm { @@ -800,6 +865,17 @@ void MCFillFragment::dump() { << " Count:" << getCount() << ">"; } +void MCInstFragment::dump() { + raw_ostream &OS = llvm::errs(); + + OS << "MCFragment::dump(); + OS << "\n "; + OS << " Inst:"; + getInst().dump_pretty(OS); + OS << ">"; +} + void MCOrgFragment::dump() { raw_ostream &OS = llvm::errs(); diff --git a/lib/MC/MCMachOStreamer.cpp b/lib/MC/MCMachOStreamer.cpp index b57f3027bad..51a2d45ed71 100644 --- a/lib/MC/MCMachOStreamer.cpp +++ b/lib/MC/MCMachOStreamer.cpp @@ -375,6 +375,9 @@ void MCMachOStreamer::EmitInstruction(const MCInst &Inst) { CurSectionData->setHasInstructions(true); + // FIXME-PERF: Common case is that we don't need to relax, encode directly + // onto the data fragments buffers. + SmallVector Fixups; SmallString<256> Code; raw_svector_ostream VecOS(Code); -- 2.34.1