diff --git a/llvm/unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp b/llvm/unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp index 6c98b51fa742..3d81d6b99f62 100644 --- a/llvm/unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp +++ b/llvm/unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp @@ -58,12 +58,47 @@ private: DestructorFunction Destructor; }; -TEST(CoreAPIsTest, AsynchronousSymbolQuerySuccessfulResolutionOnly) { - SymbolStringPool SP; - auto Foo = SP.intern("foo"); - constexpr JITTargetAddress FakeAddr = 0xdeadbeef; - SymbolNameSet Names({Foo}); +// CoreAPIsStandardTest that saves a bunch of boilerplate by providing the +// following: +// +// (1) ES -- An ExecutionSession +// (2) Foo, Bar, Baz, Qux -- SymbolStringPtrs for strings "foo", "bar", "baz", +// and "qux" respectively. +// (3) FooAddr, BarAddr, BazAddr, QuxAddr -- Dummy addresses. Guaranteed +// distinct and non-null. +// (4) FooSym, BarSym, BazSym, QuxSym -- JITEvaluatedSymbols with FooAddr, +// BarAddr, BazAddr, and QuxAddr respectively. All with default strong, +// linkage and non-hidden visibility. +// (5) V -- A VSO associated with ES. +class CoreAPIsStandardTest : public testing::Test { +public: +protected: + ExecutionSession ES; + VSO &V = ES.createVSO("V"); + SymbolStringPtr Foo = ES.getSymbolStringPool().intern("foo"); + SymbolStringPtr Bar = ES.getSymbolStringPool().intern("bar"); + SymbolStringPtr Baz = ES.getSymbolStringPool().intern("baz"); + SymbolStringPtr Qux = ES.getSymbolStringPool().intern("qux"); + constexpr static const JITTargetAddress FooAddr = 1U; + constexpr static const JITTargetAddress BarAddr = 2U; + constexpr static const JITTargetAddress BazAddr = 3U; + constexpr static const JITTargetAddress QuxAddr = 4U; + JITEvaluatedSymbol FooSym = + JITEvaluatedSymbol(FooAddr, JITSymbolFlags::Exported); + JITEvaluatedSymbol BarSym = + JITEvaluatedSymbol(BarAddr, JITSymbolFlags::Exported); + JITEvaluatedSymbol BazSym = + JITEvaluatedSymbol(BazAddr, JITSymbolFlags::Exported); + JITEvaluatedSymbol QuxSym = + JITEvaluatedSymbol(QuxAddr, JITSymbolFlags::Exported); +}; +const JITTargetAddress CoreAPIsStandardTest::FooAddr; +const JITTargetAddress CoreAPIsStandardTest::BarAddr; +const JITTargetAddress CoreAPIsStandardTest::BazAddr; +const JITTargetAddress CoreAPIsStandardTest::QuxAddr; + +TEST_F(CoreAPIsStandardTest, AsynchronousSymbolQuerySuccessfulResolutionOnly) { bool OnResolutionRun = false; bool OnReadyRun = false; auto OnResolution = @@ -72,7 +107,7 @@ TEST(CoreAPIsTest, AsynchronousSymbolQuerySuccessfulResolutionOnly) { 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) + EXPECT_EQ(I->second.getAddress(), FooAddr) << "Resolution returned incorrect result"; OnResolutionRun = true; }; @@ -81,9 +116,9 @@ TEST(CoreAPIsTest, AsynchronousSymbolQuerySuccessfulResolutionOnly) { OnReadyRun = true; }; - AsynchronousSymbolQuery Q(Names, OnResolution, OnReady); + AsynchronousSymbolQuery Q(SymbolNameSet({Foo}), OnResolution, OnReady); - Q.resolve(Foo, JITEvaluatedSymbol(FakeAddr, JITSymbolFlags::Exported)); + Q.resolve(Foo, FooSym); EXPECT_TRUE(Q.isFullyResolved()) << "Expected query to be fully resolved"; @@ -96,11 +131,7 @@ TEST(CoreAPIsTest, AsynchronousSymbolQuerySuccessfulResolutionOnly) { EXPECT_FALSE(OnReadyRun) << "OnReady unexpectedly run"; } -TEST(CoreAPIsTest, ExecutionSessionFailQuery) { - ExecutionSession ES; - auto Foo = ES.getSymbolStringPool().intern("foo"); - SymbolNameSet Names({Foo}); - +TEST_F(CoreAPIsStandardTest, ExecutionSessionFailQuery) { bool OnResolutionRun = false; bool OnReadyRun = false; @@ -116,7 +147,7 @@ TEST(CoreAPIsTest, ExecutionSessionFailQuery) { OnReadyRun = true; }; - AsynchronousSymbolQuery Q(Names, OnResolution, OnReady); + AsynchronousSymbolQuery Q(SymbolNameSet({Foo}), OnResolution, OnReady); ES.failQuery(Q, make_error("xyz", inconvertibleErrorCode())); @@ -124,12 +155,7 @@ TEST(CoreAPIsTest, ExecutionSessionFailQuery) { EXPECT_FALSE(OnReadyRun) << "OnReady unexpectedly run"; } -TEST(CoreAPIsTest, SimpleAsynchronousSymbolQueryAgainstVSO) { - ExecutionSession ES; - auto Foo = ES.getSymbolStringPool().intern("foo"); - constexpr JITTargetAddress FakeAddr = 0xdeadbeef; - SymbolNameSet Names({Foo}); - +TEST_F(CoreAPIsStandardTest, SimpleAsynchronousSymbolQueryAgainstVSO) { bool OnResolutionRun = false; bool OnReadyRun = false; @@ -139,7 +165,7 @@ TEST(CoreAPIsTest, SimpleAsynchronousSymbolQueryAgainstVSO) { 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) + EXPECT_EQ(I->second.getAddress(), FooSym.getAddress()) << "Resolution returned incorrect result"; OnResolutionRun = true; }; @@ -149,12 +175,12 @@ TEST(CoreAPIsTest, SimpleAsynchronousSymbolQueryAgainstVSO) { OnReadyRun = true; }; + SymbolNameSet Names({Foo}); + auto Q = std::make_shared(Names, OnResolution, OnReady); - auto &V = ES.createVSO("V"); - auto Defs = absoluteSymbols( - {{Foo, JITEvaluatedSymbol(FakeAddr, JITSymbolFlags::Exported)}}); + auto Defs = absoluteSymbols({{Foo, FooSym}}); cantFail(V.define(Defs)); assert(Defs == nullptr && "Defs should have been accepted"); V.lookup(Q, Names); @@ -163,10 +189,7 @@ TEST(CoreAPIsTest, SimpleAsynchronousSymbolQueryAgainstVSO) { EXPECT_TRUE(OnReadyRun) << "OnReady was not run"; } -TEST(CoreAPIsTest, EmptyVSOAndQueryLookup) { - ExecutionSession ES; - auto &V = ES.createVSO("V"); - +TEST_F(CoreAPIsStandardTest, EmptyVSOAndQueryLookup) { bool OnResolvedRun = false; bool OnReadyRun = false; @@ -187,13 +210,8 @@ TEST(CoreAPIsTest, EmptyVSOAndQueryLookup) { EXPECT_TRUE(OnReadyRun) << "OnReady was not run for empty query"; } -TEST(CoreAPIsTest, ChainedVSOLookup) { - ExecutionSession ES; - auto Foo = ES.getSymbolStringPool().intern("foo"); - auto FooSym = JITEvaluatedSymbol(1U, JITSymbolFlags::Exported); - - auto &V1 = ES.createVSO("V1"); - cantFail(V1.define(absoluteSymbols({{Foo, FooSym}}))); +TEST_F(CoreAPIsStandardTest, ChainedVSOLookup) { + cantFail(V.define(absoluteSymbols({{Foo, FooSym}}))); auto &V2 = ES.createVSO("V2"); @@ -211,36 +229,26 @@ TEST(CoreAPIsTest, ChainedVSOLookup) { OnReadyRun = true; }); - V2.lookup(Q, V1.lookup(Q, {Foo})); + V2.lookup(Q, V.lookup(Q, {Foo})); EXPECT_TRUE(OnResolvedRun) << "OnResolved was not run for empty query"; EXPECT_TRUE(OnReadyRun) << "OnReady was not run for empty query"; } -TEST(CoreAPIsTest, LookupFlagsTest) { - +TEST_F(CoreAPIsStandardTest, LookupFlagsTest) { // Test that lookupFlags works on a predefined symbol, and does not trigger - // materialization of a lazy symbol. - - 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::Exported | JITSymbolFlags::Weak); - - VSO &V = ES.createVSO("V"); + // materialization of a lazy symbol. Make the lazy symbol weak to test that + // the weak flag is propagated correctly. + BarSym.setFlags(static_cast( + JITSymbolFlags::Exported | JITSymbolFlags::Weak)); auto MU = llvm::make_unique( - SymbolFlagsMap({{Bar, BarFlags}}), + SymbolFlagsMap({{Bar, BarSym.getFlags()}}), [](MaterializationResponsibility R) { llvm_unreachable("Symbol materialized on flags lookup"); }); - cantFail(V.define( - absoluteSymbols({{Foo, JITEvaluatedSymbol(0xdeadbeef, FooFlags)}}))); + cantFail(V.define(absoluteSymbols({{Foo, FooSym}}))); cantFail(V.define(std::move(MU))); SymbolNameSet Names({Foo, Bar, Baz}); @@ -253,26 +261,15 @@ TEST(CoreAPIsTest, LookupFlagsTest) { EXPECT_EQ(SymbolFlags.size(), 2U) << "Returned symbol flags contains unexpected results"; EXPECT_EQ(SymbolFlags.count(Foo), 1U) << "Missing lookupFlags result for Foo"; - EXPECT_EQ(SymbolFlags[Foo], FooFlags) << "Incorrect flags returned for Foo"; + EXPECT_EQ(SymbolFlags[Foo], FooSym.getFlags()) + << "Incorrect flags returned for Foo"; EXPECT_EQ(SymbolFlags.count(Bar), 1U) << "Missing lookupFlags result for Bar"; - EXPECT_EQ(SymbolFlags[Bar], BarFlags) << "Incorrect flags returned for Bar"; + EXPECT_EQ(SymbolFlags[Bar], BarSym.getFlags()) + << "Incorrect flags returned for Bar"; } -TEST(CoreAPIsTest, TestBasicAliases) { - ExecutionSession ES; - auto &V = ES.createVSO("V"); - - auto Foo = ES.getSymbolStringPool().intern("foo"); - auto FooSym = JITEvaluatedSymbol(1U, JITSymbolFlags::Exported); - auto Bar = ES.getSymbolStringPool().intern("bar"); - auto BarSym = JITEvaluatedSymbol(2U, JITSymbolFlags::Exported); - - auto Baz = ES.getSymbolStringPool().intern("baz"); - auto Qux = ES.getSymbolStringPool().intern("qux"); - - auto QuxSym = JITEvaluatedSymbol(3U, JITSymbolFlags::Exported); - +TEST_F(CoreAPIsStandardTest, TestBasicAliases) { cantFail(V.define(absoluteSymbols({{Foo, FooSym}, {Bar, BarSym}}))); cantFail(V.define(symbolAliases({{Baz, {Foo, JITSymbolFlags::Exported}}, {Qux, {Bar, JITSymbolFlags::Weak}}}))); @@ -288,20 +285,10 @@ TEST(CoreAPIsTest, TestBasicAliases) { << "The \"Qux\" alias should have been overriden"; } -TEST(CoreAPIsTest, TestChainedAliases) { - ExecutionSession ES; - auto &V = ES.createVSO("V"); - - auto Foo = ES.getSymbolStringPool().intern("foo"); - auto FooSym = JITEvaluatedSymbol(1U, JITSymbolFlags::Exported); - - auto Bar = ES.getSymbolStringPool().intern("bar"); - - auto Baz = ES.getSymbolStringPool().intern("baz"); - +TEST_F(CoreAPIsStandardTest, TestChainedAliases) { cantFail(V.define(absoluteSymbols({{Foo, FooSym}}))); - cantFail(V.define(symbolAliases({{Baz, {Bar, JITSymbolFlags::Exported}}, - {Bar, {Foo, JITSymbolFlags::Exported}}}))); + cantFail(V.define(symbolAliases( + {{Baz, {Bar, BazSym.getFlags()}}, {Bar, {Foo, BarSym.getFlags()}}}))); auto Result = lookup({&V}, {Bar, Baz}); EXPECT_TRUE(!!Result) << "Unexpected lookup failure"; @@ -313,18 +300,10 @@ TEST(CoreAPIsTest, TestChainedAliases) { << "\"Baz\"'s address should match \"Foo\"'s"; } -TEST(CoreAPIsTest, TestTrivialCircularDependency) { - ExecutionSession ES; - - auto &V = ES.createVSO("V"); - - auto Foo = ES.getSymbolStringPool().intern("foo"); - auto FooFlags = JITSymbolFlags::Exported; - auto FooSym = JITEvaluatedSymbol(1U, FooFlags); - +TEST_F(CoreAPIsStandardTest, TestTrivialCircularDependency) { Optional FooR; auto FooMU = llvm::make_unique( - SymbolFlagsMap({{Foo, FooFlags}}), + SymbolFlagsMap({{Foo, FooSym.getFlags()}}), [&](MaterializationResponsibility R) { FooR.emplace(std::move(R)); }); cantFail(V.define(FooMU)); @@ -351,28 +330,14 @@ TEST(CoreAPIsTest, TestTrivialCircularDependency) { << "Self-dependency prevented symbol from being marked ready"; } -TEST(CoreAPIsTest, TestCircularDependenceInOneVSO) { +TEST_F(CoreAPIsStandardTest, TestCircularDependenceInOneVSO) { + // Test that a circular symbol dependency between three symbols in a VSO does + // not prevent any symbol from becoming 'ready' once all symbols are + // finalized. - 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). + // Create three MaterializationResponsibility objects: one for each of Foo, + // Bar and Baz. These are optional because MaterializationResponsibility + // does not have a default constructor). Optional FooR; Optional BarR; Optional BazR; @@ -380,15 +345,15 @@ TEST(CoreAPIsTest, TestCircularDependenceInOneVSO) { // Create a MaterializationUnit for each symbol that moves the // MaterializationResponsibility into one of the locals above. auto FooMU = llvm::make_unique( - SymbolFlagsMap({{Foo, FooFlags}}), + SymbolFlagsMap({{Foo, FooSym.getFlags()}}), [&](MaterializationResponsibility R) { FooR.emplace(std::move(R)); }); auto BarMU = llvm::make_unique( - SymbolFlagsMap({{Bar, BarFlags}}), + SymbolFlagsMap({{Bar, BarSym.getFlags()}}), [&](MaterializationResponsibility R) { BarR.emplace(std::move(R)); }); auto BazMU = llvm::make_unique( - SymbolFlagsMap({{Baz, BazFlags}}), + SymbolFlagsMap({{Baz, BazSym.getFlags()}}), [&](MaterializationResponsibility R) { BazR.emplace(std::move(R)); }); // Define the symbols. @@ -459,14 +424,17 @@ TEST(CoreAPIsTest, TestCircularDependenceInOneVSO) { BarR->addDependencies({{&V, SymbolNameSet({Bar})}}); BazR->addDependencies({{&V, SymbolNameSet({Baz})}}); + // Check that nothing has been resolved yet. 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"; + // Resolve the symbols (but do not finalized them). FooR->resolve({{Foo, FooSym}}); BarR->resolve({{Bar, BarSym}}); BazR->resolve({{Baz, BazSym}}); + // Verify that the symbols have been resolved, but are not ready yet. EXPECT_TRUE(FooResolved) << "\"Foo\" should be resolved now"; EXPECT_TRUE(BarResolved) << "\"Bar\" should be resolved now"; EXPECT_TRUE(BazResolved) << "\"Baz\" should be resolved now"; @@ -475,15 +443,16 @@ TEST(CoreAPIsTest, TestCircularDependenceInOneVSO) { EXPECT_FALSE(BarReady) << "\"Bar\" should not be ready yet"; EXPECT_FALSE(BazReady) << "\"Baz\" should not be ready yet"; + // Finalize two of the symbols. 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"; + // Finalize the last symbol. BazR->finalize(); // Verify that everything becomes ready once the circular dependence resolved. @@ -492,16 +461,14 @@ TEST(CoreAPIsTest, TestCircularDependenceInOneVSO) { EXPECT_TRUE(BazReady) << "\"Baz\" should be ready now"; } -TEST(CoreAPIsTest, DropMaterializerWhenEmpty) { - ExecutionSession ES; - auto Foo = ES.getSymbolStringPool().intern("foo"); - auto Bar = ES.getSymbolStringPool().intern("bar"); - +TEST_F(CoreAPIsStandardTest, DropMaterializerWhenEmpty) { bool DestructorRun = false; + JITSymbolFlags WeakExported(JITSymbolFlags::Exported); + WeakExported |= JITSymbolFlags::Weak; + auto MU = llvm::make_unique( - SymbolFlagsMap( - {{Foo, JITSymbolFlags::Weak}, {Bar, JITSymbolFlags::Weak}}), + SymbolFlagsMap({{Foo, WeakExported}, {Bar, WeakExported}}), [](MaterializationResponsibility R) { llvm_unreachable("Unexpected call to materialize"); }, @@ -515,8 +482,6 @@ TEST(CoreAPIsTest, DropMaterializerWhenEmpty) { cantFail(V.define(MU)); - auto FooSym = JITEvaluatedSymbol(1, JITSymbolFlags::Exported); - auto BarSym = JITEvaluatedSymbol(2, JITSymbolFlags::Exported); cantFail(V.define(absoluteSymbols({{Foo, FooSym}}))); EXPECT_FALSE(DestructorRun) @@ -528,31 +493,18 @@ TEST(CoreAPIsTest, DropMaterializerWhenEmpty) { << "MaterializationUnit should have been destroyed"; } -TEST(CoreAPIsTest, AddAndMaterializeLazySymbol) { - - constexpr JITTargetAddress FakeFooAddr = 0xdeadbeef; - constexpr JITTargetAddress FakeBarAddr = 0xcafef00d; - - ExecutionSession ES; - auto Foo = ES.getSymbolStringPool().intern("foo"); - auto Bar = ES.getSymbolStringPool().intern("bar"); - +TEST_F(CoreAPIsStandardTest, AddAndMaterializeLazySymbol) { bool FooMaterialized = false; bool BarDiscarded = false; - auto &V = ES.createVSO("V"); + JITSymbolFlags WeakExported(JITSymbolFlags::Exported); + WeakExported |= JITSymbolFlags::Weak; auto MU = llvm::make_unique( - SymbolFlagsMap( - {{Foo, JITSymbolFlags::Exported}, - {Bar, static_cast( - JITSymbolFlags::Exported | JITSymbolFlags::Weak)}}), + SymbolFlagsMap({{Foo, JITSymbolFlags::Exported}, {Bar, WeakExported}}), [&](MaterializationResponsibility R) { assert(BarDiscarded && "Bar should have been discarded by this point"); - SymbolMap SymbolsToResolve; - SymbolsToResolve[Foo] = - JITEvaluatedSymbol(FakeFooAddr, JITSymbolFlags::Exported); - R.resolve(std::move(SymbolsToResolve)); + R.resolve(SymbolMap({{Foo, FooSym}})); R.finalize(); FooMaterialized = true; }, @@ -562,10 +514,7 @@ TEST(CoreAPIsTest, AddAndMaterializeLazySymbol) { }); cantFail(V.define(MU)); - - ; - cantFail(V.define(absoluteSymbols( - {{Bar, JITEvaluatedSymbol(FakeBarAddr, JITSymbolFlags::Exported)}}))); + cantFail(V.define(absoluteSymbols({{Bar, BarSym}}))); SymbolNameSet Names({Foo}); @@ -578,7 +527,7 @@ TEST(CoreAPIsTest, AddAndMaterializeLazySymbol) { auto I = Result->Symbols.find(Foo); EXPECT_NE(I, Result->Symbols.end()) << "Could not find symbol definition"; - EXPECT_EQ(I->second.getAddress(), FakeFooAddr) + EXPECT_EQ(I->second.getAddress(), FooSym.getAddress()) << "Resolution returned incorrect result"; OnResolutionRun = true; }; @@ -600,14 +549,7 @@ TEST(CoreAPIsTest, AddAndMaterializeLazySymbol) { 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); - +TEST_F(CoreAPIsStandardTest, DefineMaterializingSymbol) { bool ExpectNoMoreMaterialization = false; ES.setDispatchMaterialization( [&](VSO &V, std::unique_ptr MU) { @@ -625,56 +567,19 @@ TEST(CoreAPIsTest, DefineMaterializingSymbol) { R.finalize(); }); - auto &V = ES.createVSO("V"); cantFail(V.define(MU)); + cantFail(lookup({&V}, Foo)); - auto OnResolution1 = - [&](Expected Result) { - cantFail(std::move(Result)); - }; - - auto OnReady1 = [](Error Err) { cantFail(std::move(Err)); }; - - auto Q1 = std::make_shared(SymbolNameSet({Foo}), - OnResolution1, OnReady1); - - V.lookup(std::move(Q1), {Foo}); - - bool BarResolved = false; - auto OnResolution2 = - [&](Expected 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(SymbolNameSet({Bar}), - OnResolution2, OnReady2); - + // Assert that materialization is complete by now. ExpectNoMoreMaterialization = true; - V.lookup(std::move(Q2), {Bar}); - EXPECT_TRUE(BarResolved) << "Bar should have been resolved"; + // Look up bar to verify that no further materialization happens. + auto BarResult = cantFail(lookup({&V}, Bar)); + EXPECT_EQ(BarResult.getAddress(), BarSym.getAddress()) + << "Expected Bar == BarSym"; } -TEST(CoreAPIsTest, FallbackDefinitionGeneratorTest) { - constexpr JITTargetAddress FakeFooAddr = 0xdeadbeef; - constexpr JITTargetAddress FakeBarAddr = 0xcafef00d; - - ExecutionSession ES; - auto Foo = ES.getSymbolStringPool().intern("foo"); - auto Bar = ES.getSymbolStringPool().intern("bar"); - - auto FooSym = JITEvaluatedSymbol(FakeFooAddr, JITSymbolFlags::Exported); - auto BarSym = JITEvaluatedSymbol(FakeBarAddr, JITSymbolFlags::Exported); - - auto &V = ES.createVSO("V"); - +TEST_F(CoreAPIsStandardTest, FallbackDefinitionGeneratorTest) { cantFail(V.define(absoluteSymbols({{Foo, FooSym}}))); V.setFallbackDefinitionGenerator([&](VSO &W, const SymbolNameSet &Names) { @@ -685,67 +590,42 @@ TEST(CoreAPIsTest, FallbackDefinitionGeneratorTest) { auto Result = cantFail(lookup({&V}, {Foo, Bar})); EXPECT_EQ(Result.count(Bar), 1U) << "Expected to find fallback def for 'bar'"; - EXPECT_EQ(Result[Bar].getAddress(), FakeBarAddr) - << "Expected address of fallback def for 'bar' to be " << FakeBarAddr; + EXPECT_EQ(Result[Bar].getAddress(), BarSym.getAddress()) + << "Expected fallback def for Bar to be equal to BarSym"; } -TEST(CoreAPIsTest, FailResolution) { - ExecutionSession ES; - auto Foo = ES.getSymbolStringPool().intern("foo"); - auto Bar = ES.getSymbolStringPool().intern("bar"); - - SymbolNameSet Names({Foo, Bar}); - +TEST_F(CoreAPIsStandardTest, FailResolution) { auto MU = llvm::make_unique( SymbolFlagsMap( {{Foo, JITSymbolFlags::Weak}, {Bar, JITSymbolFlags::Weak}}), [&](MaterializationResponsibility R) { R.failMaterialization(); }); - auto &V = ES.createVSO("V"); - cantFail(V.define(MU)); - auto OnResolution = - [&](Expected Result) { - handleAllErrors(Result.takeError(), - [&](FailedToMaterialize &F) { - EXPECT_EQ(F.getSymbols(), Names) - << "Expected to fail on symbols in Names"; - }, - [](ErrorInfoBase &EIB) { - std::string ErrMsg; - { - raw_string_ostream ErrOut(ErrMsg); - EIB.log(ErrOut); - } - ADD_FAILURE() - << "Expected a FailedToResolve error. Got:\n" - << ErrMsg; - }); - }; + SymbolNameSet Names({Foo, Bar}); + auto Result = lookup({&V}, Names); - auto OnReady = [](Error Err) { - cantFail(std::move(Err)); - ADD_FAILURE() << "OnReady should never be called"; - }; - - auto Q = - std::make_shared(Names, OnResolution, OnReady); - - V.lookup(std::move(Q), Names); + EXPECT_FALSE(!!Result) << "Expected failure"; + if (!Result) { + handleAllErrors(Result.takeError(), + [&](FailedToMaterialize &F) { + EXPECT_EQ(F.getSymbols(), Names) + << "Expected to fail on symbols in Names"; + }, + [](ErrorInfoBase &EIB) { + std::string ErrMsg; + { + raw_string_ostream ErrOut(ErrMsg); + EIB.log(ErrOut); + } + ADD_FAILURE() + << "Expected a FailedToResolve error. Got:\n" + << ErrMsg; + }); + } } -TEST(CoreAPIsTest, TestLambdaSymbolResolver) { - JITEvaluatedSymbol FooSym(0xdeadbeef, JITSymbolFlags::Exported); - JITEvaluatedSymbol BarSym(0xcafef00d, JITSymbolFlags::Exported); - - ExecutionSession ES; - - auto Foo = ES.getSymbolStringPool().intern("foo"); - auto Bar = ES.getSymbolStringPool().intern("bar"); - auto Baz = ES.getSymbolStringPool().intern("baz"); - - auto &V = ES.createVSO("V"); +TEST_F(CoreAPIsStandardTest, TestLambdaSymbolResolver) { cantFail(V.define(absoluteSymbols({{Foo, FooSym}, {Bar, BarSym}}))); auto Resolver = createSymbolResolver( @@ -804,13 +684,7 @@ TEST(CoreAPIsTest, TestLambdaSymbolResolver) { EXPECT_TRUE(OnResolvedRun) << "OnResolved was never run"; } -TEST(CoreAPIsTest, TestLookupWithUnthreadedMaterialization) { - constexpr JITTargetAddress FakeFooAddr = 0xdeadbeef; - JITEvaluatedSymbol FooSym(FakeFooAddr, JITSymbolFlags::Exported); - - ExecutionSession ES(std::make_shared()); - auto Foo = ES.getSymbolStringPool().intern("foo"); - +TEST_F(CoreAPIsStandardTest, TestLookupWithUnthreadedMaterialization) { auto MU = llvm::make_unique( SymbolFlagsMap({{Foo, JITSymbolFlags::Exported}}), [&](MaterializationResponsibility R) { @@ -818,8 +692,6 @@ TEST(CoreAPIsTest, TestLookupWithUnthreadedMaterialization) { R.finalize(); }); - auto &V = ES.createVSO("V"); - cantFail(V.define(MU)); auto FooLookupResult = cantFail(lookup({&V}, Foo)); @@ -830,12 +702,8 @@ TEST(CoreAPIsTest, TestLookupWithUnthreadedMaterialization) { << "lookup returned incorrect flags"; } -TEST(CoreAPIsTest, TestLookupWithThreadedMaterialization) { +TEST_F(CoreAPIsStandardTest, TestLookupWithThreadedMaterialization) { #if LLVM_ENABLE_THREADS - constexpr JITTargetAddress FakeFooAddr = 0xdeadbeef; - JITEvaluatedSymbol FooSym(FakeFooAddr, JITSymbolFlags::Exported); - - ExecutionSession ES(std::make_shared()); std::thread MaterializationThread; ES.setDispatchMaterialization( @@ -844,9 +712,7 @@ TEST(CoreAPIsTest, TestLookupWithThreadedMaterialization) { MaterializationThread = std::thread([SharedMU, &V]() { SharedMU->doMaterialize(V); }); }); - auto Foo = ES.getSymbolStringPool().intern("foo"); - auto &V = ES.createVSO("V"); cantFail(V.define(absoluteSymbols({{Foo, FooSym}}))); auto FooLookupResult = cantFail(lookup({&V}, Foo)); @@ -859,14 +725,11 @@ TEST(CoreAPIsTest, TestLookupWithThreadedMaterialization) { #endif } -TEST(CoreAPIsTest, TestGetRequestedSymbolsAndReplace) { - ExecutionSession ES; - auto Foo = ES.getSymbolStringPool().intern("foo"); - auto Bar = ES.getSymbolStringPool().intern("bar"); - - JITEvaluatedSymbol FooSym(0xdeadbeef, JITSymbolFlags::Exported); - JITEvaluatedSymbol BarSym(0xcafef00d, JITSymbolFlags::Exported); - +TEST_F(CoreAPIsStandardTest, TestGetRequestedSymbolsAndReplace) { + // Test that GetRequestedSymbols returns the set of symbols that currently + // have pending queries, and test that MaterializationResponsibility's + // replace method can be used to return definitions to the VSO in a new + // MaterializationUnit. SymbolNameSet Names({Foo, Bar}); bool FooMaterialized = false; @@ -895,8 +758,6 @@ TEST(CoreAPIsTest, TestGetRequestedSymbolsAndReplace) { FooMaterialized = true; }); - auto &V = ES.createVSO("V"); - cantFail(V.define(MU)); EXPECT_FALSE(FooMaterialized) << "Foo should not be materialized yet"; @@ -915,15 +776,7 @@ TEST(CoreAPIsTest, TestGetRequestedSymbolsAndReplace) { EXPECT_TRUE(BarMaterialized) << "Bar should be materialized now"; } -TEST(CoreAPIsTest, TestMaterializationResponsibilityDelegation) { - ExecutionSession ES; - - auto Foo = ES.getSymbolStringPool().intern("Foo"); - auto Bar = ES.getSymbolStringPool().intern("Bar"); - - JITEvaluatedSymbol FooSym(0xdeadbeef, JITSymbolFlags::Exported); - JITEvaluatedSymbol BarSym(0xcafef00d, JITSymbolFlags::Exported); - +TEST_F(CoreAPIsStandardTest, TestMaterializationResponsibilityDelegation) { auto MU = llvm::make_unique( SymbolFlagsMap({{Foo, FooSym.getFlags()}, {Bar, BarSym.getFlags()}}), [&](MaterializationResponsibility R) { @@ -935,7 +788,6 @@ TEST(CoreAPIsTest, TestMaterializationResponsibilityDelegation) { R2.finalize(); }); - auto &V = ES.createVSO("V"); cantFail(V.define(MU)); auto Result = lookup({&V}, {Foo, Bar}); @@ -949,23 +801,16 @@ TEST(CoreAPIsTest, TestMaterializationResponsibilityDelegation) { << "Address mismatch for \"Bar\""; } -TEST(CoreAPIsTest, TestMaterializeWeakSymbol) { +TEST_F(CoreAPIsStandardTest, TestMaterializeWeakSymbol) { // Confirm that once a weak definition is selected for materialization it is // treated as strong. - - constexpr JITTargetAddress FakeFooAddr = 0xdeadbeef; - JITSymbolFlags FooFlags = JITSymbolFlags::Exported; - FooFlags &= JITSymbolFlags::Weak; - auto FooSym = JITEvaluatedSymbol(FakeFooAddr, FooFlags); - - ExecutionSession ES; - auto Foo = ES.getSymbolStringPool().intern("foo"); - - auto &V = ES.createVSO("V"); + JITSymbolFlags WeakExported = JITSymbolFlags::Exported; + WeakExported &= JITSymbolFlags::Weak; std::unique_ptr FooResponsibility; auto MU = llvm::make_unique( - SymbolFlagsMap({{Foo, FooFlags}}), [&](MaterializationResponsibility R) { + SymbolFlagsMap({{Foo, FooSym.getFlags()}}), + [&](MaterializationResponsibility R) { FooResponsibility = llvm::make_unique(std::move(R)); });