[clang] [llvm] [ORC] Replace ThreadSafeContext::getContext with withContextDo. (PR #146819)
Lang Hames via llvm-commits
llvm-commits at lists.llvm.org
Wed Jul 2 22:08:03 PDT 2025
https://github.com/lhames created https://github.com/llvm/llvm-project/pull/146819
This removes ThreadSafeContext::Lock, ThreadSafeContext::getLock, and ThreadSafeContext::getContext, and replaces them with a ThreadSafeContext::withContextDo method (and const override).
The new method can be used to access an existing ThreadSafeContext-wrapped LLVMContext in a safe way:
ThreadSafeContext TSCtx = ... ;
TSCtx.withContextDo([](LLVMContext *Ctx) {
// this closure has exclusive access to Ctx.
});
The new API enforces correct locking, whereas the old APIs relied on manual locking (which almost no in-tree code preformed, relying instead on incidental exclusive access to the ThreadSafeContext).
>From bc2a43f9b08d4221cd62ac739ba26d01ad3b6369 Mon Sep 17 00:00:00 2001
From: Lang Hames <lhames at gmail.com>
Date: Thu, 3 Jul 2025 15:00:35 +1000
Subject: [PATCH] [ORC] Replace ThreadSafeContext::getContext with a
withContextDo operation.
This removes ThreadSafeContext::Lock, ThreadSafeContext::getLock, and
ThreadSafeContext::getContext, and replaces them with a
ThreadSafeContext::withContextDo method (and const override).
The new method can be used to access an existing ThreadSafeContext-wrapped
LLVMContext in a safe way:
ThreadSafeContext TSCtx = ... ;
TSCtx.withContextDo([](LLVMContext *Ctx) {
// this closure has exclusive access to Ctx.
});
The new API enforces correct locking, whereas the old APIs relied on manual
locking (which almost no in-tree code preformed, relying instead on incidental
exclusive access to the ThreadSafeContext).
---
clang/lib/Interpreter/Interpreter.cpp | 13 ++--
.../LLJITWithThinLTOSummaries.cpp | 4 +-
.../OrcV2CBindingsBasicUsage.c | 10 +--
.../OrcV2CBindingsDumpObjects.c | 5 +-
.../OrcV2CBindingsIRTransforms.c | 4 +-
.../OrcV2CBindingsLazy/OrcV2CBindingsLazy.c | 10 ++-
.../OrcV2CBindingsMCJITLikeMemoryManager.c | 11 +--
.../OrcV2CBindingsRemovableCode.c | 11 +--
.../OrcV2CBindingsVeryLazy.c | 10 +--
llvm/include/llvm-c/Orc.h | 26 +++++--
.../ExecutionEngine/Orc/ThreadSafeModule.h | 72 +++++++-----------
.../ExecutionEngine/Orc/OrcV2CBindings.cpp | 6 +-
llvm/lib/ExecutionEngine/Orc/Speculation.cpp | 2 -
.../ExecutionEngine/Orc/ThreadSafeModule.cpp | 8 +-
llvm/tools/lli/lli.cpp | 3 +-
.../Orc/RTDyldObjectLinkingLayerTest.cpp | 42 +++++------
.../Orc/ReOptimizeLayerTest.cpp | 4 +-
.../Orc/ThreadSafeModuleTest.cpp | 74 ++++++++-----------
18 files changed, 151 insertions(+), 164 deletions(-)
diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp
index 2f110659d19a4..98fc0a5e383a3 100644
--- a/clang/lib/Interpreter/Interpreter.cpp
+++ b/clang/lib/Interpreter/Interpreter.cpp
@@ -373,8 +373,11 @@ Interpreter::Interpreter(std::unique_ptr<CompilerInstance> Instance,
auto LLVMCtx = std::make_unique<llvm::LLVMContext>();
TSCtx = std::make_unique<llvm::orc::ThreadSafeContext>(std::move(LLVMCtx));
- Act = std::make_unique<IncrementalAction>(*CI, *TSCtx->getContext(), ErrOut,
- *this, std::move(Consumer));
+ Act = TSCtx->withContextDo([&](llvm::LLVMContext *Ctx) {
+ return std::make_unique<IncrementalAction>(*CI, *Ctx, ErrOut, *this,
+ std::move(Consumer));
+ });
+
if (ErrOut)
return;
CI->ExecuteAction(*Act);
@@ -495,10 +498,10 @@ Interpreter::createWithCUDA(std::unique_ptr<CompilerInstance> CI,
std::unique_ptr<Interpreter> Interp = std::move(*InterpOrErr);
llvm::Error Err = llvm::Error::success();
- llvm::LLVMContext &LLVMCtx = *Interp->TSCtx->getContext();
- auto DeviceAct =
- std::make_unique<IncrementalAction>(*DCI, LLVMCtx, Err, *Interp);
+ auto DeviceAct = Interp->TSCtx->withContextDo([&](llvm::LLVMContext *Ctx) {
+ return std::make_unique<IncrementalAction>(*DCI, *Ctx, Err, *Interp);
+ });
if (Err)
return std::move(Err);
diff --git a/llvm/examples/OrcV2Examples/LLJITWithThinLTOSummaries/LLJITWithThinLTOSummaries.cpp b/llvm/examples/OrcV2Examples/LLJITWithThinLTOSummaries/LLJITWithThinLTOSummaries.cpp
index c55aa73d50277..84f17871c03e4 100644
--- a/llvm/examples/OrcV2Examples/LLJITWithThinLTOSummaries/LLJITWithThinLTOSummaries.cpp
+++ b/llvm/examples/OrcV2Examples/LLJITWithThinLTOSummaries/LLJITWithThinLTOSummaries.cpp
@@ -169,7 +169,9 @@ Expected<ThreadSafeModule> loadModule(StringRef Path,
MemoryBufferRef BitcodeBufferRef = (**BitcodeBuffer).getMemBufferRef();
Expected<std::unique_ptr<Module>> M =
- parseBitcodeFile(BitcodeBufferRef, *TSCtx.getContext());
+ TSCtx.withContextDo([&](LLVMContext *Ctx) {
+ return parseBitcodeFile(BitcodeBufferRef, *Ctx);
+ });
if (!M)
return M.takeError();
diff --git a/llvm/examples/OrcV2Examples/OrcV2CBindingsBasicUsage/OrcV2CBindingsBasicUsage.c b/llvm/examples/OrcV2Examples/OrcV2CBindingsBasicUsage/OrcV2CBindingsBasicUsage.c
index 286fa8baac4f8..b95462f340f2f 100644
--- a/llvm/examples/OrcV2Examples/OrcV2CBindingsBasicUsage/OrcV2CBindingsBasicUsage.c
+++ b/llvm/examples/OrcV2Examples/OrcV2CBindingsBasicUsage/OrcV2CBindingsBasicUsage.c
@@ -22,11 +22,8 @@ int handleError(LLVMErrorRef Err) {
}
LLVMOrcThreadSafeModuleRef createDemoModule(void) {
- // Create a new ThreadSafeContext and underlying LLVMContext.
- LLVMOrcThreadSafeContextRef TSCtx = LLVMOrcCreateNewThreadSafeContext();
-
- // Get a reference to the underlying LLVMContext.
- LLVMContextRef Ctx = LLVMOrcThreadSafeContextGetContext(TSCtx);
+ // Create an LLVMContext.
+ LLVMContextRef Ctx = LLVMContextCreate();
// Create a new LLVM module.
LLVMModuleRef M = LLVMModuleCreateWithNameInContext("demo", Ctx);
@@ -57,6 +54,9 @@ LLVMOrcThreadSafeModuleRef createDemoModule(void) {
// - Free the builder.
LLVMDisposeBuilder(Builder);
+ // Create a new ThreadSafeContext to hold the context.
+ LLVMOrcThreadSafeContextRef TSCtx = LLVMOrcCreateNewThreadSafeContext();
+
// Our demo module is now complete. Wrap it and our ThreadSafeContext in a
// ThreadSafeModule.
LLVMOrcThreadSafeModuleRef TSM = LLVMOrcCreateNewThreadSafeModule(M, TSCtx);
diff --git a/llvm/examples/OrcV2Examples/OrcV2CBindingsDumpObjects/OrcV2CBindingsDumpObjects.c b/llvm/examples/OrcV2Examples/OrcV2CBindingsDumpObjects/OrcV2CBindingsDumpObjects.c
index 1b4102625fa1b..42a27c7054d47 100644
--- a/llvm/examples/OrcV2Examples/OrcV2CBindingsDumpObjects/OrcV2CBindingsDumpObjects.c
+++ b/llvm/examples/OrcV2Examples/OrcV2CBindingsDumpObjects/OrcV2CBindingsDumpObjects.c
@@ -31,8 +31,7 @@ int handleError(LLVMErrorRef Err) {
}
LLVMOrcThreadSafeModuleRef createDemoModule(void) {
- LLVMOrcThreadSafeContextRef TSCtx = LLVMOrcCreateNewThreadSafeContext();
- LLVMContextRef Ctx = LLVMOrcThreadSafeContextGetContext(TSCtx);
+ LLVMContextRef Ctx = LLVMContextCreate();
LLVMModuleRef M = LLVMModuleCreateWithNameInContext("demo", Ctx);
LLVMTypeRef ParamTypes[] = {LLVMInt32Type(), LLVMInt32Type()};
LLVMTypeRef SumFunctionType =
@@ -45,6 +44,8 @@ LLVMOrcThreadSafeModuleRef createDemoModule(void) {
LLVMValueRef SumArg1 = LLVMGetParam(SumFunction, 1);
LLVMValueRef Result = LLVMBuildAdd(Builder, SumArg0, SumArg1, "result");
LLVMBuildRet(Builder, Result);
+ LLVMOrcThreadSafeContextRef TSCtx =
+ LLVMOrcCreateNewThreadSafeContextFromLLVMContext(Ctx);
LLVMOrcThreadSafeModuleRef TSM = LLVMOrcCreateNewThreadSafeModule(M, TSCtx);
LLVMOrcDisposeThreadSafeContext(TSCtx);
return TSM;
diff --git a/llvm/examples/OrcV2Examples/OrcV2CBindingsIRTransforms/OrcV2CBindingsIRTransforms.c b/llvm/examples/OrcV2Examples/OrcV2CBindingsIRTransforms/OrcV2CBindingsIRTransforms.c
index 41ae6e53db1d6..62904d006da61 100644
--- a/llvm/examples/OrcV2Examples/OrcV2CBindingsIRTransforms/OrcV2CBindingsIRTransforms.c
+++ b/llvm/examples/OrcV2Examples/OrcV2CBindingsIRTransforms/OrcV2CBindingsIRTransforms.c
@@ -32,8 +32,7 @@ int handleError(LLVMErrorRef Err) {
}
LLVMOrcThreadSafeModuleRef createDemoModule(void) {
- LLVMOrcThreadSafeContextRef TSCtx = LLVMOrcCreateNewThreadSafeContext();
- LLVMContextRef Ctx = LLVMOrcThreadSafeContextGetContext(TSCtx);
+ LLVMContextRef Ctx = LLVMContextCreate();
LLVMModuleRef M = LLVMModuleCreateWithNameInContext("demo", Ctx);
LLVMTypeRef ParamTypes[] = {LLVMInt32Type(), LLVMInt32Type()};
LLVMTypeRef SumFunctionType =
@@ -47,6 +46,7 @@ LLVMOrcThreadSafeModuleRef createDemoModule(void) {
LLVMValueRef Result = LLVMBuildAdd(Builder, SumArg0, SumArg1, "result");
LLVMBuildRet(Builder, Result);
LLVMDisposeBuilder(Builder);
+ LLVMOrcThreadSafeContextRef TSCtx = LLVMOrcCreateNewThreadSafeContext();
LLVMOrcThreadSafeModuleRef TSM = LLVMOrcCreateNewThreadSafeModule(M, TSCtx);
LLVMOrcDisposeThreadSafeContext(TSCtx);
return TSM;
diff --git a/llvm/examples/OrcV2Examples/OrcV2CBindingsLazy/OrcV2CBindingsLazy.c b/llvm/examples/OrcV2Examples/OrcV2CBindingsLazy/OrcV2CBindingsLazy.c
index 33398c8cb9816..9c31f93899201 100644
--- a/llvm/examples/OrcV2Examples/OrcV2CBindingsLazy/OrcV2CBindingsLazy.c
+++ b/llvm/examples/OrcV2Examples/OrcV2CBindingsLazy/OrcV2CBindingsLazy.c
@@ -67,11 +67,9 @@ const char MainMod[] =
LLVMErrorRef parseExampleModule(const char *Source, size_t Len,
const char *Name,
LLVMOrcThreadSafeModuleRef *TSM) {
- // Create a new ThreadSafeContext and underlying LLVMContext.
- LLVMOrcThreadSafeContextRef TSCtx = LLVMOrcCreateNewThreadSafeContext();
- // Get a reference to the underlying LLVMContext.
- LLVMContextRef Ctx = LLVMOrcThreadSafeContextGetContext(TSCtx);
+ // Create an LLVMContext for the Module.
+ LLVMContextRef Ctx = LLVMContextCreate();
// Wrap Source in a MemoryBuffer
LLVMMemoryBufferRef MB =
@@ -85,6 +83,10 @@ LLVMErrorRef parseExampleModule(const char *Source, size_t Len,
// TODO: LLVMDisposeMessage(ErrMsg);
}
+ // Create a new ThreadSafeContext to hold the context.
+ LLVMOrcThreadSafeContextRef TSCtx =
+ LLVMOrcCreateNewThreadSafeContextFromLLVMContext(Ctx);
+
// Our module is now complete. Wrap it and our ThreadSafeContext in a
// ThreadSafeModule.
*TSM = LLVMOrcCreateNewThreadSafeModule(M, TSCtx);
diff --git a/llvm/examples/OrcV2Examples/OrcV2CBindingsMCJITLikeMemoryManager/OrcV2CBindingsMCJITLikeMemoryManager.c b/llvm/examples/OrcV2Examples/OrcV2CBindingsMCJITLikeMemoryManager/OrcV2CBindingsMCJITLikeMemoryManager.c
index f85430bcfda4a..6962c6980e787 100644
--- a/llvm/examples/OrcV2Examples/OrcV2CBindingsMCJITLikeMemoryManager/OrcV2CBindingsMCJITLikeMemoryManager.c
+++ b/llvm/examples/OrcV2Examples/OrcV2CBindingsMCJITLikeMemoryManager/OrcV2CBindingsMCJITLikeMemoryManager.c
@@ -150,11 +150,8 @@ int handleError(LLVMErrorRef Err) {
}
LLVMOrcThreadSafeModuleRef createDemoModule(void) {
- // Create a new ThreadSafeContext and underlying LLVMContext.
- LLVMOrcThreadSafeContextRef TSCtx = LLVMOrcCreateNewThreadSafeContext();
-
- // Get a reference to the underlying LLVMContext.
- LLVMContextRef Ctx = LLVMOrcThreadSafeContextGetContext(TSCtx);
+ // Create an LLVMContext.
+ LLVMContextRef Ctx = LLVMContextCreate();
// Create a new LLVM module.
LLVMModuleRef M = LLVMModuleCreateWithNameInContext("demo", Ctx);
@@ -182,6 +179,10 @@ LLVMOrcThreadSafeModuleRef createDemoModule(void) {
// - Build the return instruction.
LLVMBuildRet(Builder, Result);
+ // Create a new ThreadSafeContext to hold the context.
+ LLVMOrcThreadSafeContextRef TSCtx =
+ LLVMOrcCreateNewThreadSafeContextFromLLVMContext(Ctx);
+
// Our demo module is now complete. Wrap it and our ThreadSafeContext in a
// ThreadSafeModule.
LLVMOrcThreadSafeModuleRef TSM = LLVMOrcCreateNewThreadSafeModule(M, TSCtx);
diff --git a/llvm/examples/OrcV2Examples/OrcV2CBindingsRemovableCode/OrcV2CBindingsRemovableCode.c b/llvm/examples/OrcV2Examples/OrcV2CBindingsRemovableCode/OrcV2CBindingsRemovableCode.c
index 7f84a3d413435..7f8a9cd334c6b 100644
--- a/llvm/examples/OrcV2Examples/OrcV2CBindingsRemovableCode/OrcV2CBindingsRemovableCode.c
+++ b/llvm/examples/OrcV2Examples/OrcV2CBindingsRemovableCode/OrcV2CBindingsRemovableCode.c
@@ -22,11 +22,8 @@ int handleError(LLVMErrorRef Err) {
}
LLVMOrcThreadSafeModuleRef createDemoModule(void) {
- // Create a new ThreadSafeContext and underlying LLVMContext.
- LLVMOrcThreadSafeContextRef TSCtx = LLVMOrcCreateNewThreadSafeContext();
-
- // Get a reference to the underlying LLVMContext.
- LLVMContextRef Ctx = LLVMOrcThreadSafeContextGetContext(TSCtx);
+ // Create an LLVMContext.
+ LLVMContextRef Ctx = LLVMContextCreate();
// Create a new LLVM module.
LLVMModuleRef M = LLVMModuleCreateWithNameInContext("demo", Ctx);
@@ -57,6 +54,10 @@ LLVMOrcThreadSafeModuleRef createDemoModule(void) {
// - Free the builder.
LLVMDisposeBuilder(Builder);
+ // Create a new ThreadSafeContext to hold the context.
+ LLVMOrcThreadSafeContextRef TSCtx =
+ LLVMOrcCreateNewThreadSafeContextFromLLVMContext(Ctx);
+
// Our demo module is now complete. Wrap it and our ThreadSafeContext in a
// ThreadSafeModule.
LLVMOrcThreadSafeModuleRef TSM = LLVMOrcCreateNewThreadSafeModule(M, TSCtx);
diff --git a/llvm/examples/OrcV2Examples/OrcV2CBindingsVeryLazy/OrcV2CBindingsVeryLazy.c b/llvm/examples/OrcV2Examples/OrcV2CBindingsVeryLazy/OrcV2CBindingsVeryLazy.c
index 85651f728399e..3c1ff8392eff4 100644
--- a/llvm/examples/OrcV2Examples/OrcV2CBindingsVeryLazy/OrcV2CBindingsVeryLazy.c
+++ b/llvm/examples/OrcV2Examples/OrcV2CBindingsVeryLazy/OrcV2CBindingsVeryLazy.c
@@ -74,11 +74,8 @@ LLVMErrorRef applyDataLayout(void *Ctx, LLVMModuleRef M) {
LLVMErrorRef parseExampleModule(const char *Source, size_t Len,
const char *Name,
LLVMOrcThreadSafeModuleRef *TSM) {
- // Create a new ThreadSafeContext and underlying LLVMContext.
- LLVMOrcThreadSafeContextRef TSCtx = LLVMOrcCreateNewThreadSafeContext();
-
- // Get a reference to the underlying LLVMContext.
- LLVMContextRef Ctx = LLVMOrcThreadSafeContextGetContext(TSCtx);
+ // Create an LLVMContext.
+ LLVMContextRef Ctx = LLVMContextCreate();
// Wrap Source in a MemoryBuffer
LLVMMemoryBufferRef MB =
@@ -93,6 +90,9 @@ LLVMErrorRef parseExampleModule(const char *Source, size_t Len,
return Err;
}
+ // Create a new ThreadSafeContext to hold the context.
+ LLVMOrcThreadSafeContextRef TSCtx = LLVMOrcCreateNewThreadSafeContext();
+
// Our module is now complete. Wrap it and our ThreadSafeContext in a
// ThreadSafeModule.
*TSM = LLVMOrcCreateNewThreadSafeModule(M, TSCtx);
diff --git a/llvm/include/llvm-c/Orc.h b/llvm/include/llvm-c/Orc.h
index 743ba1d581782..ee80f6f9f9892 100644
--- a/llvm/include/llvm-c/Orc.h
+++ b/llvm/include/llvm-c/Orc.h
@@ -1062,20 +1062,32 @@ LLVMErrorRef LLVMOrcCreateStaticLibrarySearchGeneratorForPath(
const char *FileName);
/**
- * Create a ThreadSafeContext containing a new LLVMContext.
+ * Create a ThreadSafeContextRef containing a new LLVMContext.
*
* Ownership of the underlying ThreadSafeContext data is shared: Clients
- * can and should dispose of their ThreadSafeContext as soon as they no longer
- * need to refer to it directly. Other references (e.g. from ThreadSafeModules)
- * will keep the data alive as long as it is needed.
+ * can and should dispose of their ThreadSafeContextRef as soon as they no
+ * longer need to refer to it directly. Other references (e.g. from
+ * ThreadSafeModules) will keep the underlying data alive as long as it is
+ * needed.
*/
LLVMOrcThreadSafeContextRef LLVMOrcCreateNewThreadSafeContext(void);
/**
- * Get a reference to the wrapped LLVMContext.
+ * Create a ThreadSafeContextRef from a given LLVMContext, which must not be
+ * associated with any existing ThreadSafeContext.
+ *
+ * The underlying ThreadSafeContext will take ownership of the LLVMContext
+ * object, so clients should not free the LLVMContext passed to this
+ * function.
+ *
+ * Ownership of the underlying ThreadSafeContext data is shared: Clients
+ * can and should dispose of their ThreadSafeContextRef as soon as they no
+ * longer need to refer to it directly. Other references (e.g. from
+ * ThreadSafeModules) will keep the underlying data alive as long as it is
+ * needed.
*/
-LLVMContextRef
-LLVMOrcThreadSafeContextGetContext(LLVMOrcThreadSafeContextRef TSCtx);
+LLVMOrcThreadSafeContextRef
+LLVMOrcCreateNewThreadSafeContextFromLLVMContext(LLVMContextRef Ctx);
/**
* Dispose of a ThreadSafeContext.
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/ThreadSafeModule.h b/llvm/include/llvm/ExecutionEngine/Orc/ThreadSafeModule.h
index b61c8b8563a1a..f1353777f6ce9 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/ThreadSafeModule.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/ThreadSafeModule.h
@@ -36,16 +36,6 @@ class ThreadSafeContext {
};
public:
- // RAII based lock for ThreadSafeContext.
- class [[nodiscard]] Lock {
- public:
- Lock(std::shared_ptr<State> S) : S(std::move(S)), L(this->S->Mutex) {}
-
- private:
- std::shared_ptr<State> S;
- std::unique_lock<std::recursive_mutex> L;
- };
-
/// Construct a null context.
ThreadSafeContext() = default;
@@ -56,17 +46,20 @@ class ThreadSafeContext {
"Can not construct a ThreadSafeContext from a nullptr");
}
- /// Returns a pointer to the LLVMContext that was used to construct this
- /// instance, or null if the instance was default constructed.
- LLVMContext *getContext() { return S ? S->Ctx.get() : nullptr; }
-
- /// Returns a pointer to the LLVMContext that was used to construct this
- /// instance, or null if the instance was default constructed.
- const LLVMContext *getContext() const { return S ? S->Ctx.get() : nullptr; }
+ template <typename Func> decltype(auto) withContextDo(Func &&F) {
+ if (auto TmpS = S) {
+ std::lock_guard<std::recursive_mutex> Lock(TmpS->Mutex);
+ return F(TmpS->Ctx.get());
+ } else
+ return F((LLVMContext *)nullptr);
+ }
- Lock getLock() const {
- assert(S && "Can not lock an empty ThreadSafeContext");
- return Lock(S);
+ template <typename Func> decltype(auto) withContextDo(Func &&F) const {
+ if (auto TmpS = S) {
+ std::lock_guard<std::recursive_mutex> Lock(TmpS->Mutex);
+ return F(const_cast<const LLVMContext *>(TmpS->Ctx.get()));
+ } else
+ return F((const LLVMContext *)nullptr);
}
private:
@@ -89,10 +82,7 @@ class ThreadSafeModule {
// *before* the context that it depends on.
// We also need to lock the context to make sure the module tear-down
// does not overlap any other work on the context.
- if (M) {
- auto L = TSCtx.getLock();
- M = nullptr;
- }
+ TSCtx.withContextDo([this](LLVMContext *Ctx) { M = nullptr; });
M = std::move(Other.M);
TSCtx = std::move(Other.TSCtx);
return *this;
@@ -111,45 +101,39 @@ class ThreadSafeModule {
~ThreadSafeModule() {
// We need to lock the context while we destruct the module.
- if (M) {
- auto L = TSCtx.getLock();
- M = nullptr;
- }
+ TSCtx.withContextDo([this](LLVMContext *Ctx) { M = nullptr; });
}
/// Boolean conversion: This ThreadSafeModule will evaluate to true if it
/// wraps a non-null module.
- explicit operator bool() const {
- if (M) {
- assert(TSCtx.getContext() &&
- "Non-null module must have non-null context");
- return true;
- }
- return false;
- }
+ explicit operator bool() const { return !!M; }
/// Locks the associated ThreadSafeContext and calls the given function
/// on the contained Module.
template <typename Func> decltype(auto) withModuleDo(Func &&F) {
- assert(M && "Can not call on null module");
- auto Lock = TSCtx.getLock();
- return F(*M);
+ return TSCtx.withContextDo([&](LLVMContext *) {
+ assert(M && "Can not call on null module");
+ return F(*M);
+ });
}
/// Locks the associated ThreadSafeContext and calls the given function
/// on the contained Module.
template <typename Func> decltype(auto) withModuleDo(Func &&F) const {
- assert(M && "Can not call on null module");
- auto Lock = TSCtx.getLock();
- return F(*M);
+ return TSCtx.withContextDo([&](const LLVMContext *) {
+ assert(M && "Can not call on null module");
+ return F(*M);
+ });
}
/// Locks the associated ThreadSafeContext and calls the given function,
/// passing the contained std::unique_ptr<Module>. The given function should
/// consume the Module.
template <typename Func> decltype(auto) consumingModuleDo(Func &&F) {
- auto Lock = TSCtx.getLock();
- return F(std::move(M));
+ return TSCtx.withContextDo([&](LLVMContext *) {
+ assert(M && "Can not call on null module");
+ return F(std::move(M));
+ });
}
/// Get a raw pointer to the contained module without locking the context.
diff --git a/llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp b/llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp
index 9999e1ff3bf00..fd805fbf01fb7 100644
--- a/llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp
@@ -729,9 +729,9 @@ LLVMOrcThreadSafeContextRef LLVMOrcCreateNewThreadSafeContext(void) {
return wrap(new ThreadSafeContext(std::make_unique<LLVMContext>()));
}
-LLVMContextRef
-LLVMOrcThreadSafeContextGetContext(LLVMOrcThreadSafeContextRef TSCtx) {
- return wrap(unwrap(TSCtx)->getContext());
+LLVMOrcThreadSafeContextRef
+LLVMOrcCreateNewThreadSafeContextFromLLVMContext(LLVMContextRef Ctx) {
+ return wrap(new ThreadSafeContext(std::unique_ptr<LLVMContext>(unwrap(Ctx))));
}
void LLVMOrcDisposeThreadSafeContext(LLVMOrcThreadSafeContextRef TSCtx) {
diff --git a/llvm/lib/ExecutionEngine/Orc/Speculation.cpp b/llvm/lib/ExecutionEngine/Orc/Speculation.cpp
index 74b9eb29bdccf..fee94b96a9e8a 100644
--- a/llvm/lib/ExecutionEngine/Orc/Speculation.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/Speculation.cpp
@@ -60,8 +60,6 @@ void IRSpeculationLayer::emit(std::unique_ptr<MaterializationResponsibility> R,
ThreadSafeModule TSM) {
assert(TSM && "Speculation Layer received Null Module ?");
- assert(TSM.getContext().getContext() != nullptr &&
- "Module with null LLVMContext?");
// Instrumentation of runtime calls, lock the Module
TSM.withModuleDo([this, &R](Module &M) {
diff --git a/llvm/lib/ExecutionEngine/Orc/ThreadSafeModule.cpp b/llvm/lib/ExecutionEngine/Orc/ThreadSafeModule.cpp
index 2e128dd237443..c927f21494697 100644
--- a/llvm/lib/ExecutionEngine/Orc/ThreadSafeModule.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/ThreadSafeModule.cpp
@@ -53,9 +53,11 @@ ThreadSafeModule cloneToNewContext(const ThreadSafeModule &TSM,
"cloned module buffer");
ThreadSafeContext NewTSCtx(std::make_unique<LLVMContext>());
- auto ClonedModule = cantFail(
- parseBitcodeFile(ClonedModuleBufferRef, *NewTSCtx.getContext()));
- ClonedModule->setModuleIdentifier(M.getName());
+ auto ClonedModule = NewTSCtx.withContextDo([&](LLVMContext *Ctx) {
+ auto TmpM = cantFail(parseBitcodeFile(ClonedModuleBufferRef, *Ctx));
+ TmpM->setModuleIdentifier(M.getName());
+ return TmpM;
+ });
return ThreadSafeModule(std::move(ClonedModule), std::move(NewTSCtx));
});
}
diff --git a/llvm/tools/lli/lli.cpp b/llvm/tools/lli/lli.cpp
index ba628079170d5..c322b4f6c9828 100644
--- a/llvm/tools/lli/lli.cpp
+++ b/llvm/tools/lli/lli.cpp
@@ -878,7 +878,8 @@ static void exitOnLazyCallThroughFailure() { exit(1); }
Expected<orc::ThreadSafeModule>
loadModule(StringRef Path, orc::ThreadSafeContext TSCtx) {
SMDiagnostic Err;
- auto M = parseIRFile(Path, Err, *TSCtx.getContext());
+ auto M = TSCtx.withContextDo(
+ [&](LLVMContext *Ctx) { return parseIRFile(Path, Err, *Ctx); });
if (!M) {
std::string ErrMsg;
{
diff --git a/llvm/unittests/ExecutionEngine/Orc/RTDyldObjectLinkingLayerTest.cpp b/llvm/unittests/ExecutionEngine/Orc/RTDyldObjectLinkingLayerTest.cpp
index a0ae9308d33ab..61b99ddf0995d 100644
--- a/llvm/unittests/ExecutionEngine/Orc/RTDyldObjectLinkingLayerTest.cpp
+++ b/llvm/unittests/ExecutionEngine/Orc/RTDyldObjectLinkingLayerTest.cpp
@@ -128,29 +128,25 @@ TEST(RTDyldObjectLinkingLayerTest, TestOverrideObjectFlags) {
};
// Create a module with two void() functions: foo and bar.
- ThreadSafeContext TSCtx(std::make_unique<LLVMContext>());
ThreadSafeModule M;
{
- ModuleBuilder MB(*TSCtx.getContext(), TM->getTargetTriple().str(), "dummy");
+ auto Ctx = std::make_unique<LLVMContext>();
+ ModuleBuilder MB(*Ctx, TM->getTargetTriple().str(), "dummy");
MB.getModule()->setDataLayout(TM->createDataLayout());
Function *FooImpl = MB.createFunctionDecl(
- FunctionType::get(Type::getVoidTy(*TSCtx.getContext()), {}, false),
- "foo");
- BasicBlock *FooEntry =
- BasicBlock::Create(*TSCtx.getContext(), "entry", FooImpl);
+ FunctionType::get(Type::getVoidTy(*Ctx), {}, false), "foo");
+ BasicBlock *FooEntry = BasicBlock::Create(*Ctx, "entry", FooImpl);
IRBuilder<> B1(FooEntry);
B1.CreateRetVoid();
Function *BarImpl = MB.createFunctionDecl(
- FunctionType::get(Type::getVoidTy(*TSCtx.getContext()), {}, false),
- "bar");
- BasicBlock *BarEntry =
- BasicBlock::Create(*TSCtx.getContext(), "entry", BarImpl);
+ FunctionType::get(Type::getVoidTy(*Ctx), {}, false), "bar");
+ BasicBlock *BarEntry = BasicBlock::Create(*Ctx, "entry", BarImpl);
IRBuilder<> B2(BarEntry);
B2.CreateRetVoid();
- M = ThreadSafeModule(MB.takeModule(), std::move(TSCtx));
+ M = ThreadSafeModule(MB.takeModule(), std::move(Ctx));
}
// Create a simple stack and set the override flags option.
@@ -207,21 +203,19 @@ TEST(RTDyldObjectLinkingLayerTest, TestAutoClaimResponsibilityForSymbols) {
};
// Create a module with two void() functions: foo and bar.
- ThreadSafeContext TSCtx(std::make_unique<LLVMContext>());
ThreadSafeModule M;
{
- ModuleBuilder MB(*TSCtx.getContext(), TM->getTargetTriple().str(), "dummy");
+ auto Ctx = std::make_unique<LLVMContext>();
+ ModuleBuilder MB(*Ctx, TM->getTargetTriple().str(), "dummy");
MB.getModule()->setDataLayout(TM->createDataLayout());
Function *FooImpl = MB.createFunctionDecl(
- FunctionType::get(Type::getVoidTy(*TSCtx.getContext()), {}, false),
- "foo");
- BasicBlock *FooEntry =
- BasicBlock::Create(*TSCtx.getContext(), "entry", FooImpl);
+ FunctionType::get(Type::getVoidTy(*Ctx), {}, false), "foo");
+ BasicBlock *FooEntry = BasicBlock::Create(*Ctx, "entry", FooImpl);
IRBuilder<> B(FooEntry);
B.CreateRetVoid();
- M = ThreadSafeModule(MB.takeModule(), std::move(TSCtx));
+ M = ThreadSafeModule(MB.takeModule(), std::move(Ctx));
}
// Create a simple stack and set the override flags option.
@@ -258,21 +252,19 @@ TEST(RTDyldObjectLinkingLayerTest, TestMemoryBufferNamePropagation) {
GTEST_SKIP();
// Create a module with two void() functions: foo and bar.
- ThreadSafeContext TSCtx(std::make_unique<LLVMContext>());
ThreadSafeModule M;
{
- ModuleBuilder MB(*TSCtx.getContext(), TM->getTargetTriple().str(), "dummy");
+ auto Ctx = std::make_unique<LLVMContext>();
+ ModuleBuilder MB(*Ctx, TM->getTargetTriple().str(), "dummy");
MB.getModule()->setDataLayout(TM->createDataLayout());
Function *FooImpl = MB.createFunctionDecl(
- FunctionType::get(Type::getVoidTy(*TSCtx.getContext()), {}, false),
- "foo");
- BasicBlock *FooEntry =
- BasicBlock::Create(*TSCtx.getContext(), "entry", FooImpl);
+ FunctionType::get(Type::getVoidTy(*Ctx), {}, false), "foo");
+ BasicBlock *FooEntry = BasicBlock::Create(*Ctx, "entry", FooImpl);
IRBuilder<> B1(FooEntry);
B1.CreateRetVoid();
- M = ThreadSafeModule(MB.takeModule(), std::move(TSCtx));
+ M = ThreadSafeModule(MB.takeModule(), std::move(Ctx));
}
ExecutionSession ES{std::make_unique<UnsupportedExecutorProcessControl>()};
diff --git a/llvm/unittests/ExecutionEngine/Orc/ReOptimizeLayerTest.cpp b/llvm/unittests/ExecutionEngine/Orc/ReOptimizeLayerTest.cpp
index 962277fb4a0cb..cd10ffe53d0f0 100644
--- a/llvm/unittests/ExecutionEngine/Orc/ReOptimizeLayerTest.cpp
+++ b/llvm/unittests/ExecutionEngine/Orc/ReOptimizeLayerTest.cpp
@@ -172,8 +172,8 @@ TEST_F(ReOptimizeLayerTest, BasicReOptimization) {
});
EXPECT_THAT_ERROR(ROLayer->reigsterRuntimeFunctions(*JD), Succeeded());
- ThreadSafeContext Ctx(std::make_unique<LLVMContext>());
- auto M = std::make_unique<Module>("<main>", *Ctx.getContext());
+ auto Ctx = std::make_unique<LLVMContext>();
+ auto M = std::make_unique<Module>("<main>", *Ctx);
M->setTargetTriple(Triple(sys::getProcessTriple()));
(void)createRetFunction(M.get(), "main", 42);
diff --git a/llvm/unittests/ExecutionEngine/Orc/ThreadSafeModuleTest.cpp b/llvm/unittests/ExecutionEngine/Orc/ThreadSafeModuleTest.cpp
index 5b094e2edd58c..adaa4d97ca5f4 100644
--- a/llvm/unittests/ExecutionEngine/Orc/ThreadSafeModuleTest.cpp
+++ b/llvm/unittests/ExecutionEngine/Orc/ThreadSafeModuleTest.cpp
@@ -21,20 +21,21 @@ namespace {
TEST(ThreadSafeModuleTest, ContextWhollyOwnedByOneModule) {
// Test that ownership of a context can be transferred to a single
// ThreadSafeModule.
- ThreadSafeContext TSCtx(std::make_unique<LLVMContext>());
- auto M = std::make_unique<Module>("M", *TSCtx.getContext());
- ThreadSafeModule TSM(std::move(M), std::move(TSCtx));
+ auto Ctx = std::make_unique<LLVMContext>();
+ auto M = std::make_unique<Module>("M", *Ctx);
+ ThreadSafeModule TSM(std::move(M), std::move(Ctx));
}
TEST(ThreadSafeModuleTest, ContextOwnershipSharedByTwoModules) {
// Test that ownership of a context can be shared between more than one
// ThreadSafeModule.
- ThreadSafeContext TSCtx(std::make_unique<LLVMContext>());
+ auto Ctx = std::make_unique<LLVMContext>();
- auto M1 = std::make_unique<Module>("M1", *TSCtx.getContext());
- ThreadSafeModule TSM1(std::move(M1), TSCtx);
+ auto M1 = std::make_unique<Module>("M1", *Ctx);
+ auto M2 = std::make_unique<Module>("M2", *Ctx);
- auto M2 = std::make_unique<Module>("M2", *TSCtx.getContext());
+ ThreadSafeContext TSCtx(std::move(Ctx));
+ ThreadSafeModule TSM1(std::move(M1), TSCtx);
ThreadSafeModule TSM2(std::move(M2), std::move(TSCtx));
}
@@ -45,12 +46,14 @@ TEST(ThreadSafeModuleTest, ContextOwnershipSharedWithClient) {
{
// Create and destroy a module.
- auto M1 = std::make_unique<Module>("M1", *TSCtx.getContext());
+ auto M1 = TSCtx.withContextDo(
+ [](LLVMContext *Ctx) { return std::make_unique<Module>("M1", *Ctx); });
ThreadSafeModule TSM1(std::move(M1), TSCtx);
}
// Verify that the context is still available for re-use.
- auto M2 = std::make_unique<Module>("M2", *TSCtx.getContext());
+ auto M2 = TSCtx.withContextDo(
+ [](LLVMContext *Ctx) { return std::make_unique<Module>("M2", *Ctx); });
ThreadSafeModule TSM2(std::move(M2), std::move(TSCtx));
}
@@ -59,59 +62,44 @@ TEST(ThreadSafeModuleTest, ThreadSafeModuleMoveAssignment) {
// to the field order) to ensure that overwriting with an empty
// ThreadSafeModule does not destroy the context early.
ThreadSafeContext TSCtx(std::make_unique<LLVMContext>());
- auto M = std::make_unique<Module>("M", *TSCtx.getContext());
+ auto M = TSCtx.withContextDo(
+ [](LLVMContext *Ctx) { return std::make_unique<Module>("M", *Ctx); });
ThreadSafeModule TSM(std::move(M), std::move(TSCtx));
TSM = ThreadSafeModule();
}
-TEST(ThreadSafeModuleTest, BasicContextLockAPI) {
- // Test that basic lock API calls work.
- ThreadSafeContext TSCtx(std::make_unique<LLVMContext>());
- auto M = std::make_unique<Module>("M", *TSCtx.getContext());
- ThreadSafeModule TSM(std::move(M), TSCtx);
-
- { auto L = TSCtx.getLock(); }
-
- { auto L = TSM.getContext().getLock(); }
-}
-
-TEST(ThreadSafeModuleTest, ContextLockPreservesContext) {
- // Test that the existence of a context lock preserves the attached
- // context.
- // The trick to verify this is a bit of a hack: We attach a Module
- // (without the ThreadSafeModule wrapper) to the context, then verify
- // that this Module destructs safely (which it will not if its context
- // has been destroyed) even though all references to the context have
- // been thrown away (apart from the lock).
+TEST(ThreadSafeModuleTest, WithContextDoPreservesContext) {
+ // Test that withContextDo passes through the LLVMContext that was used
+ // to create the ThreadSafeContext.
- ThreadSafeContext TSCtx(std::make_unique<LLVMContext>());
- auto L = TSCtx.getLock();
- auto &Ctx = *TSCtx.getContext();
- auto M = std::make_unique<Module>("M", Ctx);
- TSCtx = ThreadSafeContext();
+ auto Ctx = std::make_unique<LLVMContext>();
+ LLVMContext *OriginalCtx = Ctx.get();
+ ThreadSafeContext TSCtx(std::move(Ctx));
+ TSCtx.withContextDo(
+ [&](LLVMContext *ClosureCtx) { EXPECT_EQ(ClosureCtx, OriginalCtx); });
}
TEST(ThreadSafeModuleTest, WithModuleDo) {
// Test non-const version of withModuleDo.
- ThreadSafeContext TSCtx(std::make_unique<LLVMContext>());
- ThreadSafeModule TSM(std::make_unique<Module>("M", *TSCtx.getContext()),
- TSCtx);
+ auto Ctx = std::make_unique<LLVMContext>();
+ auto M = std::make_unique<Module>("M", *Ctx);
+ ThreadSafeModule TSM(std::move(M), std::move(Ctx));
TSM.withModuleDo([](Module &M) {});
}
TEST(ThreadSafeModuleTest, WithModuleDoConst) {
// Test const version of withModuleDo.
- ThreadSafeContext TSCtx(std::make_unique<LLVMContext>());
- const ThreadSafeModule TSM(std::make_unique<Module>("M", *TSCtx.getContext()),
- TSCtx);
+ auto Ctx = std::make_unique<LLVMContext>();
+ auto M = std::make_unique<Module>("M", *Ctx);
+ const ThreadSafeModule TSM(std::move(M), std::move(Ctx));
TSM.withModuleDo([](const Module &M) {});
}
TEST(ThreadSafeModuleTest, ConsumingModuleDo) {
// Test consumingModuleDo.
- ThreadSafeContext TSCtx(std::make_unique<LLVMContext>());
- ThreadSafeModule TSM(std::make_unique<Module>("M", *TSCtx.getContext()),
- TSCtx);
+ auto Ctx = std::make_unique<LLVMContext>();
+ auto M = std::make_unique<Module>("M", *Ctx);
+ ThreadSafeModule TSM(std::move(M), std::move(Ctx));
TSM.consumingModuleDo([](std::unique_ptr<Module> M) {});
}
More information about the llvm-commits
mailing list