Files
clang-p2996/llvm/unittests/ExecutionEngine/Orc/LazyCallThroughAndReexportsTest.cpp
lhames ebe8733a11 [ORC] Merge MaterializationResponsibility notifyEmitted and addDependencies
Removes the MaterializationResponsibility::addDependencies and
addDependenciesForAll methods, and transfers dependency registration to
the notifyEmitted operation. The new dependency registration allows
dependencies to be specified for arbitrary subsets of the
MaterializationResponsibility's symbols (rather than just single symbols
or all symbols) via an array of SymbolDependenceGroups (pairs of symbol
sets and corresponding dependencies for that set).

This patch aims to both improve emission performance and simplify
dependence tracking. By eliminating some states (e.g. symbols having
registered dependencies but not yet being resolved or emitted) we make
some errors impossible by construction, and reduce the number of error
cases that we need to check. NonOwningSymbolStringPtrs are used for
dependence tracking under the session lock, which should reduce
ref-counting operations, and intra-emit dependencies are resolved
outside the session lock, which should provide better performance when
JITing concurrently (since some dependence tracking can happen in
parallel).

The Orc C API is updated to account for this change, with the
LLVMOrcMaterializationResponsibilityNotifyEmitted API being modified and
the LLVMOrcMaterializationResponsibilityAddDependencies and
LLVMOrcMaterializationResponsibilityAddDependenciesForAll operations
being removed.
2024-01-31 13:06:09 -08:00

73 lines
2.5 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());
GTEST_SKIP();
}
// Bail out if we can not build a local call-through manager.
auto LCTM = createLocalLazyCallThroughManager(JTMB->getTargetTriple(), ES,
ExecutorAddr());
if (!LCTM) {
consumeError(LCTM.takeError());
GTEST_SKIP();
}
auto DummyTarget = ES.intern("DummyTarget");
bool DummyTargetMaterialized = false;
cantFail(JD.define(std::make_unique<SimpleMaterializationUnit>(
SymbolFlagsMap({{DummyTarget, JITSymbolFlags::Exported}}),
[&](std::unique_ptr<MaterializationResponsibility> R) {
DummyTargetMaterialized = true;
// No dependencies registered, can't fail.
cantFail(R->notifyResolved({{DummyTarget,
{ExecutorAddr::fromPtr(&dummyTarget),
JITSymbolFlags::Exported}}}));
cantFail(R->notifyEmitted({}));
})));
unsigned NotifyResolvedCount = 0;
auto NotifyResolved = [&](ExecutorAddr ResolvedAddr) {
++NotifyResolvedCount;
return Error::success();
};
auto CallThroughTrampoline = cantFail((*LCTM)->getCallThroughTrampoline(
JD, DummyTarget, std::move(NotifyResolved)));
auto CTTPtr = CallThroughTrampoline.toPtr<int (*)()>();
// 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";
}