Skip to content

Commit

Permalink
[C-API] LLVMOrcCreateRTDyldObjectLinkingLayerWithMCJITMemoryManagerLi…
Browse files Browse the repository at this point in the history
…keCallbacks

Adds a LLVMOrcCreateRTDyldObjectLinkingLayerWithMCJITMemoryManagerLikeCallbacks
function that can be used to create an RTDyldObjectLinkingLayer using callbacks
that are similar (but not identical) to those used in
LLVMCreateSimpleMCJITMemoryManager. This is intended to ease the transition to
ORC for MCJIT C-API clients.

Differential Revision: https://reviews.llvm.org/D139393
  • Loading branch information
lhames committed Dec 17, 2022
1 parent 53243f2 commit 916ef9b
Show file tree
Hide file tree
Showing 4 changed files with 149 additions and 2 deletions.
37 changes: 37 additions & 0 deletions llvm/include/llvm-c/OrcEE.h
Expand Up @@ -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
Expand All @@ -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.
*
Expand Down
Expand Up @@ -50,7 +50,7 @@ class RTDyldObjectLinkingLayer
MaterializationResponsibility &R, std::unique_ptr<MemoryBuffer>)>;

using GetMemoryManagerFunction =
std::function<std::unique_ptr<RuntimeDyld::MemoryManager>()>;
unique_function<std::unique_ptr<RuntimeDyld::MemoryManager>()>;

/// Construct an ObjectLinkingLayer with the given NotifyLoaded,
/// and NotifyEmitted functors.
Expand Down
110 changes: 110 additions & 0 deletions llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp
Expand Up @@ -1069,6 +1069,116 @@ LLVMOrcCreateRTDyldObjectLinkingLayerWithSectionMemoryManager(
*unwrap(ES), [] { return std::make_unique<SectionMemoryManager>(); }));
}

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<MCJITMemoryManagerLikeCallbacksMemMgr>(CBs);
}));

return nullptr;
}

void LLVMOrcRTDyldObjectLinkingLayerRegisterJITEventListener(
LLVMOrcObjectLayerRef RTDyldObjLinkingLayer,
LLVMJITEventListenerRef Listener) {
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp
Expand Up @@ -81,7 +81,7 @@ using BaseT = RTTIExtends<RTDyldObjectLinkingLayer, ObjectLayer>;

RTDyldObjectLinkingLayer::RTDyldObjectLinkingLayer(
ExecutionSession &ES, GetMemoryManagerFunction GetMemoryManager)
: BaseT(ES), GetMemoryManager(GetMemoryManager) {
: BaseT(ES), GetMemoryManager(std::move(GetMemoryManager)) {
ES.registerResourceManager(*this);
}

Expand Down

0 comments on commit 916ef9b

Please sign in to comment.