Index: include/llvm-c/ExecutionEngine.h =================================================================== --- include/llvm-c/ExecutionEngine.h +++ include/llvm-c/ExecutionEngine.h @@ -182,6 +182,12 @@ void LLVMDisposeMCJITMemoryManager(LLVMMCJITMemoryManagerRef MM); +/*===-- JIT Event Listener functions -------------------------------------===*/ + +LLVMJITEventListenerRef LLVMCreateGDBRegistrationListener(void); +LLVMJITEventListenerRef LLVMCreateIntelJITEventListener(void); +LLVMJITEventListenerRef LLVMCreateOprofileJITEventListener(void); + /** * @} */ Index: include/llvm-c/OrcBindings.h =================================================================== --- include/llvm-c/OrcBindings.h +++ include/llvm-c/OrcBindings.h @@ -145,6 +145,20 @@ */ LLVMOrcErrorCode LLVMOrcDisposeInstance(LLVMOrcJITStackRef JITStack); +/** + * Register a JIT Event Listener. + * + * A NULL listener is ignored. + */ +void LLVMOrcRegisterJITEventListener(LLVMOrcJITStackRef JITStack, LLVMJITEventListenerRef L); + +/** + * Unegister a JIT Event Listener. + * + * A NULL listener is ignored. + */ +void LLVMOrcUnregisterJITEventListener(LLVMOrcJITStackRef JITStack, LLVMJITEventListenerRef L); + #ifdef __cplusplus } #endif /* extern "C" */ Index: include/llvm-c/Types.h =================================================================== --- include/llvm-c/Types.h +++ include/llvm-c/Types.h @@ -139,6 +139,11 @@ */ typedef struct LLVMComdat *LLVMComdatRef; +/** + * @see llvm::JITEventListener + */ +typedef struct LLVMOpaqueJITEventListener *LLVMJITEventListenerRef; + /** * @} */ Index: include/llvm/ExecutionEngine/JITEventListener.h =================================================================== --- include/llvm/ExecutionEngine/JITEventListener.h +++ include/llvm/ExecutionEngine/JITEventListener.h @@ -15,9 +15,11 @@ #ifndef LLVM_EXECUTIONENGINE_JITEVENTLISTENER_H #define LLVM_EXECUTIONENGINE_JITEVENTLISTENER_H +#include "llvm-c/ExecutionEngine.h" #include "llvm/Config/llvm-config.h" #include "llvm/ExecutionEngine/RuntimeDyld.h" #include "llvm/IR/DebugLoc.h" +#include "llvm/Support/CBindingWrapping.h" #include #include @@ -119,6 +121,20 @@ virtual void anchor(); }; +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(JITEventListener, LLVMJITEventListenerRef) + } // end namespace llvm +#ifndef LLVM_USE_INTEL_JITEVENTS +LLVMJITEventListenerRef LLVMCreateIntelJITEventListener(void) { + return nullptr; +} +#endif + +#ifndef LLVM_USE_OPROFILE +LLVMJITEventListenerRef LLVMCreateOProfileJITEventListener(void) { + return nullptr; +} +#endif + #endif // LLVM_EXECUTIONENGINE_JITEVENTLISTENER_H Index: include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h =================================================================== --- include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h +++ include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h @@ -98,7 +98,12 @@ const RuntimeDyld::LoadedObjectInfo &)>; /// @brief Functor for receiving finalization notifications. - using NotifyFinalizedFtor = std::function; + using NotifyFinalizedFtor = + std::function; + + /// @brief Functor for receiving deallocation notifications. + using NotifyFreedFtor = std::function; private: using OwnedObject = object::OwningBinary; @@ -110,21 +115,26 @@ OwnedObject Obj, MemoryManagerPtrT MemMgr, std::shared_ptr Resolver, bool ProcessAllSections) - : MemMgr(std::move(MemMgr)), + : K(std::move(K)), + Parent(Parent), + MemMgr(std::move(MemMgr)), PFC(llvm::make_unique( - Parent, std::move(K), std::move(Obj), std::move(Resolver), + std::move(Obj), std::move(Resolver), ProcessAllSections)) { buildInitialSymbolTable(PFC->Obj); } ~ConcreteLinkedObject() override { + if (this->Parent.NotifyFreed) + this->Parent.NotifyFreed(K, *ObjForNotify.getBinary()); + MemMgr->deregisterEHFrames(); } Error finalize() override { assert(PFC && "mapSectionAddress called on finalized LinkedObject"); - JITSymbolResolverAdapter ResolverAdapter(PFC->Parent.ES, *PFC->Resolver); + JITSymbolResolverAdapter ResolverAdapter(Parent.ES, *PFC->Resolver); PFC->RTDyld = llvm::make_unique(*MemMgr, ResolverAdapter); PFC->RTDyld->setProcessAllSections(PFC->ProcessAllSections); @@ -140,8 +150,8 @@ SymbolTable[KV.first] = KV.second; } - if (PFC->Parent.NotifyLoaded) - PFC->Parent.NotifyLoaded(PFC->K, *PFC->Obj.getBinary(), *Info); + if (Parent.NotifyLoaded) + Parent.NotifyLoaded(K, *PFC->Obj.getBinary(), *Info); PFC->RTDyld->finalizeWithMemoryManagerLocking(); @@ -149,10 +159,12 @@ return make_error(PFC->RTDyld->getErrorString(), inconvertibleErrorCode()); - if (PFC->Parent.NotifyFinalized) - PFC->Parent.NotifyFinalized(PFC->K); + if (Parent.NotifyFinalized) + Parent.NotifyFinalized(K, *PFC->Obj.getBinary(), *Info); // Release resources. + if (this->Parent.NotifyFreed) + ObjForNotify = std::move(PFC->Obj); // needed for callback PFC = nullptr; return Error::success(); } @@ -195,23 +207,23 @@ // Contains the information needed prior to finalization: the object files, // memory manager, resolver, and flags needed for RuntimeDyld. struct PreFinalizeContents { - PreFinalizeContents(RTDyldObjectLinkingLayer &Parent, VModuleKey K, - OwnedObject Obj, + PreFinalizeContents(OwnedObject Obj, std::shared_ptr Resolver, bool ProcessAllSections) - : Parent(Parent), K(std::move(K)), Obj(std::move(Obj)), + : Obj(std::move(Obj)), Resolver(std::move(Resolver)), ProcessAllSections(ProcessAllSections) {} - RTDyldObjectLinkingLayer &Parent; - VModuleKey K; OwnedObject Obj; std::shared_ptr Resolver; bool ProcessAllSections; std::unique_ptr RTDyld; }; + VModuleKey K; + RTDyldObjectLinkingLayer &Parent; MemoryManagerPtrT MemMgr; + OwnedObject ObjForNotify; std::unique_ptr PFC; }; @@ -240,10 +252,13 @@ RTDyldObjectLinkingLayer( ExecutionSession &ES, ResourcesGetter GetResources, NotifyLoadedFtor NotifyLoaded = NotifyLoadedFtor(), - NotifyFinalizedFtor NotifyFinalized = NotifyFinalizedFtor()) + NotifyFinalizedFtor NotifyFinalized = NotifyFinalizedFtor(), + NotifyFreedFtor NotifyFreed = NotifyFreedFtor()) : ES(ES), GetResources(std::move(GetResources)), NotifyLoaded(std::move(NotifyLoaded)), - NotifyFinalized(std::move(NotifyFinalized)), ProcessAllSections(false) { + NotifyFinalized(std::move(NotifyFinalized)), + NotifyFreed(std::move(NotifyFreed)), + ProcessAllSections(false) { } /// @brief Set the 'ProcessAllSections' flag. @@ -340,6 +355,7 @@ ResourcesGetter GetResources; NotifyLoadedFtor NotifyLoaded; NotifyFinalizedFtor NotifyFinalized; + NotifyFreedFtor NotifyFreed; bool ProcessAllSections = false; }; Index: lib/ExecutionEngine/GDBRegistrationListener.cpp =================================================================== --- lib/ExecutionEngine/GDBRegistrationListener.cpp +++ lib/ExecutionEngine/GDBRegistrationListener.cpp @@ -7,6 +7,7 @@ // //===----------------------------------------------------------------------===// +#include "llvm-c/ExecutionEngine.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ExecutionEngine/JITEventListener.h" #include "llvm/Object/ObjectFile.h" @@ -235,3 +236,8 @@ } } // namespace llvm + +LLVMJITEventListenerRef LLVMCreateGDBRegistrationListener(void) +{ + return wrap(JITEventListener::createGDBRegistrationListener()); +} Index: lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp =================================================================== --- lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp +++ lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// #include "IntelJITEventsWrapper.h" +#include "llvm-c/ExecutionEngine.h" #include "llvm/ADT/DenseMap.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/Config/config.h" @@ -238,3 +239,7 @@ } // namespace llvm +LLVMJITEventListenerRef LLVMCreateIntelJITEventListener(void) +{ + return wrap(JITEventListener::createIntelJITEventListener()); +} Index: lib/ExecutionEngine/OProfileJIT/OProfileJITEventListener.cpp =================================================================== --- lib/ExecutionEngine/OProfileJIT/OProfileJITEventListener.cpp +++ lib/ExecutionEngine/OProfileJIT/OProfileJITEventListener.cpp @@ -12,6 +12,7 @@ // //===----------------------------------------------------------------------===// +#include "llvm-c/ExecutionEngine.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/Config/config.h" #include "llvm/ExecutionEngine/JITEventListener.h" @@ -156,3 +157,7 @@ } // namespace llvm +LLVMJITEventListenerRef LLVMCreateOProfileJITEventListener(void) +{ + return wrap(JITEventListener::createOProfileJITEventListener()); +} Index: lib/ExecutionEngine/Orc/OrcCBindings.cpp =================================================================== --- lib/ExecutionEngine/Orc/OrcCBindings.cpp +++ lib/ExecutionEngine/Orc/OrcCBindings.cpp @@ -9,6 +9,7 @@ #include "OrcCBindingsStack.h" #include "llvm-c/OrcBindings.h" +#include "llvm/ExecutionEngine/JITEventListener.h" using namespace llvm; @@ -118,3 +119,13 @@ delete J; return Err; } + +void LLVMOrcRegisterJITEventListener(LLVMOrcJITStackRef JITStack, LLVMJITEventListenerRef L) +{ + unwrap(JITStack)->RegisterJITEventListener(unwrap(L)); +} + +void LLVMOrcUnregisterJITEventListener(LLVMOrcJITStackRef JITStack, LLVMJITEventListenerRef L) +{ + unwrap(JITStack)->UnregisterJITEventListener(unwrap(L)); +} Index: lib/ExecutionEngine/Orc/OrcCBindingsStack.h =================================================================== --- lib/ExecutionEngine/Orc/OrcCBindingsStack.h +++ lib/ExecutionEngine/Orc/OrcCBindingsStack.h @@ -15,6 +15,7 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/ExecutionEngine/JITSymbol.h" +#include "llvm/ExecutionEngine/JITEventListener.h" #include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h" #include "llvm/ExecutionEngine/Orc/CompileUtils.h" #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h" @@ -211,7 +212,14 @@ Resolvers.erase(ResolverI); return ObjLayerT::Resources{ std::make_shared(), Resolver}; - }), + }, + nullptr, + [this](orc::VModuleKey K, const object::ObjectFile &Obj, const RuntimeDyld::LoadedObjectInfo &LoadedObjInfo) { + this->notifyFinalized(K, Obj, LoadedObjInfo); + }, + [this](orc::VModuleKey K, const object::ObjectFile &Obj) { + this->notifyFreed(K, Obj); + }), CompileLayer(ObjectLayer, orc::SimpleCompiler(TM)), CODLayer(ES, CompileLayer, [this](orc::VModuleKey K) { @@ -402,6 +410,23 @@ const std::string &getErrorMessage() const { return ErrMsg; } + void RegisterJITEventListener(JITEventListener *L) { + if (!L) + return; + EventListeners.push_back(L); + } + + void UnregisterJITEventListener(JITEventListener *L) { + if (!L) + return; + + auto I = find(reverse(EventListeners), L); + if (I != EventListeners.rend()) { + std::swap(*I, EventListeners.back()); + EventListeners.pop_back(); + } + } + private: LLVMOrcErrorCode mapError(Error Err) { @@ -421,9 +446,23 @@ logAllUnhandledErrors(std::move(Err), errs(), "ORC error: "); }; + void notifyFinalized(orc::VModuleKey K, + const object::ObjectFile &Obj, + const RuntimeDyld::LoadedObjectInfo &LoadedObjInfo) { + for (auto &Listener : EventListeners) + Listener->NotifyObjectEmitted(Obj, LoadedObjInfo); + } + + void notifyFreed(orc::VModuleKey K, const object::ObjectFile &Obj) { + for (auto &Listener : EventListeners) + Listener->NotifyFreeingObject(Obj); + } + orc::SymbolStringPool SSP; orc::ExecutionSession ES; + std::vector EventListeners; + DataLayout DL; SectionMemoryManager CCMgrMemMgr; Index: lib/ExecutionEngine/Orc/OrcMCJITReplacement.h =================================================================== --- lib/ExecutionEngine/Orc/OrcMCJITReplacement.h +++ lib/ExecutionEngine/Orc/OrcMCJITReplacement.h @@ -431,7 +431,10 @@ public: NotifyFinalizedT(OrcMCJITReplacement &M) : M(M) {} - void operator()(VModuleKey K) { M.UnfinalizedSections.erase(K); } + void operator()(VModuleKey K, const object::ObjectFile &Obj, + const RuntimeDyld::LoadedObjectInfo &Info) { + M.UnfinalizedSections.erase(K); + } private: OrcMCJITReplacement &M;