mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-14 14:24:05 +00:00
Move target specific code to target files. The new MachineCodeEmitter
class is actually target independent! git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@6517 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@ -1,82 +0,0 @@
|
|||||||
//===-- Callback.cpp - Trap handler for function resolution ---------------===//
|
|
||||||
//
|
|
||||||
// This file defines the handler which is invoked when a reference to a
|
|
||||||
// non-codegen'd function is found. This file defines target specific code
|
|
||||||
// which is used by the JIT.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
#include "VM.h"
|
|
||||||
#include "Support/Statistic.h"
|
|
||||||
#include "llvm/CodeGen/MachineCodeEmitter.h"
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
static VM *TheVM = 0;
|
|
||||||
|
|
||||||
// CompilationCallback - Invoked the first time that a call site is found,
|
|
||||||
// which causes lazy compilation of the target function.
|
|
||||||
//
|
|
||||||
void VM::CompilationCallback() {
|
|
||||||
#if defined(i386) || defined(__i386__) || defined(__x86__)
|
|
||||||
unsigned *StackPtr = (unsigned*)__builtin_frame_address(0);
|
|
||||||
unsigned RetAddr = (unsigned)__builtin_return_address(0);
|
|
||||||
|
|
||||||
assert(StackPtr[1] == RetAddr &&
|
|
||||||
"Could not find return address on the stack!");
|
|
||||||
bool isStub = ((unsigned char*)RetAddr)[0] == 0xCD; // Interrupt marker?
|
|
||||||
|
|
||||||
// The call instruction should have pushed the return value onto the stack...
|
|
||||||
RetAddr -= 4; // Backtrack to the reference itself...
|
|
||||||
|
|
||||||
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");
|
|
||||||
|
|
||||||
// Sanity check to make sure this really is a call instruction...
|
|
||||||
assert(((unsigned char*)RetAddr)[-1] == 0xE8 && "Not a call instr!");
|
|
||||||
|
|
||||||
unsigned NewVal = (unsigned)TheVM->resolveFunctionReference((void*)RetAddr);
|
|
||||||
|
|
||||||
// Rewrite the call target... so that we don't fault every time we execute
|
|
||||||
// the call.
|
|
||||||
*(unsigned*)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*)RetAddr)[-1] = 0xE9;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Change the return address to reexecute the call instruction...
|
|
||||||
StackPtr[1] -= 5;
|
|
||||||
#else
|
|
||||||
abort();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/// emitStubForFunction - This virtual 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.
|
|
||||||
///
|
|
||||||
void *VM::emitStubForFunction(const Function &F) {
|
|
||||||
#if defined(i386) || defined(__i386__) || defined(__x86__)
|
|
||||||
MCE->startFunctionStub(F, 6);
|
|
||||||
MCE->emitByte(0xE8); // Call with 32 bit pc-rel destination...
|
|
||||||
MCE->emitGlobalAddress((GlobalValue*)&F, true);
|
|
||||||
MCE->emitByte(0xCD); // Interrupt - Just a marker identifying the stub!
|
|
||||||
return MCE->finishFunctionStub(F);
|
|
||||||
#else
|
|
||||||
abort();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void VM::registerCallback() {
|
|
||||||
TheVM = this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -43,7 +43,7 @@ ExecutionEngine *ExecutionEngine::createJIT(Module *M, unsigned Config) {
|
|||||||
if (Arch == "x86") {
|
if (Arch == "x86") {
|
||||||
TargetMachineAllocator = allocateX86TargetMachine;
|
TargetMachineAllocator = allocateX86TargetMachine;
|
||||||
} else if (Arch == "sparc") {
|
} else if (Arch == "sparc") {
|
||||||
TargetMachineAllocator = allocateSparcTargetMachine;
|
//TargetMachineAllocator = allocateSparcTargetMachine;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TargetMachineAllocator) {
|
if (TargetMachineAllocator) {
|
||||||
@ -65,11 +65,10 @@ VM::VM(Module *M, TargetMachine *tm) : ExecutionEngine(M), TM(*tm) {
|
|||||||
if (Arch == "x86") {
|
if (Arch == "x86") {
|
||||||
MCE = createX86Emitter(*this);
|
MCE = createX86Emitter(*this);
|
||||||
} else if (Arch == "sparc") {
|
} else if (Arch == "sparc") {
|
||||||
MCE = createSparcEmitter(*this);
|
//MCE = createSparcEmitter(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
setupPassManager();
|
setupPassManager();
|
||||||
registerCallback();
|
|
||||||
emitGlobals();
|
emitGlobals();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,12 +22,6 @@ class VM : public ExecutionEngine {
|
|||||||
PassManager PM; // Passes to compile a function
|
PassManager PM; // Passes to compile a function
|
||||||
MachineCodeEmitter *MCE; // MCE object
|
MachineCodeEmitter *MCE; // MCE object
|
||||||
|
|
||||||
// FunctionRefs - A mapping between addresses that refer to unresolved
|
|
||||||
// functions and the LLVM function object itself. This is used by the fault
|
|
||||||
// handler to lazily patch up references...
|
|
||||||
//
|
|
||||||
std::map<void*, Function*> FunctionRefs;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
VM(Module *M, TargetMachine *tm);
|
VM(Module *M, TargetMachine *tm);
|
||||||
~VM();
|
~VM();
|
||||||
@ -37,14 +31,6 @@ public:
|
|||||||
virtual int run(const std::string &FnName,
|
virtual int run(const std::string &FnName,
|
||||||
const std::vector<std::string> &Args);
|
const std::vector<std::string> &Args);
|
||||||
|
|
||||||
void addFunctionRef(void *Ref, Function *F) {
|
|
||||||
FunctionRefs[Ref] = F;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::string &getFunctionReferencedName(void *RefAddr);
|
|
||||||
|
|
||||||
void *resolveFunctionReference(void *RefAddr);
|
|
||||||
|
|
||||||
/// getPointerToNamedFunction - This method returns the address of the
|
/// getPointerToNamedFunction - This method returns the address of the
|
||||||
/// specified function by using the dlsym function call. As such it is only
|
/// specified function by using the dlsym function call. As such it is only
|
||||||
/// useful for resolving library symbols, not code generated symbols.
|
/// useful for resolving library symbols, not code generated symbols.
|
||||||
@ -61,21 +47,14 @@ public:
|
|||||||
///
|
///
|
||||||
static void runAtExitHandlers();
|
static void runAtExitHandlers();
|
||||||
|
|
||||||
|
/// getPointerToFunction - This returns the address of the specified function,
|
||||||
|
/// compiling it if necessary.
|
||||||
|
void *getPointerToFunction(const Function *F);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static MachineCodeEmitter *createX86Emitter(VM &V);
|
static MachineCodeEmitter *createX86Emitter(VM &V);
|
||||||
static MachineCodeEmitter *createSparcEmitter(VM &V);
|
static MachineCodeEmitter *createSparcEmitter(VM &V);
|
||||||
void setupPassManager();
|
void setupPassManager();
|
||||||
void *getPointerToFunction(const Function *F);
|
|
||||||
|
|
||||||
void registerCallback();
|
|
||||||
|
|
||||||
/// 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.
|
|
||||||
///
|
|
||||||
void *emitStubForFunction(const Function &F);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -13,38 +13,45 @@
|
|||||||
#include "llvm/Function.h"
|
#include "llvm/Function.h"
|
||||||
#include "Support/Statistic.h"
|
#include "Support/Statistic.h"
|
||||||
|
|
||||||
|
static VM *TheVM = 0;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
Statistic<> NumBytes("jello", "Number of bytes of machine code compiled");
|
Statistic<> NumBytes("jello", "Number of bytes of machine code compiled");
|
||||||
|
|
||||||
class Emitter : public MachineCodeEmitter {
|
class Emitter : public MachineCodeEmitter {
|
||||||
VM &TheVM;
|
// CurBlock - The start of the current block of memory. CurByte - The
|
||||||
|
// current byte being emitted to.
|
||||||
unsigned char *CurBlock, *CurByte;
|
unsigned char *CurBlock, *CurByte;
|
||||||
|
|
||||||
// When outputting a function stub in the context of some other function, we
|
// When outputting a function stub in the context of some other function, we
|
||||||
// save CurBlock and CurByte here.
|
// save CurBlock and CurByte here.
|
||||||
unsigned char *SavedCurBlock, *SavedCurByte;
|
unsigned char *SavedCurBlock, *SavedCurByte;
|
||||||
|
|
||||||
std::vector<std::pair<BasicBlock*, unsigned *> > BBRefs;
|
// ConstantPoolAddresses - Contains the location for each entry in the
|
||||||
std::map<BasicBlock*, unsigned> BBLocations;
|
// constant pool.
|
||||||
std::vector<void*> ConstantPoolAddresses;
|
std::vector<void*> ConstantPoolAddresses;
|
||||||
public:
|
public:
|
||||||
Emitter(VM &vm) : TheVM(vm) {}
|
Emitter(VM &vm) { TheVM = &vm; }
|
||||||
|
|
||||||
virtual void startFunction(MachineFunction &F);
|
virtual void startFunction(MachineFunction &F);
|
||||||
virtual void finishFunction(MachineFunction &F);
|
virtual void finishFunction(MachineFunction &F);
|
||||||
virtual void emitConstantPool(MachineConstantPool *MCP);
|
virtual void emitConstantPool(MachineConstantPool *MCP);
|
||||||
virtual void startBasicBlock(MachineBasicBlock &BB);
|
|
||||||
virtual void startFunctionStub(const Function &F, unsigned StubSize);
|
virtual void startFunctionStub(const Function &F, unsigned StubSize);
|
||||||
virtual void* finishFunctionStub(const Function &F);
|
virtual void* finishFunctionStub(const Function &F);
|
||||||
virtual void emitByte(unsigned char B);
|
virtual void emitByte(unsigned char B);
|
||||||
virtual void emitPCRelativeDisp(Value *V);
|
virtual void emitWord(unsigned W);
|
||||||
virtual void emitGlobalAddress(GlobalValue *V, bool isPCRelative);
|
|
||||||
virtual void emitGlobalAddress(const std::string &Name, bool isPCRelative);
|
virtual uint64_t getGlobalValueAddress(GlobalValue *V);
|
||||||
virtual void emitFunctionConstantValueAddress(unsigned ConstantNum,
|
virtual uint64_t getGlobalValueAddress(const std::string &Name);
|
||||||
int Offset);
|
virtual uint64_t getConstantPoolEntryAddress(unsigned Entry);
|
||||||
private:
|
virtual uint64_t getCurrentPCValue();
|
||||||
void emitAddress(void *Addr, bool isPCRelative);
|
|
||||||
|
// forceCompilationOf - Force the compilation of the specified function, and
|
||||||
|
// return its address, because we REALLY need the address now.
|
||||||
|
//
|
||||||
|
// FIXME: This is JIT specific!
|
||||||
|
//
|
||||||
|
virtual uint64_t forceCompilationOf(Function *F);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,21 +73,13 @@ static void *getMemory(unsigned NumPages) {
|
|||||||
|
|
||||||
|
|
||||||
void Emitter::startFunction(MachineFunction &F) {
|
void Emitter::startFunction(MachineFunction &F) {
|
||||||
CurBlock = (unsigned char *)getMemory(8);
|
CurBlock = (unsigned char *)getMemory(16);
|
||||||
CurByte = CurBlock; // Start writing at the beginning of the fn.
|
CurByte = CurBlock; // Start writing at the beginning of the fn.
|
||||||
TheVM.addGlobalMapping(F.getFunction(), CurBlock);
|
TheVM->addGlobalMapping(F.getFunction(), CurBlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Emitter::finishFunction(MachineFunction &F) {
|
void Emitter::finishFunction(MachineFunction &F) {
|
||||||
ConstantPoolAddresses.clear();
|
ConstantPoolAddresses.clear();
|
||||||
for (unsigned i = 0, e = BBRefs.size(); i != e; ++i) {
|
|
||||||
unsigned Location = BBLocations[BBRefs[i].first];
|
|
||||||
unsigned *Ref = BBRefs[i].second;
|
|
||||||
*Ref = Location-(unsigned)(intptr_t)Ref-4;
|
|
||||||
}
|
|
||||||
BBRefs.clear();
|
|
||||||
BBLocations.clear();
|
|
||||||
|
|
||||||
NumBytes += CurByte-CurBlock;
|
NumBytes += CurByte-CurBlock;
|
||||||
|
|
||||||
DEBUG(std::cerr << "Finished CodeGen of [0x" << std::hex
|
DEBUG(std::cerr << "Finished CodeGen of [0x" << std::hex
|
||||||
@ -95,18 +94,12 @@ void Emitter::emitConstantPool(MachineConstantPool *MCP) {
|
|||||||
// For now we just allocate some memory on the heap, this can be
|
// For now we just allocate some memory on the heap, this can be
|
||||||
// dramatically improved.
|
// dramatically improved.
|
||||||
const Type *Ty = ((Value*)Constants[i])->getType();
|
const Type *Ty = ((Value*)Constants[i])->getType();
|
||||||
void *Addr = malloc(TheVM.getTargetData().getTypeSize(Ty));
|
void *Addr = malloc(TheVM->getTargetData().getTypeSize(Ty));
|
||||||
TheVM.InitializeMemory(Constants[i], Addr);
|
TheVM->InitializeMemory(Constants[i], Addr);
|
||||||
ConstantPoolAddresses.push_back(Addr);
|
ConstantPoolAddresses.push_back(Addr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Emitter::startBasicBlock(MachineBasicBlock &BB) {
|
|
||||||
BBLocations[BB.getBasicBlock()] = (unsigned)(intptr_t)CurByte;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Emitter::startFunctionStub(const Function &F, unsigned StubSize) {
|
void Emitter::startFunctionStub(const Function &F, unsigned StubSize) {
|
||||||
SavedCurBlock = CurBlock; SavedCurByte = CurByte;
|
SavedCurBlock = CurBlock; SavedCurByte = CurByte;
|
||||||
// FIXME: this is a huge waste of memory.
|
// FIXME: this is a huge waste of memory.
|
||||||
@ -129,6 +122,46 @@ void Emitter::emitByte(unsigned char B) {
|
|||||||
*CurByte++ = B; // Write the byte to memory
|
*CurByte++ = B; // Write the byte to memory
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Emitter::emitWord(unsigned W) {
|
||||||
|
// FIXME: This won't work if the endianness of the host and target don't
|
||||||
|
// agree! (For a JIT this can't happen though. :)
|
||||||
|
*(unsigned*)CurByte = W;
|
||||||
|
CurByte += sizeof(unsigned);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint64_t Emitter::getGlobalValueAddress(GlobalValue *V) {
|
||||||
|
// Try looking up the function to see if it is already compiled, if not return
|
||||||
|
// 0.
|
||||||
|
return (intptr_t)TheVM->getPointerToGlobalIfAvailable(V);
|
||||||
|
}
|
||||||
|
uint64_t Emitter::getGlobalValueAddress(const std::string &Name) {
|
||||||
|
return (intptr_t)TheVM->getPointerToNamedFunction(Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// getConstantPoolEntryAddress - Return the address of the 'ConstantNum' entry
|
||||||
|
// in the constant pool that was last emitted with the 'emitConstantPool'
|
||||||
|
// method.
|
||||||
|
//
|
||||||
|
uint64_t Emitter::getConstantPoolEntryAddress(unsigned ConstantNum) {
|
||||||
|
assert(ConstantNum < ConstantPoolAddresses.size() &&
|
||||||
|
"Invalid ConstantPoolIndex!");
|
||||||
|
return (intptr_t)ConstantPoolAddresses[ConstantNum];
|
||||||
|
}
|
||||||
|
|
||||||
|
// getCurrentPCValue - This returns the address that the next emitted byte
|
||||||
|
// will be output to.
|
||||||
|
//
|
||||||
|
uint64_t Emitter::getCurrentPCValue() {
|
||||||
|
return (intptr_t)CurByte;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t Emitter::forceCompilationOf(Function *F) {
|
||||||
|
return (intptr_t)TheVM->getPointerToFunction(F);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
|
||||||
|
|
||||||
// emitPCRelativeDisp - For functions, just output a displacement that will
|
// emitPCRelativeDisp - For functions, just output a displacement that will
|
||||||
// cause a reference to the zero page, which will cause a seg-fault, causing
|
// cause a reference to the zero page, which will cause a seg-fault, causing
|
||||||
@ -157,23 +190,19 @@ void Emitter::emitAddress(void *Addr, bool isPCRelative) {
|
|||||||
void Emitter::emitGlobalAddress(GlobalValue *V, bool isPCRelative) {
|
void Emitter::emitGlobalAddress(GlobalValue *V, bool isPCRelative) {
|
||||||
if (isPCRelative) { // must be a call, this is a major hack!
|
if (isPCRelative) { // must be a call, this is a major hack!
|
||||||
// Try looking up the function to see if it is already compiled!
|
// Try looking up the function to see if it is already compiled!
|
||||||
if (void *Addr = TheVM.getPointerToGlobalIfAvailable(V)) {
|
if (void *Addr = TheVM->getPointerToGlobalIfAvailable(V)) {
|
||||||
emitAddress(Addr, isPCRelative);
|
emitAddress(Addr, isPCRelative);
|
||||||
} else { // Function has not yet been code generated!
|
} else { // Function has not yet been code generated!
|
||||||
TheVM.addFunctionRef(CurByte, cast<Function>(V));
|
TheVM->addFunctionRef(CurByte, cast<Function>(V));
|
||||||
|
|
||||||
// Delayed resolution...
|
// Delayed resolution...
|
||||||
emitAddress((void*)VM::CompilationCallback, isPCRelative);
|
emitAddress((void*)VM::CompilationCallback, isPCRelative);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
emitAddress(TheVM.getPointerToGlobal(V), isPCRelative);
|
emitAddress(TheVM->getPointerToGlobal(V), isPCRelative);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Emitter::emitGlobalAddress(const std::string &Name, bool isPCRelative) {
|
|
||||||
emitAddress(TheVM.getPointerToNamedFunction(Name), isPCRelative);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Emitter::emitFunctionConstantValueAddress(unsigned ConstantNum,
|
void Emitter::emitFunctionConstantValueAddress(unsigned ConstantNum,
|
||||||
int Offset) {
|
int Offset) {
|
||||||
assert(ConstantNum < ConstantPoolAddresses.size() &&
|
assert(ConstantNum < ConstantPoolAddresses.size() &&
|
||||||
@ -181,3 +210,4 @@ void Emitter::emitFunctionConstantValueAddress(unsigned ConstantNum,
|
|||||||
*(void**)CurByte = (char*)ConstantPoolAddresses[ConstantNum]+Offset;
|
*(void**)CurByte = (char*)ConstantPoolAddresses[ConstantNum]+Offset;
|
||||||
CurByte += 4;
|
CurByte += 4;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
@ -36,22 +36,6 @@ void VM::setupPassManager() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void *VM::resolveFunctionReference(void *RefAddr) {
|
|
||||||
Function *F = FunctionRefs[RefAddr];
|
|
||||||
assert(F && "Reference address not known!");
|
|
||||||
|
|
||||||
void *Addr = getPointerToFunction(F);
|
|
||||||
assert(Addr && "Pointer to function unknown!");
|
|
||||||
|
|
||||||
FunctionRefs.erase(RefAddr);
|
|
||||||
return Addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::string &VM::getFunctionReferencedName(void *RefAddr) {
|
|
||||||
assert(FunctionRefs[RefAddr] && "Function address unknown!");
|
|
||||||
return FunctionRefs[RefAddr]->getName();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// getPointerToFunction - This method is used to get the address of the
|
/// getPointerToFunction - This method is used to get the address of the
|
||||||
/// specified function, compiling it if neccesary.
|
/// specified function, compiling it if neccesary.
|
||||||
///
|
///
|
||||||
@ -63,12 +47,7 @@ void *VM::getPointerToFunction(const Function *F) {
|
|||||||
return Addr = getPointerToNamedFunction(F->getName());
|
return Addr = getPointerToNamedFunction(F->getName());
|
||||||
|
|
||||||
static bool isAlreadyCodeGenerating = false;
|
static bool isAlreadyCodeGenerating = false;
|
||||||
if (isAlreadyCodeGenerating) {
|
assert(!isAlreadyCodeGenerating && "ERROR: RECURSIVE COMPILATION DETECTED!");
|
||||||
// Generate a function stub instead of reentering...
|
|
||||||
void *SAddr = emitStubForFunction(*F);
|
|
||||||
assert(SAddr && "Target machine doesn't support function stub generation!");
|
|
||||||
return SAddr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: JIT all of the functions in the module. Eventually this will JIT
|
// FIXME: JIT all of the functions in the module. Eventually this will JIT
|
||||||
// functions on demand. This has the effect of populating all of the
|
// functions on demand. This has the effect of populating all of the
|
||||||
|
@ -22,12 +22,6 @@ class VM : public ExecutionEngine {
|
|||||||
PassManager PM; // Passes to compile a function
|
PassManager PM; // Passes to compile a function
|
||||||
MachineCodeEmitter *MCE; // MCE object
|
MachineCodeEmitter *MCE; // MCE object
|
||||||
|
|
||||||
// FunctionRefs - A mapping between addresses that refer to unresolved
|
|
||||||
// functions and the LLVM function object itself. This is used by the fault
|
|
||||||
// handler to lazily patch up references...
|
|
||||||
//
|
|
||||||
std::map<void*, Function*> FunctionRefs;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
VM(Module *M, TargetMachine *tm);
|
VM(Module *M, TargetMachine *tm);
|
||||||
~VM();
|
~VM();
|
||||||
@ -37,14 +31,6 @@ public:
|
|||||||
virtual int run(const std::string &FnName,
|
virtual int run(const std::string &FnName,
|
||||||
const std::vector<std::string> &Args);
|
const std::vector<std::string> &Args);
|
||||||
|
|
||||||
void addFunctionRef(void *Ref, Function *F) {
|
|
||||||
FunctionRefs[Ref] = F;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::string &getFunctionReferencedName(void *RefAddr);
|
|
||||||
|
|
||||||
void *resolveFunctionReference(void *RefAddr);
|
|
||||||
|
|
||||||
/// getPointerToNamedFunction - This method returns the address of the
|
/// getPointerToNamedFunction - This method returns the address of the
|
||||||
/// specified function by using the dlsym function call. As such it is only
|
/// specified function by using the dlsym function call. As such it is only
|
||||||
/// useful for resolving library symbols, not code generated symbols.
|
/// useful for resolving library symbols, not code generated symbols.
|
||||||
@ -61,21 +47,14 @@ public:
|
|||||||
///
|
///
|
||||||
static void runAtExitHandlers();
|
static void runAtExitHandlers();
|
||||||
|
|
||||||
|
/// getPointerToFunction - This returns the address of the specified function,
|
||||||
|
/// compiling it if necessary.
|
||||||
|
void *getPointerToFunction(const Function *F);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static MachineCodeEmitter *createX86Emitter(VM &V);
|
static MachineCodeEmitter *createX86Emitter(VM &V);
|
||||||
static MachineCodeEmitter *createSparcEmitter(VM &V);
|
static MachineCodeEmitter *createSparcEmitter(VM &V);
|
||||||
void setupPassManager();
|
void setupPassManager();
|
||||||
void *getPointerToFunction(const Function *F);
|
|
||||||
|
|
||||||
void registerCallback();
|
|
||||||
|
|
||||||
/// 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.
|
|
||||||
///
|
|
||||||
void *emitStubForFunction(const Function &F);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Reference in New Issue
Block a user