diff options
Diffstat (limited to 'lib/ExecutionEngine/MCJIT/MCJIT.cpp')
| -rw-r--r-- | lib/ExecutionEngine/MCJIT/MCJIT.cpp | 104 |
1 files changed, 83 insertions, 21 deletions
diff --git a/lib/ExecutionEngine/MCJIT/MCJIT.cpp b/lib/ExecutionEngine/MCJIT/MCJIT.cpp index fa71305..fee10e1 100644 --- a/lib/ExecutionEngine/MCJIT/MCJIT.cpp +++ b/lib/ExecutionEngine/MCJIT/MCJIT.cpp @@ -8,18 +8,20 @@ //===----------------------------------------------------------------------===// #include "MCJIT.h" -#include "MCJITMemoryManager.h" -#include "llvm/DerivedTypes.h" -#include "llvm/Function.h" #include "llvm/ExecutionEngine/GenericValue.h" -#include "llvm/ExecutionEngine/MCJIT.h" +#include "llvm/ExecutionEngine/JITEventListener.h" #include "llvm/ExecutionEngine/JITMemoryManager.h" +#include "llvm/ExecutionEngine/MCJIT.h" +#include "llvm/ExecutionEngine/ObjectBuffer.h" +#include "llvm/ExecutionEngine/ObjectImage.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Function.h" #include "llvm/MC/MCAsmInfo.h" -#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/DynamicLibrary.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/MutexGuard.h" -#include "llvm/Target/TargetData.h" using namespace llvm; @@ -44,18 +46,20 @@ ExecutionEngine *MCJIT::createJIT(Module *M, // FIXME: Don't do this here. sys::DynamicLibrary::LoadLibraryPermanently(0, NULL); - return new MCJIT(M, TM, new MCJITMemoryManager(JMM), GVsWithCode); + return new MCJIT(M, TM, JMM, GVsWithCode); } MCJIT::MCJIT(Module *m, TargetMachine *tm, RTDyldMemoryManager *MM, bool AllocateGVsWithCode) : ExecutionEngine(m), TM(tm), Ctx(0), MemMgr(MM), Dyld(MM), - isCompiled(false), M(m), OS(Buffer) { + isCompiled(false), M(m) { - setTargetData(TM->getTargetData()); + setDataLayout(TM->getDataLayout()); } MCJIT::~MCJIT() { + if (LoadedObject) + NotifyFreeingObject(*LoadedObject.get()); delete MemMgr; delete TM; } @@ -63,7 +67,7 @@ MCJIT::~MCJIT() { void MCJIT::emitObject(Module *m) { /// Currently, MCJIT only supports a single module and the module passed to /// this function call is expected to be the contained module. The module - /// is passed as a parameter here to prepare for multiple module support in + /// is passed as a parameter here to prepare for multiple module support in /// the future. assert(M == m); @@ -78,36 +82,64 @@ void MCJIT::emitObject(Module *m) { PassManager PM; - PM.add(new TargetData(*TM->getTargetData())); + PM.add(new DataLayout(*TM->getDataLayout())); + + // The RuntimeDyld will take ownership of this shortly + OwningPtr<ObjectBufferStream> Buffer(new ObjectBufferStream()); // Turn the machine code intermediate representation into bytes in memory // that may be executed. - if (TM->addPassesToEmitMC(PM, Ctx, OS, false)) { + if (TM->addPassesToEmitMC(PM, Ctx, Buffer->getOStream(), false)) { report_fatal_error("Target does not support MC emission!"); } // Initialize passes. - // FIXME: When we support multiple modules, we'll want to move the code - // gen and finalization out of the constructor here and do it more - // on-demand as part of getPointerToFunction(). PM.run(*m); - // Flush the output buffer so the SmallVector gets its data. - OS.flush(); + // Flush the output buffer to get the generated code into memory + Buffer->flush(); // Load the object into the dynamic linker. - MemoryBuffer* MB = MemoryBuffer::getMemBuffer(StringRef(Buffer.data(), - Buffer.size()), - "", false); - if (Dyld.loadObject(MB)) + // handing off ownership of the buffer + LoadedObject.reset(Dyld.loadObject(Buffer.take())); + if (!LoadedObject) report_fatal_error(Dyld.getErrorString()); // Resolve any relocations. Dyld.resolveRelocations(); + // FIXME: Make this optional, maybe even move it to a JIT event listener + LoadedObject->registerWithDebugger(); + + NotifyObjectEmitted(*LoadedObject); + // FIXME: Add support for per-module compilation state isCompiled = true; } +// FIXME: Add a parameter to identify which object is being finalized when +// MCJIT supports multiple modules. +// FIXME: Provide a way to separate code emission, relocations and page +// protection in the interface. +void MCJIT::finalizeObject() { + // If the module hasn't been compiled, just do that. + if (!isCompiled) { + // If the call to Dyld.resolveRelocations() is removed from emitObject() + // we'll need to do that here. + emitObject(M); + + // Set page permissions. + MemMgr->applyPermissions(); + + return; + } + + // Resolve any relocations. + Dyld.resolveRelocations(); + + // Set page permissions. + MemMgr->applyPermissions(); +} + void *MCJIT::getPointerToBasicBlock(BasicBlock *BB) { report_fatal_error("not yet implemented"); } @@ -272,3 +304,33 @@ void *MCJIT::getPointerToNamedFunction(const std::string &Name, } return 0; } + +void MCJIT::RegisterJITEventListener(JITEventListener *L) { + if (L == NULL) + return; + MutexGuard locked(lock); + EventListeners.push_back(L); +} +void MCJIT::UnregisterJITEventListener(JITEventListener *L) { + if (L == NULL) + return; + MutexGuard locked(lock); + SmallVector<JITEventListener*, 2>::reverse_iterator I= + std::find(EventListeners.rbegin(), EventListeners.rend(), L); + if (I != EventListeners.rend()) { + std::swap(*I, EventListeners.back()); + EventListeners.pop_back(); + } +} +void MCJIT::NotifyObjectEmitted(const ObjectImage& Obj) { + MutexGuard locked(lock); + for (unsigned I = 0, S = EventListeners.size(); I < S; ++I) { + EventListeners[I]->NotifyObjectEmitted(Obj); + } +} +void MCJIT::NotifyFreeingObject(const ObjectImage& Obj) { + MutexGuard locked(lock); + for (unsigned I = 0, S = EventListeners.size(); I < S; ++I) { + EventListeners[I]->NotifyFreeingObject(Obj); + } +} |
