Layer the memory manager between the JIT and the runtime Dyld.

The JITMemory manager references LLVM IR constructs directly, while the
runtime Dyld works at a lower level and can handle objects which may not
originate from LLVM IR. Introduce a new layer for the memory manager to
handle the interface between them. For the MCJIT, this layer will be almost
entirely simply a call-through w/ translation between the IR objects and
symbol names.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@128851 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Jim Grosbach
2011-04-04 23:04:39 +00:00
parent c15a91dfc8
commit fcbe5b7193
5 changed files with 64 additions and 25 deletions

View File

@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===//
#include "MCJIT.h"
#include "MCJITMemoryManager.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Function.h"
#include "llvm/ExecutionEngine/GenericValue.h"
@ -57,7 +58,8 @@ ExecutionEngine *MCJIT::createJIT(Module *M,
// If the target supports JIT code generation, create the JIT.
if (TargetJITInfo *TJ = TM->getJITInfo())
return new MCJIT(M, TM, *TJ, JMM, OptLevel, GVsWithCode);
return new MCJIT(M, TM, *TJ, new MCJITMemoryManager(JMM), OptLevel,
GVsWithCode);
if (ErrorStr)
*ErrorStr = "target does not support JIT code generation";
@ -65,9 +67,9 @@ ExecutionEngine *MCJIT::createJIT(Module *M,
}
MCJIT::MCJIT(Module *m, TargetMachine *tm, TargetJITInfo &tji,
JITMemoryManager *JMM, CodeGenOpt::Level OptLevel,
RTDyldMemoryManager *MM, CodeGenOpt::Level OptLevel,
bool AllocateGVsWithCode)
: ExecutionEngine(m), TM(tm), M(m), OS(Buffer), Dyld(JMM) {
: ExecutionEngine(m), TM(tm), MemMgr(MM), M(m), OS(Buffer), Dyld(MM) {
PM.add(new TargetData(*TM->getTargetData()));
@ -94,6 +96,7 @@ MCJIT::MCJIT(Module *m, TargetMachine *tm, TargetJITInfo &tji,
}
MCJIT::~MCJIT() {
delete MemMgr;
}
void *MCJIT::getPointerToBasicBlock(BasicBlock *BB) {
@ -110,7 +113,7 @@ void *MCJIT::getPointerToFunction(Function *F) {
}
Twine Name = TM->getMCAsmInfo()->getGlobalPrefix() + F->getName();
return Dyld.getSymbolAddress(Name.str());
return (void*)Dyld.getSymbolAddress(Name.str());
}
void *MCJIT::recompileAndRelinkFunction(Function *F) {

View File

@ -24,11 +24,12 @@ namespace llvm {
class MCJIT : public ExecutionEngine {
MCJIT(Module *M, TargetMachine *tm, TargetJITInfo &tji,
JITMemoryManager *JMM, CodeGenOpt::Level OptLevel,
RTDyldMemoryManager *MemMgr, CodeGenOpt::Level OptLevel,
bool AllocateGVsWithCode);
TargetMachine *TM;
MCContext *Ctx;
RTDyldMemoryManager *MemMgr;
// FIXME: These may need moved to a separate 'jitstate' member like the
// non-MC JIT does for multithreading and such. Just keep them here for now.

View File

@ -18,7 +18,6 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/ExecutionEngine/RuntimeDyld.h"
#include "llvm/ExecutionEngine/JITMemoryManager.h"
#include "llvm/Object/MachOObject.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
@ -35,12 +34,12 @@ class RuntimeDyldImpl {
unsigned CPUType;
unsigned CPUSubtype;
// The JITMemoryManager to load objects into.
JITMemoryManager *JMM;
// The MemoryManager to load objects into.
RTDyldMemoryManager *MemMgr;
// Master symbol table. As modules are loaded and external symbols are
// resolved, their addresses are stored here.
StringMap<void*> SymbolTable;
StringMap<uint64_t> SymbolTable;
// FIXME: Should have multiple data blocks, one for each loaded chunk of
// compiled code.
@ -72,11 +71,11 @@ class RuntimeDyldImpl {
const InMemoryStruct<macho::SymtabLoadCommand> &SymtabLC);
public:
RuntimeDyldImpl(JITMemoryManager *jmm) : JMM(jmm), HasError(false) {}
RuntimeDyldImpl(RTDyldMemoryManager *mm) : MemMgr(mm), HasError(false) {}
bool loadObject(MemoryBuffer *InputBuffer);
void *getSymbolAddress(StringRef Name) {
uint64_t getSymbolAddress(StringRef Name) {
// Use lookup() rather than [] because we don't want to add an entry
// if there isn't one already, which the [] operator does.
return SymbolTable.lookup(Name);
@ -314,7 +313,7 @@ loadSegment32(const MachOObject *Obj,
void *SectionBase = SectionBases[Index];
// Get the symbol address.
void *Address = (char*) SectionBase + STE->Value;
uint64_t Address = (uint64_t)SectionBase + STE->Value;
// FIXME: Check the symbol type and flags.
if (STE->Type != 0xF)
@ -335,7 +334,7 @@ loadSegment32(const MachOObject *Obj,
}
// We've loaded the section; now mark the functions in it as executable.
// FIXME: We really should use the JITMemoryManager for this.
// FIXME: We really should use the MemoryManager for this.
sys::Memory::setRangeExecutable(Data.base(), Data.size());
return false;
@ -414,7 +413,7 @@ loadSegment64(const MachOObject *Obj,
void *SectionBase = SectionBases[Index];
// Get the symbol address.
void *Address = (char*) SectionBase + STE->Value;
uint64_t Address = (uint64_t) SectionBase + STE->Value;
// FIXME: Check the symbol type and flags.
if (STE->Type != 0xF)
@ -434,7 +433,7 @@ loadSegment64(const MachOObject *Obj,
}
// We've loaded the section; now mark the functions in it as executable.
// FIXME: We really should use the JITMemoryManager for this.
// FIXME: We really should use the MemoryManager for this.
sys::Memory::setRangeExecutable(Data.base(), Data.size());
return false;
@ -530,8 +529,8 @@ bool RuntimeDyldImpl::loadObject(MemoryBuffer *InputBuffer) {
//===----------------------------------------------------------------------===//
// RuntimeDyld class implementation
RuntimeDyld::RuntimeDyld(JITMemoryManager *JMM) {
Dyld = new RuntimeDyldImpl(JMM);
RuntimeDyld::RuntimeDyld(RTDyldMemoryManager *MM) {
Dyld = new RuntimeDyldImpl(MM);
}
RuntimeDyld::~RuntimeDyld() {
@ -542,7 +541,7 @@ bool RuntimeDyld::loadObject(MemoryBuffer *InputBuffer) {
return Dyld->loadObject(InputBuffer);
}
void *RuntimeDyld::getSymbolAddress(StringRef Name) {
uint64_t RuntimeDyld::getSymbolAddress(StringRef Name) {
return Dyld->getSymbolAddress(Name);
}