From 67feadb2c757d7ff7cbaacdbcdecdf7d077a7c6d Mon Sep 17 00:00:00 2001 From: Lang Hames Date: Mon, 16 Apr 2018 18:05:24 +0000 Subject: [PATCH] [ORC] Add a MaterializationResponsibility class to track responsibility for materializing function definitions. MaterializationUnit instances are responsible for resolving and finalizing symbol definitions when their materialize method is called. By contract, the MaterializationUnit must materialize all definitions it is responsible for and no others. If it can not materialize all definitions (because of some error) then it must notify the associated VSO about each definition that could not be materialized. The MaterializationResponsibility class tracks this responsibility, asserting that all required symbols are resolved and finalized, and that no extraneous symbols are resolved or finalized. In the event of an error it provides a convenience method for notifying the VSO about each definition that could not be materialized. llvm-svn: 330142 --- llvm/include/llvm/ExecutionEngine/Orc/Core.h | 67 ++++--- .../include/llvm/ExecutionEngine/Orc/Legacy.h | 4 +- llvm/lib/ExecutionEngine/Orc/Core.cpp | 171 ++++++++++++------ .../ExecutionEngine/Orc/OrcCBindingsStack.h | 4 +- .../ExecutionEngine/Orc/OrcMCJITReplacement.h | 8 +- .../ExecutionEngine/Orc/CoreAPIsTest.cpp | 95 +++++----- .../Orc/LegacyAPIInteropTest.cpp | 2 +- 7 files changed, 214 insertions(+), 137 deletions(-) diff --git a/llvm/include/llvm/ExecutionEngine/Orc/Core.h b/llvm/include/llvm/ExecutionEngine/Orc/Core.h index 774084e841d6..f47d13c96fb6 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/Core.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/Core.h @@ -118,7 +118,7 @@ public: /// notify-finalized callback is called with the given error. /// /// It is illegal to call setFailed after both callbacks have been made. - void notifyFailed(Error Err); + void notifyMaterializationFailed(Error Err); /// @brief Set the resolved symbol information for the given symbol name. /// @@ -206,6 +206,25 @@ createSymbolResolver(LookupFlagsFn &&LookupFlags, LookupFn &&Lookup) { std::forward(LookupFlags), std::forward(Lookup)); } +/// @brief Tracks responsibility for materialization. +class MaterializationResponsibility { +public: + MaterializationResponsibility(VSO &V, SymbolFlagsMap SymbolFlags); + MaterializationResponsibility(MaterializationResponsibility &&) = default; + MaterializationResponsibility & + operator=(MaterializationResponsibility &&) = default; + ~MaterializationResponsibility(); + MaterializationResponsibility takeResponsibility(SymbolNameSet Symbols); + const VSO &getTargetVSO() const { return V; } + void resolve(const SymbolMap &Symbols); + void finalize(); + void notifyMaterializationFailed(); + +private: + VSO &V; + SymbolFlagsMap SymbolFlags; +}; + /// @brief A MaterializationUnit represents a set of symbol definitions that can /// be materialized as a group, or individually discarded (when /// overriding definitions are encountered). @@ -224,13 +243,13 @@ public: /// @brief Implementations of this method should materialize all symbols /// in the materialzation unit, except for those that have been /// previously discarded. - virtual Error materialize(VSO &V) = 0; + virtual void materialize(MaterializationResponsibility R) = 0; /// @brief Implementations of this method should discard the given symbol /// from the source (e.g. if the source is an LLVM IR Module and the /// symbol is a function, delete the function body or mark it available /// externally). - virtual void discard(VSO &V, SymbolStringPtr Name) = 0; + virtual void discard(const VSO &V, SymbolStringPtr Name) = 0; private: virtual void anchor(); @@ -254,11 +273,21 @@ public: using SetDefinitionsResult = std::map; - using MaterializationUnitList = - std::vector>; + struct Materializer { + public: + Materializer(std::unique_ptr MU, + MaterializationResponsibility R); + void operator()(); + + private: + std::unique_ptr MU; + MaterializationResponsibility R; + }; + + using MaterializerList = std::vector; struct LookupResult { - MaterializationUnitList MaterializationUnits; + MaterializerList Materializers; SymbolNameSet UnresolvedSymbols; }; @@ -321,11 +350,11 @@ public: private: class UnmaterializedInfo { public: - UnmaterializedInfo(size_t SymbolsRemaining, - std::unique_ptr MU); + UnmaterializedInfo(std::unique_ptr MU); + void discard(VSO &V, SymbolStringPtr Name); - uint64_t SymbolsRemaining; std::unique_ptr MU; + SymbolFlagsMap Symbols; }; using UnmaterializedInfoList = std::list; @@ -348,6 +377,7 @@ private: public: SymbolTableEntry(JITSymbolFlags SymbolFlags, UnmaterializedInfoIterator UnmaterializedInfoItr); + SymbolTableEntry(JITSymbolFlags SymbolFlags); SymbolTableEntry(JITEvaluatedSymbol Sym); SymbolTableEntry(SymbolTableEntry &&Other); SymbolTableEntry &operator=(SymbolTableEntry &&Other); @@ -360,8 +390,8 @@ private: void replaceWith(VSO &V, SymbolStringPtr Name, JITSymbolFlags Flags, UnmaterializedInfoIterator NewUMII); - // Move entry to materializing state, detach from UMII. - std::unique_ptr initMaterialize(VSO &V); + // Notify this entry that it is being materialized. + void notifyMaterializing(); // Move entry to resolved state. void resolve(VSO &V, JITEvaluatedSymbol Sym); @@ -380,8 +410,6 @@ private: void destroy(); }; - void detach(UnmaterializedInfoIterator UMII); - std::map Symbols; UnmaterializedInfoList UnmaterializedInfos; MaterializingInfoMap MaterializingInfos; @@ -431,20 +459,11 @@ public: /// ExecutionSession. class MaterializeOnCurrentThread { public: - MaterializeOnCurrentThread(ExecutionSession &ES) : ES(ES) {} - - void operator()(VSO &V, std::unique_ptr MU) { - if (auto Err = MU->materialize(V)) - ES.reportError(std::move(Err)); - } - -private: - ExecutionSession &ES; + void operator()(VSO::Materializer M) { M(); } }; /// Materialization function object wrapper for the lookup method. -using MaterializationDispatcher = - std::function S)>; +using MaterializationDispatcher = std::function; /// @brief Look up a set of symbols by searching a list of VSOs. /// diff --git a/llvm/include/llvm/ExecutionEngine/Orc/Legacy.h b/llvm/include/llvm/ExecutionEngine/Orc/Legacy.h index 73debf3ad193..8ea3f7b76625 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/Legacy.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/Legacy.h @@ -79,11 +79,11 @@ SymbolNameSet lookupWithLegacyFn(AsynchronousSymbolQuery &Query, Query.resolve(S, JITEvaluatedSymbol(*Addr, Sym.getFlags())); Query.finalizeSymbol(); } else { - Query.notifyFailed(Addr.takeError()); + Query.notifyMaterializationFailed(Addr.takeError()); return SymbolNameSet(); } } else if (auto Err = Sym.takeError()) { - Query.notifyFailed(std::move(Err)); + Query.notifyMaterializationFailed(std::move(Err)); return SymbolNameSet(); } else SymbolsNotFound.insert(S); diff --git a/llvm/lib/ExecutionEngine/Orc/Core.cpp b/llvm/lib/ExecutionEngine/Orc/Core.cpp index 3d7ef7d7c4e7..da0c60455b90 100644 --- a/llvm/lib/ExecutionEngine/Orc/Core.cpp +++ b/llvm/lib/ExecutionEngine/Orc/Core.cpp @@ -123,7 +123,7 @@ AsynchronousSymbolQuery::AsynchronousSymbolQuery( OutstandingResolutions = OutstandingFinalizations = Symbols.size(); } -void AsynchronousSymbolQuery::notifyFailed(Error Err) { +void AsynchronousSymbolQuery::notifyMaterializationFailed(Error Err) { if (OutstandingResolutions != 0) NotifySymbolsResolved(std::move(Err)); else if (OutstandingFinalizations != 0) @@ -159,9 +159,76 @@ void AsynchronousSymbolQuery::finalizeSymbol() { NotifySymbolsReady(Error::success()); } +MaterializationResponsibility::MaterializationResponsibility( + VSO &V, SymbolFlagsMap SymbolFlags) + : V(V), SymbolFlags(std::move(SymbolFlags)) { + assert(!this->SymbolFlags.empty() && "Materializing nothing?"); +} + +MaterializationResponsibility::~MaterializationResponsibility() { + assert(SymbolFlags.empty() && + "All symbols should have been explicitly materialized or failed"); +} + +MaterializationResponsibility +MaterializationResponsibility::takeResponsibility(SymbolNameSet Symbols) { + SymbolFlagsMap ExtractedFlags; + + for (auto &S : Symbols) { + auto I = SymbolFlags.find(S); + ExtractedFlags.insert(*I); + SymbolFlags.erase(I); + } + + return MaterializationResponsibility(V, std::move(ExtractedFlags)); +} + +void MaterializationResponsibility::resolve(const SymbolMap &Symbols) { +#ifndef NDEBUG + for (auto &KV : Symbols) { + auto I = SymbolFlags.find(KV.first); + assert(I != SymbolFlags.end() && + "Resolving symbol outside this responsibility set"); + assert(KV.second.getFlags() == I->second && + "Resolving symbol with incorrect flags"); + } +#endif + V.resolve(Symbols); +} + +void MaterializationResponsibility::finalize() { + SymbolNameSet SymbolNames; + for (auto &KV : SymbolFlags) + SymbolNames.insert(KV.first); + SymbolFlags.clear(); + V.finalize(SymbolNames); +} + +void MaterializationResponsibility::notifyMaterializationFailed() { + SymbolNameSet SymbolNames; + for (auto &KV : SymbolFlags) + SymbolNames.insert(KV.first); + SymbolFlags.clear(); + V.notifyMaterializationFailed(SymbolNames); +} + +VSO::Materializer::Materializer(std::unique_ptr MU, + MaterializationResponsibility R) + : MU(std::move(MU)), R(std::move(R)) {} + +void VSO::Materializer::operator()() { MU->materialize(std::move(R)); } + VSO::UnmaterializedInfo::UnmaterializedInfo( - size_t SymbolsRemaining, std::unique_ptr MU) - : SymbolsRemaining(SymbolsRemaining), MU(std::move(MU)) {} + std::unique_ptr MU) + : MU(std::move(MU)), Symbols(this->MU->getSymbols()) {} + +void VSO::UnmaterializedInfo::discard(VSO &V, SymbolStringPtr Name) { + assert(MU && "No materializer attached"); + MU->discard(V, Name); + auto I = Symbols.find(Name); + assert(I != Symbols.end() && "Symbol not found in this MU"); + Symbols.erase(I); +} VSO::SymbolTableEntry::SymbolTableEntry(JITSymbolFlags Flags, UnmaterializedInfoIterator UMII) @@ -204,9 +271,9 @@ void VSO::SymbolTableEntry::replaceWith(VSO &V, SymbolStringPtr Name, assert(!Flags.isMaterializing() && "Attempting to replace definition during materialization?"); if (Flags.isLazy()) { - if (UMII->MU) - UMII->MU->discard(V, Name); - V.detach(UMII); + UMII->discard(V, Name); + if (UMII->Symbols.empty()) + V.UnmaterializedInfos.erase(UMII); } destroy(); Flags = Sym.getFlags(); @@ -219,39 +286,34 @@ void VSO::SymbolTableEntry::replaceWith(VSO &V, SymbolStringPtr Name, assert(!Flags.isMaterializing() && "Attempting to replace definition during materialization?"); if (Flags.isLazy()) { - if (UMII->MU) - UMII->MU->discard(V, Name); - V.detach(UMII); + UMII->discard(V, Name); + if (UMII->Symbols.empty()) + V.UnmaterializedInfos.erase(UMII); } destroy(); Flags = NewFlags; UMII = std::move(NewUMII); } -std::unique_ptr -VSO::SymbolTableEntry::initMaterialize(VSO &V) { - assert(Flags.isLazy() && "Can't materialize non-lazy symbol"); - auto TmpMU = std::move(UMII->MU); - V.detach(UMII); - destroy(); +void VSO::SymbolTableEntry::notifyMaterializing() { + assert(Flags.isLazy() && "Can only start materializing from lazy state"); + UMII.~UnmaterializedInfoIterator(); Flags &= ~JITSymbolFlags::Lazy; Flags |= JITSymbolFlags::Materializing; Address = 0; - return TmpMU; } void VSO::SymbolTableEntry::resolve(VSO &V, JITEvaluatedSymbol Sym) { - if (Flags.isLazy()) { - assert(!UMII->MU && "Resolving with MaterializationUnit still attached?"); - V.detach(UMII); - } - destroy(); + assert(!Flags.isLazy() && Flags.isMaterializing() && + "Can only resolve in materializing state"); Flags = Sym.getFlags(); Flags |= JITSymbolFlags::Materializing; Address = Sym.getAddress(); + assert(Address != 0 && "Can not resolve to null"); } void VSO::SymbolTableEntry::finalize() { + assert(Address != 0 && "Cannot finalize with null address"); assert(Flags.isMaterializing() && !Flags.isLazy() && "Symbol should be in materializing state"); Flags &= ~JITSymbolFlags::Materializing; @@ -262,14 +324,6 @@ void VSO::SymbolTableEntry::destroy() { UMII.~UnmaterializedInfoIterator(); } -void VSO::detach(UnmaterializedInfoIterator UMII) { - assert(UMII->SymbolsRemaining > 0 && - "Detaching from empty UnmaterializedInfo?"); - --UMII->SymbolsRemaining; - if (UMII->SymbolsRemaining == 0) - UnmaterializedInfos.erase(UMII); -} - VSO::RelativeLinkageStrength VSO::compareLinkage(Optional Old, JITSymbolFlags New) { if (Old == None) @@ -325,14 +379,11 @@ Error VSO::define(SymbolMap NewSymbols) { Error VSO::defineLazy(std::unique_ptr MU) { - auto NewSymbols = MU->getSymbols(); - - auto UMII = UnmaterializedInfos.insert( - UnmaterializedInfos.end(), - UnmaterializedInfo(NewSymbols.size(), std::move(MU))); + auto UMII = UnmaterializedInfos.insert(UnmaterializedInfos.end(), + UnmaterializedInfo(std::move(MU))); Error Err = Error::success(); - for (auto &KV : NewSymbols) { + for (auto &KV : UMII->Symbols) { auto I = Symbols.find(KV.first); assert(I == Symbols.end() || @@ -345,8 +396,7 @@ Error VSO::defineLazy(std::unique_ptr MU) { // Discard weaker definitions. if (LinkageResult == ExistingDefinitionIsStronger) { - UMII->MU->discard(*this, KV.first); - detach(UMII); + UMII->discard(*this, KV.first); continue; } @@ -356,7 +406,7 @@ Error VSO::defineLazy(std::unique_ptr MU) { make_error(*KV.first)); // Duplicate definitions are discarded, so remove the duplicates from // materializer. - detach(UMII); + UMII->discard(*this, KV.first); continue; } @@ -368,6 +418,9 @@ Error VSO::defineLazy(std::unique_ptr MU) { std::make_pair(KV.first, SymbolTableEntry(KV.second, UMII))); } + if (UMII->Symbols.empty()) + UnmaterializedInfos.erase(UMII); + return Err; } @@ -417,10 +470,12 @@ void VSO::notifyMaterializationFailed(const SymbolNameSet &Names) { } for (auto &KV : ResolutionFailures) - KV.first->notifyFailed(make_error(std::move(KV.second))); + KV.first->notifyMaterializationFailed( + make_error(std::move(KV.second))); for (auto &KV : FinalizationFailures) - KV.first->notifyFailed(make_error(std::move(KV.second))); + KV.first->notifyMaterializationFailed( + make_error(std::move(KV.second))); } void VSO::finalize(const SymbolNameSet &SymbolsToFinalize) { @@ -461,7 +516,7 @@ SymbolNameSet VSO::lookupFlags(SymbolFlagsMap &Flags, SymbolNameSet Names) { VSO::LookupResult VSO::lookup(std::shared_ptr Query, SymbolNameSet Names) { - MaterializationUnitList MaterializationUnits; + MaterializerList Materializers; for (SymbolNameSet::iterator I = Names.begin(), E = Names.end(); I != E;) { auto Tmp = I++; @@ -474,11 +529,26 @@ VSO::LookupResult VSO::lookup(std::shared_ptr Query, // The symbol is in the VSO. Erase it from Names and proceed. Names.erase(Tmp); - // If this symbol has not been materialized yet, move it to materializing, - // then fall through to the materializing case below. + // If this symbol has not been materialized yet grab its materializer, + // move all of its sibling symbols to the materializing state, and + // delete its unmaterialized info. if (SymI->second.Flags.isLazy()) { - if (auto MU = SymI->second.initMaterialize(*this)) - MaterializationUnits.push_back(std::move(MU)); + assert(SymI->second.UMII->MU && + "Lazy symbol has no materializer attached"); + auto MU = std::move(SymI->second.UMII->MU); + auto SymbolFlags = std::move(SymI->second.UMII->Symbols); + UnmaterializedInfos.erase(SymI->second.UMII); + + for (auto &KV : SymbolFlags) { + auto SiblingI = Symbols.find(KV.first); + MaterializingInfos.insert( + std::make_pair(SiblingI->first, MaterializingInfo())); + SiblingI->second.notifyMaterializing(); + } + + Materializers.push_back(Materializer( + std::move(MU), + MaterializationResponsibility(*this, std::move(SymbolFlags)))); } // If this symbol already has a fully materialized value, just use it. @@ -492,10 +562,7 @@ VSO::LookupResult VSO::lookup(std::shared_ptr Query, // If this symbol is materializing, then get (or create) its // MaterializingInfo struct and appaend the query. auto J = MaterializingInfos.find(SymI->first); - if (J == MaterializingInfos.end()) - J = MaterializingInfos - .insert(std::make_pair(SymI->first, MaterializingInfo())) - .first; + assert(J != MaterializingInfos.end() && "Missing MaterializingInfo"); if (SymI->second.Address) { auto Sym = JITEvaluatedSymbol(SymI->second.Address, SymI->second.Flags); @@ -510,7 +577,7 @@ VSO::LookupResult VSO::lookup(std::shared_ptr Query, } } - return {std::move(MaterializationUnits), std::move(Names)}; + return {std::move(Materializers), std::move(Names)}; } Expected lookup(const std::vector &VSOs, SymbolNameSet Names, @@ -574,8 +641,8 @@ Expected lookup(const std::vector &VSOs, SymbolNameSet Names, auto LR = V->lookup(Query, UnresolvedSymbols); UnresolvedSymbols = std::move(LR.UnresolvedSymbols); - for (auto &MU : LR.MaterializationUnits) - DispatchMaterialization(*V, std::move(MU)); + for (auto &M : LR.Materializers) + DispatchMaterialization(std::move(M)); } #if LLVM_ENABLE_THREADS diff --git a/llvm/lib/ExecutionEngine/Orc/OrcCBindingsStack.h b/llvm/lib/ExecutionEngine/Orc/OrcCBindingsStack.h index ab0c9f07a140..268597cec66d 100644 --- a/llvm/lib/ExecutionEngine/Orc/OrcCBindingsStack.h +++ b/llvm/lib/ExecutionEngine/Orc/OrcCBindingsStack.h @@ -155,11 +155,11 @@ private: if (auto Addr = Sym.getAddress()) Query->resolve(S, JITEvaluatedSymbol(*Addr, Sym.getFlags())); else { - Query->notifyFailed(Addr.takeError()); + Query->notifyMaterializationFailed(Addr.takeError()); return orc::SymbolNameSet(); } } else if (auto Err = Sym.takeError()) { - Query->notifyFailed(std::move(Err)); + Query->notifyMaterializationFailed(std::move(Err)); return orc::SymbolNameSet(); } else UnresolvedSymbols.insert(S); diff --git a/llvm/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h b/llvm/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h index 73af52055e82..67a270e6c45b 100644 --- a/llvm/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h +++ b/llvm/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h @@ -177,22 +177,22 @@ class OrcMCJITReplacement : public ExecutionEngine { if (auto Addr = Sym.getAddress()) Query->resolve(S, JITEvaluatedSymbol(*Addr, Sym.getFlags())); else { - Query->notifyFailed(Addr.takeError()); + Query->notifyMaterializationFailed(Addr.takeError()); return SymbolNameSet(); } } else if (auto Err = Sym.takeError()) { - Query->notifyFailed(std::move(Err)); + Query->notifyMaterializationFailed(std::move(Err)); return SymbolNameSet(); } else { if (auto Sym2 = M.ClientResolver->findSymbol(*S)) { if (auto Addr = Sym2.getAddress()) Query->resolve(S, JITEvaluatedSymbol(*Addr, Sym2.getFlags())); else { - Query->notifyFailed(Addr.takeError()); + Query->notifyMaterializationFailed(Addr.takeError()); return SymbolNameSet(); } } else if (auto Err = Sym2.takeError()) { - Query->notifyFailed(std::move(Err)); + Query->notifyMaterializationFailed(std::move(Err)); return SymbolNameSet(); } else UnresolvedSymbols.insert(S); diff --git a/llvm/unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp b/llvm/unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp index a2d815a53e39..ee2b36074b30 100644 --- a/llvm/unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp +++ b/llvm/unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp @@ -22,8 +22,9 @@ namespace { class SimpleMaterializationUnit : public MaterializationUnit { public: using GetSymbolsFunction = std::function; - using MaterializeFunction = std::function; - using DiscardFunction = std::function; + using MaterializeFunction = + std::function; + using DiscardFunction = std::function; using DestructorFunction = std::function; SimpleMaterializationUnit( @@ -40,9 +41,11 @@ public: SymbolFlagsMap getSymbols() override { return GetSymbols(); } - Error materialize(VSO &V) override { return Materialize(V); } + void materialize(MaterializationResponsibility R) override { + Materialize(std::move(R)); + } - void discard(VSO &V, SymbolStringPtr Name) override { + void discard(const VSO &V, SymbolStringPtr Name) override { Discard(V, std::move(Name)); } @@ -103,7 +106,8 @@ TEST(CoreAPIsTest, AsynchronousSymbolQueryResolutionErrorOnly) { AsynchronousSymbolQuery Q(Names, OnResolution, OnReady); - Q.notifyFailed(make_error("xyz", inconvertibleErrorCode())); + Q.notifyMaterializationFailed( + make_error("xyz", inconvertibleErrorCode())); EXPECT_TRUE(OnResolutionRun) << "OnResolutionCallback was not run"; EXPECT_FALSE(OnReadyRun) << "OnReady unexpectedly run"; @@ -165,10 +169,10 @@ TEST(CoreAPIsTest, LookupFlagsTest) { [=]() { return SymbolFlagsMap({{Bar, BarFlags}}); }, - [](VSO &V) -> Error { + [](MaterializationResponsibility R) { llvm_unreachable("Symbol materialized on flags lookup"); }, - [](VSO &V, SymbolStringPtr Name) -> Error { + [](const VSO &V, SymbolStringPtr Name) { llvm_unreachable("Symbol finalized on flags lookup"); }); @@ -206,10 +210,10 @@ TEST(CoreAPIsTest, DropMaterializerWhenEmpty) { return SymbolFlagsMap( {{Foo, JITSymbolFlags::Weak}, {Bar, JITSymbolFlags::Weak}}); }, - [](VSO &V) -> Error { + [](MaterializationResponsibility R) { llvm_unreachable("Unexpected call to materialize"); }, - [&](VSO &V, SymbolStringPtr Name) { + [&](const VSO &V, SymbolStringPtr Name) { EXPECT_TRUE(Name == Foo || Name == Bar) << "Discard of unexpected symbol?"; }, @@ -253,19 +257,16 @@ TEST(CoreAPIsTest, AddAndMaterializeLazySymbol) { {Bar, static_cast( JITSymbolFlags::Exported | JITSymbolFlags::Weak)}}); }, - [&](VSO &V) { + [&](MaterializationResponsibility R) { assert(BarDiscarded && "Bar should have been discarded by this point"); SymbolMap SymbolsToResolve; SymbolsToResolve[Foo] = JITEvaluatedSymbol(FakeFooAddr, JITSymbolFlags::Exported); - V.resolve(std::move(SymbolsToResolve)); - SymbolNameSet SymbolsToFinalize; - SymbolsToFinalize.insert(Foo); - V.finalize(SymbolsToFinalize); + R.resolve(std::move(SymbolsToResolve)); + R.finalize(); FooMaterialized = true; - return Error::success(); }, - [&](VSO &V, SymbolStringPtr Name) { + [&](const VSO &V, SymbolStringPtr Name) { EXPECT_EQ(Name, Bar) << "Expected Name to be Bar"; BarDiscarded = true; }); @@ -300,8 +301,8 @@ TEST(CoreAPIsTest, AddAndMaterializeLazySymbol) { auto LR = V.lookup(std::move(Q), Names); - for (auto &SWKV : LR.MaterializationUnits) - cantFail(SWKV->materialize(V)); + for (auto &M : LR.Materializers) + M(); EXPECT_TRUE(LR.UnresolvedSymbols.empty()) << "Could not find Foo in dylib"; EXPECT_TRUE(FooMaterialized) << "Foo was not materialized"; @@ -322,11 +323,8 @@ TEST(CoreAPIsTest, FailResolution) { return SymbolFlagsMap( {{Foo, JITSymbolFlags::Weak}, {Bar, JITSymbolFlags::Weak}}); }, - [&](VSO &V) -> Error { - V.notifyMaterializationFailed(Names); - return Error::success(); - }, - [&](VSO &V, SymbolStringPtr Name) { + [&](MaterializationResponsibility R) { R.notifyMaterializationFailed(); }, + [&](const VSO &V, SymbolStringPtr Name) { llvm_unreachable("Unexpected call to discard"); }); @@ -361,8 +359,8 @@ TEST(CoreAPIsTest, FailResolution) { std::make_shared(Names, OnResolution, OnReady); auto LR = V.lookup(std::move(Q), Names); - for (auto &SWKV : LR.MaterializationUnits) - cantFail(SWKV->materialize(V)); + for (auto &M : LR.Materializers) + M(); } TEST(CoreAPIsTest, FailFinalization) { @@ -375,19 +373,18 @@ TEST(CoreAPIsTest, FailFinalization) { auto MU = llvm::make_unique( [=]() { return SymbolFlagsMap( - {{Foo, JITSymbolFlags::Weak}, {Bar, JITSymbolFlags::Weak}}); + {{Foo, JITSymbolFlags::Exported}, {Bar, JITSymbolFlags::Exported}}); }, - [&](VSO &V) -> Error { + [&](MaterializationResponsibility R) { constexpr JITTargetAddress FakeFooAddr = 0xdeadbeef; constexpr JITTargetAddress FakeBarAddr = 0xcafef00d; auto FooSym = JITEvaluatedSymbol(FakeFooAddr, JITSymbolFlags::Exported); auto BarSym = JITEvaluatedSymbol(FakeBarAddr, JITSymbolFlags::Exported); - V.resolve(SymbolMap({{Foo, FooSym}, {Bar, BarSym}})); - V.notifyMaterializationFailed(Names); - return Error::success(); + R.resolve(SymbolMap({{Foo, FooSym}, {Bar, BarSym}})); + R.notifyMaterializationFailed(); }, - [&](VSO &V, SymbolStringPtr Name) { + [&](const VSO &V, SymbolStringPtr Name) { llvm_unreachable("Unexpected call to discard"); }); @@ -421,8 +418,8 @@ TEST(CoreAPIsTest, FailFinalization) { std::make_shared(Names, OnResolution, OnReady); auto LR = V.lookup(std::move(Q), Names); - for (auto &SWKV : LR.MaterializationUnits) - cantFail(SWKV->materialize(V)); + for (auto &M : LR.Materializers) + M(); } TEST(CoreAPIsTest, TestLambdaSymbolResolver) { @@ -443,7 +440,7 @@ TEST(CoreAPIsTest, TestLambdaSymbolResolver) { }, [&](std::shared_ptr Q, SymbolNameSet Symbols) { auto LR = V.lookup(std::move(Q), Symbols); - assert(LR.MaterializationUnits.empty() && + assert(LR.Materializers.empty() && "Test generated unexpected materialization work?"); return std::move(LR.UnresolvedSymbols); }); @@ -503,12 +500,11 @@ TEST(CoreAPIsTest, TestLookupWithUnthreadedMaterialization) { [=]() { return SymbolFlagsMap({{Foo, JITSymbolFlags::Exported}}); }, - [&](VSO &V) -> Error { - V.resolve({{Foo, FooSym}}); - V.finalize({Foo}); - return Error::success(); + [&](MaterializationResponsibility R) { + R.resolve({{Foo, FooSym}}); + R.finalize(); }, - [](VSO &V, SymbolStringPtr Name) -> Error { + [](const VSO &V, SymbolStringPtr Name) { llvm_unreachable("Not expecting finalization"); }); @@ -517,7 +513,7 @@ TEST(CoreAPIsTest, TestLookupWithUnthreadedMaterialization) { cantFail(V.defineLazy(std::move(MU))); auto FooLookupResult = - cantFail(lookup({&V}, Foo, MaterializeOnCurrentThread(ES))); + cantFail(lookup({&V}, Foo, MaterializeOnCurrentThread())); EXPECT_EQ(FooLookupResult.getAddress(), FooSym.getAddress()) << "lookup returned an incorrect address"; @@ -537,12 +533,11 @@ TEST(CoreAPIsTest, TestLookupWithThreadedMaterialization) { [=]() { return SymbolFlagsMap({{Foo, JITSymbolFlags::Exported}}); }, - [&](VSO &V) -> Error { - V.resolve({{Foo, FooSym}}); - V.finalize({Foo}); - return Error::success(); + [&](MaterializationResponsibility R) { + R.resolve({{Foo, FooSym}}); + R.finalize(); }, - [](VSO &V, SymbolStringPtr Name) -> Error { + [](const VSO &V, SymbolStringPtr Name) { llvm_unreachable("Not expecting finalization"); }); @@ -551,14 +546,10 @@ TEST(CoreAPIsTest, TestLookupWithThreadedMaterialization) { cantFail(V.defineLazy(std::move(MU))); std::thread MaterializationThread; - auto MaterializeOnNewThread = [&](VSO &V, - std::unique_ptr MU) { + auto MaterializeOnNewThread = [&](VSO::Materializer M) { // FIXME: Use move capture once we move to C++14. - std::shared_ptr SharedMU = std::move(MU); - MaterializationThread = std::thread([&ES, &V, SharedMU]() { - if (auto Err = SharedMU->materialize(V)) - ES.reportError(std::move(Err)); - }); + auto SharedM = std::make_shared(std::move(M)); + MaterializationThread = std::thread([SharedM]() { (*SharedM)(); }); }; auto FooLookupResult = diff --git a/llvm/unittests/ExecutionEngine/Orc/LegacyAPIInteropTest.cpp b/llvm/unittests/ExecutionEngine/Orc/LegacyAPIInteropTest.cpp index db29024f4705..514aafaff437 100644 --- a/llvm/unittests/ExecutionEngine/Orc/LegacyAPIInteropTest.cpp +++ b/llvm/unittests/ExecutionEngine/Orc/LegacyAPIInteropTest.cpp @@ -35,7 +35,7 @@ TEST(LegacyAPIInteropTest, QueryAgainstVSO) { auto Lookup = [&](std::shared_ptr Query, SymbolNameSet Symbols) { auto R = V.lookup(std::move(Query), Symbols); - EXPECT_TRUE(R.MaterializationUnits.empty()) + EXPECT_TRUE(R.Materializers.empty()) << "Query resulted in unexpected materialization work"; return std::move(R.UnresolvedSymbols); };