summaryrefslogtreecommitdiff
path: root/llvm/unittests/ExecutionEngine/Orc/ThreadSafeModuleTest.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/unittests/ExecutionEngine/Orc/ThreadSafeModuleTest.cpp')
-rw-r--r--llvm/unittests/ExecutionEngine/Orc/ThreadSafeModuleTest.cpp123
1 files changed, 80 insertions, 43 deletions
diff --git a/llvm/unittests/ExecutionEngine/Orc/ThreadSafeModuleTest.cpp b/llvm/unittests/ExecutionEngine/Orc/ThreadSafeModuleTest.cpp
index 5b094e2edd58..bbb9e8d3d6a7 100644
--- a/llvm/unittests/ExecutionEngine/Orc/ThreadSafeModuleTest.cpp
+++ b/llvm/unittests/ExecutionEngine/Orc/ThreadSafeModuleTest.cpp
@@ -7,6 +7,13 @@
//===----------------------------------------------------------------------===//
#include "llvm/ExecutionEngine/Orc/ThreadSafeModule.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/Verifier.h"
+#include "llvm/IRReader/IRReader.h"
+#include "llvm/Support/SourceMgr.h"
+#include "llvm/Support/raw_ostream.h"
+
#include "gtest/gtest.h"
#include <atomic>
@@ -18,23 +25,42 @@ using namespace llvm::orc;
namespace {
+const llvm::StringRef FooSrc = R"(
+ define void @foo() {
+ ret void
+ }
+)";
+
+static ThreadSafeModule parseModule(llvm::StringRef Source,
+ llvm::StringRef Name) {
+ auto Ctx = std::make_unique<LLVMContext>();
+ SMDiagnostic Err;
+ auto M = parseIR(MemoryBufferRef(Source, Name), Err, *Ctx);
+ if (!M) {
+ Err.print("Testcase source failed to parse: ", errs());
+ exit(1);
+ }
+ return ThreadSafeModule(std::move(M), std::move(Ctx));
+}
+
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 +71,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,60 +87,69 @@ 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(); }
+TEST(ThreadSafeModuleTest, WithContextDoPreservesContext) {
+ // Test that withContextDo passes through the LLVMContext that was used
+ // to create the ThreadSafeContext.
- { 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).
-
- 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) {});
}
+TEST(ThreadSafeModuleTest, CloneToNewContext) {
+ auto TSM1 = parseModule(FooSrc, "foo.ll");
+ auto TSM2 = cloneToNewContext(TSM1);
+ TSM2.withModuleDo([&](Module &NewM) {
+ EXPECT_FALSE(verifyModule(NewM, &errs()));
+ TSM1.withModuleDo([&](Module &OrigM) {
+ EXPECT_NE(&NewM.getContext(), &OrigM.getContext());
+ });
+ });
+}
+
+TEST(ObjectFormatsTest, CloneToContext) {
+ auto TSM1 = parseModule(FooSrc, "foo.ll");
+
+ auto TSCtx = ThreadSafeContext(std::make_unique<LLVMContext>());
+ auto TSM2 = cloneToContext(TSM1, TSCtx);
+
+ TSM2.withModuleDo([&](Module &M) {
+ EXPECT_FALSE(verifyModule(M, &errs()));
+ TSCtx.withContextDo(
+ [&](LLVMContext *Ctx) { EXPECT_EQ(&M.getContext(), Ctx); });
+ });
+}
+
} // end anonymous namespace