[llvm-commits] CVS: llvm/lib/Target/X86/X86CodeEmitter.cpp
Chris Lattner
lattner at cs.uiuc.edu
Sat Nov 20 15:55:29 PST 2004
Changes in directory llvm/lib/Target/X86:
X86CodeEmitter.cpp updated: 1.76 -> 1.77
---
Log message:
Remove all JIT specific code and switch the code generator over to emitting
relocations for global references.
---
Diffs of the changes: (+26 -194)
Index: llvm/lib/Target/X86/X86CodeEmitter.cpp
diff -u llvm/lib/Target/X86/X86CodeEmitter.cpp:1.76 llvm/lib/Target/X86/X86CodeEmitter.cpp:1.77
--- llvm/lib/Target/X86/X86CodeEmitter.cpp:1.76 Fri Nov 19 14:57:07 2004
+++ llvm/lib/Target/X86/X86CodeEmitter.cpp Sat Nov 20 17:55:15 2004
@@ -8,12 +8,12 @@
//===----------------------------------------------------------------------===//
//
// This file contains the pass that transforms the X86 machine instructions into
-// actual executable machine code.
+// relocatable machine code.
//
//===----------------------------------------------------------------------===//
-#define DEBUG_TYPE "jit"
#include "X86TargetMachine.h"
+#include "X86Relocations.h"
#include "X86.h"
#include "llvm/PassManager.h"
#include "llvm/CodeGen/MachineCodeEmitter.h"
@@ -21,170 +21,14 @@
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/Function.h"
-#include "llvm/Support/Debug.h"
#include "llvm/ADT/Statistic.h"
-#include "llvm/Config/alloca.h"
using namespace llvm;
namespace {
Statistic<>
NumEmitted("x86-emitter", "Number of machine instructions emitted");
-
- class JITResolver {
- MachineCodeEmitter &MCE;
-
- // LazyCodeGenMap - Keep track of call sites for functions that are to be
- // lazily resolved.
- std::map<unsigned, Function*> LazyCodeGenMap;
-
- // LazyResolverMap - Keep track of the lazy resolver created for a
- // particular function so that we can reuse them if necessary.
- std::map<Function*, unsigned> LazyResolverMap;
- public:
- JITResolver(MachineCodeEmitter &mce) : MCE(mce) {}
- unsigned getLazyResolver(Function *F);
- unsigned addFunctionReference(unsigned Address, Function *F);
-
- private:
- unsigned emitStubForFunction(Function *F);
- static void CompilationCallback();
- unsigned resolveFunctionReference(unsigned RetAddr);
- };
-
- static JITResolver &getResolver(MachineCodeEmitter &MCE) {
- static JITResolver *TheJITResolver = 0;
- if (TheJITResolver == 0)
- TheJITResolver = new JITResolver(MCE);
- return *TheJITResolver;
- }
-}
-
-
-void *X86JITInfo::getJITStubForFunction(Function *F, MachineCodeEmitter &MCE) {
- return (void*)(intptr_t)getResolver(MCE).getLazyResolver(F);
-}
-
-void X86JITInfo::replaceMachineCodeForFunction (void *Old, void *New) {
- unsigned char *OldByte = (unsigned char *) Old;
- *OldByte++ = 0xE9; // Emit JMP opcode.
- int32_t *OldWord = (int32_t *) OldByte;
- int32_t NewAddr = (intptr_t) New;
- int32_t OldAddr = (intptr_t) OldWord;
- *OldWord = NewAddr - OldAddr - 4; // Emit PC-relative addr of New code.
-}
-
-/// addFunctionReference - This method is called when we need to emit the
-/// address of a function that has not yet been emitted, so we don't know the
-/// address. Instead, we emit a call to the CompilationCallback method, and
-/// keep track of where we are.
-///
-unsigned JITResolver::addFunctionReference(unsigned Address, Function *F) {
- DEBUG(std::cerr << "Emitting lazily resolved reference to function '"
- << F->getName() << "' at address " << std::hex << Address
- << std::dec << "\n");
- LazyCodeGenMap[Address] = F;
- return (intptr_t)&JITResolver::CompilationCallback;
-}
-
-unsigned JITResolver::resolveFunctionReference(unsigned RetAddr) {
- std::map<unsigned, Function*>::iterator I = LazyCodeGenMap.find(RetAddr);
- assert(I != LazyCodeGenMap.end() && "Not in map!");
- Function *F = I->second;
- LazyCodeGenMap.erase(I);
- return MCE.forceCompilationOf(F);
-}
-
-unsigned JITResolver::getLazyResolver(Function *F) {
- std::map<Function*, unsigned>::iterator I = LazyResolverMap.lower_bound(F);
- if (I != LazyResolverMap.end() && I->first == F) return I->second;
-
-//std::cerr << "Getting lazy resolver for : " << ((Value*)F)->getName() << "\n";
-
- unsigned Stub = emitStubForFunction(F);
- LazyResolverMap.insert(I, std::make_pair(F, Stub));
- return Stub;
-}
-
-#ifdef _MSC_VER
-#pragma optimize("y", off)
-#endif
-
-void JITResolver::CompilationCallback() {
-#ifdef _MSC_VER
- unsigned *StackPtr, RetAddr;
- __asm mov StackPtr, ebp;
- __asm mov eax, DWORD PTR [ebp + 4];
- __asm mov RetAddr, eax;
-#else
- unsigned *StackPtr = (unsigned*)__builtin_frame_address(0);
- unsigned RetAddr = (unsigned)(intptr_t)__builtin_return_address(0);
-
- // FIXME: __builtin_frame_address doesn't work if frame pointer elimination
- // has been performed. Having a variable sized alloca disables frame pointer
- // elimination currently, even if it's dead. This is a gross hack.
- alloca(10+(RetAddr >> 31));
-
-#endif
- assert(StackPtr[1] == RetAddr &&
- "Could not find return address on the stack!");
-
- // It's a stub if there is an interrupt marker after the call...
- bool isStub = ((unsigned char*)(intptr_t)RetAddr)[0] == 0xCD;
-
- // The call instruction should have pushed the return value onto the stack...
- RetAddr -= 4; // Backtrack to the reference itself...
-
-#if 0
- DEBUG(std::cerr << "In callback! Addr=0x" << std::hex << RetAddr
- << " ESP=0x" << (unsigned)StackPtr << std::dec
- << ": Resolving call to function: "
- << TheVM->getFunctionReferencedName((void*)RetAddr) << "\n");
-#endif
-
- // Sanity check to make sure this really is a call instruction...
- assert(((unsigned char*)(intptr_t)RetAddr)[-1] == 0xE8 &&"Not a call instr!");
-
- JITResolver &JR = getResolver(*(MachineCodeEmitter*)0);
- unsigned NewVal = JR.resolveFunctionReference(RetAddr);
-
- // Rewrite the call target... so that we don't fault every time we execute
- // the call.
- *(unsigned*)(intptr_t)RetAddr = NewVal-RetAddr-4;
-
- if (isStub) {
- // If this is a stub, rewrite the call into an unconditional branch
- // instruction so that two return addresses are not pushed onto the stack
- // when the requested function finally gets called. This also makes the
- // 0xCD byte (interrupt) dead, so the marker doesn't effect anything.
- ((unsigned char*)(intptr_t)RetAddr)[-1] = 0xE9;
- }
-
- // Change the return address to reexecute the call instruction...
- StackPtr[1] -= 5;
-}
-
-#ifdef _MSC_VER
-#pragma optimize( "", on )
-#endif
-
-/// emitStubForFunction - This method is used by the JIT when it needs to emit
-/// the address of a function for a function whose code has not yet been
-/// generated. In order to do this, it generates a stub which jumps to the lazy
-/// function compiler, which will eventually get fixed to call the function
-/// directly.
-///
-unsigned JITResolver::emitStubForFunction(Function *F) {
- MCE.startFunctionStub(*F, 6);
- MCE.emitByte(0xE8); // Call with 32 bit pc-rel destination...
-
- unsigned Address = addFunctionReference(MCE.getCurrentPCValue(), F);
- MCE.emitWord(Address-MCE.getCurrentPCValue()-4);
-
- MCE.emitByte(0xCD); // Interrupt - Just a marker identifying the stub!
- return (intptr_t)MCE.finishFunctionStub(*F);
}
-
namespace {
class Emitter : public MachineFunctionPass {
const X86InstrInfo *II;
@@ -211,6 +55,7 @@
void emitPCRelativeValue(unsigned Address);
void emitGlobalAddressForCall(GlobalValue *GV);
void emitGlobalAddressForPtr(GlobalValue *GV, int Disp = 0);
+ void emitExternalSymbolAddress(const char *ES, bool isPCRelative);
void emitRegModRMByte(unsigned ModRMReg, unsigned RegOpcodeField);
void emitSIBByte(unsigned SS, unsigned Index, unsigned Base);
@@ -265,6 +110,12 @@
emitInstruction(*I);
}
+/// emitPCRelativeValue - Emit a 32-bit PC relative address.
+///
+void Emitter::emitPCRelativeValue(unsigned Address) {
+ MCE.emitWord(Address-MCE.getCurrentPCValue()-4);
+}
+
/// emitPCRelativeBlockAddress - This method emits the PC relative address of
/// the specified basic block, or if the basic block hasn't been emitted yet
/// (because this is a forward branch), it keeps track of the information
@@ -276,8 +127,7 @@
std::map<const MachineBasicBlock*, unsigned>::iterator I =
BasicBlockAddrs.find(MBB);
if (I != BasicBlockAddrs.end()) {
- unsigned Location = I->second;
- MCE.emitWord(Location-MCE.getCurrentPCValue()-4);
+ emitPCRelativeValue(I->second);
} else {
// Otherwise, remember where this reference was and where it is to so we can
// deal with it later.
@@ -286,25 +136,13 @@
}
}
-/// emitPCRelativeValue - Emit a 32-bit PC relative address.
-///
-void Emitter::emitPCRelativeValue(unsigned Address) {
- MCE.emitWord(Address-MCE.getCurrentPCValue()-4);
-}
-
/// emitGlobalAddressForCall - Emit the specified address to the code stream
/// assuming this is part of a function call, which is PC relative.
///
void Emitter::emitGlobalAddressForCall(GlobalValue *GV) {
- // Get the address from the backend...
- unsigned Address = MCE.getGlobalValueAddress(GV);
-
- if (Address == 0) {
- // FIXME: this is JIT specific!
- Address = getResolver(MCE).addFunctionReference(MCE.getCurrentPCValue(),
- cast<Function>(GV));
- }
- emitPCRelativeValue(Address);
+ MCE.addRelocation(MachineRelocation(MCE.getCurrentPCOffset(),
+ X86::reloc_pcrel_word, GV));
+ MCE.emitWord(0);
}
/// emitGlobalAddress - Emit the specified address to the code stream assuming
@@ -312,21 +150,19 @@
/// PC relative.
///
void Emitter::emitGlobalAddressForPtr(GlobalValue *GV, int Disp /* = 0 */) {
- // Get the address from the backend...
- unsigned Address = MCE.getGlobalValueAddress(GV);
-
- // If the machine code emitter doesn't know what the address IS yet, we have
- // to take special measures.
- //
- if (Address == 0) {
- // FIXME: this is JIT specific!
- Address = getResolver(MCE).getLazyResolver((Function*)GV);
- }
-
- MCE.emitWord(Address + Disp);
+ MCE.addRelocation(MachineRelocation(MCE.getCurrentPCOffset(),
+ X86::reloc_absolute_word, GV));
+ MCE.emitWord(Disp); // The relocated value will be added to the displacement
}
-
+/// emitExternalSymbolAddress - Arrange for the address of an external symbol to
+/// be emitted to the current location in the function, and allow it to be PC
+/// relative.
+void Emitter::emitExternalSymbolAddress(const char *ES, bool isPCRelative) {
+ MCE.addRelocation(MachineRelocation(MCE.getCurrentPCOffset(),
+ isPCRelative ? X86::reloc_pcrel_word : X86::reloc_absolute_word, ES));
+ MCE.emitWord(0);
+}
/// N86 namespace - Native X86 Register numbers... used by X86 backend.
///
@@ -560,9 +396,7 @@
assert(MO.isPCRelative() && "Call target is not PC Relative?");
emitGlobalAddressForCall(MO.getGlobal());
} else if (MO.isExternalSymbol()) {
- unsigned Address = MCE.getGlobalValueAddress(MO.getSymbolName());
- assert(Address && "Unknown external symbol!");
- emitPCRelativeValue(Address);
+ emitExternalSymbolAddress(MO.getSymbolName(), true);
} else if (MO.isImmediate()) {
emitConstant(MO.getImmedValue(), sizeOfImm(Desc));
} else {
@@ -587,9 +421,7 @@
} else if (MO1.isExternalSymbol()) {
assert(sizeOfImm(Desc) == 4 &&
"Don't know how to emit non-pointer values!");
- unsigned Address = MCE.getGlobalValueAddress(MO1.getSymbolName());
- assert(Address && "Unknown external symbol!");
- MCE.emitWord(Address);
+ emitExternalSymbolAddress(MO1.getSymbolName(), false);
} else {
emitConstant(MO1.getImmedValue(), sizeOfImm(Desc));
}
More information about the llvm-commits
mailing list