diff options
| author | 2019-06-23 21:36:31 +0000 | |
|---|---|---|
| committer | 2019-06-23 21:36:31 +0000 | |
| commit | 23f101f37937a1bd4a29726cab2f76e0fb038b35 (patch) | |
| tree | f7da7d6b32c2e07114da399150bfa88d72187012 /gnu/llvm/unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp | |
| parent | sort previous; ok deraadt (diff) | |
| download | wireguard-openbsd-23f101f37937a1bd4a29726cab2f76e0fb038b35.tar.xz wireguard-openbsd-23f101f37937a1bd4a29726cab2f76e0fb038b35.zip | |
Import LLVM 8.0.0 release including clang, lld and lldb.
Diffstat (limited to 'gnu/llvm/unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp')
| -rw-r--r-- | gnu/llvm/unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp | 433 |
1 files changed, 292 insertions, 141 deletions
diff --git a/gnu/llvm/unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp b/gnu/llvm/unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp index baa1e3b5e8c..22be76a2eb6 100644 --- a/gnu/llvm/unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp +++ b/gnu/llvm/unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp @@ -22,43 +22,6 @@ class CoreAPIsStandardTest : public CoreAPIsBasedStandardTest {}; namespace { -class SimpleMaterializationUnit : public MaterializationUnit { -public: - using MaterializeFunction = - std::function<void(MaterializationResponsibility)>; - using DiscardFunction = std::function<void(const VSO &, 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 VSO &V, SymbolStringPtr Name) override { - if (Discard) - Discard(V, 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; @@ -79,13 +42,14 @@ TEST_F(CoreAPIsStandardTest, BasicSuccessfulLookup) { std::shared_ptr<MaterializationResponsibility> FooMR; - cantFail(V.define(llvm::make_unique<SimpleMaterializationUnit>( + cantFail(JD.define(llvm::make_unique<SimpleMaterializationUnit>( SymbolFlagsMap({{Foo, FooSym.getFlags()}}), [&](MaterializationResponsibility R) { FooMR = std::make_shared<MaterializationResponsibility>(std::move(R)); }))); - ES.lookup({&V}, {Foo}, OnResolution, OnReady, NoDependenciesToRegister); + ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo}, OnResolution, OnReady, + NoDependenciesToRegister); EXPECT_FALSE(OnResolutionRun) << "Should not have been resolved yet"; EXPECT_FALSE(OnReadyRun) << "Should not have been marked ready yet"; @@ -95,7 +59,7 @@ TEST_F(CoreAPIsStandardTest, BasicSuccessfulLookup) { EXPECT_TRUE(OnResolutionRun) << "Should have been resolved"; EXPECT_FALSE(OnReadyRun) << "Should not have been marked ready yet"; - FooMR->finalize(); + FooMR->emit(); EXPECT_TRUE(OnReadyRun) << "Should have been marked ready"; } @@ -138,16 +102,105 @@ TEST_F(CoreAPIsStandardTest, EmptyLookup) { OnReadyRun = true; }; - ES.lookup({&V}, {}, OnResolution, OnReady, NoDependenciesToRegister); + ES.lookup(JITDylibSearchList({{&JD, false}}), {}, OnResolution, OnReady, + NoDependenciesToRegister); EXPECT_TRUE(OnResolvedRun) << "OnResolved was not run for empty query"; EXPECT_TRUE(OnReadyRun) << "OnReady was not run for empty query"; } -TEST_F(CoreAPIsStandardTest, ChainedVSOLookup) { - cantFail(V.define(absoluteSymbols({{Foo, FooSym}}))); +TEST_F(CoreAPIsStandardTest, RemoveSymbolsTest) { + // Test that: + // (1) Missing symbols generate a SymbolsNotFound error. + // (2) Materializing symbols generate a SymbolCouldNotBeRemoved error. + // (3) Removal of unmaterialized symbols triggers discard on the + // materialization unit. + // (4) Removal of symbols destroys empty materialization units. + // (5) Removal of materialized symbols works. - auto &V2 = ES.createVSO("V2"); + // Foo will be fully materialized. + cantFail(JD.define(absoluteSymbols({{Foo, FooSym}}))); + + // Bar will be unmaterialized. + bool BarDiscarded = false; + bool BarMaterializerDestructed = false; + cantFail(JD.define(llvm::make_unique<SimpleMaterializationUnit>( + SymbolFlagsMap({{Bar, BarSym.getFlags()}}), + [this](MaterializationResponsibility R) { + ADD_FAILURE() << "Unexpected materialization of \"Bar\""; + R.resolve({{Bar, BarSym}}); + R.emit(); + }, + [&](const JITDylib &JD, const SymbolStringPtr &Name) { + EXPECT_EQ(Name, Bar) << "Expected \"Bar\" to be discarded"; + if (Name == Bar) + BarDiscarded = true; + }, + [&]() { BarMaterializerDestructed = true; }))); + + // Baz will be in the materializing state initially, then + // materialized for the final removal attempt. + Optional<MaterializationResponsibility> BazR; + cantFail(JD.define(llvm::make_unique<SimpleMaterializationUnit>( + SymbolFlagsMap({{Baz, BazSym.getFlags()}}), + [&](MaterializationResponsibility R) { BazR.emplace(std::move(R)); }, + [](const JITDylib &JD, const SymbolStringPtr &Name) { + ADD_FAILURE() << "\"Baz\" discarded unexpectedly"; + }))); + + bool OnResolvedRun = false; + bool OnReadyRun = false; + ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo, Baz}, + [&](Expected<SymbolMap> Result) { + EXPECT_TRUE(!!Result) << "OnResolved failed unexpectedly"; + consumeError(Result.takeError()); + OnResolvedRun = true; + }, + [&](Error Err) { + EXPECT_FALSE(!!Err) << "OnReady failed unexpectedly"; + consumeError(std::move(Err)); + OnReadyRun = true; + }, + NoDependenciesToRegister); + + { + // Attempt 1: Search for a missing symbol, Qux. + auto Err = JD.remove({Foo, Bar, Baz, Qux}); + EXPECT_TRUE(!!Err) << "Expected failure"; + EXPECT_TRUE(Err.isA<SymbolsNotFound>()) + << "Expected a SymbolsNotFound error"; + consumeError(std::move(Err)); + } + + { + // Attempt 2: Search for a symbol that is still materializing, Baz. + auto Err = JD.remove({Foo, Bar, Baz}); + EXPECT_TRUE(!!Err) << "Expected failure"; + EXPECT_TRUE(Err.isA<SymbolsCouldNotBeRemoved>()) + << "Expected a SymbolsNotFound error"; + consumeError(std::move(Err)); + } + + BazR->resolve({{Baz, BazSym}}); + BazR->emit(); + { + // Attempt 3: Search now that all symbols are fully materialized + // (Foo, Baz), or not yet materialized (Bar). + auto Err = JD.remove({Foo, Bar, Baz}); + EXPECT_FALSE(!!Err) << "Expected failure"; + } + + EXPECT_TRUE(BarDiscarded) << "\"Bar\" should have been discarded"; + EXPECT_TRUE(BarMaterializerDestructed) + << "\"Bar\"'s materializer should have been destructed"; + EXPECT_TRUE(OnResolvedRun) << "OnResolved should have been run"; + EXPECT_TRUE(OnReadyRun) << "OnReady should have been run"; +} + +TEST_F(CoreAPIsStandardTest, ChainedJITDylibLookup) { + cantFail(JD.define(absoluteSymbols({{Foo, FooSym}}))); + + auto &JD2 = ES.createJITDylib("JD2"); bool OnResolvedRun = false; bool OnReadyRun = false; @@ -163,12 +216,32 @@ TEST_F(CoreAPIsStandardTest, ChainedVSOLookup) { OnReadyRun = true; }); - V2.legacyLookup(Q, V.legacyLookup(Q, {Foo})); + JD2.legacyLookup(Q, JD.legacyLookup(Q, {Foo})); EXPECT_TRUE(OnResolvedRun) << "OnResolved was not run for empty query"; EXPECT_TRUE(OnReadyRun) << "OnReady was not run for empty query"; } +TEST_F(CoreAPIsStandardTest, LookupWithHiddenSymbols) { + auto BarHiddenFlags = BarSym.getFlags() & ~JITSymbolFlags::Exported; + auto BarHiddenSym = JITEvaluatedSymbol(BarSym.getAddress(), BarHiddenFlags); + + cantFail(JD.define(absoluteSymbols({{Foo, FooSym}, {Bar, BarHiddenSym}}))); + + auto &JD2 = ES.createJITDylib("JD2"); + cantFail(JD2.define(absoluteSymbols({{Bar, QuxSym}}))); + + /// Try a blocking lookup. + auto Result = cantFail( + ES.lookup(JITDylibSearchList({{&JD, false}, {&JD2, false}}), {Foo, Bar})); + + EXPECT_EQ(Result.size(), 2U) << "Unexpected number of results"; + EXPECT_EQ(Result.count(Foo), 1U) << "Missing result for \"Foo\""; + EXPECT_EQ(Result.count(Bar), 1U) << "Missing result for \"Bar\""; + EXPECT_EQ(Result[Bar].getAddress(), QuxSym.getAddress()) + << "Wrong result for \"Bar\""; +} + TEST_F(CoreAPIsStandardTest, LookupFlagsTest) { // Test that lookupFlags works on a predefined symbol, and does not trigger // materialization of a lazy symbol. Make the lazy symbol weak to test that @@ -182,12 +255,12 @@ TEST_F(CoreAPIsStandardTest, LookupFlagsTest) { llvm_unreachable("Symbol materialized on flags lookup"); }); - cantFail(V.define(absoluteSymbols({{Foo, FooSym}}))); - cantFail(V.define(std::move(MU))); + cantFail(JD.define(absoluteSymbols({{Foo, FooSym}}))); + cantFail(JD.define(std::move(MU))); SymbolNameSet Names({Foo, Bar, Baz}); - auto SymbolFlags = V.lookupFlags(Names); + auto SymbolFlags = JD.lookupFlags(Names); EXPECT_EQ(SymbolFlags.size(), 2U) << "Returned symbol flags contains unexpected results"; @@ -201,12 +274,12 @@ TEST_F(CoreAPIsStandardTest, LookupFlagsTest) { } TEST_F(CoreAPIsStandardTest, TestBasicAliases) { - cantFail(V.define(absoluteSymbols({{Foo, FooSym}, {Bar, BarSym}}))); - cantFail(V.define(symbolAliases({{Baz, {Foo, JITSymbolFlags::Exported}}, - {Qux, {Bar, JITSymbolFlags::Weak}}}))); - cantFail(V.define(absoluteSymbols({{Qux, QuxSym}}))); + cantFail(JD.define(absoluteSymbols({{Foo, FooSym}, {Bar, BarSym}}))); + cantFail(JD.define(symbolAliases({{Baz, {Foo, JITSymbolFlags::Exported}}, + {Qux, {Bar, JITSymbolFlags::Weak}}}))); + cantFail(JD.define(absoluteSymbols({{Qux, QuxSym}}))); - auto Result = lookup({&V}, {Baz, Qux}); + auto Result = ES.lookup(JITDylibSearchList({{&JD, false}}), {Baz, Qux}); EXPECT_TRUE(!!Result) << "Unexpected lookup failure"; EXPECT_EQ(Result->count(Baz), 1U) << "No result for \"baz\""; EXPECT_EQ(Result->count(Qux), 1U) << "No result for \"qux\""; @@ -217,11 +290,11 @@ TEST_F(CoreAPIsStandardTest, TestBasicAliases) { } TEST_F(CoreAPIsStandardTest, TestChainedAliases) { - cantFail(V.define(absoluteSymbols({{Foo, FooSym}}))); - cantFail(V.define(symbolAliases( + cantFail(JD.define(absoluteSymbols({{Foo, FooSym}}))); + cantFail(JD.define(symbolAliases( {{Baz, {Bar, BazSym.getFlags()}}, {Bar, {Foo, BarSym.getFlags()}}}))); - auto Result = lookup({&V}, {Bar, Baz}); + auto Result = ES.lookup(JITDylibSearchList({{&JD, false}}), {Bar, Baz}); EXPECT_TRUE(!!Result) << "Unexpected lookup failure"; EXPECT_EQ(Result->count(Bar), 1U) << "No result for \"bar\""; EXPECT_EQ(Result->count(Baz), 1U) << "No result for \"baz\""; @@ -233,14 +306,14 @@ TEST_F(CoreAPIsStandardTest, TestChainedAliases) { TEST_F(CoreAPIsStandardTest, TestBasicReExports) { // Test that the basic use case of re-exporting a single symbol from another - // VSO works. - cantFail(V.define(absoluteSymbols({{Foo, FooSym}}))); + // JITDylib works. + cantFail(JD.define(absoluteSymbols({{Foo, FooSym}}))); - auto &V2 = ES.createVSO("V2"); + auto &JD2 = ES.createJITDylib("JD2"); - cantFail(V2.define(reexports(V, {{Bar, {Foo, BarSym.getFlags()}}}))); + cantFail(JD2.define(reexports(JD, {{Bar, {Foo, BarSym.getFlags()}}}))); - auto Result = cantFail(lookup({&V2}, Bar)); + auto Result = cantFail(ES.lookup(JITDylibSearchList({{&JD2, false}}), Bar)); EXPECT_EQ(Result.getAddress(), FooSym.getAddress()) << "Re-export Bar for symbol Foo should match FooSym's address"; } @@ -248,7 +321,7 @@ TEST_F(CoreAPIsStandardTest, TestBasicReExports) { TEST_F(CoreAPIsStandardTest, TestThatReExportsDontUnnecessarilyMaterialize) { // Test that re-exports do not materialize symbols that have not been queried // for. - cantFail(V.define(absoluteSymbols({{Foo, FooSym}}))); + cantFail(JD.define(absoluteSymbols({{Foo, FooSym}}))); bool BarMaterialized = false; auto BarMU = llvm::make_unique<SimpleMaterializationUnit>( @@ -256,30 +329,50 @@ TEST_F(CoreAPIsStandardTest, TestThatReExportsDontUnnecessarilyMaterialize) { [&](MaterializationResponsibility R) { BarMaterialized = true; R.resolve({{Bar, BarSym}}); - R.finalize(); + R.emit(); }); - cantFail(V.define(BarMU)); + cantFail(JD.define(BarMU)); - auto &V2 = ES.createVSO("V2"); + auto &JD2 = ES.createJITDylib("JD2"); - cantFail(V2.define(reexports( - V, {{Baz, {Foo, BazSym.getFlags()}}, {Qux, {Bar, QuxSym.getFlags()}}}))); + cantFail(JD2.define(reexports( + JD, {{Baz, {Foo, BazSym.getFlags()}}, {Qux, {Bar, QuxSym.getFlags()}}}))); - auto Result = cantFail(lookup({&V2}, Baz)); + auto Result = cantFail(ES.lookup(JITDylibSearchList({{&JD2, false}}), Baz)); EXPECT_EQ(Result.getAddress(), FooSym.getAddress()) << "Re-export Baz for symbol Foo should match FooSym's address"; EXPECT_FALSE(BarMaterialized) << "Bar should not have been materialized"; } +TEST_F(CoreAPIsStandardTest, TestReexportsGenerator) { + // Test that a re-exports generator can dynamically generate reexports. + + auto &JD2 = ES.createJITDylib("JD2"); + cantFail(JD2.define(absoluteSymbols({{Foo, FooSym}, {Bar, BarSym}}))); + + auto Filter = [this](SymbolStringPtr Name) { return Name != Bar; }; + + JD.setGenerator(ReexportsGenerator(JD2, false, Filter)); + + auto Flags = JD.lookupFlags({Foo, Bar, Baz}); + EXPECT_EQ(Flags.size(), 1U) << "Unexpected number of results"; + EXPECT_EQ(Flags[Foo], FooSym.getFlags()) << "Unexpected flags for Foo"; + + auto Result = cantFail(ES.lookup(JITDylibSearchList({{&JD, false}}), Foo)); + + EXPECT_EQ(Result.getAddress(), FooSym.getAddress()) + << "Incorrect reexported symbol address"; +} + TEST_F(CoreAPIsStandardTest, TestTrivialCircularDependency) { Optional<MaterializationResponsibility> FooR; auto FooMU = llvm::make_unique<SimpleMaterializationUnit>( SymbolFlagsMap({{Foo, FooSym.getFlags()}}), [&](MaterializationResponsibility R) { FooR.emplace(std::move(R)); }); - cantFail(V.define(FooMU)); + cantFail(JD.define(FooMU)); bool FooReady = false; auto OnResolution = [](Expected<SymbolMap> R) { cantFail(std::move(R)); }; @@ -288,20 +381,20 @@ TEST_F(CoreAPIsStandardTest, TestTrivialCircularDependency) { FooReady = true; }; - ES.lookup({&V}, {Foo}, std::move(OnResolution), std::move(OnReady), - NoDependenciesToRegister); + ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo}, std::move(OnResolution), + std::move(OnReady), NoDependenciesToRegister); FooR->resolve({{Foo, FooSym}}); - FooR->finalize(); + FooR->emit(); EXPECT_TRUE(FooReady) << "Self-dependency prevented symbol from being marked ready"; } -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. +TEST_F(CoreAPIsStandardTest, TestCircularDependenceInOneJITDylib) { + // Test that a circular symbol dependency between three symbols in a JITDylib + // does not prevent any symbol from becoming 'ready' once all symbols are + // emitted. // Create three MaterializationResponsibility objects: one for each of Foo, // Bar and Baz. These are optional because MaterializationResponsibility @@ -325,9 +418,9 @@ TEST_F(CoreAPIsStandardTest, TestCircularDependenceInOneVSO) { [&](MaterializationResponsibility R) { BazR.emplace(std::move(R)); }); // Define the symbols. - cantFail(V.define(FooMU)); - cantFail(V.define(BarMU)); - cantFail(V.define(BazMU)); + cantFail(JD.define(FooMU)); + cantFail(JD.define(BarMU)); + cantFail(JD.define(BazMU)); // Query each of the symbols to trigger materialization. bool FooResolved = false; @@ -345,7 +438,8 @@ TEST_F(CoreAPIsStandardTest, TestCircularDependenceInOneVSO) { // Issue a lookup for Foo. Use NoDependenciesToRegister: We're going to add // the dependencies manually below. - ES.lookup({&V}, {Foo}, std::move(OnFooResolution), std::move(OnFooReady), + ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo}, + std::move(OnFooResolution), std::move(OnFooReady), NoDependenciesToRegister); bool BarResolved = false; @@ -360,7 +454,8 @@ TEST_F(CoreAPIsStandardTest, TestCircularDependenceInOneVSO) { BarReady = true; }; - ES.lookup({&V}, {Bar}, std::move(OnBarResolution), std::move(OnBarReady), + ES.lookup(JITDylibSearchList({{&JD, false}}), {Bar}, + std::move(OnBarResolution), std::move(OnBarReady), NoDependenciesToRegister); bool BazResolved = false; @@ -376,26 +471,27 @@ TEST_F(CoreAPIsStandardTest, TestCircularDependenceInOneVSO) { BazReady = true; }; - ES.lookup({&V}, {Baz}, std::move(OnBazResolution), std::move(OnBazReady), + ES.lookup(JITDylibSearchList({{&JD, false}}), {Baz}, + std::move(OnBazResolution), std::move(OnBazReady), NoDependenciesToRegister); // Add a circular dependency: Foo -> Bar, Bar -> Baz, Baz -> Foo. - FooR->addDependenciesForAll({{&V, SymbolNameSet({Bar})}}); - BarR->addDependenciesForAll({{&V, SymbolNameSet({Baz})}}); - BazR->addDependenciesForAll({{&V, SymbolNameSet({Foo})}}); + FooR->addDependenciesForAll({{&JD, SymbolNameSet({Bar})}}); + BarR->addDependenciesForAll({{&JD, SymbolNameSet({Baz})}}); + BazR->addDependenciesForAll({{&JD, SymbolNameSet({Foo})}}); // Add self-dependencies for good measure. This tests that the implementation // of addDependencies filters these out. - FooR->addDependenciesForAll({{&V, SymbolNameSet({Foo})}}); - BarR->addDependenciesForAll({{&V, SymbolNameSet({Bar})}}); - BazR->addDependenciesForAll({{&V, SymbolNameSet({Baz})}}); + FooR->addDependenciesForAll({{&JD, SymbolNameSet({Foo})}}); + BarR->addDependenciesForAll({{&JD, SymbolNameSet({Bar})}}); + BazR->addDependenciesForAll({{&JD, 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). + // Resolve the symbols (but do not emit them). FooR->resolve({{Foo, FooSym}}); BarR->resolve({{Bar, BarSym}}); BazR->resolve({{Baz, BazSym}}); @@ -409,17 +505,17 @@ TEST_F(CoreAPIsStandardTest, 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(); + // Emit two of the symbols. + FooR->emit(); + BarR->emit(); // 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(); + // Emit the last symbol. + BazR->emit(); // Verify that everything becomes ready once the circular dependence resolved. EXPECT_TRUE(FooReady) << "\"Foo\" should be ready now"; @@ -438,20 +534,20 @@ TEST_F(CoreAPIsStandardTest, DropMaterializerWhenEmpty) { [](MaterializationResponsibility R) { llvm_unreachable("Unexpected call to materialize"); }, - [&](const VSO &V, SymbolStringPtr Name) { + [&](const JITDylib &JD, SymbolStringPtr Name) { EXPECT_TRUE(Name == Foo || Name == Bar) << "Discard of unexpected symbol?"; }, [&]() { DestructorRun = true; }); - cantFail(V.define(MU)); + cantFail(JD.define(MU)); - cantFail(V.define(absoluteSymbols({{Foo, FooSym}}))); + cantFail(JD.define(absoluteSymbols({{Foo, FooSym}}))); EXPECT_FALSE(DestructorRun) << "MaterializationUnit should not have been destroyed yet"; - cantFail(V.define(absoluteSymbols({{Bar, BarSym}}))); + cantFail(JD.define(absoluteSymbols({{Bar, BarSym}}))); EXPECT_TRUE(DestructorRun) << "MaterializationUnit should have been destroyed"; @@ -469,16 +565,16 @@ TEST_F(CoreAPIsStandardTest, AddAndMaterializeLazySymbol) { [&](MaterializationResponsibility R) { assert(BarDiscarded && "Bar should have been discarded by this point"); R.resolve(SymbolMap({{Foo, FooSym}})); - R.finalize(); + R.emit(); FooMaterialized = true; }, - [&](const VSO &V, SymbolStringPtr Name) { + [&](const JITDylib &JD, SymbolStringPtr Name) { EXPECT_EQ(Name, Bar) << "Expected Name to be Bar"; BarDiscarded = true; }); - cantFail(V.define(MU)); - cantFail(V.define(absoluteSymbols({{Bar, BarSym}}))); + cantFail(JD.define(MU)); + cantFail(JD.define(absoluteSymbols({{Bar, BarSym}}))); SymbolNameSet Names({Foo}); @@ -499,8 +595,8 @@ TEST_F(CoreAPIsStandardTest, AddAndMaterializeLazySymbol) { OnReadyRun = true; }; - ES.lookup({&V}, Names, std::move(OnResolution), std::move(OnReady), - NoDependenciesToRegister); + ES.lookup(JITDylibSearchList({{&JD, false}}), Names, std::move(OnResolution), + std::move(OnReady), NoDependenciesToRegister); EXPECT_TRUE(FooMaterialized) << "Foo was not materialized"; EXPECT_TRUE(BarDiscarded) << "Bar was not discarded"; @@ -508,13 +604,63 @@ TEST_F(CoreAPIsStandardTest, AddAndMaterializeLazySymbol) { EXPECT_TRUE(OnReadyRun) << "OnReady was not run"; } +TEST_F(CoreAPIsStandardTest, TestBasicWeakSymbolMaterialization) { + // Test that weak symbols are materialized correctly when we look them up. + BarSym.setFlags(BarSym.getFlags() | JITSymbolFlags::Weak); + + bool BarMaterialized = false; + auto MU1 = llvm::make_unique<SimpleMaterializationUnit>( + SymbolFlagsMap({{Foo, FooSym.getFlags()}, {Bar, BarSym.getFlags()}}), + [&](MaterializationResponsibility R) { + R.resolve(SymbolMap({{Foo, FooSym}, {Bar, BarSym}})), R.emit(); + BarMaterialized = true; + }); + + bool DuplicateBarDiscarded = false; + auto MU2 = llvm::make_unique<SimpleMaterializationUnit>( + SymbolFlagsMap({{Bar, BarSym.getFlags()}}), + [&](MaterializationResponsibility R) { + ADD_FAILURE() << "Attempt to materialize Bar from the wrong unit"; + R.failMaterialization(); + }, + [&](const JITDylib &JD, SymbolStringPtr Name) { + EXPECT_EQ(Name, Bar) << "Expected \"Bar\" to be discarded"; + DuplicateBarDiscarded = true; + }); + + cantFail(JD.define(MU1)); + cantFail(JD.define(MU2)); + + bool OnResolvedRun = false; + bool OnReadyRun = false; + + auto OnResolution = [&](Expected<SymbolMap> Result) { + cantFail(std::move(Result)); + OnResolvedRun = true; + }; + + auto OnReady = [&](Error Err) { + cantFail(std::move(Err)); + OnReadyRun = true; + }; + + ES.lookup(JITDylibSearchList({{&JD, false}}), {Bar}, std::move(OnResolution), + std::move(OnReady), NoDependenciesToRegister); + + EXPECT_TRUE(OnResolvedRun) << "OnResolved not run"; + EXPECT_TRUE(OnReadyRun) << "OnReady not run"; + EXPECT_TRUE(BarMaterialized) << "Bar was not materialized at all"; + EXPECT_TRUE(DuplicateBarDiscarded) + << "Duplicate bar definition not discarded"; +} + TEST_F(CoreAPIsStandardTest, DefineMaterializingSymbol) { bool ExpectNoMoreMaterialization = false; ES.setDispatchMaterialization( - [&](VSO &V, std::unique_ptr<MaterializationUnit> MU) { + [&](JITDylib &JD, std::unique_ptr<MaterializationUnit> MU) { if (ExpectNoMoreMaterialization) ADD_FAILURE() << "Unexpected materialization"; - MU->doMaterialize(V); + MU->doMaterialize(JD); }); auto MU = llvm::make_unique<SimpleMaterializationUnit>( @@ -523,30 +669,31 @@ TEST_F(CoreAPIsStandardTest, DefineMaterializingSymbol) { cantFail( R.defineMaterializing(SymbolFlagsMap({{Bar, BarSym.getFlags()}}))); R.resolve(SymbolMap({{Foo, FooSym}, {Bar, BarSym}})); - R.finalize(); + R.emit(); }); - cantFail(V.define(MU)); - cantFail(lookup({&V}, Foo)); + cantFail(JD.define(MU)); + cantFail(ES.lookup(JITDylibSearchList({{&JD, false}}), Foo)); // Assert that materialization is complete by now. ExpectNoMoreMaterialization = true; // Look up bar to verify that no further materialization happens. - auto BarResult = cantFail(lookup({&V}, Bar)); + auto BarResult = cantFail(ES.lookup(JITDylibSearchList({{&JD, false}}), Bar)); EXPECT_EQ(BarResult.getAddress(), BarSym.getAddress()) << "Expected Bar == BarSym"; } -TEST_F(CoreAPIsStandardTest, FallbackDefinitionGeneratorTest) { - cantFail(V.define(absoluteSymbols({{Foo, FooSym}}))); +TEST_F(CoreAPIsStandardTest, GeneratorTest) { + cantFail(JD.define(absoluteSymbols({{Foo, FooSym}}))); - V.setFallbackDefinitionGenerator([&](VSO &W, const SymbolNameSet &Names) { - cantFail(W.define(absoluteSymbols({{Bar, BarSym}}))); + JD.setGenerator([&](JITDylib &JD2, const SymbolNameSet &Names) { + cantFail(JD2.define(absoluteSymbols({{Bar, BarSym}}))); return SymbolNameSet({Bar}); }); - auto Result = cantFail(lookup({&V}, {Foo, Bar})); + auto Result = + cantFail(ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo, Bar})); EXPECT_EQ(Result.count(Bar), 1U) << "Expected to find fallback def for 'bar'"; EXPECT_EQ(Result[Bar].getAddress(), BarSym.getAddress()) @@ -555,14 +702,14 @@ TEST_F(CoreAPIsStandardTest, FallbackDefinitionGeneratorTest) { TEST_F(CoreAPIsStandardTest, FailResolution) { auto MU = llvm::make_unique<SimpleMaterializationUnit>( - SymbolFlagsMap( - {{Foo, JITSymbolFlags::Weak}, {Bar, JITSymbolFlags::Weak}}), + SymbolFlagsMap({{Foo, JITSymbolFlags::Exported | JITSymbolFlags::Weak}, + {Bar, JITSymbolFlags::Exported | JITSymbolFlags::Weak}}), [&](MaterializationResponsibility R) { R.failMaterialization(); }); - cantFail(V.define(MU)); + cantFail(JD.define(MU)); SymbolNameSet Names({Foo, Bar}); - auto Result = lookup({&V}, Names); + auto Result = ES.lookup(JITDylibSearchList({{&JD, false}}), Names); EXPECT_FALSE(!!Result) << "Expected failure"; if (!Result) { @@ -589,12 +736,13 @@ TEST_F(CoreAPIsStandardTest, TestLookupWithUnthreadedMaterialization) { SymbolFlagsMap({{Foo, JITSymbolFlags::Exported}}), [&](MaterializationResponsibility R) { R.resolve({{Foo, FooSym}}); - R.finalize(); + R.emit(); }); - cantFail(V.define(MU)); + cantFail(JD.define(MU)); - auto FooLookupResult = cantFail(lookup({&V}, Foo)); + auto FooLookupResult = + cantFail(ES.lookup(JITDylibSearchList({{&JD, false}}), Foo)); EXPECT_EQ(FooLookupResult.getAddress(), FooSym.getAddress()) << "lookup returned an incorrect address"; @@ -607,15 +755,16 @@ TEST_F(CoreAPIsStandardTest, TestLookupWithThreadedMaterialization) { std::thread MaterializationThread; ES.setDispatchMaterialization( - [&](VSO &V, std::unique_ptr<MaterializationUnit> MU) { + [&](JITDylib &JD, std::unique_ptr<MaterializationUnit> MU) { auto SharedMU = std::shared_ptr<MaterializationUnit>(std::move(MU)); MaterializationThread = - std::thread([SharedMU, &V]() { SharedMU->doMaterialize(V); }); + std::thread([SharedMU, &JD]() { SharedMU->doMaterialize(JD); }); }); - cantFail(V.define(absoluteSymbols({{Foo, FooSym}}))); + cantFail(JD.define(absoluteSymbols({{Foo, FooSym}}))); - auto FooLookupResult = cantFail(lookup({&V}, Foo)); + auto FooLookupResult = + cantFail(ES.lookup(JITDylibSearchList({{&JD, false}}), Foo)); EXPECT_EQ(FooLookupResult.getAddress(), FooSym.getAddress()) << "lookup returned an incorrect address"; @@ -628,7 +777,7 @@ TEST_F(CoreAPIsStandardTest, TestLookupWithThreadedMaterialization) { 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 + // replace method can be used to return definitions to the JITDylib in a new // MaterializationUnit. SymbolNameSet Names({Foo, Bar}); @@ -646,31 +795,33 @@ TEST_F(CoreAPIsStandardTest, TestGetRequestedSymbolsAndReplace) { SymbolFlagsMap({{Bar, BarSym.getFlags()}}), [&](MaterializationResponsibility R2) { R2.resolve(SymbolMap({{Bar, BarSym}})); - R2.finalize(); + R2.emit(); BarMaterialized = true; }); R.replace(std::move(NewMU)); R.resolve(SymbolMap({{Foo, FooSym}})); - R.finalize(); + R.emit(); FooMaterialized = true; }); - cantFail(V.define(MU)); + cantFail(JD.define(MU)); EXPECT_FALSE(FooMaterialized) << "Foo should not be materialized yet"; EXPECT_FALSE(BarMaterialized) << "Bar should not be materialized yet"; - auto FooSymResult = cantFail(lookup({&V}, Foo)); + auto FooSymResult = + cantFail(ES.lookup(JITDylibSearchList({{&JD, false}}), Foo)); EXPECT_EQ(FooSymResult.getAddress(), FooSym.getAddress()) << "Address mismatch for Foo"; EXPECT_TRUE(FooMaterialized) << "Foo should be materialized now"; EXPECT_FALSE(BarMaterialized) << "Bar still should not be materialized"; - auto BarSymResult = cantFail(lookup({&V}, Bar)); + auto BarSymResult = + cantFail(ES.lookup(JITDylibSearchList({{&JD, false}}), Bar)); EXPECT_EQ(BarSymResult.getAddress(), BarSym.getAddress()) << "Address mismatch for Bar"; EXPECT_TRUE(BarMaterialized) << "Bar should be materialized now"; @@ -683,14 +834,14 @@ TEST_F(CoreAPIsStandardTest, TestMaterializationResponsibilityDelegation) { auto R2 = R.delegate({Bar}); R.resolve({{Foo, FooSym}}); - R.finalize(); + R.emit(); R2.resolve({{Bar, BarSym}}); - R2.finalize(); + R2.emit(); }); - cantFail(V.define(MU)); + cantFail(JD.define(MU)); - auto Result = lookup({&V}, {Foo, Bar}); + auto Result = ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo, Bar}); EXPECT_TRUE(!!Result) << "Result should be a success value"; EXPECT_EQ(Result->count(Foo), 1U) << "\"Foo\" entry missing"; @@ -715,15 +866,15 @@ TEST_F(CoreAPIsStandardTest, TestMaterializeWeakSymbol) { llvm::make_unique<MaterializationResponsibility>(std::move(R)); }); - cantFail(V.define(MU)); + cantFail(JD.define(MU)); auto OnResolution = [](Expected<SymbolMap> Result) { cantFail(std::move(Result)); }; auto OnReady = [](Error Err) { cantFail(std::move(Err)); }; - ES.lookup({&V}, {Foo}, std::move(OnResolution), std::move(OnReady), - NoDependenciesToRegister); + ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo}, std::move(OnResolution), + std::move(OnReady), NoDependenciesToRegister); auto MU2 = llvm::make_unique<SimpleMaterializationUnit>( SymbolFlagsMap({{Foo, JITSymbolFlags::Exported}}), @@ -731,14 +882,14 @@ TEST_F(CoreAPIsStandardTest, TestMaterializeWeakSymbol) { llvm_unreachable("This unit should never be materialized"); }); - auto Err = V.define(MU2); + auto Err = JD.define(MU2); EXPECT_TRUE(!!Err) << "Expected failure value"; EXPECT_TRUE(Err.isA<DuplicateDefinition>()) << "Expected a duplicate definition error"; consumeError(std::move(Err)); FooResponsibility->resolve(SymbolMap({{Foo, FooSym}})); - FooResponsibility->finalize(); + FooResponsibility->emit(); } } // namespace |
