diff options
Diffstat (limited to 'llvm')
-rw-r--r-- | llvm/include/llvm/ExecutionEngine/Orc/Core.h | 40 | ||||
-rw-r--r-- | llvm/lib/ExecutionEngine/Orc/Core.cpp | 89 | ||||
-rw-r--r-- | llvm/unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp | 29 |
3 files changed, 149 insertions, 9 deletions
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/Core.h b/llvm/include/llvm/ExecutionEngine/Orc/Core.h index 4bd08043091..92272166b96 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/Core.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/Core.h @@ -245,6 +245,46 @@ absoluteSymbols(SymbolMap Symbols) { std::move(Symbols)); } +struct SymbolAliasMapEntry { + SymbolStringPtr Aliasee; + JITSymbolFlags AliasFlags; +}; + +/// A map of Symbols to (Symbol, Flags) pairs. +using SymbolAliasMap = std::map<SymbolStringPtr, SymbolAliasMapEntry>; + +/// A materialization unit for symbol aliases. Allows existing symbols to be +/// aliased with alternate flags. +class SymbolAliasesMaterializationUnit : public MaterializationUnit { +public: + SymbolAliasesMaterializationUnit(SymbolAliasMap Aliases); + +private: + void materialize(MaterializationResponsibility R) override; + void discard(const VSO &V, SymbolStringPtr Name) override; + static SymbolFlagsMap extractFlags(const SymbolAliasMap &Aliases); + + SymbolAliasMap Aliases; +}; + +/// Create a SymbolAliasesMaterializationUnit with the given aliases. +/// Useful for defining symbol aliases.: E.g., given a VSO V containing symbols +/// "foo" and "bar", we can define aliases "baz" (for "foo") and "qux" (for +/// "bar") with: +/// \code{.cpp} +/// SymbolStringPtr Baz = ...; +/// SymbolStringPtr Qux = ...; +/// if (auto Err = V.define(symbolAliases({ +/// {Baz, { Foo, JITSymbolFlags::Exported }}, +/// {Qux, { Bar, JITSymbolFlags::Weak }}})) +/// return Err; +/// \endcode +inline std::unique_ptr<SymbolAliasesMaterializationUnit> +symbolAliases(SymbolAliasMap Aliases) { + return llvm::make_unique<SymbolAliasesMaterializationUnit>( + std::move(Aliases)); +} + /// Base utilities for ExecutionSession. class ExecutionSessionBase { public: diff --git a/llvm/lib/ExecutionEngine/Orc/Core.cpp b/llvm/lib/ExecutionEngine/Orc/Core.cpp index a14a8e064e2..751e931f26d 100644 --- a/llvm/lib/ExecutionEngine/Orc/Core.cpp +++ b/llvm/lib/ExecutionEngine/Orc/Core.cpp @@ -344,6 +344,69 @@ AbsoluteSymbolsMaterializationUnit::extractFlags(const SymbolMap &Symbols) { return Flags; } +SymbolAliasesMaterializationUnit::SymbolAliasesMaterializationUnit( + SymbolAliasMap Aliases) + : MaterializationUnit(extractFlags(Aliases)), Aliases(std::move(Aliases)) {} + +void SymbolAliasesMaterializationUnit::materialize( + MaterializationResponsibility R) { + auto &V = R.getTargetVSO(); + auto &ES = V.getExecutionSession(); + + // FIXME: Use a unique_ptr when we move to C++14 and have generalized lambda + // capture. + auto SharedR = std::make_shared<MaterializationResponsibility>(std::move(R)); + + auto OnResolve = [this, SharedR]( + Expected<AsynchronousSymbolQuery::ResolutionResult> RR) { + if (RR) { + SymbolMap ResolutionMap; + for (auto &KV : Aliases) { + assert(RR->Symbols.count(KV.second.Aliasee) && + "Result map missing entry?"); + ResolutionMap[KV.first] = JITEvaluatedSymbol( + RR->Symbols[KV.second.Aliasee].getAddress(), KV.second.AliasFlags); + } + + SharedR->resolve(ResolutionMap); + SharedR->finalize(); + } else { + auto &ES = SharedR->getTargetVSO().getExecutionSession(); + ES.reportError(RR.takeError()); + SharedR->failMaterialization(); + } + }; + + auto OnReady = [&ES](Error Err) { ES.reportError(std::move(Err)); }; + + SymbolNameSet Aliasees; + for (auto &KV : Aliases) + Aliasees.insert(KV.second.Aliasee); + + auto Q = std::make_shared<AsynchronousSymbolQuery>( + Aliasees, std::move(OnResolve), std::move(OnReady)); + auto Unresolved = V.lookup(Q, Aliasees); + + if (!Unresolved.empty()) + ES.failQuery(*Q, make_error<SymbolsNotFound>(std::move(Unresolved))); +} + +void SymbolAliasesMaterializationUnit::discard(const VSO &V, + SymbolStringPtr Name) { + assert(Aliases.count(Name) && + "Symbol not covered by this MaterializationUnit"); + Aliases.erase(Name); +} + +SymbolFlagsMap +SymbolAliasesMaterializationUnit::extractFlags(const SymbolAliasMap &Aliases) { + SymbolFlagsMap SymbolFlags; + for (auto &KV : Aliases) + SymbolFlags[KV.first] = KV.second.AliasFlags; + + return SymbolFlags; +} + Error VSO::defineMaterializing(const SymbolFlagsMap &SymbolFlags) { return ES.runSessionLocked([&]() -> Error { std::vector<SymbolMap::iterator> AddedSyms; @@ -858,7 +921,13 @@ void VSO::dump(raw_ostream &OS) { Error VSO::defineImpl(MaterializationUnit &MU) { SymbolNameSet Duplicates; SymbolNameSet MUDefsOverridden; - std::vector<SymbolMap::iterator> ExistingDefsOverridden; + + struct ExistingDefOverriddenEntry { + SymbolMap::iterator ExistingDefItr; + JITSymbolFlags NewFlags; + }; + std::vector<ExistingDefOverriddenEntry> ExistingDefsOverridden; + for (auto &KV : MU.getSymbols()) { assert(!KV.second.isLazy() && "Lazy flag should be managed internally."); assert(!KV.second.isMaterializing() && @@ -879,7 +948,7 @@ Error VSO::defineImpl(MaterializationUnit &MU) { (EntryItr->second.getFlags() & JITSymbolFlags::Materializing)) Duplicates.insert(KV.first); else - ExistingDefsOverridden.push_back(EntryItr); + ExistingDefsOverridden.push_back({EntryItr, NewFlags}); } else MUDefsOverridden.insert(KV.first); } @@ -892,8 +961,8 @@ Error VSO::defineImpl(MaterializationUnit &MU) { continue; bool Found = false; - for (const auto &I : ExistingDefsOverridden) - if (I->first == KV.first) + for (const auto &EDO : ExistingDefsOverridden) + if (EDO.ExistingDefItr->first == KV.first) Found = true; if (!Found) @@ -905,16 +974,18 @@ Error VSO::defineImpl(MaterializationUnit &MU) { } // Update flags on existing defs and call discard on their materializers. - for (auto &ExistingDefItr : ExistingDefsOverridden) { - assert(ExistingDefItr->second.getFlags().isLazy() && - !ExistingDefItr->second.getFlags().isMaterializing() && + for (auto &EDO : ExistingDefsOverridden) { + assert(EDO.ExistingDefItr->second.getFlags().isLazy() && + !EDO.ExistingDefItr->second.getFlags().isMaterializing() && "Overridden existing def should be in the Lazy state"); - auto UMII = UnmaterializedInfos.find(ExistingDefItr->first); + EDO.ExistingDefItr->second.setFlags(EDO.NewFlags); + + auto UMII = UnmaterializedInfos.find(EDO.ExistingDefItr->first); assert(UMII != UnmaterializedInfos.end() && "Overridden existing def should have an UnmaterializedInfo"); - UMII->second->MU->doDiscard(*this, ExistingDefItr->first); + UMII->second->MU->doDiscard(*this, EDO.ExistingDefItr->first); } // Discard overridden symbols povided by MU. diff --git a/llvm/unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp b/llvm/unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp index 6e6c7371e1d..5b85ffafc9f 100644 --- a/llvm/unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp +++ b/llvm/unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp @@ -259,6 +259,35 @@ TEST(CoreAPIsTest, LookupFlagsTest) { EXPECT_EQ(SymbolFlags[Bar], BarFlags) << "Incorrect flags returned for Bar"; } +TEST(CoreAPIsTest, TestAliases) { + ExecutionSession ES; + auto &V = ES.createVSO("V"); + + auto Foo = ES.getSymbolStringPool().intern("foo"); + auto FooSym = JITEvaluatedSymbol(1U, JITSymbolFlags::Exported); + auto Bar = ES.getSymbolStringPool().intern("bar"); + auto BarSym = JITEvaluatedSymbol(2U, JITSymbolFlags::Exported); + + auto Baz = ES.getSymbolStringPool().intern("baz"); + auto Qux = ES.getSymbolStringPool().intern("qux"); + + auto QuxSym = JITEvaluatedSymbol(3U, JITSymbolFlags::Exported); + + 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}}))); + + auto Result = lookup({&V}, {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\""; + EXPECT_EQ((*Result)[Baz].getAddress(), FooSym.getAddress()) + << "\"Baz\"'s address should match \"Foo\"'s"; + EXPECT_EQ((*Result)[Qux].getAddress(), QuxSym.getAddress()) + << "The \"Qux\" alias should have been overriden"; +} + TEST(CoreAPIsTest, TestTrivialCircularDependency) { ExecutionSession ES; |