diff options
Diffstat (limited to 'llvm')
| -rw-r--r-- | llvm/include/llvm/ExecutionEngine/Orc/Core.h | 103 | ||||
| -rw-r--r-- | llvm/lib/ExecutionEngine/Orc/Core.cpp | 278 | ||||
| -rw-r--r-- | llvm/unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp | 105 | ||||
| -rw-r--r-- | llvm/unittests/ExecutionEngine/Orc/LegacyAPIInteropTest.cpp | 2 |
4 files changed, 281 insertions, 207 deletions
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/Core.h b/llvm/include/llvm/ExecutionEngine/Orc/Core.h index bddef0e83ba..26fec8b359f 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/Core.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/Core.h @@ -157,22 +157,25 @@ createSymbolResolver(LookupFlagsFn &&LookupFlags, LookupFn &&Lookup) { std::forward<LookupFlagsFn>(LookupFlags), std::forward<LookupFn>(Lookup)); } -/// @brief Represents a source of symbol definitions which may be materialized -/// (turned into data / code through some materialization process) or -/// discarded (if the definition is overridden by a stronger one). +/// @brief A MaterializationUnit represents a set of symbol definitions that can +/// be materialized as a group, or individually discarded (when +/// overriding definitions are encountered). /// -/// SymbolSources are used when providing lazy definitions of symbols to VSOs. -/// The VSO will call materialize when the address of a symbol is requested via -/// the lookup method. The VSO will call discard if a stronger definition is -/// added or already present. -class SymbolSource { +/// MaterializationUnits are used when providing lazy definitions of symbols to +/// VSOs. The VSO will call materialize when the address of a symbol is +/// requested via the lookup method. The VSO will call discard if a stronger +/// definition is added or already present. +class MaterializationUnit { public: - virtual ~SymbolSource() {} + virtual ~MaterializationUnit() {} - /// @brief Implementations of this method should materialize the given - /// symbols (plus any additional symbols required) by adding a - /// Materializer to the ExecutionSession's MaterializationQueue. - virtual Error materialize(VSO &V, SymbolNameSet Symbols) = 0; + /// @brief Return the set of symbols that this source provides. + virtual SymbolFlagsMap getSymbols() = 0; + + /// @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; /// @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 @@ -201,10 +204,12 @@ public: using SetDefinitionsResult = std::map<SymbolStringPtr, RelativeLinkageStrength>; - using SourceWorkMap = std::map<std::shared_ptr<SymbolSource>, SymbolNameSet>; + + using MaterializationUnitList = + std::vector<std::unique_ptr<MaterializationUnit>>; struct LookupResult { - SourceWorkMap MaterializationWork; + MaterializationUnitList MaterializationUnits; SymbolNameSet UnresolvedSymbols; }; @@ -231,8 +236,7 @@ public: Error define(SymbolMap NewSymbols); /// @brief Adds the given symbols to the mapping as lazy symbols. - Error defineLazy(const SymbolFlagsMap &NewSymbols, - std::shared_ptr<SymbolSource> Source); + Error defineLazy(std::unique_ptr<MaterializationUnit> Source); /// @brief Add the given symbol/address mappings to the dylib, but do not /// mark the symbols as finalized yet. @@ -265,50 +269,54 @@ public: private: class MaterializationInfo { public: - MaterializationInfo(JITSymbolFlags Flags, - std::shared_ptr<SymbolSource> Query); - JITSymbolFlags getFlags() const; - JITTargetAddress getAddress() const; - void replaceWithSource(VSO &V, SymbolStringPtr Name, - JITSymbolFlags NewFlags, - std::shared_ptr<SymbolSource> NewSource); - std::shared_ptr<SymbolSource> - query(SymbolStringPtr Name, std::shared_ptr<AsynchronousSymbolQuery> Query); - void resolve(VSO &V, SymbolStringPtr Name, JITEvaluatedSymbol Sym); - void finalize(); + using QueryList = std::vector<std::shared_ptr<AsynchronousSymbolQuery>>; - private: - JITSymbolFlags Flags; - JITTargetAddress Address = 0; - std::shared_ptr<SymbolSource> Source; - std::vector<std::shared_ptr<AsynchronousSymbolQuery>> PendingResolution; - std::vector<std::shared_ptr<AsynchronousSymbolQuery>> PendingFinalization; + MaterializationInfo(size_t SymbolsRemaining, + std::unique_ptr<MaterializationUnit> MU); + + uint64_t SymbolsRemaining; + std::unique_ptr<MaterializationUnit> MU; + SymbolMap Symbols; + std::map<SymbolStringPtr, QueryList> PendingResolution; + std::map<SymbolStringPtr, QueryList> PendingFinalization; }; + using MaterializationInfoSet = std::set<std::unique_ptr<MaterializationInfo>>; + + using MaterializationInfoIterator = MaterializationInfoSet::iterator; + class SymbolTableEntry { public: - SymbolTableEntry(JITSymbolFlags Flags, - std::shared_ptr<SymbolSource> Source); + SymbolTableEntry(JITSymbolFlags SymbolFlags, + MaterializationInfoIterator MaterializationInfoItr); SymbolTableEntry(JITEvaluatedSymbol Sym); SymbolTableEntry(SymbolTableEntry &&Other); ~SymbolTableEntry(); + + SymbolTableEntry &operator=(JITEvaluatedSymbol Sym); + JITSymbolFlags getFlags() const; - void replaceWithSource(VSO &V, SymbolStringPtr Name, JITSymbolFlags Flags, - std::shared_ptr<SymbolSource> NewSource); - std::shared_ptr<SymbolSource> + void replaceWith(VSO &V, SymbolStringPtr Name, JITSymbolFlags Flags, + MaterializationInfoIterator NewMaterializationInfoItr); + std::unique_ptr<MaterializationUnit> query(SymbolStringPtr Name, std::shared_ptr<AsynchronousSymbolQuery> Query); void resolve(VSO &V, SymbolStringPtr Name, JITEvaluatedSymbol Sym); - void finalize(); + void finalize(VSO &V, SymbolStringPtr Name); + void discard(VSO &V, SymbolStringPtr Name); private: + void destroy(); + JITSymbolFlags Flags; + MaterializationInfoIterator MII; union { JITTargetAddress Address; - std::unique_ptr<MaterializationInfo> MatInfo; + MaterializationInfoIterator MaterializationInfoItr; }; }; std::map<SymbolStringPtr, SymbolTableEntry> Symbols; + MaterializationInfoSet MaterializationInfos; }; /// @brief An ExecutionSession represents a running JIT program. @@ -350,15 +358,14 @@ public: ErrorReporter ReportError = logErrorsToStdErr; }; -/// Runs SymbolSource materializations on the current thread and reports errors -/// to the given ExecutionSession. +/// Runs Materializers on the current thread and reports errors to the given +/// ExecutionSession. class MaterializeOnCurrentThread { public: MaterializeOnCurrentThread(ExecutionSession &ES) : ES(ES) {} - void operator()(VSO &V, std::shared_ptr<SymbolSource> Source, - SymbolNameSet Names) { - if (auto Err = Source->materialize(V, std::move(Names))) + void operator()(VSO &V, std::unique_ptr<MaterializationUnit> MU) { + if (auto Err = MU->materialize(V)) ES.reportError(std::move(Err)); } @@ -367,8 +374,8 @@ private: }; /// Materialization function object wrapper for the lookup method. -using MaterializationDispatcher = std::function<void( - VSO &V, std::shared_ptr<SymbolSource> S, SymbolNameSet Names)>; +using MaterializationDispatcher = + std::function<void(VSO &V, std::unique_ptr<MaterializationUnit> S)>; /// @brief Look up a set of symbols by searching a list of VSOs. /// diff --git a/llvm/lib/ExecutionEngine/Orc/Core.cpp b/llvm/lib/ExecutionEngine/Orc/Core.cpp index 19ca781fa67..cb8304b5ed2 100644 --- a/llvm/lib/ExecutionEngine/Orc/Core.cpp +++ b/llvm/lib/ExecutionEngine/Orc/Core.cpp @@ -1,4 +1,4 @@ -//===--------- Core.cpp - Core ORC APIs (SymbolSource, VSO, etc.) ---------===// +//===----- Core.cpp - Core ORC APIs (MaterializationUnit, VSO, etc.) ------===// // // The LLVM Compiler Infrastructure // @@ -17,8 +17,8 @@ namespace llvm { namespace orc { +void MaterializationUnit::anchor() {} void SymbolResolver::anchor() {} -void SymbolSource::anchor() {} AsynchronousSymbolQuery::AsynchronousSymbolQuery( const SymbolNameSet &Symbols, SymbolsResolvedCallback NotifySymbolsResolved, @@ -69,68 +69,13 @@ void AsynchronousSymbolQuery::notifySymbolFinalized() { } VSO::MaterializationInfo::MaterializationInfo( - JITSymbolFlags Flags, std::shared_ptr<SymbolSource> Source) - : Flags(std::move(Flags)), Source(std::move(Source)) {} + size_t SymbolsRemaining, std::unique_ptr<MaterializationUnit> MU) + : SymbolsRemaining(SymbolsRemaining), MU(std::move(MU)) {} -JITSymbolFlags VSO::MaterializationInfo::getFlags() const { return Flags; } - -JITTargetAddress VSO::MaterializationInfo::getAddress() const { - return Address; -} - -void VSO::MaterializationInfo::replaceWithSource( - VSO &V, SymbolStringPtr Name, JITSymbolFlags NewFlags, - std::shared_ptr<SymbolSource> NewSource) { - assert(Address == 0 && PendingResolution.empty() && - PendingFinalization.empty() && - "Cannot replace source during or after materialization"); - Source->discard(V, Name); - Flags = std::move(NewFlags); - Source = std::move(NewSource); -} - -std::shared_ptr<SymbolSource> VSO::MaterializationInfo::query( - SymbolStringPtr Name, std::shared_ptr<AsynchronousSymbolQuery> Query) { - if (Address == 0) { - PendingResolution.push_back(std::move(Query)); - auto S = std::move(Source); - Source = nullptr; - return S; - } - - Query->setDefinition(Name, JITEvaluatedSymbol(Address, Flags)); - PendingFinalization.push_back(std::move(Query)); - return nullptr; -} - -void VSO::MaterializationInfo::resolve(VSO &V, SymbolStringPtr Name, - JITEvaluatedSymbol Sym) { - if (Source) { - Source->discard(V, Name); - Source = nullptr; - } - - // FIXME: Sanity check flags? - Flags = Sym.getFlags(); - Address = Sym.getAddress(); - for (auto &Query : PendingResolution) { - Query->setDefinition(Name, std::move(Sym)); - PendingFinalization.push_back(std::move(Query)); - } - PendingResolution = {}; -} - -void VSO::MaterializationInfo::finalize() { - for (auto &Query : PendingFinalization) - Query->notifySymbolFinalized(); - PendingFinalization = {}; -} - -VSO::SymbolTableEntry::SymbolTableEntry(JITSymbolFlags Flags, - std::shared_ptr<SymbolSource> Source) +VSO::SymbolTableEntry::SymbolTableEntry( + JITSymbolFlags Flags, MaterializationInfoIterator MaterializationInfoItr) : Flags(JITSymbolFlags::FlagNames(Flags | JITSymbolFlags::NotMaterialized)), - MatInfo( - llvm::make_unique<MaterializationInfo>(Flags, std::move(Source))) { + MaterializationInfoItr(std::move(MaterializationInfoItr)) { // FIXME: Assert flag sanity. } @@ -144,37 +89,83 @@ VSO::SymbolTableEntry::SymbolTableEntry(SymbolTableEntry &&Other) if (Flags.isMaterialized()) Address = Other.Address; else - MatInfo = std::move(Other.MatInfo); + MaterializationInfoItr = std::move(Other.MaterializationInfoItr); } -VSO::SymbolTableEntry::~SymbolTableEntry() { +VSO::SymbolTableEntry::~SymbolTableEntry() { destroy(); } + +VSO::SymbolTableEntry &VSO::SymbolTableEntry:: +operator=(JITEvaluatedSymbol Sym) { + destroy(); + Flags = Sym.getFlags(); + Address = Sym.getAddress(); + return *this; +} + +void VSO::SymbolTableEntry::destroy() { if (!Flags.isMaterialized()) - MatInfo.std::unique_ptr<MaterializationInfo>::~unique_ptr(); + MaterializationInfoItr + .MaterializationInfoIterator::~MaterializationInfoIterator(); } JITSymbolFlags VSO::SymbolTableEntry::getFlags() const { return Flags; } -void VSO::SymbolTableEntry::replaceWithSource( +void VSO::SymbolTableEntry::replaceWith( VSO &V, SymbolStringPtr Name, JITSymbolFlags NewFlags, - std::shared_ptr<SymbolSource> NewSource) { - bool ReplaceExisting = !Flags.isMaterialized(); + MaterializationInfoIterator NewMaterializationInfoItr) { + bool ReplaceExistingLazyDefinition = !Flags.isMaterialized(); Flags = NewFlags; - if (ReplaceExisting) - MatInfo->replaceWithSource(V, Name, Flags, std::move(NewSource)); - else - new (&MatInfo) std::unique_ptr<MaterializationInfo>( - llvm::make_unique<MaterializationInfo>(Flags, std::move(NewSource))); + if (ReplaceExistingLazyDefinition) { + // If we are replacing an existing lazy definition with a stronger one, + // we need to notify the old lazy definition to discard its definition. + assert((*MaterializationInfoItr)->MU != nullptr && + (*MaterializationInfoItr)->Symbols.count(Name) == 0 && + (*MaterializationInfoItr)->PendingResolution.count(Name) == 0 && + (*MaterializationInfoItr)->PendingFinalization.count(Name) == 0 && + "Attempt to replace materializer during materialization"); + + if (--(*MaterializationInfoItr)->SymbolsRemaining == 0) + V.MaterializationInfos.erase(MaterializationInfoItr); + } + MaterializationInfoItr = std::move(NewMaterializationInfoItr); } -std::shared_ptr<SymbolSource> +std::unique_ptr<MaterializationUnit> VSO::SymbolTableEntry::query(SymbolStringPtr Name, std::shared_ptr<AsynchronousSymbolQuery> Query) { if (Flags.isMaterialized()) { Query->setDefinition(std::move(Name), JITEvaluatedSymbol(Address, Flags)); Query->notifySymbolFinalized(); return nullptr; - } else - return MatInfo->query(std::move(Name), std::move(Query)); + } else { + if ((*MaterializationInfoItr)->MU) { + assert((*MaterializationInfoItr)->PendingResolution.count(Name) == 0 && + (*MaterializationInfoItr)->PendingFinalization.count(Name) == 0 && + "Materializer should have been activated on first query"); + (*MaterializationInfoItr) + ->PendingResolution[Name] + .push_back(std::move(Query)); + return std::move((*MaterializationInfoItr)->MU); + } else { + assert((*MaterializationInfoItr)->MU == nullptr && + "Materializer should have been activated on first query"); + auto SymValueItr = (*MaterializationInfoItr)->Symbols.find(Name); + if (SymValueItr == (*MaterializationInfoItr)->Symbols.end()) { + // Symbol has not been resolved yet. + (*MaterializationInfoItr) + ->PendingResolution[Name] + .push_back(std::move(Query)); + return nullptr; + } else { + // Symbol has already resolved, is just waiting on finalization. + Query->setDefinition(Name, SymValueItr->second); + (*MaterializationInfoItr) + ->PendingFinalization[Name] + .push_back(std::move(Query)); + return nullptr; + } + } + } } void VSO::SymbolTableEntry::resolve(VSO &V, SymbolStringPtr Name, @@ -185,22 +176,69 @@ void VSO::SymbolTableEntry::resolve(VSO &V, SymbolStringPtr Name, // in VSO? Flags = Sym.getFlags(); Address = Sym.getAddress(); - } else - MatInfo->resolve(V, std::move(Name), std::move(Sym)); + } else { + assert((*MaterializationInfoItr)->MU == nullptr && + "Can not resolve a symbol that has not been materialized"); + assert((*MaterializationInfoItr)->Symbols.count(Name) == 0 && + "Symbol resolved more than once"); + + // Add the symbol to the MaterializationInfo Symbols table. + (*MaterializationInfoItr)->Symbols[Name] = Sym; + + // If there are any queries waiting on this symbol then notify them that it + // has been resolved, then move them to the PendingFinalization list. + auto I = (*MaterializationInfoItr)->PendingResolution.find(Name); + if (I != (*MaterializationInfoItr)->PendingResolution.end()) { + assert((*MaterializationInfoItr)->PendingFinalization.count(Name) == 0 && + "Queries already pending finalization on newly resolved symbol"); + auto &PendingFinalization = + (*MaterializationInfoItr)->PendingFinalization[Name]; + + for (auto &Query : I->second) { + Query->setDefinition(Name, Sym); + PendingFinalization.push_back(Query); + } + + // Clear the PendingResolution list for this symbol. + (*MaterializationInfoItr)->PendingResolution.erase(I); + } + } } -void VSO::SymbolTableEntry::finalize() { +void VSO::SymbolTableEntry::finalize(VSO &V, SymbolStringPtr Name) { if (!Flags.isMaterialized()) { - auto TmpMatInfo = std::move(MatInfo); - MatInfo.std::unique_ptr<MaterializationInfo>::~unique_ptr(); - // FIXME: Assert flag sanity? - Flags = TmpMatInfo->getFlags(); - Address = TmpMatInfo->getAddress(); - TmpMatInfo->finalize(); + auto SymI = (*MaterializationInfoItr)->Symbols.find(Name); + assert(SymI != (*MaterializationInfoItr)->Symbols.end() && + "Finalizing an unresolved symbol"); + auto Sym = SymI->second; + (*MaterializationInfoItr)->Symbols.erase(SymI); + auto I = (*MaterializationInfoItr)->PendingFinalization.find(Name); + if (I != (*MaterializationInfoItr)->PendingFinalization.end()) { + for (auto &Query : I->second) + Query->notifySymbolFinalized(); + (*MaterializationInfoItr)->PendingFinalization.erase(I); + } + + if (--(*MaterializationInfoItr)->SymbolsRemaining == 0) + V.MaterializationInfos.erase(MaterializationInfoItr); + + // Destruct the iterator and re-define this entry using the final symbol + // value. + MaterializationInfoItr + .MaterializationInfoIterator::~MaterializationInfoIterator(); + Flags = Sym.getFlags(); + Address = Sym.getAddress(); } assert(Flags.isMaterialized() && "Trying to finalize not-emitted symbol"); } +void VSO::SymbolTableEntry::discard(VSO &V, SymbolStringPtr Name) { + assert((*MaterializationInfoItr)->MU != nullptr && + "Can not override a symbol after it has been materialized"); + (*MaterializationInfoItr)->MU->discard(V, Name); + --(*MaterializationInfoItr)->SymbolsRemaining; +} + VSO::RelativeLinkageStrength VSO::compareLinkage(Optional<JITSymbolFlags> Old, JITSymbolFlags New) { if (Old == None) @@ -249,16 +287,25 @@ Error VSO::define(SymbolMap NewSymbols) { } if (I != Symbols.end()) { - I->second.resolve(*this, KV.first, std::move(KV.second)); - I->second.finalize(); + // This is an override -- discard the overridden definition and overwrite. + I->second.discard(*this, KV.first); + I->second = std::move(KV.second); } else Symbols.insert(std::make_pair(KV.first, std::move(KV.second))); } return Err; } -Error VSO::defineLazy(const SymbolFlagsMap &NewSymbols, - std::shared_ptr<SymbolSource> Source) { +Error VSO::defineLazy(std::unique_ptr<MaterializationUnit> MU) { + + auto NewSymbols = MU->getSymbols(); + + auto MaterializationInfoItr = + MaterializationInfos + .insert(llvm::make_unique<MaterializationInfo>(NewSymbols.size(), + std::move(MU))) + .first; + Error Err = Error::success(); for (auto &KV : NewSymbols) { auto I = Symbols.find(KV.first); @@ -269,22 +316,38 @@ Error VSO::defineLazy(const SymbolFlagsMap &NewSymbols, KV.second); // Discard weaker definitions. - if (LinkageResult == ExistingDefinitionIsStronger) - Source->discard(*this, KV.first); + if (LinkageResult == ExistingDefinitionIsStronger) { + (*MaterializationInfoItr)->MU->discard(*this, KV.first); + assert((*MaterializationInfoItr)->SymbolsRemaining > 0 && + "Discarding non-existant symbols?"); + --(*MaterializationInfoItr)->SymbolsRemaining; + continue; + } // Report duplicate definition errors. if (LinkageResult == DuplicateDefinition) { Err = joinErrors(std::move(Err), make_error<orc::DuplicateDefinition>(*KV.first)); + // Duplicate definitions are discarded, so remove the duplicates from + // materializer. + assert((*MaterializationInfoItr)->SymbolsRemaining > 0 && + "Discarding non-existant symbols?"); + --(*MaterializationInfoItr)->SymbolsRemaining; continue; } if (I != Symbols.end()) - I->second.replaceWithSource(*this, KV.first, KV.second, Source); + I->second.replaceWith(*this, KV.first, KV.second, MaterializationInfoItr); else - Symbols.emplace( - std::make_pair(KV.first, SymbolTableEntry(KV.second, Source))); + Symbols.emplace(std::make_pair( + KV.first, SymbolTableEntry(KV.second, MaterializationInfoItr))); } + + // If we ended up overriding all definitions in this materializer then delete + // it. + if ((*MaterializationInfoItr)->SymbolsRemaining == 0) + MaterializationInfos.erase(MaterializationInfoItr); + return Err; } @@ -300,7 +363,7 @@ void VSO::finalize(SymbolNameSet SymbolsToFinalize) { for (auto &S : SymbolsToFinalize) { auto I = Symbols.find(S); assert(I != Symbols.end() && "Finalizing symbol not present in this dylib"); - I->second.finalize(); + I->second.finalize(*this, S); } } @@ -325,7 +388,7 @@ SymbolNameSet VSO::lookupFlags(SymbolFlagsMap &Flags, SymbolNameSet Names) { VSO::LookupResult VSO::lookup(std::shared_ptr<AsynchronousSymbolQuery> Query, SymbolNameSet Names) { - SourceWorkMap MaterializationWork; + MaterializationUnitList MaterializationUnits; for (SymbolNameSet::iterator I = Names.begin(), E = Names.end(); I != E;) { auto Tmp = I++; @@ -341,11 +404,11 @@ VSO::LookupResult VSO::lookup(std::shared_ptr<AsynchronousSymbolQuery> Query, // Forward the query to the given SymbolTableEntry, and if it return a // layer to perform materialization with, add that to the // MaterializationWork map. - if (auto Source = SymI->second.query(SymI->first, Query)) - MaterializationWork[Source].insert(SymI->first); + if (auto MU = SymI->second.query(SymI->first, Query)) + MaterializationUnits.push_back(std::move(MU)); } - return {std::move(MaterializationWork), std::move(Names)}; + return {std::move(MaterializationUnits), std::move(Names)}; } Expected<SymbolMap> lookup(const std::vector<VSO *> &VSOs, SymbolNameSet Names, @@ -400,24 +463,17 @@ Expected<SymbolMap> lookup(const std::vector<VSO *> &VSOs, SymbolNameSet Names, Names, std::move(OnResolve), std::move(OnReady)); SymbolNameSet UnresolvedSymbols(std::move(Names)); - for (auto *VSO : VSOs) { + for (auto *V : VSOs) { if (UnresolvedSymbols.empty()) break; - assert(VSO && "VSO pointers in VSOs list should be non-null"); - auto LR = VSO->lookup(Query, UnresolvedSymbols); + assert(V && "VSO pointers in VSOs list should be non-null"); + auto LR = V->lookup(Query, UnresolvedSymbols); UnresolvedSymbols = std::move(LR.UnresolvedSymbols); - for (auto I = LR.MaterializationWork.begin(), - E = LR.MaterializationWork.end(); - I != E;) { - auto Tmp = I++; - std::shared_ptr<SymbolSource> Source = Tmp->first; - SymbolNameSet Names = std::move(Tmp->second); - LR.MaterializationWork.erase(Tmp); - DispatchMaterialization(*VSO, std::move(Source), std::move(Names)); - } + for (auto &MU : LR.MaterializationUnits) + DispatchMaterialization(*V, std::move(MU)); } #if LLVM_ENABLE_THREADS diff --git a/llvm/unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp b/llvm/unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp index 5a74246b1c3..d37596ec5df 100644 --- a/llvm/unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp +++ b/llvm/unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp @@ -19,23 +19,28 @@ using namespace llvm::orc; namespace { -class SimpleSource : public SymbolSource { +class SimpleMaterializationUnit : public MaterializationUnit { public: - using MaterializeFunction = std::function<Error(VSO &, SymbolNameSet)>; + using GetSymbolsFunction = std::function<SymbolFlagsMap()>; + using MaterializeFunction = std::function<Error(VSO &)>; using DiscardFunction = std::function<void(VSO &, SymbolStringPtr)>; - SimpleSource(MaterializeFunction Materialize, DiscardFunction Discard) - : Materialize(std::move(Materialize)), Discard(std::move(Discard)) {} + SimpleMaterializationUnit(GetSymbolsFunction GetSymbols, + MaterializeFunction Materialize, + DiscardFunction Discard) + : GetSymbols(std::move(GetSymbols)), Materialize(std::move(Materialize)), + Discard(std::move(Discard)) {} - Error materialize(VSO &V, SymbolNameSet Symbols) override { - return Materialize(V, std::move(Symbols)); - } + SymbolFlagsMap getSymbols() override { return GetSymbols(); } + + Error materialize(VSO &V) override { return Materialize(V); } void discard(VSO &V, SymbolStringPtr Name) override { Discard(V, std::move(Name)); } private: + GetSymbolsFunction GetSymbols; MaterializeFunction Materialize; DiscardFunction Discard; }; @@ -142,26 +147,28 @@ TEST(CoreAPIsTest, LookupFlagsTest) { auto Bar = SP.intern("bar"); auto Baz = SP.intern("baz"); + JITSymbolFlags FooFlags = JITSymbolFlags::Exported; + JITSymbolFlags BarFlags = static_cast<JITSymbolFlags::FlagNames>( + JITSymbolFlags::Exported | JITSymbolFlags::Weak); + VSO V; - auto Source = std::make_shared<SimpleSource>( - [](VSO &V, SymbolNameSet Symbols) -> Error { + auto MU = llvm::make_unique<SimpleMaterializationUnit>( + [=]() { + return SymbolFlagsMap({{Bar, BarFlags}}); + }, + [](VSO &V) -> Error { llvm_unreachable("Symbol materialized on flags lookup"); }, [](VSO &V, SymbolStringPtr Name) -> Error { llvm_unreachable("Symbol finalized on flags lookup"); }); - JITSymbolFlags FooFlags = JITSymbolFlags::Exported; - JITSymbolFlags BarFlags = static_cast<JITSymbolFlags::FlagNames>( - JITSymbolFlags::Exported | JITSymbolFlags::Weak); - SymbolMap InitialDefs; InitialDefs[Foo] = JITEvaluatedSymbol(0xdeadbeef, FooFlags); cantFail(V.define(std::move(InitialDefs))); - SymbolFlagsMap InitialLazyDefs({{Bar, BarFlags}}); - cantFail(V.defineLazy(InitialLazyDefs, Source)); + cantFail(V.defineLazy(std::move(MU))); SymbolNameSet Names({Foo, Bar, Baz}); @@ -193,12 +200,15 @@ TEST(CoreAPIsTest, AddAndMaterializeLazySymbol) { VSO V; - auto Source = std::make_shared<SimpleSource>( - [&](VSO &V, SymbolNameSet Symbols) { - EXPECT_EQ(Symbols.size(), 1U) - << "Expected Symbols set size to be 1 ({ Foo })"; - EXPECT_EQ(*Symbols.begin(), Foo) << "Expected Symbols == { Foo }"; - + auto MU = llvm::make_unique<SimpleMaterializationUnit>( + [=]() { + return SymbolFlagsMap( + {{Foo, JITSymbolFlags::Exported}, + {Bar, static_cast<JITSymbolFlags::FlagNames>( + JITSymbolFlags::Exported | JITSymbolFlags::Weak)}}); + }, + [&](VSO &V) { + assert(BarDiscarded && "Bar should have been discarded by this point"); SymbolMap SymbolsToResolve; SymbolsToResolve[Foo] = JITEvaluatedSymbol(FakeFooAddr, JITSymbolFlags::Exported); @@ -214,11 +224,7 @@ TEST(CoreAPIsTest, AddAndMaterializeLazySymbol) { BarDiscarded = true; }); - SymbolFlagsMap InitialSymbols( - {{Foo, JITSymbolFlags::Exported}, - {Bar, static_cast<JITSymbolFlags::FlagNames>(JITSymbolFlags::Exported | - JITSymbolFlags::Weak)}}); - cantFail(V.defineLazy(InitialSymbols, Source)); + cantFail(V.defineLazy(std::move(MU))); SymbolMap BarOverride; BarOverride[Bar] = JITEvaluatedSymbol(FakeBarAddr, JITSymbolFlags::Exported); @@ -248,8 +254,8 @@ TEST(CoreAPIsTest, AddAndMaterializeLazySymbol) { auto LR = V.lookup(std::move(Q), Names); - for (auto &SWKV : LR.MaterializationWork) - cantFail(SWKV.first->materialize(V, std::move(SWKV.second))); + for (auto &SWKV : LR.MaterializationUnits) + cantFail(SWKV->materialize(V)); EXPECT_TRUE(LR.UnresolvedSymbols.empty()) << "Could not find Foo in dylib"; EXPECT_TRUE(FooMaterialized) << "Foo was not materialized"; @@ -276,9 +282,8 @@ TEST(CoreAPIsTest, TestLambdaSymbolResolver) { }, [&](std::shared_ptr<AsynchronousSymbolQuery> Q, SymbolNameSet Symbols) { auto LR = V.lookup(std::move(Q), Symbols); - assert(LR.MaterializationWork.empty() && - "Test generated unexpected materialization " - "work?"); + assert(LR.MaterializationUnits.empty() && + "Test generated unexpected materialization work?"); return std::move(LR.UnresolvedSymbols); }); @@ -333,8 +338,11 @@ TEST(CoreAPIsTest, TestLookupWithUnthreadedMaterialization) { SymbolStringPool SSP; auto Foo = SSP.intern("foo"); - auto Source = std::make_shared<SimpleSource>( - [&](VSO &V, SymbolNameSet Symbols) -> Error { + auto MU = llvm::make_unique<SimpleMaterializationUnit>( + [=]() { + return SymbolFlagsMap({{Foo, JITSymbolFlags::Exported}}); + }, + [&](VSO &V) -> Error { V.resolve({{Foo, FooSym}}); V.finalize({Foo}); return Error::success(); @@ -345,8 +353,7 @@ TEST(CoreAPIsTest, TestLookupWithUnthreadedMaterialization) { VSO V; - SymbolFlagsMap InitialSymbols({{Foo, JITSymbolFlags::Exported}}); - cantFail(V.defineLazy(InitialSymbols, Source)); + cantFail(V.defineLazy(std::move(MU))); ExecutionSession ES(SSP); auto FooLookupResult = @@ -366,8 +373,11 @@ TEST(CoreAPIsTest, TestLookupWithThreadedMaterialization) { SymbolStringPool SSP; auto Foo = SSP.intern("foo"); - auto Source = std::make_shared<SimpleSource>( - [&](VSO &V, SymbolNameSet Symbols) -> Error { + auto MU = llvm::make_unique<SimpleMaterializationUnit>( + [=]() { + return SymbolFlagsMap({{Foo, JITSymbolFlags::Exported}}); + }, + [&](VSO &V) -> Error { V.resolve({{Foo, FooSym}}); V.finalize({Foo}); return Error::success(); @@ -378,19 +388,20 @@ TEST(CoreAPIsTest, TestLookupWithThreadedMaterialization) { VSO V; - SymbolFlagsMap InitialSymbols({{Foo, JITSymbolFlags::Exported}}); - cantFail(V.defineLazy(InitialSymbols, Source)); + cantFail(V.defineLazy(std::move(MU))); ExecutionSession ES(SSP); - auto MaterializeOnNewThread = - [&ES](VSO &V, std::shared_ptr<SymbolSource> Source, SymbolNameSet Names) { - std::thread( - [&ES, &V, Source, Names]() { - if (auto Err = Source->materialize(V, std::move(Names))) - ES.reportError(std::move(Err)); - }).detach(); - }; + auto MaterializeOnNewThread = [&ES](VSO &V, + std::unique_ptr<MaterializationUnit> MU) { + // FIXME: Use move capture once we move to C++14. + std::shared_ptr<MaterializationUnit> SharedMU = std::move(MU); + std::thread([&ES, &V, SharedMU]() { + if (auto Err = SharedMU->materialize(V)) + ES.reportError(std::move(Err)); + }) + .detach(); + }; auto FooLookupResult = cantFail(lookup({&V}, Foo, MaterializeOnNewThread)); diff --git a/llvm/unittests/ExecutionEngine/Orc/LegacyAPIInteropTest.cpp b/llvm/unittests/ExecutionEngine/Orc/LegacyAPIInteropTest.cpp index 9fce90fe186..6c7384a9af5 100644 --- a/llvm/unittests/ExecutionEngine/Orc/LegacyAPIInteropTest.cpp +++ b/llvm/unittests/ExecutionEngine/Orc/LegacyAPIInteropTest.cpp @@ -36,7 +36,7 @@ TEST(LegacyAPIInteropTest, QueryAgainstVSO) { auto Lookup = [&](std::shared_ptr<AsynchronousSymbolQuery> Query, SymbolNameSet Symbols) { auto R = V.lookup(std::move(Query), Symbols); - EXPECT_TRUE(R.MaterializationWork.empty()) + EXPECT_TRUE(R.MaterializationUnits.empty()) << "Query resulted in unexpected materialization work"; return std::move(R.UnresolvedSymbols); }; |

