diff options
| -rw-r--r-- | llvm/include/llvm/MC/MCAssembler.h | 43 | ||||
| -rw-r--r-- | llvm/lib/MC/MCAssembler.cpp | 84 | ||||
| -rw-r--r-- | llvm/lib/MC/MCMachOStreamer.cpp | 3 | 
3 files changed, 124 insertions, 6 deletions
diff --git a/llvm/include/llvm/MC/MCAssembler.h b/llvm/include/llvm/MC/MCAssembler.h index 8a7a7853c6d..ff32eb26fc0 100644 --- a/llvm/include/llvm/MC/MCAssembler.h +++ b/llvm/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 <vector> // 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<MCFragment> {  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/llvm/lib/MC/MCAssembler.cpp b/llvm/lib/MC/MCAssembler.cpp index 8cb72706fec..ba2e5de73e5 100644 --- a/llvm/lib/MC/MCAssembler.cpp +++ b/llvm/lib/MC/MCAssembler.cpp @@ -327,6 +327,10 @@ void MCAssembler::LayoutSection(MCSectionData &SD,        break;      } +    case MCFragment::FT_Inst: +      F.setFileSize(cast<MCInstFragment>(F).getInstSize()); +      break; +      case MCFragment::FT_Org: {        MCOrgFragment &OF = cast<MCOrgFragment>(F); @@ -471,7 +475,9 @@ static void WriteFragmentData(const MCFragment &F, MCObjectWriter *OW) {    }    case MCFragment::FT_Data: { -    OW->WriteBytes(cast<MCDataFragment>(F).getContents().str()); +    MCDataFragment &DF = cast<MCDataFragment>(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<MCOrgFragment>(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<MCObjectWriter> 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<MCInstFragment>(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<MCFixup, 4> 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 << "<MCInstFragment "; +  this->MCFragment::dump(); +  OS << "\n       "; +  OS << " Inst:"; +  getInst().dump_pretty(OS); +  OS << ">"; +} +  void MCOrgFragment::dump() {    raw_ostream &OS = llvm::errs(); diff --git a/llvm/lib/MC/MCMachOStreamer.cpp b/llvm/lib/MC/MCMachOStreamer.cpp index b57f3027bad..51a2d45ed71 100644 --- a/llvm/lib/MC/MCMachOStreamer.cpp +++ b/llvm/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<MCFixup, 4> Fixups;    SmallString<256> Code;    raw_svector_ostream VecOS(Code);  | 

