[llvm-commits] [llvm] r99256 - in /llvm/trunk/lib/MC: MCAssembler.cpp MCMachOStreamer.cpp

Daniel Dunbar daniel at zuster.org
Mon Mar 22 22:09:03 PDT 2010


Author: ddunbar
Date: Tue Mar 23 00:09:03 2010
New Revision: 99256

URL: http://llvm.org/viewvc/llvm-project?rev=99256&view=rev
Log:
MC: Switch to using MCInst fragments to do relaxation.

Also, both MCMachOStreamer and MCAssembler are now target independent!

Modified:
    llvm/trunk/lib/MC/MCAssembler.cpp
    llvm/trunk/lib/MC/MCMachOStreamer.cpp

Modified: llvm/trunk/lib/MC/MCAssembler.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCAssembler.cpp?rev=99256&r1=99255&r2=99256&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCAssembler.cpp (original)
+++ llvm/trunk/lib/MC/MCAssembler.cpp Tue Mar 23 00:09:03 2010
@@ -25,9 +25,6 @@
 #include "llvm/Target/TargetRegistry.h"
 #include "llvm/Target/TargetAsmBackend.h"
 
-// FIXME: Gross.
-#include "../Target/X86/X86FixupKinds.h"
-
 #include <vector>
 using namespace llvm;
 
@@ -551,10 +548,6 @@
 bool MCAssembler::FixupNeedsRelaxation(const MCAsmFixup &Fixup,
                                        const MCFragment *DF,
                                        const MCAsmLayout &Layout) const {
-  // Currently we only need to relax X86::reloc_pcrel_1byte.
-  if (unsigned(Fixup.Kind) != X86::reloc_pcrel_1byte)
-    return false;
-
   // If we cannot resolve the fixup value, it requires relaxation.
   MCValue Target;
   uint64_t Value;
@@ -565,6 +558,22 @@
   return int64_t(Value) != int64_t(int8_t(Value));
 }
 
+bool MCAssembler::FragmentNeedsRelaxation(const MCInstFragment *IF,
+                                          const MCAsmLayout &Layout) const {
+  // If this inst doesn't ever need relaxation, ignore it. This occurs when we
+  // are intentionally pushing out inst fragments, or because we relaxed a
+  // previous instruction to one that doesn't need relaxation.
+  if (!getBackend().MayNeedRelaxation(IF->getInst(), IF->getFixups()))
+    return false;
+
+  for (MCInstFragment::const_fixup_iterator it = IF->fixup_begin(),
+         ie = IF->fixup_end(); it != ie; ++it)
+    if (FixupNeedsRelaxation(*it, IF, Layout))
+      return true;
+
+  return false;
+}
+
 bool MCAssembler::LayoutOnce(MCAsmLayout &Layout) {
   // Layout the concrete sections and fragments.
   uint64_t Address = 0;
@@ -609,87 +618,50 @@
     Address += SD.getSize();
   }
 
