mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-23 17:24:48 +00:00
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:
@ -21,7 +21,29 @@ namespace llvm {
|
|||||||
|
|
||||||
class RuntimeDyldImpl;
|
class RuntimeDyldImpl;
|
||||||
class MemoryBuffer;
|
class MemoryBuffer;
|
||||||
class JITMemoryManager;
|
|
||||||
|
// RuntimeDyld clients often want to handle the memory management of
|
||||||
|
// what gets placed where. For JIT clients, this is an abstraction layer
|
||||||
|
// over the JITMemoryManager, which references objects by their source
|
||||||
|
// representations in LLVM IR.
|
||||||
|
// FIXME: As the RuntimeDyld fills out, additional routines will be needed
|
||||||
|
// for the varying types of objects to be allocated.
|
||||||
|
class RTDyldMemoryManager {
|
||||||
|
RTDyldMemoryManager(const RTDyldMemoryManager&); // DO NOT IMPLEMENT
|
||||||
|
void operator=(const RTDyldMemoryManager&); // DO NOT IMPLEMENT
|
||||||
|
public:
|
||||||
|
RTDyldMemoryManager() {}
|
||||||
|
|
||||||
|
// Allocate ActualSize bytes, or more, for the named function. Return
|
||||||
|
// a pointer to the allocated memory and update Size to reflect how much
|
||||||
|
// memory was acutally allocated.
|
||||||
|
virtual uint64_t startFunctionBody(const char *Name, uintptr_t &Size) = 0;
|
||||||
|
|
||||||
|
// Mark the end of the function, including how much of the allocated
|
||||||
|
// memory was actually used.
|
||||||
|
virtual void endFunctionBody(const char *Name, uint64_t FunctionStart,
|
||||||
|
uint64_t FunctionEnd) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
class RuntimeDyld {
|
class RuntimeDyld {
|
||||||
RuntimeDyld(const RuntimeDyld &); // DO NOT IMPLEMENT
|
RuntimeDyld(const RuntimeDyld &); // DO NOT IMPLEMENT
|
||||||
@ -31,11 +53,12 @@ class RuntimeDyld {
|
|||||||
// interface.
|
// interface.
|
||||||
RuntimeDyldImpl *Dyld;
|
RuntimeDyldImpl *Dyld;
|
||||||
public:
|
public:
|
||||||
RuntimeDyld(JITMemoryManager*);
|
RuntimeDyld(RTDyldMemoryManager*);
|
||||||
~RuntimeDyld();
|
~RuntimeDyld();
|
||||||
|
|
||||||
bool loadObject(MemoryBuffer *InputBuffer);
|
bool loadObject(MemoryBuffer *InputBuffer);
|
||||||
void *getSymbolAddress(StringRef Name);
|
uint64_t getSymbolAddress(StringRef Name);
|
||||||
|
void reassignSymbolAddress(StringRef Name, uint64_t Addr);
|
||||||
// FIXME: Should be parameterized to get the memory block associated with
|
// FIXME: Should be parameterized to get the memory block associated with
|
||||||
// a particular loaded object.
|
// a particular loaded object.
|
||||||
sys::MemoryBlock getMemoryBlock();
|
sys::MemoryBlock getMemoryBlock();
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#include "MCJIT.h"
|
#include "MCJIT.h"
|
||||||
|
#include "MCJITMemoryManager.h"
|
||||||
#include "llvm/DerivedTypes.h"
|
#include "llvm/DerivedTypes.h"
|
||||||
#include "llvm/Function.h"
|
#include "llvm/Function.h"
|
||||||
#include "llvm/ExecutionEngine/GenericValue.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 the target supports JIT code generation, create the JIT.
|
||||||
if (TargetJITInfo *TJ = TM->getJITInfo())
|
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)
|
if (ErrorStr)
|
||||||
*ErrorStr = "target does not support JIT code generation";
|
*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,
|
MCJIT::MCJIT(Module *m, TargetMachine *tm, TargetJITInfo &tji,
|
||||||
JITMemoryManager *JMM, CodeGenOpt::Level OptLevel,
|
RTDyldMemoryManager *MM, CodeGenOpt::Level OptLevel,
|
||||||
bool AllocateGVsWithCode)
|
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()));
|
PM.add(new TargetData(*TM->getTargetData()));
|
||||||
|
|
||||||
@ -94,6 +96,7 @@ MCJIT::MCJIT(Module *m, TargetMachine *tm, TargetJITInfo &tji,
|
|||||||
}
|
}
|
||||||
|
|
||||||
MCJIT::~MCJIT() {
|
MCJIT::~MCJIT() {
|
||||||
|
delete MemMgr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *MCJIT::getPointerToBasicBlock(BasicBlock *BB) {
|
void *MCJIT::getPointerToBasicBlock(BasicBlock *BB) {
|
||||||
@ -110,7 +113,7 @@ void *MCJIT::getPointerToFunction(Function *F) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Twine Name = TM->getMCAsmInfo()->getGlobalPrefix() + F->getName();
|
Twine Name = TM->getMCAsmInfo()->getGlobalPrefix() + F->getName();
|
||||||
return Dyld.getSymbolAddress(Name.str());
|
return (void*)Dyld.getSymbolAddress(Name.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void *MCJIT::recompileAndRelinkFunction(Function *F) {
|
void *MCJIT::recompileAndRelinkFunction(Function *F) {
|
||||||
|
@ -24,11 +24,12 @@ namespace llvm {
|
|||||||
|
|
||||||
class MCJIT : public ExecutionEngine {
|
class MCJIT : public ExecutionEngine {
|
||||||
MCJIT(Module *M, TargetMachine *tm, TargetJITInfo &tji,
|
MCJIT(Module *M, TargetMachine *tm, TargetJITInfo &tji,
|
||||||
JITMemoryManager *JMM, CodeGenOpt::Level OptLevel,
|
RTDyldMemoryManager *MemMgr, CodeGenOpt::Level OptLevel,
|
||||||
bool AllocateGVsWithCode);
|
bool AllocateGVsWithCode);
|
||||||
|
|
||||||
TargetMachine *TM;
|
TargetMachine *TM;
|
||||||
MCContext *Ctx;
|
MCContext *Ctx;
|
||||||
|
RTDyldMemoryManager *MemMgr;
|
||||||
|
|
||||||
// FIXME: These may need moved to a separate 'jitstate' member like the
|
// 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.
|
// non-MC JIT does for multithreading and such. Just keep them here for now.
|
||||||
|
@ -18,7 +18,6 @@
|
|||||||
#include "llvm/ADT/StringRef.h"
|
#include "llvm/ADT/StringRef.h"
|
||||||
#include "llvm/ADT/Twine.h"
|
#include "llvm/ADT/Twine.h"
|
||||||
#include "llvm/ExecutionEngine/RuntimeDyld.h"
|
#include "llvm/ExecutionEngine/RuntimeDyld.h"
|
||||||
#include "llvm/ExecutionEngine/JITMemoryManager.h"
|
|
||||||
#include "llvm/Object/MachOObject.h"
|
#include "llvm/Object/MachOObject.h"
|
||||||
#include "llvm/Support/Debug.h"
|
#include "llvm/Support/Debug.h"
|
||||||
#include "llvm/Support/ErrorHandling.h"
|
#include "llvm/Support/ErrorHandling.h"
|
||||||
@ -35,12 +34,12 @@ class RuntimeDyldImpl {
|
|||||||
unsigned CPUType;
|
unsigned CPUType;
|
||||||
unsigned CPUSubtype;
|
unsigned CPUSubtype;
|
||||||
|
|
||||||
// The JITMemoryManager to load objects into.
|
// The MemoryManager to load objects into.
|
||||||
JITMemoryManager *JMM;
|
RTDyldMemoryManager *MemMgr;
|
||||||
|
|
||||||
// Master symbol table. As modules are loaded and external symbols are
|
// Master symbol table. As modules are loaded and external symbols are
|
||||||
// resolved, their addresses are stored here.
|
// 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
|
// FIXME: Should have multiple data blocks, one for each loaded chunk of
|
||||||
// compiled code.
|
// compiled code.
|
||||||
@ -72,11 +71,11 @@ class RuntimeDyldImpl {
|
|||||||
const InMemoryStruct<macho::SymtabLoadCommand> &SymtabLC);
|
const InMemoryStruct<macho::SymtabLoadCommand> &SymtabLC);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
RuntimeDyldImpl(JITMemoryManager *jmm) : JMM(jmm), HasError(false) {}
|
RuntimeDyldImpl(RTDyldMemoryManager *mm) : MemMgr(mm), HasError(false) {}
|
||||||
|
|
||||||
bool loadObject(MemoryBuffer *InputBuffer);
|
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
|
// Use lookup() rather than [] because we don't want to add an entry
|
||||||
// if there isn't one already, which the [] operator does.
|
// if there isn't one already, which the [] operator does.
|
||||||
return SymbolTable.lookup(Name);
|
return SymbolTable.lookup(Name);
|
||||||
@ -314,7 +313,7 @@ loadSegment32(const MachOObject *Obj,
|
|||||||
void *SectionBase = SectionBases[Index];
|
void *SectionBase = SectionBases[Index];
|
||||||
|
|
||||||
// Get the symbol address.
|
// 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.
|
// FIXME: Check the symbol type and flags.
|
||||||
if (STE->Type != 0xF)
|
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.
|
// 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());
|
sys::Memory::setRangeExecutable(Data.base(), Data.size());
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@ -414,7 +413,7 @@ loadSegment64(const MachOObject *Obj,
|
|||||||
void *SectionBase = SectionBases[Index];
|
void *SectionBase = SectionBases[Index];
|
||||||
|
|
||||||
// Get the symbol address.
|
// 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.
|
// FIXME: Check the symbol type and flags.
|
||||||
if (STE->Type != 0xF)
|
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.
|
// 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());
|
sys::Memory::setRangeExecutable(Data.base(), Data.size());
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@ -530,8 +529,8 @@ bool RuntimeDyldImpl::loadObject(MemoryBuffer *InputBuffer) {
|
|||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// RuntimeDyld class implementation
|
// RuntimeDyld class implementation
|
||||||
RuntimeDyld::RuntimeDyld(JITMemoryManager *JMM) {
|
RuntimeDyld::RuntimeDyld(RTDyldMemoryManager *MM) {
|
||||||
Dyld = new RuntimeDyldImpl(JMM);
|
Dyld = new RuntimeDyldImpl(MM);
|
||||||
}
|
}
|
||||||
|
|
||||||
RuntimeDyld::~RuntimeDyld() {
|
RuntimeDyld::~RuntimeDyld() {
|
||||||
@ -542,7 +541,7 @@ bool RuntimeDyld::loadObject(MemoryBuffer *InputBuffer) {
|
|||||||
return Dyld->loadObject(InputBuffer);
|
return Dyld->loadObject(InputBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *RuntimeDyld::getSymbolAddress(StringRef Name) {
|
uint64_t RuntimeDyld::getSymbolAddress(StringRef Name) {
|
||||||
return Dyld->getSymbolAddress(Name);
|
return Dyld->getSymbolAddress(Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,7 +13,6 @@
|
|||||||
|
|
||||||
#include "llvm/ADT/StringMap.h"
|
#include "llvm/ADT/StringMap.h"
|
||||||
#include "llvm/ADT/OwningPtr.h"
|
#include "llvm/ADT/OwningPtr.h"
|
||||||
#include "llvm/ExecutionEngine/JITMemoryManager.h"
|
|
||||||
#include "llvm/ExecutionEngine/RuntimeDyld.h"
|
#include "llvm/ExecutionEngine/RuntimeDyld.h"
|
||||||
#include "llvm/Object/MachOObject.h"
|
#include "llvm/Object/MachOObject.h"
|
||||||
#include "llvm/Support/CommandLine.h"
|
#include "llvm/Support/CommandLine.h"
|
||||||
@ -41,6 +40,20 @@ Action(cl::desc("Action to perform:"),
|
|||||||
|
|
||||||
/* *** */
|
/* *** */
|
||||||
|
|
||||||
|
// A trivial memory manager that doesn't do anything fancy, just uses the
|
||||||
|
// support library allocation routines directly.
|
||||||
|
class TrivialMemoryManager : public RTDyldMemoryManager {
|
||||||
|
public:
|
||||||
|
uint64_t startFunctionBody(const char *Name, uintptr_t &Size);
|
||||||
|
void endFunctionBody(const char *Name, uint64_t FunctionStart,
|
||||||
|
uint64_t FunctionEnd) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
uint64_t TrivialMemoryManager::startFunctionBody(const char *Name,
|
||||||
|
uintptr_t &Size) {
|
||||||
|
return (uint64_t)sys::Memory::AllocateRWX(Size, 0, 0).base();
|
||||||
|
}
|
||||||
|
|
||||||
static const char *ProgramName;
|
static const char *ProgramName;
|
||||||
|
|
||||||
static void Message(const char *Type, const Twine &Msg) {
|
static void Message(const char *Type, const Twine &Msg) {
|
||||||
@ -61,7 +74,7 @@ static int executeInput() {
|
|||||||
return Error("unable to read input: '" + ec.message() + "'");
|
return Error("unable to read input: '" + ec.message() + "'");
|
||||||
|
|
||||||
// Instantiate a dynamic linker.
|
// Instantiate a dynamic linker.
|
||||||
RuntimeDyld Dyld(JITMemoryManager::CreateDefaultMemManager());
|
RuntimeDyld Dyld(new TrivialMemoryManager);
|
||||||
|
|
||||||
// Load the object file into it.
|
// Load the object file into it.
|
||||||
if (Dyld.loadObject(InputBuffer.take())) {
|
if (Dyld.loadObject(InputBuffer.take())) {
|
||||||
@ -69,7 +82,7 @@ static int executeInput() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get the address of "_main".
|
// Get the address of "_main".
|
||||||
void *MainAddress = Dyld.getSymbolAddress("_main");
|
uint64_t MainAddress = Dyld.getSymbolAddress("_main");
|
||||||
if (MainAddress == 0)
|
if (MainAddress == 0)
|
||||||
return Error("no definition for '_main'");
|
return Error("no definition for '_main'");
|
||||||
|
|
||||||
@ -83,7 +96,7 @@ static int executeInput() {
|
|||||||
return Error("unable to mark function executable: '" + ErrorStr + "'");
|
return Error("unable to mark function executable: '" + ErrorStr + "'");
|
||||||
|
|
||||||
// Dispatch to _main().
|
// Dispatch to _main().
|
||||||
errs() << "loaded '_main' at: " << MainAddress << "\n";
|
errs() << "loaded '_main' at: " << (void*)MainAddress << "\n";
|
||||||
|
|
||||||
int (*Main)(int, const char**) =
|
int (*Main)(int, const char**) =
|
||||||
(int(*)(int,const char**)) uintptr_t(MainAddress);
|
(int(*)(int,const char**)) uintptr_t(MainAddress);
|
||||||
|
Reference in New Issue
Block a user