notifyResolved/notifyEmitted. The 'notify' prefix better describes what these methods do: they update the JIT symbol states and notify any pending queries that the 'resolved' and 'emitted' states have been reached (rather than actually performing the resolution or emission themselves). Since new states are going to be introduced in the near future (to track symbol registration/initialization) it's worth changing the convention pre-emptively to avoid further confusion. llvm-svn: 363322
76 lines
2.6 KiB
C++
76 lines
2.6 KiB
C++
#include "OrcTestCommon.h"
|
|
#include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.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.intern("DummyTarget");
|
|
|
|
bool DummyTargetMaterialized = false;
|
|
|
|
cantFail(JD.define(llvm::make_unique<SimpleMaterializationUnit>(
|
|
SymbolFlagsMap({{DummyTarget, JITSymbolFlags::Exported}}),
|
|
[&](MaterializationResponsibility R) {
|
|
DummyTargetMaterialized = true;
|
|
R.notifyResolved(
|
|
{{DummyTarget,
|
|
JITEvaluatedSymbol(static_cast<JITTargetAddress>(
|
|
reinterpret_cast<uintptr_t>(&dummyTarget)),
|
|
JITSymbolFlags::Exported)}});
|
|
R.notifyEmitted();
|
|
})));
|
|
|
|
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";
|
|
}
|