-  // Scan the fixups in order and relax any that don't fit.
+  // Scan for fragments that need relaxation.
   for (iterator it = begin(), ie = end(); it != ie; ++it) {
     MCSectionData &SD = *it;
 
     for (MCSectionData::iterator it2 = SD.begin(),
            ie2 = SD.end(); it2 != ie2; ++it2) {
-      MCDataFragment *DF = dyn_cast<MCDataFragment>(it2);
-      if (!DF)
+      // Check if this is an instruction fragment that needs relaxation.
+      MCInstFragment *IF = dyn_cast<MCInstFragment>(it2);
+      if (!IF || !FragmentNeedsRelaxation(IF, Layout))
         continue;
 
-      for (MCDataFragment::fixup_iterator it3 = DF->fixup_begin(),
-             ie3 = DF->fixup_end(); it3 != ie3; ++it3) {
-        MCAsmFixup &Fixup = *it3;
-
-        // Check whether we need to relax this fixup.
-        if (!FixupNeedsRelaxation(Fixup, DF, Layout))
-          continue;
-
-        // Relax the instruction.
-        //
-        // FIXME: This is a huge temporary hack which just looks for x86
-        // branches; the only thing we need to relax on x86 is
-        // 'X86::reloc_pcrel_1byte'. Once we have MCInst fragments, this will be
-        // replaced by a TargetAsmBackend hook (most likely tblgen'd) to relax
-        // an individual MCInst.
-        SmallVectorImpl<char> &C = DF->getContents();
-        uint64_t PrevOffset = Fixup.Offset;
-        unsigned Amt = 0;
-
-          // jcc instructions
-        if (unsigned(C[Fixup.Offset-1]) >= 0x70 &&
-            unsigned(C[Fixup.Offset-1]) <= 0x7f) {
-          C[Fixup.Offset] = C[Fixup.Offset-1] + 0x10;
-          C[Fixup.Offset-1] = char(0x0f);
-          ++Fixup.Offset;
-          Amt = 4;
-
-          // jmp rel8
-        } else if (C[Fixup.Offset-1] == char(0xeb)) {
-          C[Fixup.Offset-1] = char(0xe9);
-          Amt = 3;
-
-        } else
-          llvm_unreachable("unknown 1 byte pcrel instruction!");
-
-        Fixup.Value = MCBinaryExpr::Create(
-          MCBinaryExpr::Sub, Fixup.Value,
-          MCConstantExpr::Create(3, getContext()),
-          getContext());
-        C.insert(C.begin() + Fixup.Offset, Amt, char(0));
-        Fixup.Kind = MCFixupKind(X86::reloc_pcrel_4byte);
-
-        // Update the remaining fixups, which have slid.
-        //
-        // FIXME: This is bad for performance, but will be eliminated by the
-        // move to MCInst specific fragments.
-        ++it3;
-        for (; it3 != ie3; ++it3)
-          it3->Offset += Amt;
-
-        // Update all the symbols for this fragment, which may have slid.
-        //
-        // FIXME: This is really really bad for performance, but will be
-        // eliminated by the move to MCInst specific fragments.
-        for (MCAssembler::symbol_iterator it = symbol_begin(),
-               ie = symbol_end(); it != ie; ++it) {
-          MCSymbolData &SD = *it;
+      // FIXME-PERF: We could immediately lower out instructions if we can tell
+      // they are fully resolved, to avoid retesting on later passes.
 
-          if (it->getFragment() != DF)
-            continue;
+      // Relax the fragment.
 
-          if (SD.getOffset() > PrevOffset)
-            SD.setOffset(SD.getOffset() + Amt);
-        }
+      MCInst Relaxed;
+      getBackend().RelaxInstruction(IF, Relaxed);
 
-        // Restart layout.
-        //
-        // FIXME-PERF: This is O(N^2), but will be eliminated once we have a
-        // smart MCAsmLayout object.
-        return true;
+      // Encode the new instruction.
+      //
+      // FIXME-PERF: If it matters, we could let the target do this. It can
+      // probably do so more efficiently in many cases.
+      SmallVector<MCFixup, 4> Fixups;
+      SmallString<256> Code;
+      raw_svector_ostream VecOS(Code);
+      getEmitter().EncodeInstruction(Relaxed, VecOS, Fixups);
+      VecOS.flush();
+
+      // Update the instruction fragment.
+      IF->setInst(Relaxed);
+      IF->getCode() = Code;
+      IF->getFixups().clear();
+      for (unsigned i = 0, e = Fixups.size(); i != e; ++i) {
+        MCFixup &F = Fixups[i];
+        IF->getFixups().push_back(MCAsmFixup(F.getOffset(), *F.getValue(),
+                                             F.getKind()));
       }
+
+      // Restart layout.
+      //
+      // FIXME-PERF: This is O(N^2), but will be eliminated once we have a
+      // smart MCAsmLayout object.
+      return true;
     }
   }
 

Modified: llvm/trunk/lib/MC/MCMachOStreamer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCMachOStreamer.cpp?rev=99256&r1=99255&r2=99256&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCMachOStreamer.cpp (original)
+++ llvm/trunk/lib/MC/MCMachOStreamer.cpp Tue Mar 23 00:09:03 2010
@@ -18,6 +18,8 @@
 #include "llvm/MC/MCSymbol.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/raw_ostream.h"
+#include "llvm/Target/TargetAsmBackend.h"
+
 using namespace llvm;
 
 namespace {
@@ -391,6 +393,32 @@
                                    F.getKind()));
   }
 
+  // See if we might need to relax this instruction, if so it needs its own
+  // fragment.
+  //
+  // FIXME-PERF: Support target hook to do a fast path that avoids the encoder,
+  // when we can immediately tell that we will get something which might need
+  // relaxation (and compute its size).
+  //
+  // FIXME-PERF: We should also be smart about immediately relaxing instructions
+  // which we can already show will never possibly fit (we can also do a very
+  // good job of this before we do the first relaxation pass, because we have
+  // total knowledge about undefined symbols at that point). Even now, though,
+  // we can do a decent job, especially on Darwin where scattering means that we
+  // are going to often know that we can never fully resolve a fixup.
+  if (Assembler.getBackend().MayNeedRelaxation(Inst, AsmFixups)) {
+    MCInstFragment *IF = new MCInstFragment(Inst, CurSectionData);
+
+    // Add the fixups and data.
+    //
+    // FIXME: Revisit this design decision when relaxation is done, we may be
+    // able to get away with not storing any extra data in the MCInst.
+    IF->getCode() = Code;
+    IF->getFixups() = AsmFixups;
+
+    return;
+  }
+
   // Add the fixups and data.
   MCDataFragment *DF = getOrCreateDataFragment();
   for (unsigned i = 0, e = AsmFixups.size(); i != e; ++i) {





More information about the llvm-commits mailing list