[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