summaryrefslogtreecommitdiffstats
path: root/llvm/unittests/ExecutionEngine/Orc
diff options
context:
space:
mode:
authorLang Hames <lhames@gmail.com>2018-09-26 04:18:30 +0000
committerLang Hames <lhames@gmail.com>2018-09-26 04:18:30 +0000
commitc1275e72cb47b7a9ef5a6a2ffe1961f3e0025528 (patch)
treeee4cec8e7dd8a4ce68e2948d094aaf23a6a4ebbb /llvm/unittests/ExecutionEngine/Orc
parentea0b7bb548befa8539ce3a9b02584fa001fd89f3 (diff)
downloadbcm5719-llvm-c1275e72cb47b7a9ef5a6a2ffe1961f3e0025528.tar.gz
bcm5719-llvm-c1275e72cb47b7a9ef5a6a2ffe1961f3e0025528.zip
[ORC] Add a "lazy call-through" utility based on the same underlying trampoline
implementation as lazy compile callbacks, and a "lazy re-exports" utility that builds lazy call-throughs. Lazy call-throughs are similar to lazy compile callbacks (and are based on the same underlying state saving/restoring trampolines) but resolve their targets by performing a standard ORC lookup rather than invoking a user supplied compiler callback. This allows them to inherit the thread-safety of ORC lookups while blocking only the calling thread (whereas compile callbacks also block one compile thread). Lazy re-exports provide a simple way of building lazy call-throughs. Unlike a regular re-export, a lazy re-export generates a new address (a stub entry point) that will act like the re-exported symbol when called. The first call via a lazy re-export will trigger compilation of the re-exported symbol before calling through to it. llvm-svn: 343061
Diffstat (limited to 'llvm/unittests/ExecutionEngine/Orc')
-rw-r--r--llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt1
-rw-r--r--llvm/unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp38
-rw-r--r--llvm/unittests/ExecutionEngine/Orc/LazyCallThroughAndReexportsTest.cpp75
-rw-r--r--llvm/unittests/ExecutionEngine/Orc/OrcTestCommon.h38
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:
OpenPOWER on IntegriCloud