diff --git a/llvm/include/llvm-c/OrcEE.h b/llvm/include/llvm-c/OrcEE.h index e7ae0f5e6be20..d451187aaef59 100644 --- a/llvm/include/llvm-c/OrcEE.h +++ b/llvm/include/llvm-c/OrcEE.h @@ -32,6 +32,9 @@ LLVM_C_EXTERN_C_BEGIN +typedef void *(*LLVMMemoryManagerCreateContextCallback)(void *CtxCtx); +typedef void (*LLVMMemoryManagerNotifyTerminatingCallback)(void *CtxCtx); + /** * @defgroup LLVMCExecutionEngineORCEE ExecutionEngine-based ORC Utils * @ingroup LLVMCExecutionEngine @@ -47,6 +50,40 @@ LLVMOrcObjectLayerRef LLVMOrcCreateRTDyldObjectLinkingLayerWithSectionMemoryManager( LLVMOrcExecutionSessionRef ES); +/** + * Create a RTDyldObjectLinkingLayer instance using MCJIT-memory-manager-like + * callbacks. + * + * This is intended to simplify transitions for existing MCJIT clients. The + * callbacks used are similar (but not identical) to the callbacks for + * LLVMCreateSimpleMCJITMemoryManager: Unlike MCJIT, RTDyldObjectLinkingLayer + * will create a new memory manager for each object linked by calling the given + * CreateContext callback. This allows for code removal by destroying each + * allocator individually. Every allocator will be destroyed (if it has not been + * already) at RTDyldObjectLinkingLayer destruction time, and the + * NotifyTerminating callback will be called to indicate that no further + * allocation contexts will be created. + * + * To implement MCJIT-like behavior clients can implement CreateContext, + * NotifyTerminating, and Destroy as: + * + * void *CreateContext(void *CtxCtx) { return CtxCtx; } + * void NotifyTerminating(void *CtxCtx) { MyOriginalDestroy(CtxCtx); } + * void Destroy(void *Ctx) { } + * + * This scheme simply reuses the CreateContextCtx pointer as the one-and-only + * allocation context. + */ +LLVMOrcObjectLayerRef +LLVMOrcCreateRTDyldObjectLinkingLayerWithMCJITMemoryManagerLikeCallbacks( + LLVMOrcExecutionSessionRef ES, void *CreateContextCtx, + LLVMMemoryManagerCreateContextCallback CreateContext, + LLVMMemoryManagerNotifyTerminatingCallback NotifyTerminating, + LLVMMemoryManagerAllocateCodeSectionCallback AllocateCodeSection, + LLVMMemoryManagerAllocateDataSectionCallback AllocateDataSection, + LLVMMemoryManagerFinalizeMemoryCallback FinalizeMemory, + LLVMMemoryManagerDestroyCallback Destroy); + /** * Add the given listener to the given RTDyldObjectLinkingLayer. * diff --git a/llvm/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h b/llvm/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h index 78f85e827c053..d5a55182aeb6e 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h @@ -50,7 +50,7 @@ class RTDyldObjectLinkingLayer MaterializationResponsibility &R, std::unique_ptr)>; using GetMemoryManagerFunction = - std::function()>; + unique_function()>; /// Construct an ObjectLinkingLayer with the given NotifyLoaded, /// and NotifyEmitted functors. diff --git a/llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp b/llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp index 6575bf3e89235..b823197b404f6 100644 --- a/llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp +++ b/llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp @@ -1069,6 +1069,116 @@ LLVMOrcCreateRTDyldObjectLinkingLayerWithSectionMemoryManager( *unwrap(ES), [] { return std::make_unique(); })); } +LLVMOrcObjectLayerRef +LLVMOrcCreateRTDyldObjectLinkingLayerWithMCJITMemoryManagerLikeCallbacks( + LLVMOrcExecutionSessionRef ES, void *CreateContextCtx, + LLVMMemoryManagerCreateContextCallback CreateContext, + LLVMMemoryManagerNotifyTerminatingCallback NotifyTerminating, + LLVMMemoryManagerAllocateCodeSectionCallback AllocateCodeSection, + LLVMMemoryManagerAllocateDataSectionCallback AllocateDataSection, + LLVMMemoryManagerFinalizeMemoryCallback FinalizeMemory, + LLVMMemoryManagerDestroyCallback Destroy) { + + struct MCJITMemoryManagerLikeCallbacks { + MCJITMemoryManagerLikeCallbacks() = default; + MCJITMemoryManagerLikeCallbacks( + void *CreateContextCtx, + LLVMMemoryManagerCreateContextCallback CreateContext, + LLVMMemoryManagerNotifyTerminatingCallback NotifyTerminating, + LLVMMemoryManagerAllocateCodeSectionCallback AllocateCodeSection, + LLVMMemoryManagerAllocateDataSectionCallback AllocateDataSection, + LLVMMemoryManagerFinalizeMemoryCallback FinalizeMemory, + LLVMMemoryManagerDestroyCallback Destroy) + : CreateContextCtx(CreateContextCtx), CreateContext(CreateContext), + NotifyTerminating(NotifyTerminating), + AllocateCodeSection(AllocateCodeSection), + AllocateDataSection(AllocateDataSection), + FinalizeMemory(FinalizeMemory), Destroy(Destroy) {} + + MCJITMemoryManagerLikeCallbacks(MCJITMemoryManagerLikeCallbacks &&Other) { + std::swap(CreateContextCtx, Other.CreateContextCtx); + std::swap(CreateContext, Other.CreateContext); + std::swap(NotifyTerminating, Other.NotifyTerminating); + std::swap(AllocateCodeSection, Other.AllocateCodeSection); + std::swap(AllocateDataSection, Other.AllocateDataSection); + std::swap(FinalizeMemory, Other.FinalizeMemory); + std::swap(Destroy, Other.Destroy); + } + + ~MCJITMemoryManagerLikeCallbacks() { + if (NotifyTerminating) + NotifyTerminating(CreateContextCtx); + } + + void *CreateContextCtx = nullptr; + LLVMMemoryManagerCreateContextCallback CreateContext = nullptr; + LLVMMemoryManagerNotifyTerminatingCallback NotifyTerminating = nullptr; + LLVMMemoryManagerAllocateCodeSectionCallback AllocateCodeSection = nullptr; + LLVMMemoryManagerAllocateDataSectionCallback AllocateDataSection = nullptr; + LLVMMemoryManagerFinalizeMemoryCallback FinalizeMemory = nullptr; + LLVMMemoryManagerDestroyCallback Destroy = nullptr; + }; + + class MCJITMemoryManagerLikeCallbacksMemMgr : public RTDyldMemoryManager { + public: + MCJITMemoryManagerLikeCallbacksMemMgr( + const MCJITMemoryManagerLikeCallbacks &CBs) + : CBs(CBs) { + Opaque = CBs.CreateContext(CBs.CreateContextCtx); + } + ~MCJITMemoryManagerLikeCallbacksMemMgr() override { CBs.Destroy(Opaque); } + + uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, + unsigned SectionID, + StringRef SectionName) override { + return CBs.AllocateCodeSection(Opaque, Size, Alignment, SectionID, + SectionName.str().c_str()); + } + + uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, + unsigned SectionID, StringRef SectionName, + bool isReadOnly) override { + return CBs.AllocateDataSection(Opaque, Size, Alignment, SectionID, + SectionName.str().c_str(), isReadOnly); + } + + bool finalizeMemory(std::string *ErrMsg) override { + char *ErrMsgCString = nullptr; + bool Result = CBs.FinalizeMemory(Opaque, &ErrMsgCString); + assert((Result || !ErrMsgCString) && + "Did not expect an error message if FinalizeMemory succeeded"); + if (ErrMsgCString) { + if (ErrMsg) + *ErrMsg = ErrMsgCString; + free(ErrMsgCString); + } + return Result; + } + + private: + const MCJITMemoryManagerLikeCallbacks &CBs; + void *Opaque = nullptr; + }; + + assert(ES && "ES must not be null"); + assert(CreateContext && "CreateContext must not be null"); + assert(NotifyTerminating && "NotifyTerminating must not be null"); + assert(AllocateCodeSection && "AllocateCodeSection must not be null"); + assert(AllocateDataSection && "AllocateDataSection must not be null"); + assert(FinalizeMemory && "FinalizeMemory must not be null"); + assert(Destroy && "Destroy must not be null"); + + MCJITMemoryManagerLikeCallbacks CBs( + CreateContextCtx, CreateContext, NotifyTerminating, AllocateCodeSection, + AllocateDataSection, FinalizeMemory, Destroy); + + return wrap(new RTDyldObjectLinkingLayer(*unwrap(ES), [CBs = std::move(CBs)] { + return std::make_unique(CBs); + })); + + return nullptr; +} + void LLVMOrcRTDyldObjectLinkingLayerRegisterJITEventListener( LLVMOrcObjectLayerRef RTDyldObjLinkingLayer, LLVMJITEventListenerRef Listener) { diff --git a/llvm/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp b/llvm/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp index e55a607cba1da..8e9d4cda1c237 100644 --- a/llvm/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp +++ b/llvm/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp @@ -81,7 +81,7 @@ using BaseT = RTTIExtends; RTDyldObjectLinkingLayer::RTDyldObjectLinkingLayer( ExecutionSession &ES, GetMemoryManagerFunction GetMemoryManager) - : BaseT(ES), GetMemoryManager(GetMemoryManager) { + : BaseT(ES), GetMemoryManager(std::move(GetMemoryManager)) { ES.registerResourceManager(*this); }