diff options
Diffstat (limited to 'llvm/unittests/ExecutionEngine')
3 files changed, 382 insertions, 211 deletions
diff --git a/llvm/unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp b/llvm/unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp index ad17671f1b1..c36b347d670 100644 --- a/llvm/unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp +++ b/llvm/unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp @@ -22,36 +22,36 @@ namespace { class SimpleMaterializationUnit : public MaterializationUnit { public: - using GetSymbolsFunction = std::function<SymbolFlagsMap()>; using MaterializeFunction = std::function<void(MaterializationResponsibility)>; using DiscardFunction = std::function<void(const VSO &, SymbolStringPtr)>; using DestructorFunction = std::function<void()>; SimpleMaterializationUnit( - GetSymbolsFunction GetSymbols, MaterializeFunction Materialize, - DiscardFunction Discard, + SymbolFlagsMap SymbolFlags, MaterializeFunction Materialize, + DiscardFunction Discard = DiscardFunction(), DestructorFunction Destructor = DestructorFunction()) - : GetSymbols(std::move(GetSymbols)), Materialize(std::move(Materialize)), - Discard(std::move(Discard)), Destructor(std::move(Destructor)) {} + : MaterializationUnit(std::move(SymbolFlags)), + Materialize(std::move(Materialize)), Discard(std::move(Discard)), + Destructor(std::move(Destructor)) {} ~SimpleMaterializationUnit() override { if (Destructor) Destructor(); } - SymbolFlagsMap getSymbols() override { return GetSymbols(); } - void materialize(MaterializationResponsibility R) override { Materialize(std::move(R)); } void discard(const VSO &V, SymbolStringPtr Name) override { - Discard(V, std::move(Name)); + if (Discard) + Discard(V, std::move(Name)); + else + llvm_unreachable("Discard not supported"); } private: - GetSymbolsFunction GetSymbols; MaterializeFunction Materialize; DiscardFunction Discard; DestructorFunction Destructor; @@ -65,14 +65,16 @@ TEST(CoreAPIsTest, AsynchronousSymbolQuerySuccessfulResolutionOnly) { bool OnResolutionRun = false; bool OnReadyRun = false; - auto OnResolution = [&](Expected<SymbolMap> Result) { - EXPECT_TRUE(!!Result) << "Resolution unexpectedly returned error"; - auto I = Result->find(Foo); - EXPECT_NE(I, Result->end()) << "Could not find symbol definition"; - EXPECT_EQ(I->second.getAddress(), FakeAddr) - << "Resolution returned incorrect result"; - OnResolutionRun = true; - }; + auto OnResolution = + [&](Expected<AsynchronousSymbolQuery::ResolutionResult> Result) { + EXPECT_TRUE(!!Result) << "Resolution unexpectedly returned error"; + auto &Resolved = Result->Symbols; + auto I = Resolved.find(Foo); + EXPECT_NE(I, Resolved.end()) << "Could not find symbol definition"; + EXPECT_EQ(I->second.getAddress(), FakeAddr) + << "Resolution returned incorrect result"; + OnResolutionRun = true; + }; auto OnReady = [&](Error Err) { cantFail(std::move(Err)); OnReadyRun = true; @@ -82,24 +84,32 @@ TEST(CoreAPIsTest, AsynchronousSymbolQuerySuccessfulResolutionOnly) { Q.resolve(Foo, JITEvaluatedSymbol(FakeAddr, JITSymbolFlags::Exported)); + EXPECT_TRUE(Q.isFullyResolved()) << "Expected query to be fully resolved"; + + if (!Q.isFullyResolved()) + return; + + Q.handleFullyResolved(); + EXPECT_TRUE(OnResolutionRun) << "OnResolutionCallback was not run"; EXPECT_FALSE(OnReadyRun) << "OnReady unexpectedly run"; } -TEST(CoreAPIsTest, AsynchronousSymbolQueryResolutionErrorOnly) { - SymbolStringPool SP; - auto Foo = SP.intern("foo"); +TEST(CoreAPIsTest, ExecutionSessionFailQuery) { + ExecutionSession ES; + auto Foo = ES.getSymbolStringPool().intern("foo"); SymbolNameSet Names({Foo}); bool OnResolutionRun = false; bool OnReadyRun = false; - auto OnResolution = [&](Expected<SymbolMap> Result) { - EXPECT_FALSE(!!Result) << "Resolution unexpectedly returned success"; - auto Msg = toString(Result.takeError()); - EXPECT_EQ(Msg, "xyz") << "Resolution returned incorrect result"; - OnResolutionRun = true; - }; + auto OnResolution = + [&](Expected<AsynchronousSymbolQuery::ResolutionResult> Result) { + EXPECT_FALSE(!!Result) << "Resolution unexpectedly returned success"; + auto Msg = toString(Result.takeError()); + EXPECT_EQ(Msg, "xyz") << "Resolution returned incorrect result"; + OnResolutionRun = true; + }; auto OnReady = [&](Error Err) { cantFail(std::move(Err)); OnReadyRun = true; @@ -107,30 +117,31 @@ TEST(CoreAPIsTest, AsynchronousSymbolQueryResolutionErrorOnly) { AsynchronousSymbolQuery Q(Names, OnResolution, OnReady); - Q.notifyMaterializationFailed( - make_error<StringError>("xyz", inconvertibleErrorCode())); + ES.failQuery(Q, make_error<StringError>("xyz", inconvertibleErrorCode())); EXPECT_TRUE(OnResolutionRun) << "OnResolutionCallback was not run"; EXPECT_FALSE(OnReadyRun) << "OnReady unexpectedly run"; } TEST(CoreAPIsTest, SimpleAsynchronousSymbolQueryAgainstVSO) { - SymbolStringPool SP; - auto Foo = SP.intern("foo"); + ExecutionSession ES; + auto Foo = ES.getSymbolStringPool().intern("foo"); constexpr JITTargetAddress FakeAddr = 0xdeadbeef; SymbolNameSet Names({Foo}); bool OnResolutionRun = false; bool OnReadyRun = false; - auto OnResolution = [&](Expected<SymbolMap> Result) { - EXPECT_TRUE(!!Result) << "Query unexpectedly returned error"; - auto I = Result->find(Foo); - EXPECT_NE(I, Result->end()) << "Could not find symbol definition"; - EXPECT_EQ(I->second.getAddress(), FakeAddr) - << "Resolution returned incorrect result"; - OnResolutionRun = true; - }; + auto OnResolution = + [&](Expected<AsynchronousSymbolQuery::ResolutionResult> Result) { + EXPECT_TRUE(!!Result) << "Query unexpectedly returned error"; + auto &Resolved = Result->Symbols; + auto I = Resolved.find(Foo); + EXPECT_NE(I, Resolved.end()) << "Could not find symbol definition"; + EXPECT_EQ(I->second.getAddress(), FakeAddr) + << "Resolution returned incorrect result"; + OnResolutionRun = true; + }; auto OnReady = [&](Error Err) { cantFail(std::move(Err)); @@ -139,11 +150,12 @@ TEST(CoreAPIsTest, SimpleAsynchronousSymbolQueryAgainstVSO) { auto Q = std::make_shared<AsynchronousSymbolQuery>(Names, OnResolution, OnReady); - VSO V; + auto &V = ES.createVSO("V"); - SymbolMap Defs; - Defs[Foo] = JITEvaluatedSymbol(FakeAddr, JITSymbolFlags::Exported); - cantFail(V.define(std::move(Defs))); + auto Defs = absoluteSymbols( + {{Foo, JITEvaluatedSymbol(FakeAddr, JITSymbolFlags::Exported)}}); + cantFail(V.define(Defs)); + assert(Defs == nullptr && "Defs should have been accepted"); V.lookup(Q, Names); EXPECT_TRUE(OnResolutionRun) << "OnResolutionCallback was not run"; @@ -155,33 +167,26 @@ TEST(CoreAPIsTest, LookupFlagsTest) { // Test that lookupFlags works on a predefined symbol, and does not trigger // materialization of a lazy symbol. - SymbolStringPool SP; - auto Foo = SP.intern("foo"); - auto Bar = SP.intern("bar"); - auto Baz = SP.intern("baz"); + ExecutionSession ES; + auto Foo = ES.getSymbolStringPool().intern("foo"); + auto Bar = ES.getSymbolStringPool().intern("bar"); + auto Baz = ES.getSymbolStringPool().intern("baz"); JITSymbolFlags FooFlags = JITSymbolFlags::Exported; JITSymbolFlags BarFlags = static_cast<JITSymbolFlags::FlagNames>( JITSymbolFlags::Exported | JITSymbolFlags::Weak); - VSO V; + VSO &V = ES.createVSO("V"); auto MU = llvm::make_unique<SimpleMaterializationUnit>( - [=]() { - return SymbolFlagsMap({{Bar, BarFlags}}); - }, + SymbolFlagsMap({{Bar, BarFlags}}), [](MaterializationResponsibility R) { llvm_unreachable("Symbol materialized on flags lookup"); - }, - [](const VSO &V, SymbolStringPtr Name) { - llvm_unreachable("Symbol finalized on flags lookup"); }); - SymbolMap InitialDefs; - InitialDefs[Foo] = JITEvaluatedSymbol(0xdeadbeef, FooFlags); - cantFail(V.define(std::move(InitialDefs))); - - cantFail(V.defineLazy(std::move(MU))); + cantFail(V.define( + absoluteSymbols({{Foo, JITEvaluatedSymbol(0xdeadbeef, FooFlags)}}))); + cantFail(V.define(std::move(MU))); SymbolNameSet Names({Foo, Bar, Baz}); @@ -199,18 +204,150 @@ TEST(CoreAPIsTest, LookupFlagsTest) { EXPECT_EQ(SymbolFlags[Bar], BarFlags) << "Incorrect flags returned for Bar"; } +TEST(CoreAPIsTest, TestCircularDependenceInOneVSO) { + + ExecutionSession ES; + + auto &V = ES.createVSO("V"); + + // Create three symbols: Foo, Bar and Baz. + auto Foo = ES.getSymbolStringPool().intern("foo"); + auto FooFlags = JITSymbolFlags::Exported; + auto FooSym = JITEvaluatedSymbol(1U, FooFlags); + + auto Bar = ES.getSymbolStringPool().intern("bar"); + auto BarFlags = JITSymbolFlags::Exported; + auto BarSym = JITEvaluatedSymbol(2U, BarFlags); + + auto Baz = ES.getSymbolStringPool().intern("baz"); + auto BazFlags = JITSymbolFlags::Exported; + auto BazSym = JITEvaluatedSymbol(3U, BazFlags); + + // Create three MaterializationResponsibility objects: one for each symbol + // (these are optional because MaterializationResponsibility does not have + // a default constructor). + Optional<MaterializationResponsibility> FooR; + Optional<MaterializationResponsibility> BarR; + Optional<MaterializationResponsibility> BazR; + + // Create a MaterializationUnit for each symbol that moves the + // MaterializationResponsibility into one of the locals above. + auto FooMU = llvm::make_unique<SimpleMaterializationUnit>( + SymbolFlagsMap({{Foo, FooFlags}}), + [&](MaterializationResponsibility R) { FooR.emplace(std::move(R)); }); + + auto BarMU = llvm::make_unique<SimpleMaterializationUnit>( + SymbolFlagsMap({{Bar, BarFlags}}), + [&](MaterializationResponsibility R) { BarR.emplace(std::move(R)); }); + + auto BazMU = llvm::make_unique<SimpleMaterializationUnit>( + SymbolFlagsMap({{Baz, BazFlags}}), + [&](MaterializationResponsibility R) { BazR.emplace(std::move(R)); }); + + // Define the symbols. + cantFail(V.define(FooMU)); + cantFail(V.define(BarMU)); + cantFail(V.define(BazMU)); + + // Query each of the symbols to trigger materialization. + bool FooResolved = false; + bool FooReady = false; + auto FooQ = std::make_shared<AsynchronousSymbolQuery>( + SymbolNameSet({Foo}), + [&](Expected<AsynchronousSymbolQuery::ResolutionResult> RR) { + cantFail(std::move(RR)); + FooResolved = true; + }, + [&](Error Err) { + cantFail(std::move(Err)); + FooReady = true; + }); + { + auto Unresolved = V.lookup(FooQ, {Foo}); + EXPECT_TRUE(Unresolved.empty()) << "Failed to resolve \"Foo\""; + } + + bool BarResolved = false; + bool BarReady = false; + auto BarQ = std::make_shared<AsynchronousSymbolQuery>( + SymbolNameSet({Bar}), + [&](Expected<AsynchronousSymbolQuery::ResolutionResult> RR) { + cantFail(std::move(RR)); + BarResolved = true; + }, + [&](Error Err) { + cantFail(std::move(Err)); + BarReady = true; + }); + { + auto Unresolved = V.lookup(BarQ, {Bar}); + EXPECT_TRUE(Unresolved.empty()) << "Failed to resolve \"Bar\""; + } + + bool BazResolved = false; + bool BazReady = false; + auto BazQ = std::make_shared<AsynchronousSymbolQuery>( + SymbolNameSet({Baz}), + [&](Expected<AsynchronousSymbolQuery::ResolutionResult> RR) { + cantFail(std::move(RR)); + BazResolved = true; + }, + [&](Error Err) { + cantFail(std::move(Err)); + BazReady = true; + }); + { + auto Unresolved = V.lookup(BazQ, {Baz}); + EXPECT_TRUE(Unresolved.empty()) << "Failed to resolve \"Baz\""; + } + + FooR->addDependencies({{&V, SymbolNameSet({Bar})}}); + BarR->addDependencies({{&V, SymbolNameSet({Baz})}}); + BazR->addDependencies({{&V, SymbolNameSet({Foo})}}); + + EXPECT_FALSE(FooResolved) << "\"Foo\" should not be resolved yet"; + EXPECT_FALSE(BarResolved) << "\"Bar\" should not be resolved yet"; + EXPECT_FALSE(BazResolved) << "\"Baz\" should not be resolved yet"; + + FooR->resolve({{Foo, FooSym}}); + BarR->resolve({{Bar, BarSym}}); + BazR->resolve({{Baz, BazSym}}); + + EXPECT_TRUE(FooResolved) << "\"Foo\" should be resolved now"; + EXPECT_TRUE(BarResolved) << "\"Bar\" should be resolved now"; + EXPECT_TRUE(BazResolved) << "\"Baz\" should be resolved now"; + + EXPECT_FALSE(FooReady) << "\"Foo\" should not be ready yet"; + EXPECT_FALSE(BarReady) << "\"Bar\" should not be ready yet"; + EXPECT_FALSE(BazReady) << "\"Baz\" should not be ready yet"; + + FooR->finalize(); + BarR->finalize(); + + // Verify that nothing is ready until the circular dependence is resolved. + + EXPECT_FALSE(FooReady) << "\"Foo\" still should not be ready"; + EXPECT_FALSE(BarReady) << "\"Bar\" still should not be ready"; + EXPECT_FALSE(BazReady) << "\"Baz\" still should not be ready"; + + BazR->finalize(); + + // Verify that everything becomes ready once the circular dependence resolved. + EXPECT_TRUE(FooReady) << "\"Foo\" should be ready now"; + EXPECT_TRUE(BarReady) << "\"Bar\" should be ready now"; + EXPECT_TRUE(BazReady) << "\"Baz\" should be ready now"; +} + TEST(CoreAPIsTest, DropMaterializerWhenEmpty) { - SymbolStringPool SP; - auto Foo = SP.intern("foo"); - auto Bar = SP.intern("bar"); + ExecutionSession ES; + auto Foo = ES.getSymbolStringPool().intern("foo"); + auto Bar = ES.getSymbolStringPool().intern("bar"); bool DestructorRun = false; auto MU = llvm::make_unique<SimpleMaterializationUnit>( - [=]() { - return SymbolFlagsMap( - {{Foo, JITSymbolFlags::Weak}, {Bar, JITSymbolFlags::Weak}}); - }, + SymbolFlagsMap( + {{Foo, JITSymbolFlags::Weak}, {Bar, JITSymbolFlags::Weak}}), [](MaterializationResponsibility R) { llvm_unreachable("Unexpected call to materialize"); }, @@ -220,18 +357,18 @@ TEST(CoreAPIsTest, DropMaterializerWhenEmpty) { }, [&]() { DestructorRun = true; }); - VSO V; + auto &V = ES.createVSO("V"); - cantFail(V.defineLazy(std::move(MU))); + cantFail(V.define(MU)); auto FooSym = JITEvaluatedSymbol(1, JITSymbolFlags::Exported); auto BarSym = JITEvaluatedSymbol(2, JITSymbolFlags::Exported); - cantFail(V.define(SymbolMap({{Foo, FooSym}}))); + cantFail(V.define(absoluteSymbols({{Foo, FooSym}}))); EXPECT_FALSE(DestructorRun) << "MaterializationUnit should not have been destroyed yet"; - cantFail(V.define(SymbolMap({{Bar, BarSym}}))); + cantFail(V.define(absoluteSymbols({{Bar, BarSym}}))); EXPECT_TRUE(DestructorRun) << "MaterializationUnit should have been destroyed"; @@ -242,22 +379,20 @@ TEST(CoreAPIsTest, AddAndMaterializeLazySymbol) { constexpr JITTargetAddress FakeFooAddr = 0xdeadbeef; constexpr JITTargetAddress FakeBarAddr = 0xcafef00d; - SymbolStringPool SP; - auto Foo = SP.intern("foo"); - auto Bar = SP.intern("bar"); + ExecutionSession ES; + auto Foo = ES.getSymbolStringPool().intern("foo"); + auto Bar = ES.getSymbolStringPool().intern("bar"); bool FooMaterialized = false; bool BarDiscarded = false; - VSO V; + auto &V = ES.createVSO("V"); auto MU = llvm::make_unique<SimpleMaterializationUnit>( - [=]() { - return SymbolFlagsMap( - {{Foo, JITSymbolFlags::Exported}, - {Bar, static_cast<JITSymbolFlags::FlagNames>( - JITSymbolFlags::Exported | JITSymbolFlags::Weak)}}); - }, + SymbolFlagsMap( + {{Foo, JITSymbolFlags::Exported}, + {Bar, static_cast<JITSymbolFlags::FlagNames>( + JITSymbolFlags::Exported | JITSymbolFlags::Weak)}}), [&](MaterializationResponsibility R) { assert(BarDiscarded && "Bar should have been discarded by this point"); SymbolMap SymbolsToResolve; @@ -272,25 +407,27 @@ TEST(CoreAPIsTest, AddAndMaterializeLazySymbol) { BarDiscarded = true; }); - cantFail(V.defineLazy(std::move(MU))); + cantFail(V.define(MU)); - SymbolMap BarOverride; - BarOverride[Bar] = JITEvaluatedSymbol(FakeBarAddr, JITSymbolFlags::Exported); - cantFail(V.define(std::move(BarOverride))); + ; + cantFail(V.define(absoluteSymbols( + {{Bar, JITEvaluatedSymbol(FakeBarAddr, JITSymbolFlags::Exported)}}))); SymbolNameSet Names({Foo}); bool OnResolutionRun = false; bool OnReadyRun = false; - auto OnResolution = [&](Expected<SymbolMap> Result) { - EXPECT_TRUE(!!Result) << "Resolution unexpectedly returned error"; - auto I = Result->find(Foo); - EXPECT_NE(I, Result->end()) << "Could not find symbol definition"; - EXPECT_EQ(I->second.getAddress(), FakeFooAddr) - << "Resolution returned incorrect result"; - OnResolutionRun = true; - }; + auto OnResolution = + [&](Expected<AsynchronousSymbolQuery::ResolutionResult> Result) { + EXPECT_TRUE(!!Result) << "Resolution unexpectedly returned error"; + auto I = Result->Symbols.find(Foo); + EXPECT_NE(I, Result->Symbols.end()) + << "Could not find symbol definition"; + EXPECT_EQ(I->second.getAddress(), FakeFooAddr) + << "Resolution returned incorrect result"; + OnResolutionRun = true; + }; auto OnReady = [&](Error Err) { cantFail(std::move(Err)); @@ -300,40 +437,98 @@ TEST(CoreAPIsTest, AddAndMaterializeLazySymbol) { auto Q = std::make_shared<AsynchronousSymbolQuery>(Names, OnResolution, OnReady); - auto LR = V.lookup(std::move(Q), Names); - - for (auto &M : LR.Materializers) - M(); + auto Unresolved = V.lookup(std::move(Q), Names); - EXPECT_TRUE(LR.UnresolvedSymbols.empty()) << "Could not find Foo in dylib"; + EXPECT_TRUE(Unresolved.empty()) << "Could not find Foo in dylib"; EXPECT_TRUE(FooMaterialized) << "Foo was not materialized"; EXPECT_TRUE(BarDiscarded) << "Bar was not discarded"; EXPECT_TRUE(OnResolutionRun) << "OnResolutionCallback was not run"; EXPECT_TRUE(OnReadyRun) << "OnReady was not run"; } +TEST(CoreAPIsTest, DefineMaterializingSymbol) { + ExecutionSession ES; + auto Foo = ES.getSymbolStringPool().intern("foo"); + auto Bar = ES.getSymbolStringPool().intern("bar"); + + auto FooSym = JITEvaluatedSymbol(1, JITSymbolFlags::Exported); + auto BarSym = JITEvaluatedSymbol(2, JITSymbolFlags::Exported); + + bool ExpectNoMoreMaterialization = false; + ES.setDispatchMaterialization( + [&](VSO &V, std::unique_ptr<MaterializationUnit> MU) { + if (ExpectNoMoreMaterialization) + ADD_FAILURE() << "Unexpected materialization"; + MU->doMaterialize(V); + }); + + auto MU = llvm::make_unique<SimpleMaterializationUnit>( + SymbolFlagsMap({{Foo, FooSym.getFlags()}}), + [&](MaterializationResponsibility R) { + cantFail( + R.defineMaterializing(SymbolFlagsMap({{Bar, BarSym.getFlags()}}))); + R.resolve(SymbolMap({{Foo, FooSym}, {Bar, BarSym}})); + R.finalize(); + }); + + auto &V = ES.createVSO("V"); + cantFail(V.define(MU)); + + auto OnResolution1 = + [&](Expected<AsynchronousSymbolQuery::ResolutionResult> Result) { + cantFail(std::move(Result)); + }; + + auto OnReady1 = [](Error Err) { cantFail(std::move(Err)); }; + + auto Q1 = std::make_shared<AsynchronousSymbolQuery>(SymbolNameSet({Foo}), + OnResolution1, OnReady1); + + V.lookup(std::move(Q1), {Foo}); + + bool BarResolved = false; + auto OnResolution2 = + [&](Expected<AsynchronousSymbolQuery::ResolutionResult> Result) { + auto R = cantFail(std::move(Result)); + EXPECT_EQ(R.Symbols.size(), 1U) << "Expected to resolve one symbol"; + EXPECT_EQ(R.Symbols.count(Bar), 1U) << "Expected to resolve 'Bar'"; + EXPECT_EQ(R.Symbols[Bar].getAddress(), BarSym.getAddress()) + << "Expected Bar == BarSym"; + BarResolved = true; + }; + + auto OnReady2 = [](Error Err) { cantFail(std::move(Err)); }; + + auto Q2 = std::make_shared<AsynchronousSymbolQuery>(SymbolNameSet({Bar}), + OnResolution2, OnReady2); + + ExpectNoMoreMaterialization = true; + V.lookup(std::move(Q2), {Bar}); + + EXPECT_TRUE(BarResolved) << "Bar should have been resolved"; +} + TEST(CoreAPIsTest, FailResolution) { - SymbolStringPool SP; - auto Foo = SP.intern("foo"); - auto Bar = SP.intern("bar"); + ExecutionSession ES; + auto Foo = ES.getSymbolStringPool().intern("foo"); + auto Bar = ES.getSymbolStringPool().intern("bar"); SymbolNameSet Names({Foo, Bar}); auto MU = llvm::make_unique<SimpleMaterializationUnit>( - [=]() { - return SymbolFlagsMap( - {{Foo, JITSymbolFlags::Weak}, {Bar, JITSymbolFlags::Weak}}); - }, - [&](MaterializationResponsibility R) { R.notifyMaterializationFailed(); }, - [&](const VSO &V, SymbolStringPtr Name) { - llvm_unreachable("Unexpected call to discard"); + SymbolFlagsMap( + {{Foo, JITSymbolFlags::Weak}, {Bar, JITSymbolFlags::Weak}}), + [&](MaterializationResponsibility R) { + R.failMaterialization( + [&]() { return make_error<FailedToResolve>(Names); }); }); - VSO V; + auto &V = ES.createVSO("V"); - cantFail(V.defineLazy(std::move(MU))); + cantFail(V.define(MU)); - auto OnResolution = [&](Expected<SymbolMap> Result) { + auto OnResolution = [&](Expected<AsynchronousSymbolQuery::ResolutionResult> + Result) { handleAllErrors(Result.takeError(), [&](FailedToResolve &F) { EXPECT_EQ(F.getSymbols(), Names) @@ -359,23 +554,19 @@ TEST(CoreAPIsTest, FailResolution) { auto Q = std::make_shared<AsynchronousSymbolQuery>(Names, OnResolution, OnReady); - auto LR = V.lookup(std::move(Q), Names); - for (auto &M : LR.Materializers) - M(); + V.lookup(std::move(Q), Names); } TEST(CoreAPIsTest, FailFinalization) { - SymbolStringPool SP; - auto Foo = SP.intern("foo"); - auto Bar = SP.intern("bar"); + ExecutionSession ES; + auto Foo = ES.getSymbolStringPool().intern("foo"); + auto Bar = ES.getSymbolStringPool().intern("bar"); SymbolNameSet Names({Foo, Bar}); auto MU = llvm::make_unique<SimpleMaterializationUnit>( - [=]() { - return SymbolFlagsMap( - {{Foo, JITSymbolFlags::Exported}, {Bar, JITSymbolFlags::Exported}}); - }, + SymbolFlagsMap( + {{Foo, JITSymbolFlags::Exported}, {Bar, JITSymbolFlags::Exported}}), [&](MaterializationResponsibility R) { constexpr JITTargetAddress FakeFooAddr = 0xdeadbeef; constexpr JITTargetAddress FakeBarAddr = 0xcafef00d; @@ -383,19 +574,18 @@ TEST(CoreAPIsTest, FailFinalization) { auto FooSym = JITEvaluatedSymbol(FakeFooAddr, JITSymbolFlags::Exported); auto BarSym = JITEvaluatedSymbol(FakeBarAddr, JITSymbolFlags::Exported); R.resolve(SymbolMap({{Foo, FooSym}, {Bar, BarSym}})); - R.notifyMaterializationFailed(); - }, - [&](const VSO &V, SymbolStringPtr Name) { - llvm_unreachable("Unexpected call to discard"); + R.failMaterialization( + [&]() { return make_error<FailedToFinalize>(Names); }); }); - VSO V; + auto &V = ES.createVSO("V"); - cantFail(V.defineLazy(std::move(MU))); + cantFail(V.define(MU)); - auto OnResolution = [](Expected<SymbolMap> Result) { - cantFail(std::move(Result)); - }; + auto OnResolution = + [](Expected<AsynchronousSymbolQuery::ResolutionResult> Result) { + cantFail(std::move(Result)); + }; auto OnReady = [&](Error Err) { handleAllErrors(std::move(Err), @@ -418,32 +608,28 @@ TEST(CoreAPIsTest, FailFinalization) { auto Q = std::make_shared<AsynchronousSymbolQuery>(Names, OnResolution, OnReady); - auto LR = V.lookup(std::move(Q), Names); - for (auto &M : LR.Materializers) - M(); + V.lookup(std::move(Q), Names); } TEST(CoreAPIsTest, TestLambdaSymbolResolver) { JITEvaluatedSymbol FooSym(0xdeadbeef, JITSymbolFlags::Exported); JITEvaluatedSymbol BarSym(0xcafef00d, JITSymbolFlags::Exported); - SymbolStringPool SP; - auto Foo = SP.intern("foo"); - auto Bar = SP.intern("bar"); - auto Baz = SP.intern("baz"); + ExecutionSession ES; - VSO V; - cantFail(V.define({{Foo, FooSym}, {Bar, BarSym}})); + auto Foo = ES.getSymbolStringPool().intern("foo"); + auto Bar = ES.getSymbolStringPool().intern("bar"); + auto Baz = ES.getSymbolStringPool().intern("baz"); + + auto &V = ES.createVSO("V"); + cantFail(V.define(absoluteSymbols({{Foo, FooSym}, {Bar, BarSym}}))); auto Resolver = createSymbolResolver( [&](SymbolFlagsMap &SymbolFlags, const SymbolNameSet &Symbols) { return V.lookupFlags(SymbolFlags, Symbols); }, [&](std::shared_ptr<AsynchronousSymbolQuery> Q, SymbolNameSet Symbols) { - auto LR = V.lookup(std::move(Q), Symbols); - assert(LR.Materializers.empty() && - "Test generated unexpected materialization work?"); - return std::move(LR.UnresolvedSymbols); + return V.lookup(std::move(Q), Symbols); }); SymbolNameSet Symbols({Foo, Bar, Baz}); @@ -466,17 +652,21 @@ TEST(CoreAPIsTest, TestLambdaSymbolResolver) { bool OnResolvedRun = false; - auto OnResolved = [&](Expected<SymbolMap> Result) { - OnResolvedRun = true; - EXPECT_TRUE(!!Result) << "Unexpected error"; - EXPECT_EQ(Result->size(), 2U) << "Unexpected number of resolved symbols"; - EXPECT_EQ(Result->count(Foo), 1U) << "Missing lookup result for foo"; - EXPECT_EQ(Result->count(Bar), 1U) << "Missing lookup result for bar"; - EXPECT_EQ((*Result)[Foo].getAddress(), FooSym.getAddress()) - << "Incorrect address for foo"; - EXPECT_EQ((*Result)[Bar].getAddress(), BarSym.getAddress()) - << "Incorrect address for bar"; - }; + auto OnResolved = + [&](Expected<AsynchronousSymbolQuery::ResolutionResult> Result) { + OnResolvedRun = true; + EXPECT_TRUE(!!Result) << "Unexpected error"; + EXPECT_EQ(Result->Symbols.size(), 2U) + << "Unexpected number of resolved symbols"; + EXPECT_EQ(Result->Symbols.count(Foo), 1U) + << "Missing lookup result for foo"; + EXPECT_EQ(Result->Symbols.count(Bar), 1U) + << "Missing lookup result for bar"; + EXPECT_EQ(Result->Symbols[Foo].getAddress(), FooSym.getAddress()) + << "Incorrect address for foo"; + EXPECT_EQ(Result->Symbols[Bar].getAddress(), BarSym.getAddress()) + << "Incorrect address for bar"; + }; auto OnReady = [&](Error Err) { EXPECT_FALSE(!!Err) << "Finalization should never fail in this test"; }; @@ -498,23 +688,17 @@ TEST(CoreAPIsTest, TestLookupWithUnthreadedMaterialization) { auto Foo = ES.getSymbolStringPool().intern("foo"); auto MU = llvm::make_unique<SimpleMaterializationUnit>( - [=]() { - return SymbolFlagsMap({{Foo, JITSymbolFlags::Exported}}); - }, + SymbolFlagsMap({{Foo, JITSymbolFlags::Exported}}), [&](MaterializationResponsibility R) { R.resolve({{Foo, FooSym}}); R.finalize(); - }, - [](const VSO &V, SymbolStringPtr Name) { - llvm_unreachable("Not expecting finalization"); }); - VSO V; + auto &V = ES.createVSO("V"); - cantFail(V.defineLazy(std::move(MU))); + cantFail(V.define(MU)); - auto FooLookupResult = - cantFail(lookup({&V}, Foo, MaterializeOnCurrentThread())); + auto FooLookupResult = cantFail(lookup({&V}, Foo, nullptr)); EXPECT_EQ(FooLookupResult.getAddress(), FooSym.getAddress()) << "lookup returned an incorrect address"; @@ -528,33 +712,20 @@ TEST(CoreAPIsTest, TestLookupWithThreadedMaterialization) { JITEvaluatedSymbol FooSym(FakeFooAddr, JITSymbolFlags::Exported); ExecutionSession ES(std::make_shared<SymbolStringPool>()); - auto Foo = ES.getSymbolStringPool().intern("foo"); - auto MU = llvm::make_unique<SimpleMaterializationUnit>( - [=]() { - return SymbolFlagsMap({{Foo, JITSymbolFlags::Exported}}); - }, - [&](MaterializationResponsibility R) { - R.resolve({{Foo, FooSym}}); - R.finalize(); - }, - [](const VSO &V, SymbolStringPtr Name) { - llvm_unreachable("Not expecting finalization"); + std::thread MaterializationThread; + ES.setDispatchMaterialization( + [&](VSO &V, std::unique_ptr<MaterializationUnit> MU) { + auto SharedMU = std::shared_ptr<MaterializationUnit>(std::move(MU)); + MaterializationThread = + std::thread([SharedMU, &V]() { SharedMU->doMaterialize(V); }); }); + auto Foo = ES.getSymbolStringPool().intern("foo"); - VSO V; - - cantFail(V.defineLazy(std::move(MU))); - - std::thread MaterializationThread; - auto MaterializeOnNewThread = [&](VSO::Materializer M) { - // FIXME: Use move capture once we move to C++14. - auto SharedM = std::make_shared<VSO::Materializer>(std::move(M)); - MaterializationThread = std::thread([SharedM]() { (*SharedM)(); }); - }; + auto &V = ES.createVSO("V"); + cantFail(V.define(absoluteSymbols({{Foo, FooSym}}))); - auto FooLookupResult = - cantFail(lookup({&V}, Foo, MaterializeOnNewThread)); + auto FooLookupResult = cantFail(lookup({&V}, Foo, nullptr)); EXPECT_EQ(FooLookupResult.getAddress(), FooSym.getAddress()) << "lookup returned an incorrect address"; diff --git a/llvm/unittests/ExecutionEngine/Orc/LegacyAPIInteropTest.cpp b/llvm/unittests/ExecutionEngine/Orc/LegacyAPIInteropTest.cpp index 514aafaff43..ade5aa26470 100644 --- a/llvm/unittests/ExecutionEngine/Orc/LegacyAPIInteropTest.cpp +++ b/llvm/unittests/ExecutionEngine/Orc/LegacyAPIInteropTest.cpp @@ -21,11 +21,9 @@ TEST(LegacyAPIInteropTest, QueryAgainstVSO) { ExecutionSession ES(std::make_shared<SymbolStringPool>()); auto Foo = ES.getSymbolStringPool().intern("foo"); - VSO V; - SymbolMap Defs; + auto &V = ES.createVSO("V"); JITEvaluatedSymbol FooSym(0xdeadbeef, JITSymbolFlags::Exported); - Defs[Foo] = FooSym; - cantFail(V.define(std::move(Defs))); + cantFail(V.define(absoluteSymbols({{Foo, FooSym}}))); auto LookupFlags = [&](SymbolFlagsMap &SymbolFlags, const SymbolNameSet &Names) { @@ -34,15 +32,12 @@ TEST(LegacyAPIInteropTest, QueryAgainstVSO) { auto Lookup = [&](std::shared_ptr<AsynchronousSymbolQuery> Query, SymbolNameSet Symbols) { - auto R = V.lookup(std::move(Query), Symbols); - EXPECT_TRUE(R.Materializers.empty()) - << "Query resulted in unexpected materialization work"; - return std::move(R.UnresolvedSymbols); + return V.lookup(std::move(Query), Symbols); }; auto UnderlyingResolver = createSymbolResolver(std::move(LookupFlags), std::move(Lookup)); - JITSymbolResolverAdapter Resolver(ES, *UnderlyingResolver); + JITSymbolResolverAdapter Resolver(ES, *UnderlyingResolver, nullptr); JITSymbolResolver::LookupSet Names{StringRef("foo")}; @@ -90,10 +85,10 @@ TEST(LegacyAPIInteropTset, LegacyLookupHelpersFn) { return nullptr; }; - SymbolStringPool SP; - auto Foo = SP.intern("foo"); - auto Bar = SP.intern("bar"); - auto Baz = SP.intern("baz"); + ExecutionSession ES; + auto Foo = ES.getSymbolStringPool().intern("foo"); + auto Bar = ES.getSymbolStringPool().intern("bar"); + auto Baz = ES.getSymbolStringPool().intern("baz"); SymbolNameSet Symbols({Foo, Bar, Baz}); @@ -115,24 +110,29 @@ TEST(LegacyAPIInteropTset, LegacyLookupHelpersFn) { bool OnResolvedRun = false; bool OnReadyRun = false; - auto OnResolved = [&](Expected<SymbolMap> Result) { - OnResolvedRun = true; - EXPECT_TRUE(!!Result) << "lookuWithLegacy failed to resolve"; - EXPECT_EQ(Result->size(), 2U) << "Wrong number of symbols resolved"; - EXPECT_EQ(Result->count(Foo), 1U) << "Result for foo missing"; - EXPECT_EQ(Result->count(Bar), 1U) << "Result for bar missing"; - EXPECT_EQ((*Result)[Foo].getAddress(), FooAddr) << "Wrong address for foo"; - EXPECT_EQ((*Result)[Foo].getFlags(), FooFlags) << "Wrong flags for foo"; - EXPECT_EQ((*Result)[Bar].getAddress(), BarAddr) << "Wrong address for bar"; - EXPECT_EQ((*Result)[Bar].getFlags(), BarFlags) << "Wrong flags for bar"; - }; + auto OnResolved = + [&](Expected<AsynchronousSymbolQuery::ResolutionResult> Result) { + OnResolvedRun = true; + EXPECT_TRUE(!!Result) << "lookuWithLegacy failed to resolve"; + + auto &Resolved = Result->Symbols; + EXPECT_EQ(Resolved.size(), 2U) << "Wrong number of symbols resolved"; + EXPECT_EQ(Resolved.count(Foo), 1U) << "Result for foo missing"; + EXPECT_EQ(Resolved.count(Bar), 1U) << "Result for bar missing"; + EXPECT_EQ(Resolved[Foo].getAddress(), FooAddr) + << "Wrong address for foo"; + EXPECT_EQ(Resolved[Foo].getFlags(), FooFlags) << "Wrong flags for foo"; + EXPECT_EQ(Resolved[Bar].getAddress(), BarAddr) + << "Wrong address for bar"; + EXPECT_EQ(Resolved[Bar].getFlags(), BarFlags) << "Wrong flags for bar"; + }; auto OnReady = [&](Error Err) { EXPECT_FALSE(!!Err) << "Finalization unexpectedly failed"; OnReadyRun = true; }; AsynchronousSymbolQuery Q({Foo, Bar}, OnResolved, OnReady); - auto Unresolved = lookupWithLegacyFn(Q, Symbols, LegacyLookup); + auto Unresolved = lookupWithLegacyFn(ES, Q, Symbols, LegacyLookup); EXPECT_TRUE(OnResolvedRun) << "OnResolved was not run"; EXPECT_TRUE(OnReadyRun) << "OnReady was not run"; diff --git a/llvm/unittests/ExecutionEngine/Orc/RTDyldObjectLinkingLayerTest.cpp b/llvm/unittests/ExecutionEngine/Orc/RTDyldObjectLinkingLayerTest.cpp index 650fd524812..17f733c99d2 100644 --- a/llvm/unittests/ExecutionEngine/Orc/RTDyldObjectLinkingLayerTest.cpp +++ b/llvm/unittests/ExecutionEngine/Orc/RTDyldObjectLinkingLayerTest.cpp @@ -190,7 +190,7 @@ TEST_F(RTDyldObjectLinkingLayerExecutionTest, NoDuplicateFinalization) { }, [&](std::shared_ptr<AsynchronousSymbolQuery> Query, const SymbolNameSet &Symbols) { - return lookupWithLegacyFn(*Query, Symbols, LegacyLookup); + return lookupWithLegacyFn(ES, *Query, Symbols, LegacyLookup); }); cantFail(ObjLayer.addObject(K2, std::move(Obj2))); |