diff --git a/include/llvm/ExecutionEngine/RuntimeDyld.h b/include/llvm/ExecutionEngine/RuntimeDyld.h index ade0047a591..01fc3383164 100644 --- a/include/llvm/ExecutionEngine/RuntimeDyld.h +++ b/include/llvm/ExecutionEngine/RuntimeDyld.h @@ -21,7 +21,29 @@ namespace llvm { class RuntimeDyldImpl; 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 { RuntimeDyld(const RuntimeDyld &); // DO NOT IMPLEMENT @@ -31,11 +53,12 @@ class RuntimeDyld { // interface. RuntimeDyldImpl *Dyld; public: - RuntimeDyld(JITMemoryManager*); + RuntimeDyld(RTDyldMemoryManager*); ~RuntimeDyld(); 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 // a particular loaded object. sys::MemoryBlock getMemoryBlock(); diff --git a/lib/ExecutionEngine/MCJIT/MCJIT.cpp b/lib/ExecutionEngine/MCJIT/MCJIT.cpp index 2e3c9310fb2..148e0d91b48 100644 --- a/lib/ExecutionEngine/MCJIT/MCJIT.cpp +++ b/lib/ExecutionEngine/MCJIT/MCJIT.cpp @@ -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) { diff --git a/lib/ExecutionEngine/MCJIT/MCJIT.h b/lib/ExecutionEngine/MCJIT/MCJIT.h index 915ca0ea1e0..1b507663e4a 100644 --- a/lib/ExecutionEngine/MCJIT/MCJIT.h +++ b/lib/ExecutionEngine/MCJIT/MCJIT.h @@ -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. diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp index c041c940de9..536013a2793 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp @@ -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 SymbolTable; + StringMap SymbolTable; // FIXME: Should have multiple data blocks, one for each loaded chunk of // compiled code. @@ -72,11 +71,11 @@ class RuntimeDyldImpl { const InMemoryStruct &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); } diff --git a/tools/llvm-rtdyld/llvm-rtdyld.cpp b/tools/llvm-rtdyld/llvm-rtdyld.cpp index a6709442356..e09f14ad784 100644 --- a/tools/llvm-rtdyld/llvm-rtdyld.cpp +++ b/tools/llvm-rtdyld/llvm-rtdyld.cpp @@ -13,7 +13,6 @@ #include "llvm/ADT/StringMap.h" #include "llvm/ADT/OwningPtr.h" -#include "llvm/ExecutionEngine/JITMemoryManager.h" #include "llvm/ExecutionEngine/RuntimeDyld.h" #include "llvm/Object/MachOObject.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 void Message(const char *Type, const Twine &Msg) { @@ -61,7 +74,7 @@ static int executeInput() { return Error("unable to read input: '" + ec.message() + "'"); // Instantiate a dynamic linker. - RuntimeDyld Dyld(JITMemoryManager::CreateDefaultMemManager()); + RuntimeDyld Dyld(new TrivialMemoryManager); // Load the object file into it. if (Dyld.loadObject(InputBuffer.take())) { @@ -69,7 +82,7 @@ static int executeInput() { } // Get the address of "_main". - void *MainAddress = Dyld.getSymbolAddress("_main"); + uint64_t MainAddress = Dyld.getSymbolAddress("_main"); if (MainAddress == 0) return Error("no definition for '_main'"); @@ -83,7 +96,7 @@ static int executeInput() { return Error("unable to mark function executable: '" + ErrorStr + "'"); // Dispatch to _main(). - errs() << "loaded '_main' at: " << MainAddress << "\n"; + errs() << "loaded '_main' at: " << (void*)MainAddress << "\n"; int (*Main)(int, const char**) = (int(*)(int,const char**)) uintptr_t(MainAddress);