15ad09de9SLang Hames //===--- ThreadSafeModuleTest.cpp - Test basic use of ThreadSafeModule ----===// 25ad09de9SLang Hames // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 65ad09de9SLang Hames // 75ad09de9SLang Hames //===----------------------------------------------------------------------===// 85ad09de9SLang Hames 95ad09de9SLang Hames #include "llvm/ExecutionEngine/Orc/ThreadSafeModule.h" 105ad09de9SLang Hames #include "gtest/gtest.h" 115ad09de9SLang Hames 125ad09de9SLang Hames #include <atomic> 135ad09de9SLang Hames #include <future> 145ad09de9SLang Hames #include <thread> 155ad09de9SLang Hames 165ad09de9SLang Hames using namespace llvm; 175ad09de9SLang Hames using namespace llvm::orc; 185ad09de9SLang Hames 195ad09de9SLang Hames namespace { 205ad09de9SLang Hames 215ad09de9SLang Hames TEST(ThreadSafeModuleTest, ContextWhollyOwnedByOneModule) { 225ad09de9SLang Hames // Test that ownership of a context can be transferred to a single 235ad09de9SLang Hames // ThreadSafeModule. 245ad09de9SLang Hames ThreadSafeContext TSCtx(llvm::make_unique<LLVMContext>()); 25f1c96490SLang Hames auto M = llvm::make_unique<Module>("M", *TSCtx.getContext()); 26f1c96490SLang Hames ThreadSafeModule TSM(std::move(M), std::move(TSCtx)); 275ad09de9SLang Hames } 285ad09de9SLang Hames 295ad09de9SLang Hames TEST(ThreadSafeModuleTest, ContextOwnershipSharedByTwoModules) { 305ad09de9SLang Hames // Test that ownership of a context can be shared between more than one 315ad09de9SLang Hames // ThreadSafeModule. 325ad09de9SLang Hames ThreadSafeContext TSCtx(llvm::make_unique<LLVMContext>()); 335ad09de9SLang Hames 34f1c96490SLang Hames auto M1 = llvm::make_unique<Module>("M1", *TSCtx.getContext()); 35f1c96490SLang Hames ThreadSafeModule TSM1(std::move(M1), TSCtx); 36f1c96490SLang Hames 37f1c96490SLang Hames auto M2 = llvm::make_unique<Module>("M2", *TSCtx.getContext()); 38f1c96490SLang Hames ThreadSafeModule TSM2(std::move(M2), std::move(TSCtx)); 395ad09de9SLang Hames } 405ad09de9SLang Hames 415ad09de9SLang Hames TEST(ThreadSafeModuleTest, ContextOwnershipSharedWithClient) { 425ad09de9SLang Hames // Test that ownership of a context can be shared with a client-held 435ad09de9SLang Hames // ThreadSafeContext so that it can be re-used for new modules. 445ad09de9SLang Hames ThreadSafeContext TSCtx(llvm::make_unique<LLVMContext>()); 455ad09de9SLang Hames 465ad09de9SLang Hames { 475ad09de9SLang Hames // Create and destroy a module. 48f1c96490SLang Hames auto M1 = llvm::make_unique<Module>("M1", *TSCtx.getContext()); 49f1c96490SLang Hames ThreadSafeModule TSM1(std::move(M1), TSCtx); 505ad09de9SLang Hames } 515ad09de9SLang Hames 525ad09de9SLang Hames // Verify that the context is still available for re-use. 53f1c96490SLang Hames auto M2 = llvm::make_unique<Module>("M2", *TSCtx.getContext()); 54f1c96490SLang Hames ThreadSafeModule TSM2(std::move(M2), std::move(TSCtx)); 555ad09de9SLang Hames } 565ad09de9SLang Hames 575ad09de9SLang Hames TEST(ThreadSafeModuleTest, ThreadSafeModuleMoveAssignment) { 585ad09de9SLang Hames // Move assignment needs to move the module before the context (opposite 595ad09de9SLang Hames // to the field order) to ensure that overwriting with an empty 605ad09de9SLang Hames // ThreadSafeModule does not destroy the context early. 615ad09de9SLang Hames ThreadSafeContext TSCtx(llvm::make_unique<LLVMContext>()); 62f1c96490SLang Hames auto M = llvm::make_unique<Module>("M", *TSCtx.getContext()); 63f1c96490SLang Hames ThreadSafeModule TSM(std::move(M), std::move(TSCtx)); 645ad09de9SLang Hames TSM = ThreadSafeModule(); 655ad09de9SLang Hames } 665ad09de9SLang Hames 675ad09de9SLang Hames TEST(ThreadSafeModuleTest, BasicContextLockAPI) { 685ad09de9SLang Hames // Test that basic lock API calls work. 695ad09de9SLang Hames ThreadSafeContext TSCtx(llvm::make_unique<LLVMContext>()); 70f1c96490SLang Hames auto M = llvm::make_unique<Module>("M", *TSCtx.getContext()); 71f1c96490SLang Hames ThreadSafeModule TSM(std::move(M), TSCtx); 725ad09de9SLang Hames 735ad09de9SLang Hames { auto L = TSCtx.getLock(); } 745ad09de9SLang Hames 75*809e9d1eSLang Hames { auto L = TSM.getContext().getLock(); } 765ad09de9SLang Hames } 775ad09de9SLang Hames 785ad09de9SLang Hames TEST(ThreadSafeModuleTest, ContextLockPreservesContext) { 795ad09de9SLang Hames // Test that the existence of a context lock preserves the attached 805ad09de9SLang Hames // context. 815ad09de9SLang Hames // The trick to verify this is a bit of a hack: We attach a Module 825ad09de9SLang Hames // (without the ThreadSafeModule wrapper) to the context, then verify 835ad09de9SLang Hames // that this Module destructs safely (which it will not if its context 845ad09de9SLang Hames // has been destroyed) even though all references to the context have 855ad09de9SLang Hames // been thrown away (apart from the lock). 865ad09de9SLang Hames 875ad09de9SLang Hames ThreadSafeContext TSCtx(llvm::make_unique<LLVMContext>()); 885ad09de9SLang Hames auto L = TSCtx.getLock(); 895ad09de9SLang Hames auto &Ctx = *TSCtx.getContext(); 905ad09de9SLang Hames auto M = llvm::make_unique<Module>("M", Ctx); 915ad09de9SLang Hames TSCtx = ThreadSafeContext(); 925ad09de9SLang Hames } 935ad09de9SLang Hames 945ad09de9SLang Hames } // end anonymous namespace 95