diff options
Diffstat (limited to 'llvm/unittests/ExecutionEngine/Orc')
4 files changed, 114 insertions, 38 deletions
diff --git a/llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt b/llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt index f0fd5896426..c18c9361cb0 100644 --- a/llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt +++ b/llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt @@ -14,6 +14,7 @@ add_llvm_unittest(OrcJITTests CoreAPIsTest.cpp IndirectionUtilsTest.cpp GlobalMappingLayerTest.cpp + LazyCallThroughAndReexportsTest.cpp LazyEmittingLayerTest.cpp LegacyAPIInteropTest.cpp ObjectTransformLayerTest.cpp diff --git a/llvm/unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp b/llvm/unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp index b3cd4b517ca..d0e4effe75e 100644 --- a/llvm/unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp +++ b/llvm/unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp @@ -22,44 +22,6 @@ class CoreAPIsStandardTest : public CoreAPIsBasedStandardTest {}; namespace { -class SimpleMaterializationUnit : public MaterializationUnit { -public: - using MaterializeFunction = - std::function<void(MaterializationResponsibility)>; - using DiscardFunction = - std::function<void(const JITDylib &, SymbolStringPtr)>; - using DestructorFunction = std::function<void()>; - - SimpleMaterializationUnit( - SymbolFlagsMap SymbolFlags, MaterializeFunction Materialize, - DiscardFunction Discard = DiscardFunction(), - DestructorFunction Destructor = DestructorFunction()) - : MaterializationUnit(std::move(SymbolFlags)), - Materialize(std::move(Materialize)), Discard(std::move(Discard)), - Destructor(std::move(Destructor)) {} - - ~SimpleMaterializationUnit() override { - if (Destructor) - Destructor(); - } - - void materialize(MaterializationResponsibility R) override { - Materialize(std::move(R)); - } - - void discard(const JITDylib &JD, SymbolStringPtr Name) override { - if (Discard) - Discard(JD, std::move(Name)); - else - llvm_unreachable("Discard not supported"); - } - -private: - MaterializeFunction Materialize; - DiscardFunction Discard; - DestructorFunction Destructor; -}; - TEST_F(CoreAPIsStandardTest, BasicSuccessfulLookup) { bool OnResolutionRun = false; bool OnReadyRun = false; diff --git a/llvm/unittests/ExecutionEngine/Orc/LazyCallThroughAndReexportsTest.cpp b/llvm/unittests/ExecutionEngine/Orc/LazyCallThroughAndReexportsTest.cpp new file mode 100644 index 00000000000..7caaa767242 --- /dev/null +++ b/llvm/unittests/ExecutionEngine/Orc/LazyCallThroughAndReexportsTest.cpp @@ -0,0 +1,75 @@ +#include "OrcTestCommon.h" +#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h" +#include "llvm/ExecutionEngine/Orc/LazyReexports.h" +#include "gtest/gtest.h" + +using namespace llvm; +using namespace llvm::orc; + +class LazyReexportsTest : public CoreAPIsBasedStandardTest {}; + +static int dummyTarget() { return 42; } + +TEST_F(LazyReexportsTest, BasicLocalCallThroughManagerOperation) { + // Create a callthrough manager for the host (if possible) and verify that + // a call to the lazy call-through: + // (1) Materializes the MU. This verifies that the symbol was looked up, and + // that we didn't arrive at the target via some other path + // (2) Returns the expected value (which we take as proof that the call + // reached the target). + + auto JTMB = JITTargetMachineBuilder::detectHost(); + + // Bail out if we can not detect the host. + if (!JTMB) { + consumeError(JTMB.takeError()); + return; + } + + // Bail out if we can not build a local call-through manager. + auto LCTM = createLocalLazyCallThroughManager(JTMB->getTargetTriple(), ES, 0); + if (!LCTM) { + consumeError(LCTM.takeError()); + return; + } + + auto DummyTarget = ES.getSymbolStringPool().intern("DummyTarget"); + + bool DummyTargetMaterialized = false; + + cantFail(JD.define(llvm::make_unique<SimpleMaterializationUnit>( + SymbolFlagsMap({{DummyTarget, JITSymbolFlags::Exported}}), + [&](MaterializationResponsibility R) { + DummyTargetMaterialized = true; + R.resolve( + {{DummyTarget, + JITEvaluatedSymbol(static_cast<JITTargetAddress>( + reinterpret_cast<uintptr_t>(&dummyTarget)), + JITSymbolFlags::Exported)}}); + R.emit(); + }))); + + unsigned NotifyResolvedCount = 0; + auto NotifyResolved = LazyCallThroughManager::createNotifyResolvedFunction( + [&](JITDylib &JD, const SymbolStringPtr &SymbolName, + JITTargetAddress ResolvedAddr) { + ++NotifyResolvedCount; + return Error::success(); + }); + + auto CallThroughTrampoline = cantFail((*LCTM)->getCallThroughTrampoline( + JD, DummyTarget, std::move(NotifyResolved))); + + auto CTTPtr = reinterpret_cast<int (*)()>( + static_cast<uintptr_t>(CallThroughTrampoline)); + + // Call twice to verify nothing unexpected happens on redundant calls. + auto Result = CTTPtr(); + (void)CTTPtr(); + + EXPECT_TRUE(DummyTargetMaterialized) + << "CallThrough did not materialize target"; + EXPECT_EQ(NotifyResolvedCount, 1U) + << "CallThrough should have generated exactly one 'NotifyResolved' call"; + EXPECT_EQ(Result, 42) << "Failed to call through to target"; +} diff --git a/llvm/unittests/ExecutionEngine/Orc/OrcTestCommon.h b/llvm/unittests/ExecutionEngine/Orc/OrcTestCommon.h index acc0e5b04ab..23ca74cc364 100644 --- a/llvm/unittests/ExecutionEngine/Orc/OrcTestCommon.h +++ b/llvm/unittests/ExecutionEngine/Orc/OrcTestCommon.h @@ -85,6 +85,44 @@ private: static bool NativeTargetInitialized; }; +class SimpleMaterializationUnit : public orc::MaterializationUnit { +public: + using MaterializeFunction = + std::function<void(orc::MaterializationResponsibility)>; + using DiscardFunction = + std::function<void(const orc::JITDylib &, orc::SymbolStringPtr)>; + using DestructorFunction = std::function<void()>; + + SimpleMaterializationUnit( + orc::SymbolFlagsMap SymbolFlags, MaterializeFunction Materialize, + DiscardFunction Discard = DiscardFunction(), + DestructorFunction Destructor = DestructorFunction()) + : MaterializationUnit(std::move(SymbolFlags)), + Materialize(std::move(Materialize)), Discard(std::move(Discard)), + Destructor(std::move(Destructor)) {} + + ~SimpleMaterializationUnit() override { + if (Destructor) + Destructor(); + } + + void materialize(orc::MaterializationResponsibility R) override { + Materialize(std::move(R)); + } + + void discard(const orc::JITDylib &JD, orc::SymbolStringPtr Name) override { + if (Discard) + Discard(JD, std::move(Name)); + else + llvm_unreachable("Discard not supported"); + } + +private: + MaterializeFunction Materialize; + DiscardFunction Discard; + DestructorFunction Destructor; +}; + // Base class for Orc tests that will execute code. class OrcExecutionTest { public: |