Please use GitHub pull requests for new patches. Avoid migrating existing patches. Phabricator shutdown timeline
Changeset View
Changeset View
Standalone View
Standalone View
llvm/unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp
Show All 31 Lines | auto OnCompletion = [&](Expected<SymbolMap> Result) { | ||||
EXPECT_NE(I, Resolved.end()) << "Could not find symbol definition"; | EXPECT_NE(I, Resolved.end()) << "Could not find symbol definition"; | ||||
EXPECT_EQ(I->second.getAddress(), FooAddr) | EXPECT_EQ(I->second.getAddress(), FooAddr) | ||||
<< "Resolution returned incorrect result"; | << "Resolution returned incorrect result"; | ||||
OnCompletionRun = true; | OnCompletionRun = true; | ||||
}; | }; | ||||
std::shared_ptr<MaterializationResponsibility> FooMR; | std::shared_ptr<MaterializationResponsibility> FooMR; | ||||
cantFail(JD.define(std::make_unique<SimpleMaterializationUnit>( | llvm_cantFail(JD.define(std::make_unique<SimpleMaterializationUnit>( | ||||
SymbolFlagsMap({{Foo, FooSym.getFlags()}}), | SymbolFlagsMap({{Foo, FooSym.getFlags()}}), | ||||
[&](MaterializationResponsibility R) { | [&](MaterializationResponsibility R) { | ||||
FooMR = std::make_shared<MaterializationResponsibility>(std::move(R)); | FooMR = std::make_shared<MaterializationResponsibility>(std::move(R)); | ||||
}))); | }))); | ||||
ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo}, SymbolState::Ready, | ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo}, SymbolState::Ready, | ||||
OnCompletion, NoDependenciesToRegister); | OnCompletion, NoDependenciesToRegister); | ||||
EXPECT_FALSE(OnCompletionRun) << "Should not have been resolved yet"; | EXPECT_FALSE(OnCompletionRun) << "Should not have been resolved yet"; | ||||
cantFail(FooMR->notifyResolved({{Foo, FooSym}})); | llvm_cantFail(FooMR->notifyResolved({{Foo, FooSym}})); | ||||
EXPECT_FALSE(OnCompletionRun) << "Should not be ready yet"; | EXPECT_FALSE(OnCompletionRun) << "Should not be ready yet"; | ||||
cantFail(FooMR->notifyEmitted()); | llvm_cantFail(FooMR->notifyEmitted()); | ||||
EXPECT_TRUE(OnCompletionRun) << "Should have been marked ready"; | EXPECT_TRUE(OnCompletionRun) << "Should have been marked ready"; | ||||
} | } | ||||
TEST_F(CoreAPIsStandardTest, ExecutionSessionFailQuery) { | TEST_F(CoreAPIsStandardTest, ExecutionSessionFailQuery) { | ||||
bool OnCompletionRun = false; | bool OnCompletionRun = false; | ||||
auto OnCompletion = [&](Expected<SymbolMap> Result) { | auto OnCompletion = [&](Expected<SymbolMap> Result) { | ||||
Show All 11 Lines | TEST_F(CoreAPIsStandardTest, ExecutionSessionFailQuery) { | ||||
EXPECT_TRUE(OnCompletionRun) << "OnCompletionCallback was not run"; | EXPECT_TRUE(OnCompletionRun) << "OnCompletionCallback was not run"; | ||||
} | } | ||||
TEST_F(CoreAPIsStandardTest, EmptyLookup) { | TEST_F(CoreAPIsStandardTest, EmptyLookup) { | ||||
bool OnCompletionRun = false; | bool OnCompletionRun = false; | ||||
auto OnCompletion = [&](Expected<SymbolMap> Result) { | auto OnCompletion = [&](Expected<SymbolMap> Result) { | ||||
cantFail(std::move(Result)); | llvm_cantFail(std::move(Result)); | ||||
OnCompletionRun = true; | OnCompletionRun = true; | ||||
}; | }; | ||||
ES.lookup(JITDylibSearchList({{&JD, false}}), {}, SymbolState::Ready, | ES.lookup(JITDylibSearchList({{&JD, false}}), {}, SymbolState::Ready, | ||||
OnCompletion, NoDependenciesToRegister); | OnCompletion, NoDependenciesToRegister); | ||||
EXPECT_TRUE(OnCompletionRun) << "OnCompletion was not run for empty query"; | EXPECT_TRUE(OnCompletionRun) << "OnCompletion was not run for empty query"; | ||||
} | } | ||||
TEST_F(CoreAPIsStandardTest, RemoveSymbolsTest) { | TEST_F(CoreAPIsStandardTest, RemoveSymbolsTest) { | ||||
// Test that: | // Test that: | ||||
// (1) Missing symbols generate a SymbolsNotFound error. | // (1) Missing symbols generate a SymbolsNotFound error. | ||||
// (2) Materializing symbols generate a SymbolCouldNotBeRemoved error. | // (2) Materializing symbols generate a SymbolCouldNotBeRemoved error. | ||||
// (3) Removal of unmaterialized symbols triggers discard on the | // (3) Removal of unmaterialized symbols triggers discard on the | ||||
// materialization unit. | // materialization unit. | ||||
// (4) Removal of symbols destroys empty materialization units. | // (4) Removal of symbols destroys empty materialization units. | ||||
// (5) Removal of materialized symbols works. | // (5) Removal of materialized symbols works. | ||||
// Foo will be fully materialized. | // Foo will be fully materialized. | ||||
cantFail(JD.define(absoluteSymbols({{Foo, FooSym}}))); | llvm_cantFail(JD.define(absoluteSymbols({{Foo, FooSym}}))); | ||||
// Bar will be unmaterialized. | // Bar will be unmaterialized. | ||||
bool BarDiscarded = false; | bool BarDiscarded = false; | ||||
bool BarMaterializerDestructed = false; | bool BarMaterializerDestructed = false; | ||||
cantFail(JD.define(std::make_unique<SimpleMaterializationUnit>( | llvm_cantFail(JD.define(std::make_unique<SimpleMaterializationUnit>( | ||||
SymbolFlagsMap({{Bar, BarSym.getFlags()}}), | SymbolFlagsMap({{Bar, BarSym.getFlags()}}), | ||||
[this](MaterializationResponsibility R) { | [this](MaterializationResponsibility R) { | ||||
ADD_FAILURE() << "Unexpected materialization of \"Bar\""; | ADD_FAILURE() << "Unexpected materialization of \"Bar\""; | ||||
cantFail(R.notifyResolved({{Bar, BarSym}})); | llvm_cantFail(R.notifyResolved({{Bar, BarSym}})); | ||||
cantFail(R.notifyEmitted()); | llvm_cantFail(R.notifyEmitted()); | ||||
}, | }, | ||||
[&](const JITDylib &JD, const SymbolStringPtr &Name) { | [&](const JITDylib &JD, const SymbolStringPtr &Name) { | ||||
EXPECT_EQ(Name, Bar) << "Expected \"Bar\" to be discarded"; | EXPECT_EQ(Name, Bar) << "Expected \"Bar\" to be discarded"; | ||||
if (Name == Bar) | if (Name == Bar) | ||||
BarDiscarded = true; | BarDiscarded = true; | ||||
}, | }, | ||||
[&]() { BarMaterializerDestructed = true; }))); | [&]() { BarMaterializerDestructed = true; }))); | ||||
// Baz will be in the materializing state initially, then | // Baz will be in the materializing state initially, then | ||||
// materialized for the final removal attempt. | // materialized for the final removal attempt. | ||||
Optional<MaterializationResponsibility> BazR; | Optional<MaterializationResponsibility> BazR; | ||||
cantFail(JD.define(std::make_unique<SimpleMaterializationUnit>( | llvm_cantFail(JD.define(std::make_unique<SimpleMaterializationUnit>( | ||||
SymbolFlagsMap({{Baz, BazSym.getFlags()}}), | SymbolFlagsMap({{Baz, BazSym.getFlags()}}), | ||||
[&](MaterializationResponsibility R) { BazR.emplace(std::move(R)); }, | [&](MaterializationResponsibility R) { BazR.emplace(std::move(R)); }, | ||||
[](const JITDylib &JD, const SymbolStringPtr &Name) { | [](const JITDylib &JD, const SymbolStringPtr &Name) { | ||||
ADD_FAILURE() << "\"Baz\" discarded unexpectedly"; | ADD_FAILURE() << "\"Baz\" discarded unexpectedly"; | ||||
}))); | }))); | ||||
bool OnCompletionRun = false; | bool OnCompletionRun = false; | ||||
ES.lookup( | ES.lookup( | ||||
JITDylibSearchList({{&JD, false}}), {Foo, Baz}, SymbolState::Ready, | JITDylibSearchList({{&JD, false}}), {Foo, Baz}, SymbolState::Ready, | ||||
[&](Expected<SymbolMap> Result) { | [&](Expected<SymbolMap> Result) { | ||||
cantFail(Result.takeError()); | llvm_cantFail(Result.takeError()); | ||||
OnCompletionRun = true; | OnCompletionRun = true; | ||||
}, | }, | ||||
NoDependenciesToRegister); | NoDependenciesToRegister); | ||||
{ | { | ||||
// Attempt 1: Search for a missing symbol, Qux. | // Attempt 1: Search for a missing symbol, Qux. | ||||
auto Err = JD.remove({Foo, Bar, Baz, Qux}); | auto Err = JD.remove({Foo, Bar, Baz, Qux}); | ||||
EXPECT_TRUE(!!Err) << "Expected failure"; | EXPECT_TRUE(!!Err) << "Expected failure"; | ||||
EXPECT_TRUE(Err.isA<SymbolsNotFound>()) | EXPECT_TRUE(Err.isA<SymbolsNotFound>()) | ||||
<< "Expected a SymbolsNotFound error"; | << "Expected a SymbolsNotFound error"; | ||||
consumeError(std::move(Err)); | consumeError(std::move(Err)); | ||||
} | } | ||||
{ | { | ||||
// Attempt 2: Search for a symbol that is still materializing, Baz. | // Attempt 2: Search for a symbol that is still materializing, Baz. | ||||
auto Err = JD.remove({Foo, Bar, Baz}); | auto Err = JD.remove({Foo, Bar, Baz}); | ||||
EXPECT_TRUE(!!Err) << "Expected failure"; | EXPECT_TRUE(!!Err) << "Expected failure"; | ||||
EXPECT_TRUE(Err.isA<SymbolsCouldNotBeRemoved>()) | EXPECT_TRUE(Err.isA<SymbolsCouldNotBeRemoved>()) | ||||
<< "Expected a SymbolsNotFound error"; | << "Expected a SymbolsNotFound error"; | ||||
consumeError(std::move(Err)); | consumeError(std::move(Err)); | ||||
} | } | ||||
cantFail(BazR->notifyResolved({{Baz, BazSym}})); | llvm_cantFail(BazR->notifyResolved({{Baz, BazSym}})); | ||||
cantFail(BazR->notifyEmitted()); | llvm_cantFail(BazR->notifyEmitted()); | ||||
{ | { | ||||
// Attempt 3: Search now that all symbols are fully materialized | // Attempt 3: Search now that all symbols are fully materialized | ||||
// (Foo, Baz), or not yet materialized (Bar). | // (Foo, Baz), or not yet materialized (Bar). | ||||
auto Err = JD.remove({Foo, Bar, Baz}); | auto Err = JD.remove({Foo, Bar, Baz}); | ||||
EXPECT_FALSE(!!Err) << "Expected failure"; | EXPECT_FALSE(!!Err) << "Expected failure"; | ||||
} | } | ||||
EXPECT_TRUE(BarDiscarded) << "\"Bar\" should have been discarded"; | EXPECT_TRUE(BarDiscarded) << "\"Bar\" should have been discarded"; | ||||
EXPECT_TRUE(BarMaterializerDestructed) | EXPECT_TRUE(BarMaterializerDestructed) | ||||
<< "\"Bar\"'s materializer should have been destructed"; | << "\"Bar\"'s materializer should have been destructed"; | ||||
EXPECT_TRUE(OnCompletionRun) << "OnCompletion should have been run"; | EXPECT_TRUE(OnCompletionRun) << "OnCompletion should have been run"; | ||||
} | } | ||||
TEST_F(CoreAPIsStandardTest, ChainedJITDylibLookup) { | TEST_F(CoreAPIsStandardTest, ChainedJITDylibLookup) { | ||||
cantFail(JD.define(absoluteSymbols({{Foo, FooSym}}))); | llvm_cantFail(JD.define(absoluteSymbols({{Foo, FooSym}}))); | ||||
auto &JD2 = ES.createJITDylib("JD2"); | auto &JD2 = ES.createJITDylib("JD2"); | ||||
bool OnCompletionRun = false; | bool OnCompletionRun = false; | ||||
auto Q = std::make_shared<AsynchronousSymbolQuery>( | auto Q = std::make_shared<AsynchronousSymbolQuery>( | ||||
SymbolNameSet({Foo}), SymbolState::Ready, | SymbolNameSet({Foo}), SymbolState::Ready, | ||||
[&](Expected<SymbolMap> Result) { | [&](Expected<SymbolMap> Result) { | ||||
cantFail(std::move(Result)); | llvm_cantFail(std::move(Result)); | ||||
OnCompletionRun = true; | OnCompletionRun = true; | ||||
}); | }); | ||||
cantFail(JD2.legacyLookup(Q, cantFail(JD.legacyLookup(Q, {Foo})))); | llvm_cantFail(JD2.legacyLookup(Q, cantFail(JD.legacyLookup(Q, {Foo})))); | ||||
EXPECT_TRUE(OnCompletionRun) << "OnCompletion was not run for empty query"; | EXPECT_TRUE(OnCompletionRun) << "OnCompletion was not run for empty query"; | ||||
} | } | ||||
TEST_F(CoreAPIsStandardTest, LookupWithHiddenSymbols) { | TEST_F(CoreAPIsStandardTest, LookupWithHiddenSymbols) { | ||||
auto BarHiddenFlags = BarSym.getFlags() & ~JITSymbolFlags::Exported; | auto BarHiddenFlags = BarSym.getFlags() & ~JITSymbolFlags::Exported; | ||||
auto BarHiddenSym = JITEvaluatedSymbol(BarSym.getAddress(), BarHiddenFlags); | auto BarHiddenSym = JITEvaluatedSymbol(BarSym.getAddress(), BarHiddenFlags); | ||||
cantFail(JD.define(absoluteSymbols({{Foo, FooSym}, {Bar, BarHiddenSym}}))); | llvm_cantFail(JD.define(absoluteSymbols({{Foo, FooSym}, {Bar, BarHiddenSym}}))); | ||||
auto &JD2 = ES.createJITDylib("JD2"); | auto &JD2 = ES.createJITDylib("JD2"); | ||||
cantFail(JD2.define(absoluteSymbols({{Bar, QuxSym}}))); | llvm_cantFail(JD2.define(absoluteSymbols({{Bar, QuxSym}}))); | ||||
/// Try a blocking lookup. | /// Try a blocking lookup. | ||||
auto Result = cantFail( | auto Result = llvm_cantFail( | ||||
ES.lookup(JITDylibSearchList({{&JD, false}, {&JD2, false}}), {Foo, Bar})); | ES.lookup(JITDylibSearchList({{&JD, false}, {&JD2, false}}), {Foo, Bar})); | ||||
EXPECT_EQ(Result.size(), 2U) << "Unexpected number of results"; | EXPECT_EQ(Result.size(), 2U) << "Unexpected number of results"; | ||||
EXPECT_EQ(Result.count(Foo), 1U) << "Missing result for \"Foo\""; | EXPECT_EQ(Result.count(Foo), 1U) << "Missing result for \"Foo\""; | ||||
EXPECT_EQ(Result.count(Bar), 1U) << "Missing result for \"Bar\""; | EXPECT_EQ(Result.count(Bar), 1U) << "Missing result for \"Bar\""; | ||||
EXPECT_EQ(Result[Bar].getAddress(), QuxSym.getAddress()) | EXPECT_EQ(Result[Bar].getAddress(), QuxSym.getAddress()) | ||||
<< "Wrong result for \"Bar\""; | << "Wrong result for \"Bar\""; | ||||
} | } | ||||
TEST_F(CoreAPIsStandardTest, LookupFlagsTest) { | TEST_F(CoreAPIsStandardTest, LookupFlagsTest) { | ||||
// Test that lookupFlags works on a predefined symbol, and does not trigger | // 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 | // materialization of a lazy symbol. Make the lazy symbol weak to test that | ||||
// the weak flag is propagated correctly. | // the weak flag is propagated correctly. | ||||
BarSym.setFlags(static_cast<JITSymbolFlags::FlagNames>( | BarSym.setFlags(static_cast<JITSymbolFlags::FlagNames>( | ||||
JITSymbolFlags::Exported | JITSymbolFlags::Weak)); | JITSymbolFlags::Exported | JITSymbolFlags::Weak)); | ||||
auto MU = std::make_unique<SimpleMaterializationUnit>( | auto MU = std::make_unique<SimpleMaterializationUnit>( | ||||
SymbolFlagsMap({{Bar, BarSym.getFlags()}}), | SymbolFlagsMap({{Bar, BarSym.getFlags()}}), | ||||
[](MaterializationResponsibility R) { | [](MaterializationResponsibility R) { | ||||
llvm_unreachable("Symbol materialized on flags lookup"); | llvm_unreachable("Symbol materialized on flags lookup"); | ||||
}); | }); | ||||
cantFail(JD.define(absoluteSymbols({{Foo, FooSym}}))); | llvm_cantFail(JD.define(absoluteSymbols({{Foo, FooSym}}))); | ||||
cantFail(JD.define(std::move(MU))); | llvm_cantFail(JD.define(std::move(MU))); | ||||
SymbolNameSet Names({Foo, Bar, Baz}); | SymbolNameSet Names({Foo, Bar, Baz}); | ||||
auto SymbolFlags = cantFail(JD.lookupFlags(Names)); | auto SymbolFlags = llvm_cantFail(JD.lookupFlags(Names)); | ||||
EXPECT_EQ(SymbolFlags.size(), 2U) | EXPECT_EQ(SymbolFlags.size(), 2U) | ||||
<< "Returned symbol flags contains unexpected results"; | << "Returned symbol flags contains unexpected results"; | ||||
EXPECT_EQ(SymbolFlags.count(Foo), 1U) << "Missing lookupFlags result for Foo"; | EXPECT_EQ(SymbolFlags.count(Foo), 1U) << "Missing lookupFlags result for Foo"; | ||||
EXPECT_EQ(SymbolFlags[Foo], FooSym.getFlags()) | EXPECT_EQ(SymbolFlags[Foo], FooSym.getFlags()) | ||||
<< "Incorrect flags returned for Foo"; | << "Incorrect flags returned for Foo"; | ||||
EXPECT_EQ(SymbolFlags.count(Bar), 1U) | EXPECT_EQ(SymbolFlags.count(Bar), 1U) | ||||
<< "Missing lookupFlags result for Bar"; | << "Missing lookupFlags result for Bar"; | ||||
Show All 19 Lines | TEST_F(CoreAPIsStandardTest, LookupWithGeneratorFailure) { | ||||
EXPECT_THAT_ERROR( | EXPECT_THAT_ERROR( | ||||
ES.lookup(JITDylibSearchList({{&JD, false}}), SymbolNameSet({Foo})) | ES.lookup(JITDylibSearchList({{&JD, false}}), SymbolNameSet({Foo})) | ||||
.takeError(), | .takeError(), | ||||
Failed<StringError>()) | Failed<StringError>()) | ||||
<< "Generator failure did not propagate through lookup"; | << "Generator failure did not propagate through lookup"; | ||||
} | } | ||||
TEST_F(CoreAPIsStandardTest, TestBasicAliases) { | TEST_F(CoreAPIsStandardTest, TestBasicAliases) { | ||||
cantFail(JD.define(absoluteSymbols({{Foo, FooSym}, {Bar, BarSym}}))); | llvm_cantFail(JD.define(absoluteSymbols({{Foo, FooSym}, {Bar, BarSym}}))); | ||||
cantFail(JD.define(symbolAliases({{Baz, {Foo, JITSymbolFlags::Exported}}, | llvm_cantFail(JD.define(symbolAliases({{Baz, {Foo, JITSymbolFlags::Exported}}, | ||||
{Qux, {Bar, JITSymbolFlags::Weak}}}))); | {Qux, {Bar, JITSymbolFlags::Weak}}}))); | ||||
cantFail(JD.define(absoluteSymbols({{Qux, QuxSym}}))); | llvm_cantFail(JD.define(absoluteSymbols({{Qux, QuxSym}}))); | ||||
auto Result = ES.lookup(JITDylibSearchList({{&JD, false}}), {Baz, Qux}); | auto Result = ES.lookup(JITDylibSearchList({{&JD, false}}), {Baz, Qux}); | ||||
EXPECT_TRUE(!!Result) << "Unexpected lookup failure"; | EXPECT_TRUE(!!Result) << "Unexpected lookup failure"; | ||||
EXPECT_EQ(Result->count(Baz), 1U) << "No result for \"baz\""; | EXPECT_EQ(Result->count(Baz), 1U) << "No result for \"baz\""; | ||||
EXPECT_EQ(Result->count(Qux), 1U) << "No result for \"qux\""; | EXPECT_EQ(Result->count(Qux), 1U) << "No result for \"qux\""; | ||||
EXPECT_EQ((*Result)[Baz].getAddress(), FooSym.getAddress()) | EXPECT_EQ((*Result)[Baz].getAddress(), FooSym.getAddress()) | ||||
<< "\"Baz\"'s address should match \"Foo\"'s"; | << "\"Baz\"'s address should match \"Foo\"'s"; | ||||
EXPECT_EQ((*Result)[Qux].getAddress(), QuxSym.getAddress()) | EXPECT_EQ((*Result)[Qux].getAddress(), QuxSym.getAddress()) | ||||
<< "The \"Qux\" alias should have been overriden"; | << "The \"Qux\" alias should have been overriden"; | ||||
} | } | ||||
TEST_F(CoreAPIsStandardTest, TestChainedAliases) { | TEST_F(CoreAPIsStandardTest, TestChainedAliases) { | ||||
cantFail(JD.define(absoluteSymbols({{Foo, FooSym}}))); | llvm_cantFail(JD.define(absoluteSymbols({{Foo, FooSym}}))); | ||||
cantFail(JD.define(symbolAliases( | llvm_cantFail(JD.define(symbolAliases( | ||||
{{Baz, {Bar, BazSym.getFlags()}}, {Bar, {Foo, BarSym.getFlags()}}}))); | {{Baz, {Bar, BazSym.getFlags()}}, {Bar, {Foo, BarSym.getFlags()}}}))); | ||||
auto Result = ES.lookup(JITDylibSearchList({{&JD, false}}), {Bar, Baz}); | auto Result = ES.lookup(JITDylibSearchList({{&JD, false}}), {Bar, Baz}); | ||||
EXPECT_TRUE(!!Result) << "Unexpected lookup failure"; | EXPECT_TRUE(!!Result) << "Unexpected lookup failure"; | ||||
EXPECT_EQ(Result->count(Bar), 1U) << "No result for \"bar\""; | EXPECT_EQ(Result->count(Bar), 1U) << "No result for \"bar\""; | ||||
EXPECT_EQ(Result->count(Baz), 1U) << "No result for \"baz\""; | EXPECT_EQ(Result->count(Baz), 1U) << "No result for \"baz\""; | ||||
EXPECT_EQ((*Result)[Bar].getAddress(), FooSym.getAddress()) | EXPECT_EQ((*Result)[Bar].getAddress(), FooSym.getAddress()) | ||||
<< "\"Bar\"'s address should match \"Foo\"'s"; | << "\"Bar\"'s address should match \"Foo\"'s"; | ||||
EXPECT_EQ((*Result)[Baz].getAddress(), FooSym.getAddress()) | EXPECT_EQ((*Result)[Baz].getAddress(), FooSym.getAddress()) | ||||
<< "\"Baz\"'s address should match \"Foo\"'s"; | << "\"Baz\"'s address should match \"Foo\"'s"; | ||||
} | } | ||||
TEST_F(CoreAPIsStandardTest, TestBasicReExports) { | TEST_F(CoreAPIsStandardTest, TestBasicReExports) { | ||||
// Test that the basic use case of re-exporting a single symbol from another | // Test that the basic use case of re-exporting a single symbol from another | ||||
// JITDylib works. | // JITDylib works. | ||||
cantFail(JD.define(absoluteSymbols({{Foo, FooSym}}))); | llvm_cantFail(JD.define(absoluteSymbols({{Foo, FooSym}}))); | ||||
auto &JD2 = ES.createJITDylib("JD2"); | auto &JD2 = ES.createJITDylib("JD2"); | ||||
cantFail(JD2.define(reexports(JD, {{Bar, {Foo, BarSym.getFlags()}}}))); | llvm_cantFail(JD2.define(reexports(JD, {{Bar, {Foo, BarSym.getFlags()}}}))); | ||||
auto Result = cantFail(ES.lookup(JITDylibSearchList({{&JD2, false}}), Bar)); | auto Result = llvm_cantFail(ES.lookup(JITDylibSearchList({{&JD2, false}}), Bar)); | ||||
EXPECT_EQ(Result.getAddress(), FooSym.getAddress()) | EXPECT_EQ(Result.getAddress(), FooSym.getAddress()) | ||||
<< "Re-export Bar for symbol Foo should match FooSym's address"; | << "Re-export Bar for symbol Foo should match FooSym's address"; | ||||
} | } | ||||
TEST_F(CoreAPIsStandardTest, TestThatReExportsDontUnnecessarilyMaterialize) { | TEST_F(CoreAPIsStandardTest, TestThatReExportsDontUnnecessarilyMaterialize) { | ||||
// Test that re-exports do not materialize symbols that have not been queried | // Test that re-exports do not materialize symbols that have not been queried | ||||
// for. | // for. | ||||
cantFail(JD.define(absoluteSymbols({{Foo, FooSym}}))); | llvm_cantFail(JD.define(absoluteSymbols({{Foo, FooSym}}))); | ||||
bool BarMaterialized = false; | bool BarMaterialized = false; | ||||
auto BarMU = std::make_unique<SimpleMaterializationUnit>( | auto BarMU = std::make_unique<SimpleMaterializationUnit>( | ||||
SymbolFlagsMap({{Bar, BarSym.getFlags()}}), | SymbolFlagsMap({{Bar, BarSym.getFlags()}}), | ||||
[&](MaterializationResponsibility R) { | [&](MaterializationResponsibility R) { | ||||
BarMaterialized = true; | BarMaterialized = true; | ||||
cantFail(R.notifyResolved({{Bar, BarSym}})); | llvm_cantFail(R.notifyResolved({{Bar, BarSym}})); | ||||
cantFail(R.notifyEmitted()); | llvm_cantFail(R.notifyEmitted()); | ||||
}); | }); | ||||
cantFail(JD.define(BarMU)); | llvm_cantFail(JD.define(BarMU)); | ||||
auto &JD2 = ES.createJITDylib("JD2"); | auto &JD2 = ES.createJITDylib("JD2"); | ||||
cantFail(JD2.define(reexports( | llvm_cantFail(JD2.define(reexports( | ||||
JD, {{Baz, {Foo, BazSym.getFlags()}}, {Qux, {Bar, QuxSym.getFlags()}}}))); | JD, {{Baz, {Foo, BazSym.getFlags()}}, {Qux, {Bar, QuxSym.getFlags()}}}))); | ||||
auto Result = cantFail(ES.lookup(JITDylibSearchList({{&JD2, false}}), Baz)); | auto Result = llvm_cantFail(ES.lookup(JITDylibSearchList({{&JD2, false}}), Baz)); | ||||
EXPECT_EQ(Result.getAddress(), FooSym.getAddress()) | EXPECT_EQ(Result.getAddress(), FooSym.getAddress()) | ||||
<< "Re-export Baz for symbol Foo should match FooSym's address"; | << "Re-export Baz for symbol Foo should match FooSym's address"; | ||||
EXPECT_FALSE(BarMaterialized) << "Bar should not have been materialized"; | EXPECT_FALSE(BarMaterialized) << "Bar should not have been materialized"; | ||||
} | } | ||||
TEST_F(CoreAPIsStandardTest, TestReexportsGenerator) { | TEST_F(CoreAPIsStandardTest, TestReexportsGenerator) { | ||||
// Test that a re-exports generator can dynamically generate reexports. | // Test that a re-exports generator can dynamically generate reexports. | ||||
auto &JD2 = ES.createJITDylib("JD2"); | auto &JD2 = ES.createJITDylib("JD2"); | ||||
cantFail(JD2.define(absoluteSymbols({{Foo, FooSym}, {Bar, BarSym}}))); | llvm_cantFail(JD2.define(absoluteSymbols({{Foo, FooSym}, {Bar, BarSym}}))); | ||||
auto Filter = [this](SymbolStringPtr Name) { return Name != Bar; }; | auto Filter = [this](SymbolStringPtr Name) { return Name != Bar; }; | ||||
JD.addGenerator(std::make_unique<ReexportsGenerator>(JD2, false, Filter)); | JD.addGenerator(std::make_unique<ReexportsGenerator>(JD2, false, Filter)); | ||||
auto Flags = cantFail(JD.lookupFlags({Foo, Bar, Baz})); | auto Flags = llvm_cantFail(JD.lookupFlags({Foo, Bar, Baz})); | ||||
EXPECT_EQ(Flags.size(), 1U) << "Unexpected number of results"; | EXPECT_EQ(Flags.size(), 1U) << "Unexpected number of results"; | ||||
EXPECT_EQ(Flags[Foo], FooSym.getFlags()) << "Unexpected flags for Foo"; | EXPECT_EQ(Flags[Foo], FooSym.getFlags()) << "Unexpected flags for Foo"; | ||||
auto Result = cantFail(ES.lookup(JITDylibSearchList({{&JD, false}}), Foo)); | auto Result = llvm_cantFail(ES.lookup(JITDylibSearchList({{&JD, false}}), Foo)); | ||||
EXPECT_EQ(Result.getAddress(), FooSym.getAddress()) | EXPECT_EQ(Result.getAddress(), FooSym.getAddress()) | ||||
<< "Incorrect reexported symbol address"; | << "Incorrect reexported symbol address"; | ||||
} | } | ||||
TEST_F(CoreAPIsStandardTest, TestTrivialCircularDependency) { | TEST_F(CoreAPIsStandardTest, TestTrivialCircularDependency) { | ||||
Optional<MaterializationResponsibility> FooR; | Optional<MaterializationResponsibility> FooR; | ||||
auto FooMU = std::make_unique<SimpleMaterializationUnit>( | auto FooMU = std::make_unique<SimpleMaterializationUnit>( | ||||
SymbolFlagsMap({{Foo, FooSym.getFlags()}}), | SymbolFlagsMap({{Foo, FooSym.getFlags()}}), | ||||
[&](MaterializationResponsibility R) { FooR.emplace(std::move(R)); }); | [&](MaterializationResponsibility R) { FooR.emplace(std::move(R)); }); | ||||
cantFail(JD.define(FooMU)); | llvm_cantFail(JD.define(FooMU)); | ||||
bool FooReady = false; | bool FooReady = false; | ||||
auto OnCompletion = [&](Expected<SymbolMap> Result) { | auto OnCompletion = [&](Expected<SymbolMap> Result) { | ||||
cantFail(std::move(Result)); | llvm_cantFail(std::move(Result)); | ||||
FooReady = true; | FooReady = true; | ||||
}; | }; | ||||
ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo}, SymbolState::Ready, | ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo}, SymbolState::Ready, | ||||
OnCompletion, NoDependenciesToRegister); | OnCompletion, NoDependenciesToRegister); | ||||
FooR->addDependenciesForAll({{&JD, SymbolNameSet({Foo})}}); | FooR->addDependenciesForAll({{&JD, SymbolNameSet({Foo})}}); | ||||
EXPECT_THAT_ERROR(FooR->notifyResolved({{Foo, FooSym}}), Succeeded()) | EXPECT_THAT_ERROR(FooR->notifyResolved({{Foo, FooSym}}), Succeeded()) | ||||
Show All 27 Lines | auto BarMU = std::make_unique<SimpleMaterializationUnit>( | ||||
SymbolFlagsMap({{Bar, BarSym.getFlags()}}), | SymbolFlagsMap({{Bar, BarSym.getFlags()}}), | ||||
[&](MaterializationResponsibility R) { BarR.emplace(std::move(R)); }); | [&](MaterializationResponsibility R) { BarR.emplace(std::move(R)); }); | ||||
auto BazMU = std::make_unique<SimpleMaterializationUnit>( | auto BazMU = std::make_unique<SimpleMaterializationUnit>( | ||||
SymbolFlagsMap({{Baz, BazSym.getFlags()}}), | SymbolFlagsMap({{Baz, BazSym.getFlags()}}), | ||||
[&](MaterializationResponsibility R) { BazR.emplace(std::move(R)); }); | [&](MaterializationResponsibility R) { BazR.emplace(std::move(R)); }); | ||||
// Define the symbols. | // Define the symbols. | ||||
cantFail(JD.define(FooMU)); | llvm_cantFail(JD.define(FooMU)); | ||||
cantFail(JD.define(BarMU)); | llvm_cantFail(JD.define(BarMU)); | ||||
cantFail(JD.define(BazMU)); | llvm_cantFail(JD.define(BazMU)); | ||||
// Query each of the symbols to trigger materialization. | // Query each of the symbols to trigger materialization. | ||||
bool FooResolved = false; | bool FooResolved = false; | ||||
bool FooReady = false; | bool FooReady = false; | ||||
auto OnFooResolution = [&](Expected<SymbolMap> Result) { | auto OnFooResolution = [&](Expected<SymbolMap> Result) { | ||||
cantFail(std::move(Result)); | llvm_cantFail(std::move(Result)); | ||||
FooResolved = true; | FooResolved = true; | ||||
}; | }; | ||||
auto OnFooReady = [&](Expected<SymbolMap> Result) { | auto OnFooReady = [&](Expected<SymbolMap> Result) { | ||||
cantFail(std::move(Result)); | llvm_cantFail(std::move(Result)); | ||||
FooReady = true; | FooReady = true; | ||||
}; | }; | ||||
// Issue lookups for Foo. Use NoDependenciesToRegister: We're going to add | // Issue lookups for Foo. Use NoDependenciesToRegister: We're going to add | ||||
// the dependencies manually below. | // the dependencies manually below. | ||||
ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo}, SymbolState::Resolved, | ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo}, SymbolState::Resolved, | ||||
std::move(OnFooResolution), NoDependenciesToRegister); | std::move(OnFooResolution), NoDependenciesToRegister); | ||||
ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo}, SymbolState::Ready, | ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo}, SymbolState::Ready, | ||||
std::move(OnFooReady), NoDependenciesToRegister); | std::move(OnFooReady), NoDependenciesToRegister); | ||||
bool BarResolved = false; | bool BarResolved = false; | ||||
bool BarReady = false; | bool BarReady = false; | ||||
auto OnBarResolution = [&](Expected<SymbolMap> Result) { | auto OnBarResolution = [&](Expected<SymbolMap> Result) { | ||||
cantFail(std::move(Result)); | llvm_cantFail(std::move(Result)); | ||||
BarResolved = true; | BarResolved = true; | ||||
}; | }; | ||||
auto OnBarReady = [&](Expected<SymbolMap> Result) { | auto OnBarReady = [&](Expected<SymbolMap> Result) { | ||||
cantFail(std::move(Result)); | llvm_cantFail(std::move(Result)); | ||||
BarReady = true; | BarReady = true; | ||||
}; | }; | ||||
ES.lookup(JITDylibSearchList({{&JD, false}}), {Bar}, SymbolState::Resolved, | ES.lookup(JITDylibSearchList({{&JD, false}}), {Bar}, SymbolState::Resolved, | ||||
std::move(OnBarResolution), NoDependenciesToRegister); | std::move(OnBarResolution), NoDependenciesToRegister); | ||||
ES.lookup(JITDylibSearchList({{&JD, false}}), {Bar}, SymbolState::Ready, | ES.lookup(JITDylibSearchList({{&JD, false}}), {Bar}, SymbolState::Ready, | ||||
std::move(OnBarReady), NoDependenciesToRegister); | std::move(OnBarReady), NoDependenciesToRegister); | ||||
bool BazResolved = false; | bool BazResolved = false; | ||||
bool BazReady = false; | bool BazReady = false; | ||||
auto OnBazResolution = [&](Expected<SymbolMap> Result) { | auto OnBazResolution = [&](Expected<SymbolMap> Result) { | ||||
cantFail(std::move(Result)); | llvm_cantFail(std::move(Result)); | ||||
BazResolved = true; | BazResolved = true; | ||||
}; | }; | ||||
auto OnBazReady = [&](Expected<SymbolMap> Result) { | auto OnBazReady = [&](Expected<SymbolMap> Result) { | ||||
cantFail(std::move(Result)); | llvm_cantFail(std::move(Result)); | ||||
BazReady = true; | BazReady = true; | ||||
}; | }; | ||||
ES.lookup(JITDylibSearchList({{&JD, false}}), {Baz}, SymbolState::Resolved, | ES.lookup(JITDylibSearchList({{&JD, false}}), {Baz}, SymbolState::Resolved, | ||||
std::move(OnBazResolution), NoDependenciesToRegister); | std::move(OnBazResolution), NoDependenciesToRegister); | ||||
ES.lookup(JITDylibSearchList({{&JD, false}}), {Baz}, SymbolState::Ready, | ES.lookup(JITDylibSearchList({{&JD, false}}), {Baz}, SymbolState::Ready, | ||||
std::move(OnBazReady), NoDependenciesToRegister); | std::move(OnBazReady), NoDependenciesToRegister); | ||||
▲ Show 20 Lines • Show All 62 Lines • ▼ Show 20 Lines | auto FooMU = std::make_unique<SimpleMaterializationUnit>( | ||||
SymbolFlagsMap({{Foo, FooSym.getFlags()}}), | SymbolFlagsMap({{Foo, FooSym.getFlags()}}), | ||||
[&](MaterializationResponsibility R) { FooR.emplace(std::move(R)); }); | [&](MaterializationResponsibility R) { FooR.emplace(std::move(R)); }); | ||||
auto BarMU = std::make_unique<SimpleMaterializationUnit>( | auto BarMU = std::make_unique<SimpleMaterializationUnit>( | ||||
SymbolFlagsMap({{Bar, BarSym.getFlags()}}), | SymbolFlagsMap({{Bar, BarSym.getFlags()}}), | ||||
[&](MaterializationResponsibility R) { BarR.emplace(std::move(R)); }); | [&](MaterializationResponsibility R) { BarR.emplace(std::move(R)); }); | ||||
// Define the symbols. | // Define the symbols. | ||||
cantFail(JD.define(FooMU)); | llvm_cantFail(JD.define(FooMU)); | ||||
cantFail(JD.define(BarMU)); | llvm_cantFail(JD.define(BarMU)); | ||||
bool OnFooReadyRun = false; | bool OnFooReadyRun = false; | ||||
auto OnFooReady = [&](Expected<SymbolMap> Result) { | auto OnFooReady = [&](Expected<SymbolMap> Result) { | ||||
EXPECT_THAT_EXPECTED(std::move(Result), Failed()); | EXPECT_THAT_EXPECTED(std::move(Result), Failed()); | ||||
OnFooReadyRun = true; | OnFooReadyRun = true; | ||||
}; | }; | ||||
ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo}, SymbolState::Ready, | ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo}, SymbolState::Ready, | ||||
▲ Show 20 Lines • Show All 45 Lines • ▼ Show 20 Lines | auto FooMU = std::make_unique<SimpleMaterializationUnit>( | ||||
SymbolFlagsMap({{Foo, FooSym.getFlags()}}), | SymbolFlagsMap({{Foo, FooSym.getFlags()}}), | ||||
[&](MaterializationResponsibility R) { FooR.emplace(std::move(R)); }); | [&](MaterializationResponsibility R) { FooR.emplace(std::move(R)); }); | ||||
auto BarMU = std::make_unique<SimpleMaterializationUnit>( | auto BarMU = std::make_unique<SimpleMaterializationUnit>( | ||||
SymbolFlagsMap({{Bar, BarSym.getFlags()}}), | SymbolFlagsMap({{Bar, BarSym.getFlags()}}), | ||||
[&](MaterializationResponsibility R) { BarR.emplace(std::move(R)); }); | [&](MaterializationResponsibility R) { BarR.emplace(std::move(R)); }); | ||||
// Define the symbols. | // Define the symbols. | ||||
cantFail(JD.define(FooMU)); | llvm_cantFail(JD.define(FooMU)); | ||||
cantFail(JD.define(BarMU)); | llvm_cantFail(JD.define(BarMU)); | ||||
bool OnFooReadyRun = false; | bool OnFooReadyRun = false; | ||||
auto OnFooReady = [&](Expected<SymbolMap> Result) { | auto OnFooReady = [&](Expected<SymbolMap> Result) { | ||||
EXPECT_THAT_EXPECTED(std::move(Result), Failed()); | EXPECT_THAT_EXPECTED(std::move(Result), Failed()); | ||||
OnFooReadyRun = true; | OnFooReadyRun = true; | ||||
}; | }; | ||||
ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo}, SymbolState::Ready, | ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo}, SymbolState::Ready, | ||||
▲ Show 20 Lines • Show All 46 Lines • ▼ Show 20 Lines | auto FooMU = std::make_unique<SimpleMaterializationUnit>( | ||||
SymbolFlagsMap({{Foo, FooSym.getFlags()}}), | SymbolFlagsMap({{Foo, FooSym.getFlags()}}), | ||||
[&](MaterializationResponsibility R) { FooR.emplace(std::move(R)); }); | [&](MaterializationResponsibility R) { FooR.emplace(std::move(R)); }); | ||||
auto BarMU = std::make_unique<SimpleMaterializationUnit>( | auto BarMU = std::make_unique<SimpleMaterializationUnit>( | ||||
SymbolFlagsMap({{Bar, BarSym.getFlags()}}), | SymbolFlagsMap({{Bar, BarSym.getFlags()}}), | ||||
[&](MaterializationResponsibility R) { BarR.emplace(std::move(R)); }); | [&](MaterializationResponsibility R) { BarR.emplace(std::move(R)); }); | ||||
// Define the symbols. | // Define the symbols. | ||||
cantFail(JD.define(FooMU)); | llvm_cantFail(JD.define(FooMU)); | ||||
cantFail(JD.define(BarMU)); | llvm_cantFail(JD.define(BarMU)); | ||||
bool OnFooReadyRun = false; | bool OnFooReadyRun = false; | ||||
auto OnFooReady = [&](Expected<SymbolMap> Result) { | auto OnFooReady = [&](Expected<SymbolMap> Result) { | ||||
EXPECT_THAT_EXPECTED(std::move(Result), Failed()); | EXPECT_THAT_EXPECTED(std::move(Result), Failed()); | ||||
OnFooReadyRun = true; | OnFooReadyRun = true; | ||||
}; | }; | ||||
ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo}, SymbolState::Ready, | ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo}, SymbolState::Ready, | ||||
▲ Show 20 Lines • Show All 46 Lines • ▼ Show 20 Lines | auto FooMU = std::make_unique<SimpleMaterializationUnit>( | ||||
SymbolFlagsMap({{Foo, FooSym.getFlags()}}), | SymbolFlagsMap({{Foo, FooSym.getFlags()}}), | ||||
[&](MaterializationResponsibility R) { FooR.emplace(std::move(R)); }); | [&](MaterializationResponsibility R) { FooR.emplace(std::move(R)); }); | ||||
auto BarMU = std::make_unique<SimpleMaterializationUnit>( | auto BarMU = std::make_unique<SimpleMaterializationUnit>( | ||||
SymbolFlagsMap({{Bar, BarSym.getFlags()}}), | SymbolFlagsMap({{Bar, BarSym.getFlags()}}), | ||||
[&](MaterializationResponsibility R) { BarR.emplace(std::move(R)); }); | [&](MaterializationResponsibility R) { BarR.emplace(std::move(R)); }); | ||||
// Define the symbols. | // Define the symbols. | ||||
cantFail(JD.define(FooMU)); | llvm_cantFail(JD.define(FooMU)); | ||||
cantFail(JD.define(BarMU)); | llvm_cantFail(JD.define(BarMU)); | ||||
bool OnFooReadyRun = false; | bool OnFooReadyRun = false; | ||||
auto OnFooReady = [&](Expected<SymbolMap> Result) { | auto OnFooReady = [&](Expected<SymbolMap> Result) { | ||||
EXPECT_THAT_EXPECTED(std::move(Result), Failed()); | EXPECT_THAT_EXPECTED(std::move(Result), Failed()); | ||||
OnFooReadyRun = true; | OnFooReadyRun = true; | ||||
}; | }; | ||||
ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo}, SymbolState::Ready, | ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo}, SymbolState::Ready, | ||||
Show All 34 Lines | TEST_F(CoreAPIsStandardTest, FailMaterializerWithUnqueriedSymbols) { | ||||
auto MU = std::make_unique<SimpleMaterializationUnit>( | auto MU = std::make_unique<SimpleMaterializationUnit>( | ||||
SymbolFlagsMap( | SymbolFlagsMap( | ||||
{{Foo, JITSymbolFlags::Exported}, {Bar, JITSymbolFlags::Exported}}), | {{Foo, JITSymbolFlags::Exported}, {Bar, JITSymbolFlags::Exported}}), | ||||
[&](MaterializationResponsibility R) { | [&](MaterializationResponsibility R) { | ||||
MaterializerRun = true; | MaterializerRun = true; | ||||
R.failMaterialization(); | R.failMaterialization(); | ||||
}); | }); | ||||
cantFail(JD.define(std::move(MU))); | llvm_cantFail(JD.define(std::move(MU))); | ||||
// Issue a query for Foo, but not bar. | // Issue a query for Foo, but not bar. | ||||
EXPECT_THAT_EXPECTED(ES.lookup({&JD}, {Foo}), Failed()) | EXPECT_THAT_EXPECTED(ES.lookup({&JD}, {Foo}), Failed()) | ||||
<< "Expected lookup to fail."; | << "Expected lookup to fail."; | ||||
// Check that the materializer (and therefore failMaterialization) ran. | // Check that the materializer (and therefore failMaterialization) ran. | ||||
EXPECT_TRUE(MaterializerRun) << "Expected materializer to have run by now"; | EXPECT_TRUE(MaterializerRun) << "Expected materializer to have run by now"; | ||||
Show All 16 Lines | auto MU = std::make_unique<SimpleMaterializationUnit>( | ||||
llvm_unreachable("Unexpected call to materialize"); | llvm_unreachable("Unexpected call to materialize"); | ||||
}, | }, | ||||
[&](const JITDylib &JD, SymbolStringPtr Name) { | [&](const JITDylib &JD, SymbolStringPtr Name) { | ||||
EXPECT_TRUE(Name == Foo || Name == Bar) | EXPECT_TRUE(Name == Foo || Name == Bar) | ||||
<< "Discard of unexpected symbol?"; | << "Discard of unexpected symbol?"; | ||||
}, | }, | ||||
[&]() { DestructorRun = true; }); | [&]() { DestructorRun = true; }); | ||||
cantFail(JD.define(MU)); | llvm_cantFail(JD.define(MU)); | ||||
cantFail(JD.define(absoluteSymbols({{Foo, FooSym}}))); | llvm_cantFail(JD.define(absoluteSymbols({{Foo, FooSym}}))); | ||||
EXPECT_FALSE(DestructorRun) | EXPECT_FALSE(DestructorRun) | ||||
<< "MaterializationUnit should not have been destroyed yet"; | << "MaterializationUnit should not have been destroyed yet"; | ||||
cantFail(JD.define(absoluteSymbols({{Bar, BarSym}}))); | llvm_cantFail(JD.define(absoluteSymbols({{Bar, BarSym}}))); | ||||
EXPECT_TRUE(DestructorRun) | EXPECT_TRUE(DestructorRun) | ||||
<< "MaterializationUnit should have been destroyed"; | << "MaterializationUnit should have been destroyed"; | ||||
} | } | ||||
TEST_F(CoreAPIsStandardTest, AddAndMaterializeLazySymbol) { | TEST_F(CoreAPIsStandardTest, AddAndMaterializeLazySymbol) { | ||||
bool FooMaterialized = false; | bool FooMaterialized = false; | ||||
bool BarDiscarded = false; | bool BarDiscarded = false; | ||||
JITSymbolFlags WeakExported(JITSymbolFlags::Exported); | JITSymbolFlags WeakExported(JITSymbolFlags::Exported); | ||||
WeakExported |= JITSymbolFlags::Weak; | WeakExported |= JITSymbolFlags::Weak; | ||||
auto MU = std::make_unique<SimpleMaterializationUnit>( | auto MU = std::make_unique<SimpleMaterializationUnit>( | ||||
SymbolFlagsMap({{Foo, JITSymbolFlags::Exported}, {Bar, WeakExported}}), | SymbolFlagsMap({{Foo, JITSymbolFlags::Exported}, {Bar, WeakExported}}), | ||||
[&](MaterializationResponsibility R) { | [&](MaterializationResponsibility R) { | ||||
assert(BarDiscarded && "Bar should have been discarded by this point"); | assert(BarDiscarded && "Bar should have been discarded by this point"); | ||||
cantFail(R.notifyResolved(SymbolMap({{Foo, FooSym}}))); | llvm_cantFail(R.notifyResolved(SymbolMap({{Foo, FooSym}}))); | ||||
cantFail(R.notifyEmitted()); | llvm_cantFail(R.notifyEmitted()); | ||||
FooMaterialized = true; | FooMaterialized = true; | ||||
}, | }, | ||||
[&](const JITDylib &JD, SymbolStringPtr Name) { | [&](const JITDylib &JD, SymbolStringPtr Name) { | ||||
EXPECT_EQ(Name, Bar) << "Expected Name to be Bar"; | EXPECT_EQ(Name, Bar) << "Expected Name to be Bar"; | ||||
BarDiscarded = true; | BarDiscarded = true; | ||||
}); | }); | ||||
cantFail(JD.define(MU)); | llvm_cantFail(JD.define(MU)); | ||||
cantFail(JD.define(absoluteSymbols({{Bar, BarSym}}))); | llvm_cantFail(JD.define(absoluteSymbols({{Bar, BarSym}}))); | ||||
SymbolNameSet Names({Foo}); | SymbolNameSet Names({Foo}); | ||||
bool OnCompletionRun = false; | bool OnCompletionRun = false; | ||||
auto OnCompletion = [&](Expected<SymbolMap> Result) { | auto OnCompletion = [&](Expected<SymbolMap> Result) { | ||||
EXPECT_TRUE(!!Result) << "Resolution unexpectedly returned error"; | EXPECT_TRUE(!!Result) << "Resolution unexpectedly returned error"; | ||||
auto I = Result->find(Foo); | auto I = Result->find(Foo); | ||||
Show All 14 Lines | |||||
TEST_F(CoreAPIsStandardTest, TestBasicWeakSymbolMaterialization) { | TEST_F(CoreAPIsStandardTest, TestBasicWeakSymbolMaterialization) { | ||||
// Test that weak symbols are materialized correctly when we look them up. | // Test that weak symbols are materialized correctly when we look them up. | ||||
BarSym.setFlags(BarSym.getFlags() | JITSymbolFlags::Weak); | BarSym.setFlags(BarSym.getFlags() | JITSymbolFlags::Weak); | ||||
bool BarMaterialized = false; | bool BarMaterialized = false; | ||||
auto MU1 = std::make_unique<SimpleMaterializationUnit>( | auto MU1 = std::make_unique<SimpleMaterializationUnit>( | ||||
SymbolFlagsMap({{Foo, FooSym.getFlags()}, {Bar, BarSym.getFlags()}}), | SymbolFlagsMap({{Foo, FooSym.getFlags()}, {Bar, BarSym.getFlags()}}), | ||||
[&](MaterializationResponsibility R) { | [&](MaterializationResponsibility R) { | ||||
cantFail(R.notifyResolved(SymbolMap({{Foo, FooSym}, {Bar, BarSym}}))); | llvm_cantFail(R.notifyResolved(SymbolMap({{Foo, FooSym}, {Bar, BarSym}}))); | ||||
cantFail(R.notifyEmitted()); | llvm_cantFail(R.notifyEmitted()); | ||||
BarMaterialized = true; | BarMaterialized = true; | ||||
}); | }); | ||||
bool DuplicateBarDiscarded = false; | bool DuplicateBarDiscarded = false; | ||||
auto MU2 = std::make_unique<SimpleMaterializationUnit>( | auto MU2 = std::make_unique<SimpleMaterializationUnit>( | ||||
SymbolFlagsMap({{Bar, BarSym.getFlags()}}), | SymbolFlagsMap({{Bar, BarSym.getFlags()}}), | ||||
[&](MaterializationResponsibility R) { | [&](MaterializationResponsibility R) { | ||||
ADD_FAILURE() << "Attempt to materialize Bar from the wrong unit"; | ADD_FAILURE() << "Attempt to materialize Bar from the wrong unit"; | ||||
R.failMaterialization(); | R.failMaterialization(); | ||||
}, | }, | ||||
[&](const JITDylib &JD, SymbolStringPtr Name) { | [&](const JITDylib &JD, SymbolStringPtr Name) { | ||||
EXPECT_EQ(Name, Bar) << "Expected \"Bar\" to be discarded"; | EXPECT_EQ(Name, Bar) << "Expected \"Bar\" to be discarded"; | ||||
DuplicateBarDiscarded = true; | DuplicateBarDiscarded = true; | ||||
}); | }); | ||||
cantFail(JD.define(MU1)); | llvm_cantFail(JD.define(MU1)); | ||||
cantFail(JD.define(MU2)); | llvm_cantFail(JD.define(MU2)); | ||||
bool OnCompletionRun = false; | bool OnCompletionRun = false; | ||||
auto OnCompletion = [&](Expected<SymbolMap> Result) { | auto OnCompletion = [&](Expected<SymbolMap> Result) { | ||||
cantFail(std::move(Result)); | llvm_cantFail(std::move(Result)); | ||||
OnCompletionRun = true; | OnCompletionRun = true; | ||||
}; | }; | ||||
ES.lookup(JITDylibSearchList({{&JD, false}}), {Bar}, SymbolState::Ready, | ES.lookup(JITDylibSearchList({{&JD, false}}), {Bar}, SymbolState::Ready, | ||||
std::move(OnCompletion), NoDependenciesToRegister); | std::move(OnCompletion), NoDependenciesToRegister); | ||||
EXPECT_TRUE(OnCompletionRun) << "OnCompletion not run"; | EXPECT_TRUE(OnCompletionRun) << "OnCompletion not run"; | ||||
EXPECT_TRUE(BarMaterialized) << "Bar was not materialized at all"; | EXPECT_TRUE(BarMaterialized) << "Bar was not materialized at all"; | ||||
EXPECT_TRUE(DuplicateBarDiscarded) | EXPECT_TRUE(DuplicateBarDiscarded) | ||||
<< "Duplicate bar definition not discarded"; | << "Duplicate bar definition not discarded"; | ||||
} | } | ||||
TEST_F(CoreAPIsStandardTest, DefineMaterializingSymbol) { | TEST_F(CoreAPIsStandardTest, DefineMaterializingSymbol) { | ||||
bool ExpectNoMoreMaterialization = false; | bool ExpectNoMoreMaterialization = false; | ||||
ES.setDispatchMaterialization( | ES.setDispatchMaterialization( | ||||
[&](JITDylib &JD, std::unique_ptr<MaterializationUnit> MU) { | [&](JITDylib &JD, std::unique_ptr<MaterializationUnit> MU) { | ||||
if (ExpectNoMoreMaterialization) | if (ExpectNoMoreMaterialization) | ||||
ADD_FAILURE() << "Unexpected materialization"; | ADD_FAILURE() << "Unexpected materialization"; | ||||
MU->doMaterialize(JD); | MU->doMaterialize(JD); | ||||
}); | }); | ||||
auto MU = std::make_unique<SimpleMaterializationUnit>( | auto MU = std::make_unique<SimpleMaterializationUnit>( | ||||
SymbolFlagsMap({{Foo, FooSym.getFlags()}}), | SymbolFlagsMap({{Foo, FooSym.getFlags()}}), | ||||
[&](MaterializationResponsibility R) { | [&](MaterializationResponsibility R) { | ||||
cantFail( | llvm_cantFail( | ||||
R.defineMaterializing(SymbolFlagsMap({{Bar, BarSym.getFlags()}}))); | R.defineMaterializing(SymbolFlagsMap({{Bar, BarSym.getFlags()}}))); | ||||
cantFail(R.notifyResolved(SymbolMap({{Foo, FooSym}, {Bar, BarSym}}))); | llvm_cantFail(R.notifyResolved(SymbolMap({{Foo, FooSym}, {Bar, BarSym}}))); | ||||
cantFail(R.notifyEmitted()); | llvm_cantFail(R.notifyEmitted()); | ||||
}); | }); | ||||
cantFail(JD.define(MU)); | llvm_cantFail(JD.define(MU)); | ||||
cantFail(ES.lookup(JITDylibSearchList({{&JD, false}}), Foo)); | llvm_cantFail(ES.lookup(JITDylibSearchList({{&JD, false}}), Foo)); | ||||
// Assert that materialization is complete by now. | // Assert that materialization is complete by now. | ||||
ExpectNoMoreMaterialization = true; | ExpectNoMoreMaterialization = true; | ||||
// Look up bar to verify that no further materialization happens. | // Look up bar to verify that no further materialization happens. | ||||
auto BarResult = cantFail(ES.lookup(JITDylibSearchList({{&JD, false}}), Bar)); | auto BarResult = llvm_cantFail(ES.lookup(JITDylibSearchList({{&JD, false}}), Bar)); | ||||
EXPECT_EQ(BarResult.getAddress(), BarSym.getAddress()) | EXPECT_EQ(BarResult.getAddress(), BarSym.getAddress()) | ||||
<< "Expected Bar == BarSym"; | << "Expected Bar == BarSym"; | ||||
} | } | ||||
TEST_F(CoreAPIsStandardTest, GeneratorTest) { | TEST_F(CoreAPIsStandardTest, GeneratorTest) { | ||||
cantFail(JD.define(absoluteSymbols({{Foo, FooSym}}))); | llvm_cantFail(JD.define(absoluteSymbols({{Foo, FooSym}}))); | ||||
class TestGenerator : public JITDylib::DefinitionGenerator { | class TestGenerator : public JITDylib::DefinitionGenerator { | ||||
public: | public: | ||||
TestGenerator(SymbolMap Symbols) : Symbols(std::move(Symbols)) {} | TestGenerator(SymbolMap Symbols) : Symbols(std::move(Symbols)) {} | ||||
Expected<SymbolNameSet> tryToGenerate(JITDylib &JD, | Expected<SymbolNameSet> tryToGenerate(JITDylib &JD, | ||||
const SymbolNameSet &Names) { | const SymbolNameSet &Names) { | ||||
SymbolMap NewDefs; | SymbolMap NewDefs; | ||||
SymbolNameSet NewNames; | SymbolNameSet NewNames; | ||||
for (auto &Name : Names) { | for (auto &Name : Names) { | ||||
if (Symbols.count(Name)) { | if (Symbols.count(Name)) { | ||||
NewDefs[Name] = Symbols[Name]; | NewDefs[Name] = Symbols[Name]; | ||||
NewNames.insert(Name); | NewNames.insert(Name); | ||||
} | } | ||||
} | } | ||||
cantFail(JD.define(absoluteSymbols(std::move(NewDefs)))); | llvm_cantFail(JD.define(absoluteSymbols(std::move(NewDefs)))); | ||||
return NewNames; | return NewNames; | ||||
}; | }; | ||||
private: | private: | ||||
SymbolMap Symbols; | SymbolMap Symbols; | ||||
}; | }; | ||||
JD.addGenerator(std::make_unique<TestGenerator>(SymbolMap({{Bar, BarSym}}))); | JD.addGenerator(std::make_unique<TestGenerator>(SymbolMap({{Bar, BarSym}}))); | ||||
auto Result = | auto Result = | ||||
cantFail(ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo, Bar})); | llvm_cantFail(ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo, Bar})); | ||||
EXPECT_EQ(Result.count(Bar), 1U) << "Expected to find fallback def for 'bar'"; | EXPECT_EQ(Result.count(Bar), 1U) << "Expected to find fallback def for 'bar'"; | ||||
EXPECT_EQ(Result[Bar].getAddress(), BarSym.getAddress()) | EXPECT_EQ(Result[Bar].getAddress(), BarSym.getAddress()) | ||||
<< "Expected fallback def for Bar to be equal to BarSym"; | << "Expected fallback def for Bar to be equal to BarSym"; | ||||
} | } | ||||
TEST_F(CoreAPIsStandardTest, FailResolution) { | TEST_F(CoreAPIsStandardTest, FailResolution) { | ||||
auto MU = std::make_unique<SimpleMaterializationUnit>( | auto MU = std::make_unique<SimpleMaterializationUnit>( | ||||
SymbolFlagsMap({{Foo, JITSymbolFlags::Exported | JITSymbolFlags::Weak}, | SymbolFlagsMap({{Foo, JITSymbolFlags::Exported | JITSymbolFlags::Weak}, | ||||
{Bar, JITSymbolFlags::Exported | JITSymbolFlags::Weak}}), | {Bar, JITSymbolFlags::Exported | JITSymbolFlags::Weak}}), | ||||
[&](MaterializationResponsibility R) { | [&](MaterializationResponsibility R) { | ||||
R.failMaterialization(); | R.failMaterialization(); | ||||
}); | }); | ||||
cantFail(JD.define(MU)); | llvm_cantFail(JD.define(MU)); | ||||
SymbolNameSet Names({Foo, Bar}); | SymbolNameSet Names({Foo, Bar}); | ||||
auto Result = ES.lookup(JITDylibSearchList({{&JD, false}}), Names); | auto Result = ES.lookup(JITDylibSearchList({{&JD, false}}), Names); | ||||
EXPECT_FALSE(!!Result) << "Expected failure"; | EXPECT_FALSE(!!Result) << "Expected failure"; | ||||
if (!Result) { | if (!Result) { | ||||
handleAllErrors( | handleAllErrors( | ||||
Result.takeError(), | Result.takeError(), | ||||
Show All 11 Lines | handleAllErrors( | ||||
} | } | ||||
ADD_FAILURE() << "Expected a FailedToResolve error. Got:\n" << ErrMsg; | ADD_FAILURE() << "Expected a FailedToResolve error. Got:\n" << ErrMsg; | ||||
}); | }); | ||||
} | } | ||||
} | } | ||||
TEST_F(CoreAPIsStandardTest, FailEmissionAfterResolution) { | TEST_F(CoreAPIsStandardTest, FailEmissionAfterResolution) { | ||||
cantFail(JD.define(absoluteSymbols({{Baz, BazSym}}))); | llvm_cantFail(JD.define(absoluteSymbols({{Baz, BazSym}}))); | ||||
auto MU = std::make_unique<SimpleMaterializationUnit>( | auto MU = std::make_unique<SimpleMaterializationUnit>( | ||||
SymbolFlagsMap({{Foo, FooSym.getFlags()}, {Bar, BarSym.getFlags()}}), | SymbolFlagsMap({{Foo, FooSym.getFlags()}, {Bar, BarSym.getFlags()}}), | ||||
[&](MaterializationResponsibility R) { | [&](MaterializationResponsibility R) { | ||||
cantFail(R.notifyResolved(SymbolMap({{Foo, FooSym}, {Bar, BarSym}}))); | llvm_cantFail(R.notifyResolved(SymbolMap({{Foo, FooSym}, {Bar, BarSym}}))); | ||||
ES.lookup( | ES.lookup( | ||||
JITDylibSearchList({{&JD, false}}), SymbolNameSet({Baz}), | JITDylibSearchList({{&JD, false}}), SymbolNameSet({Baz}), | ||||
SymbolState::Resolved, | SymbolState::Resolved, | ||||
[&R](Expected<SymbolMap> Result) { | [&R](Expected<SymbolMap> Result) { | ||||
// Called when "baz" is resolved. We don't actually depend | // Called when "baz" is resolved. We don't actually depend | ||||
// on or care about baz, but use it to trigger failure of | // on or care about baz, but use it to trigger failure of | ||||
// this materialization before Baz has been finalized in | // this materialization before Baz has been finalized in | ||||
// order to test that error propagation is correct in this | // order to test that error propagation is correct in this | ||||
// scenario. | // scenario. | ||||
cantFail(std::move(Result)); | llvm_cantFail(std::move(Result)); | ||||
R.failMaterialization(); | R.failMaterialization(); | ||||
}, | }, | ||||
[&](const SymbolDependenceMap &Deps) { | [&](const SymbolDependenceMap &Deps) { | ||||
R.addDependenciesForAll(Deps); | R.addDependenciesForAll(Deps); | ||||
}); | }); | ||||
}); | }); | ||||
cantFail(JD.define(MU)); | llvm_cantFail(JD.define(MU)); | ||||
SymbolNameSet Names({Foo, Bar}); | SymbolNameSet Names({Foo, Bar}); | ||||
auto Result = ES.lookup(JITDylibSearchList({{&JD, false}}), Names); | auto Result = ES.lookup(JITDylibSearchList({{&JD, false}}), Names); | ||||
EXPECT_THAT_EXPECTED(std::move(Result), Failed()) | EXPECT_THAT_EXPECTED(std::move(Result), Failed()) | ||||
<< "Unexpected success while trying to test error propagation"; | << "Unexpected success while trying to test error propagation"; | ||||
} | } | ||||
TEST_F(CoreAPIsStandardTest, FailAfterPartialResolution) { | TEST_F(CoreAPIsStandardTest, FailAfterPartialResolution) { | ||||
cantFail(JD.define(absoluteSymbols({{Foo, FooSym}}))); | llvm_cantFail(JD.define(absoluteSymbols({{Foo, FooSym}}))); | ||||
// Fail materialization of bar. | // Fail materialization of bar. | ||||
auto BarMU = std::make_unique<SimpleMaterializationUnit>( | auto BarMU = std::make_unique<SimpleMaterializationUnit>( | ||||
SymbolFlagsMap({{Bar, BarSym.getFlags()}}), | SymbolFlagsMap({{Bar, BarSym.getFlags()}}), | ||||
[&](MaterializationResponsibility R) { R.failMaterialization(); }); | [&](MaterializationResponsibility R) { R.failMaterialization(); }); | ||||
cantFail(JD.define(std::move(BarMU))); | llvm_cantFail(JD.define(std::move(BarMU))); | ||||
bool QueryHandlerRun = false; | bool QueryHandlerRun = false; | ||||
ES.lookup( | ES.lookup( | ||||
JITDylibSearchList({{&JD, false}}), SymbolNameSet({Foo, Bar}), | JITDylibSearchList({{&JD, false}}), SymbolNameSet({Foo, Bar}), | ||||
SymbolState::Resolved, | SymbolState::Resolved, | ||||
[&](Expected<SymbolMap> Result) { | [&](Expected<SymbolMap> Result) { | ||||
EXPECT_THAT_EXPECTED(std::move(Result), Failed()) | EXPECT_THAT_EXPECTED(std::move(Result), Failed()) | ||||
<< "Expected query to fail"; | << "Expected query to fail"; | ||||
QueryHandlerRun = true; | QueryHandlerRun = true; | ||||
}, | }, | ||||
NoDependenciesToRegister); | NoDependenciesToRegister); | ||||
EXPECT_TRUE(QueryHandlerRun) << "Query handler never ran"; | EXPECT_TRUE(QueryHandlerRun) << "Query handler never ran"; | ||||
} | } | ||||
TEST_F(CoreAPIsStandardTest, TestLookupWithUnthreadedMaterialization) { | TEST_F(CoreAPIsStandardTest, TestLookupWithUnthreadedMaterialization) { | ||||
auto MU = std::make_unique<SimpleMaterializationUnit>( | auto MU = std::make_unique<SimpleMaterializationUnit>( | ||||
SymbolFlagsMap({{Foo, JITSymbolFlags::Exported}}), | SymbolFlagsMap({{Foo, JITSymbolFlags::Exported}}), | ||||
[&](MaterializationResponsibility R) { | [&](MaterializationResponsibility R) { | ||||
cantFail(R.notifyResolved({{Foo, FooSym}})); | llvm_cantFail(R.notifyResolved({{Foo, FooSym}})); | ||||
cantFail(R.notifyEmitted()); | llvm_cantFail(R.notifyEmitted()); | ||||
}); | }); | ||||
cantFail(JD.define(MU)); | llvm_cantFail(JD.define(MU)); | ||||
auto FooLookupResult = | auto FooLookupResult = | ||||
cantFail(ES.lookup(JITDylibSearchList({{&JD, false}}), Foo)); | llvm_cantFail(ES.lookup(JITDylibSearchList({{&JD, false}}), Foo)); | ||||
EXPECT_EQ(FooLookupResult.getAddress(), FooSym.getAddress()) | EXPECT_EQ(FooLookupResult.getAddress(), FooSym.getAddress()) | ||||
<< "lookup returned an incorrect address"; | << "lookup returned an incorrect address"; | ||||
EXPECT_EQ(FooLookupResult.getFlags(), FooSym.getFlags()) | EXPECT_EQ(FooLookupResult.getFlags(), FooSym.getFlags()) | ||||
<< "lookup returned incorrect flags"; | << "lookup returned incorrect flags"; | ||||
} | } | ||||
TEST_F(CoreAPIsStandardTest, TestLookupWithThreadedMaterialization) { | TEST_F(CoreAPIsStandardTest, TestLookupWithThreadedMaterialization) { | ||||
#if LLVM_ENABLE_THREADS | #if LLVM_ENABLE_THREADS | ||||
std::thread MaterializationThread; | std::thread MaterializationThread; | ||||
ES.setDispatchMaterialization( | ES.setDispatchMaterialization( | ||||
[&](JITDylib &JD, std::unique_ptr<MaterializationUnit> MU) { | [&](JITDylib &JD, std::unique_ptr<MaterializationUnit> MU) { | ||||
MaterializationThread = | MaterializationThread = | ||||
std::thread([MU = std::move(MU), &JD] { MU->doMaterialize(JD); }); | std::thread([MU = std::move(MU), &JD] { MU->doMaterialize(JD); }); | ||||
}); | }); | ||||
cantFail(JD.define(absoluteSymbols({{Foo, FooSym}}))); | llvm_cantFail(JD.define(absoluteSymbols({{Foo, FooSym}}))); | ||||
auto FooLookupResult = | auto FooLookupResult = | ||||
cantFail(ES.lookup(JITDylibSearchList({{&JD, false}}), Foo)); | llvm_cantFail(ES.lookup(JITDylibSearchList({{&JD, false}}), Foo)); | ||||
EXPECT_EQ(FooLookupResult.getAddress(), FooSym.getAddress()) | EXPECT_EQ(FooLookupResult.getAddress(), FooSym.getAddress()) | ||||
<< "lookup returned an incorrect address"; | << "lookup returned an incorrect address"; | ||||
EXPECT_EQ(FooLookupResult.getFlags(), FooSym.getFlags()) | EXPECT_EQ(FooLookupResult.getFlags(), FooSym.getFlags()) | ||||
<< "lookup returned incorrect flags"; | << "lookup returned incorrect flags"; | ||||
MaterializationThread.join(); | MaterializationThread.join(); | ||||
#endif | #endif | ||||
} | } | ||||
Show All 13 Lines | auto MU = std::make_unique<SimpleMaterializationUnit>( | ||||
[&](MaterializationResponsibility R) { | [&](MaterializationResponsibility R) { | ||||
auto Requested = R.getRequestedSymbols(); | auto Requested = R.getRequestedSymbols(); | ||||
EXPECT_EQ(Requested.size(), 1U) << "Expected one symbol requested"; | EXPECT_EQ(Requested.size(), 1U) << "Expected one symbol requested"; | ||||
EXPECT_EQ(*Requested.begin(), Foo) << "Expected \"Foo\" requested"; | EXPECT_EQ(*Requested.begin(), Foo) << "Expected \"Foo\" requested"; | ||||
auto NewMU = std::make_unique<SimpleMaterializationUnit>( | auto NewMU = std::make_unique<SimpleMaterializationUnit>( | ||||
SymbolFlagsMap({{Bar, BarSym.getFlags()}}), | SymbolFlagsMap({{Bar, BarSym.getFlags()}}), | ||||
[&](MaterializationResponsibility R2) { | [&](MaterializationResponsibility R2) { | ||||
cantFail(R2.notifyResolved(SymbolMap({{Bar, BarSym}}))); | llvm_cantFail(R2.notifyResolved(SymbolMap({{Bar, BarSym}}))); | ||||
cantFail(R2.notifyEmitted()); | llvm_cantFail(R2.notifyEmitted()); | ||||
BarMaterialized = true; | BarMaterialized = true; | ||||
}); | }); | ||||
R.replace(std::move(NewMU)); | R.replace(std::move(NewMU)); | ||||
cantFail(R.notifyResolved(SymbolMap({{Foo, FooSym}}))); | llvm_cantFail(R.notifyResolved(SymbolMap({{Foo, FooSym}}))); | ||||
cantFail(R.notifyEmitted()); | llvm_cantFail(R.notifyEmitted()); | ||||
FooMaterialized = true; | FooMaterialized = true; | ||||
}); | }); | ||||
cantFail(JD.define(MU)); | llvm_cantFail(JD.define(MU)); | ||||
EXPECT_FALSE(FooMaterialized) << "Foo should not be materialized yet"; | EXPECT_FALSE(FooMaterialized) << "Foo should not be materialized yet"; | ||||
EXPECT_FALSE(BarMaterialized) << "Bar should not be materialized yet"; | EXPECT_FALSE(BarMaterialized) << "Bar should not be materialized yet"; | ||||
auto FooSymResult = | auto FooSymResult = | ||||
cantFail(ES.lookup(JITDylibSearchList({{&JD, false}}), Foo)); | llvm_cantFail(ES.lookup(JITDylibSearchList({{&JD, false}}), Foo)); | ||||
EXPECT_EQ(FooSymResult.getAddress(), FooSym.getAddress()) | EXPECT_EQ(FooSymResult.getAddress(), FooSym.getAddress()) | ||||
<< "Address mismatch for Foo"; | << "Address mismatch for Foo"; | ||||
EXPECT_TRUE(FooMaterialized) << "Foo should be materialized now"; | EXPECT_TRUE(FooMaterialized) << "Foo should be materialized now"; | ||||
EXPECT_FALSE(BarMaterialized) << "Bar still should not be materialized"; | EXPECT_FALSE(BarMaterialized) << "Bar still should not be materialized"; | ||||
auto BarSymResult = | auto BarSymResult = | ||||
cantFail(ES.lookup(JITDylibSearchList({{&JD, false}}), Bar)); | llvm_cantFail(ES.lookup(JITDylibSearchList({{&JD, false}}), Bar)); | ||||
EXPECT_EQ(BarSymResult.getAddress(), BarSym.getAddress()) | EXPECT_EQ(BarSymResult.getAddress(), BarSym.getAddress()) | ||||
<< "Address mismatch for Bar"; | << "Address mismatch for Bar"; | ||||
EXPECT_TRUE(BarMaterialized) << "Bar should be materialized now"; | EXPECT_TRUE(BarMaterialized) << "Bar should be materialized now"; | ||||
} | } | ||||
TEST_F(CoreAPIsStandardTest, TestMaterializationResponsibilityDelegation) { | TEST_F(CoreAPIsStandardTest, TestMaterializationResponsibilityDelegation) { | ||||
auto MU = std::make_unique<SimpleMaterializationUnit>( | auto MU = std::make_unique<SimpleMaterializationUnit>( | ||||
SymbolFlagsMap({{Foo, FooSym.getFlags()}, {Bar, BarSym.getFlags()}}), | SymbolFlagsMap({{Foo, FooSym.getFlags()}, {Bar, BarSym.getFlags()}}), | ||||
[&](MaterializationResponsibility R) { | [&](MaterializationResponsibility R) { | ||||
auto R2 = R.delegate({Bar}); | auto R2 = R.delegate({Bar}); | ||||
cantFail(R.notifyResolved({{Foo, FooSym}})); | llvm_cantFail(R.notifyResolved({{Foo, FooSym}})); | ||||
cantFail(R.notifyEmitted()); | llvm_cantFail(R.notifyEmitted()); | ||||
cantFail(R2.notifyResolved({{Bar, BarSym}})); | llvm_cantFail(R2.notifyResolved({{Bar, BarSym}})); | ||||
cantFail(R2.notifyEmitted()); | llvm_cantFail(R2.notifyEmitted()); | ||||
}); | }); | ||||
cantFail(JD.define(MU)); | llvm_cantFail(JD.define(MU)); | ||||
auto Result = ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo, Bar}); | auto Result = ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo, Bar}); | ||||
EXPECT_TRUE(!!Result) << "Result should be a success value"; | EXPECT_TRUE(!!Result) << "Result should be a success value"; | ||||
EXPECT_EQ(Result->count(Foo), 1U) << "\"Foo\" entry missing"; | EXPECT_EQ(Result->count(Foo), 1U) << "\"Foo\" entry missing"; | ||||
EXPECT_EQ(Result->count(Bar), 1U) << "\"Bar\" entry missing"; | EXPECT_EQ(Result->count(Bar), 1U) << "\"Bar\" entry missing"; | ||||
EXPECT_EQ((*Result)[Foo].getAddress(), FooSym.getAddress()) | EXPECT_EQ((*Result)[Foo].getAddress(), FooSym.getAddress()) | ||||
<< "Address mismatch for \"Foo\""; | << "Address mismatch for \"Foo\""; | ||||
Show All 10 Lines | TEST_F(CoreAPIsStandardTest, TestMaterializeWeakSymbol) { | ||||
std::unique_ptr<MaterializationResponsibility> FooResponsibility; | std::unique_ptr<MaterializationResponsibility> FooResponsibility; | ||||
auto MU = std::make_unique<SimpleMaterializationUnit>( | auto MU = std::make_unique<SimpleMaterializationUnit>( | ||||
SymbolFlagsMap({{Foo, FooSym.getFlags()}}), | SymbolFlagsMap({{Foo, FooSym.getFlags()}}), | ||||
[&](MaterializationResponsibility R) { | [&](MaterializationResponsibility R) { | ||||
FooResponsibility = | FooResponsibility = | ||||
std::make_unique<MaterializationResponsibility>(std::move(R)); | std::make_unique<MaterializationResponsibility>(std::move(R)); | ||||
}); | }); | ||||
cantFail(JD.define(MU)); | llvm_cantFail(JD.define(MU)); | ||||
auto OnCompletion = [](Expected<SymbolMap> Result) { | auto OnCompletion = [](Expected<SymbolMap> Result) { | ||||
cantFail(std::move(Result)); | llvm_cantFail(std::move(Result)); | ||||
}; | }; | ||||
ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo}, SymbolState::Ready, | ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo}, SymbolState::Ready, | ||||
std::move(OnCompletion), NoDependenciesToRegister); | std::move(OnCompletion), NoDependenciesToRegister); | ||||
auto MU2 = std::make_unique<SimpleMaterializationUnit>( | auto MU2 = std::make_unique<SimpleMaterializationUnit>( | ||||
SymbolFlagsMap({{Foo, JITSymbolFlags::Exported}}), | SymbolFlagsMap({{Foo, JITSymbolFlags::Exported}}), | ||||
[](MaterializationResponsibility R) { | [](MaterializationResponsibility R) { | ||||
llvm_unreachable("This unit should never be materialized"); | llvm_unreachable("This unit should never be materialized"); | ||||
}); | }); | ||||
auto Err = JD.define(MU2); | auto Err = JD.define(MU2); | ||||
EXPECT_TRUE(!!Err) << "Expected failure value"; | EXPECT_TRUE(!!Err) << "Expected failure value"; | ||||
EXPECT_TRUE(Err.isA<DuplicateDefinition>()) | EXPECT_TRUE(Err.isA<DuplicateDefinition>()) | ||||
<< "Expected a duplicate definition error"; | << "Expected a duplicate definition error"; | ||||
consumeError(std::move(Err)); | consumeError(std::move(Err)); | ||||
// No dependencies registered, can't fail: | // No dependencies registered, can't fail: | ||||
cantFail(FooResponsibility->notifyResolved(SymbolMap({{Foo, FooSym}}))); | llvm_cantFail(FooResponsibility->notifyResolved(SymbolMap({{Foo, FooSym}}))); | ||||
cantFail(FooResponsibility->notifyEmitted()); | llvm_cantFail(FooResponsibility->notifyEmitted()); | ||||
} | } | ||||
} // namespace | } // namespace |