LCOV - code coverage report
Current view: top level - lib/ExecutionEngine/Orc - Core.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 325 446 72.9 %
Date: 2018-06-17 00:07:59 Functions: 57 74 77.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===----- Core.cpp - Core ORC APIs (MaterializationUnit, VSO, etc.) ------===//
       2             : //
       3             : //                     The LLVM Compiler Infrastructure
       4             : //
       5             : // This file is distributed under the University of Illinois Open Source
       6             : // License. See LICENSE.TXT for details.
       7             : //
       8             : //===----------------------------------------------------------------------===//
       9             : 
      10             : #include "llvm/ExecutionEngine/Orc/Core.h"
      11             : #include "llvm/Config/llvm-config.h"
      12             : #include "llvm/ExecutionEngine/Orc/OrcError.h"
      13             : #include "llvm/Support/Format.h"
      14             : 
      15             : #if LLVM_ENABLE_THREADS
      16             : #include <future>
      17             : #endif
      18             : 
      19             : namespace llvm {
      20             : namespace orc {
      21             : 
      22             : char FailedToMaterialize::ID = 0;
      23             : char SymbolsNotFound::ID = 0;
      24             : 
      25           0 : void MaterializationUnit::anchor() {}
      26           0 : void SymbolResolver::anchor() {}
      27             : 
      28           0 : raw_ostream &operator<<(raw_ostream &OS, const JITSymbolFlags &Flags) {
      29           0 :   if (Flags.isWeak())
      30             :     OS << 'W';
      31           0 :   else if (Flags.isCommon())
      32             :     OS << 'C';
      33             :   else
      34             :     OS << 'S';
      35             : 
      36           0 :   if (Flags.isExported())
      37             :     OS << 'E';
      38             :   else
      39             :     OS << 'H';
      40             : 
      41           0 :   return OS;
      42             : }
      43             : 
      44           0 : raw_ostream &operator<<(raw_ostream &OS, const JITEvaluatedSymbol &Sym) {
      45           0 :   OS << format("0x%016x", Sym.getAddress()) << " " << Sym.getFlags();
      46           0 :   return OS;
      47             : }
      48             : 
      49           0 : raw_ostream &operator<<(raw_ostream &OS, const SymbolMap::value_type &KV) {
      50           0 :   OS << "\"" << *KV.first << "\": " << KV.second;
      51           0 :   return OS;
      52             : }
      53             : 
      54           0 : raw_ostream &operator<<(raw_ostream &OS, const SymbolNameSet &Symbols) {
      55           0 :   OS << "{";
      56           0 :   if (!Symbols.empty()) {
      57           0 :     OS << " \"" << **Symbols.begin() << "\"";
      58           0 :     for (auto &Sym : make_range(std::next(Symbols.begin()), Symbols.end()))
      59           0 :       OS << ", \"" << *Sym << "\"";
      60             :   }
      61           0 :   OS << " }";
      62           0 :   return OS;
      63             : }
      64             : 
      65           0 : raw_ostream &operator<<(raw_ostream &OS, const SymbolMap &Symbols) {
      66           0 :   OS << "{";
      67           0 :   if (!Symbols.empty()) {
      68           0 :     OS << " {" << *Symbols.begin() << "}";
      69           0 :     for (auto &Sym : make_range(std::next(Symbols.begin()), Symbols.end()))
      70           0 :       OS << ", {" << Sym << "}";
      71             :   }
      72           0 :   OS << " }";
      73           0 :   return OS;
      74             : }
      75             : 
      76           0 : raw_ostream &operator<<(raw_ostream &OS, const SymbolFlagsMap &SymbolFlags) {
      77           0 :   OS << "{";
      78           0 :   if (!SymbolFlags.empty()) {
      79           0 :     OS << " {\"" << *SymbolFlags.begin()->first
      80           0 :        << "\": " << SymbolFlags.begin()->second << "}";
      81             :     for (auto &KV :
      82           0 :          make_range(std::next(SymbolFlags.begin()), SymbolFlags.end()))
      83           0 :       OS << ", {\"" << *KV.first << "\": " << KV.second << "}";
      84             :   }
      85           0 :   OS << " }";
      86           0 :   return OS;
      87             : }
      88             : 
      89           0 : raw_ostream &operator<<(raw_ostream &OS, const SymbolDependenceMap &Deps) {
      90           0 :   OS << "{";
      91           0 :   if (!Deps.empty()) {
      92           0 :     OS << " { " << Deps.begin()->first->getName() << ": "
      93           0 :        << Deps.begin()->second << " }";
      94           0 :     for (auto &KV : make_range(std::next(Deps.begin()), Deps.end()))
      95           0 :       OS << ", { " << KV.first->getName() << ": " << KV.second << " }";
      96             :   }
      97           0 :   OS << " }";
      98           0 :   return OS;
      99             : }
     100             : 
     101           1 : FailedToMaterialize::FailedToMaterialize(SymbolNameSet Symbols)
     102           1 :     : Symbols(std::move(Symbols)) {
     103             :   assert(!this->Symbols.empty() && "Can not fail to resolve an empty set");
     104           1 : }
     105             : 
     106           0 : std::error_code FailedToMaterialize::convertToErrorCode() const {
     107           0 :   return orcError(OrcErrorCode::UnknownORCError);
     108             : }
     109             : 
     110           0 : void FailedToMaterialize::log(raw_ostream &OS) const {
     111           0 :   OS << "Failed to materialize symbols: " << Symbols;
     112           0 : }
     113             : 
     114           0 : SymbolsNotFound::SymbolsNotFound(SymbolNameSet Symbols)
     115           0 :     : Symbols(std::move(Symbols)) {
     116             :   assert(!this->Symbols.empty() && "Can not fail to resolve an empty set");
     117           0 : }
     118             : 
     119           0 : std::error_code SymbolsNotFound::convertToErrorCode() const {
     120           0 :   return orcError(OrcErrorCode::UnknownORCError);
     121             : }
     122             : 
     123           0 : void SymbolsNotFound::log(raw_ostream &OS) const {
     124           0 :   OS << "Symbols not found: " << Symbols;
     125           0 : }
     126             : 
     127           1 : void ExecutionSessionBase::failQuery(AsynchronousSymbolQuery &Q, Error Err) {
     128           1 :   bool DeliveredError = true;
     129           3 :   runSessionLocked([&]() -> void {
     130           2 :     Q.detach();
     131           1 :     if (Q.canStillFail())
     132           3 :       Q.handleFailed(std::move(Err));
     133             :     else
     134           0 :       DeliveredError = false;
     135           1 :   });
     136             : 
     137           1 :   if (!DeliveredError)
     138           0 :     reportError(std::move(Err));
     139           1 : }
     140             : 
     141          86 : AsynchronousSymbolQuery::AsynchronousSymbolQuery(
     142             :     const SymbolNameSet &Symbols, SymbolsResolvedCallback NotifySymbolsResolved,
     143          86 :     SymbolsReadyCallback NotifySymbolsReady)
     144             :     : NotifySymbolsResolved(std::move(NotifySymbolsResolved)),
     145          86 :       NotifySymbolsReady(std::move(NotifySymbolsReady)) {
     146          86 :   NotYetResolvedCount = NotYetReadyCount = Symbols.size();
     147             : 
     148         211 :   for (auto &S : Symbols)
     149         125 :     ResolvedSymbols[S] = nullptr;
     150          86 : }
     151             : 
     152         122 : void AsynchronousSymbolQuery::resolve(const SymbolStringPtr &Name,
     153             :                                       JITEvaluatedSymbol Sym) {
     154             :   auto I = ResolvedSymbols.find(Name);
     155             :   assert(I != ResolvedSymbols.end() &&
     156             :          "Resolving symbol outside the requested set");
     157             :   assert(I->second.getAddress() == 0 && "Redundantly resolving symbol Name");
     158         122 :   I->second = std::move(Sym);
     159         122 :   --NotYetResolvedCount;
     160         122 : }
     161             : 
     162          84 : void AsynchronousSymbolQuery::handleFullyResolved() {
     163             :   assert(NotYetResolvedCount == 0 && "Not fully resolved?");
     164             :   assert(NotifySymbolsResolved &&
     165             :          "NotifySymbolsResolved already called or error occurred");
     166          84 :   NotifySymbolsResolved(
     167         252 :       ResolutionResult(std::move(ResolvedSymbols), QueryRegistrations));
     168         168 :   NotifySymbolsResolved = SymbolsResolvedCallback();
     169          84 : }
     170             : 
     171         121 : void AsynchronousSymbolQuery::notifySymbolReady() {
     172             :   assert(NotYetReadyCount != 0 && "All symbols already finalized");
     173         121 :   --NotYetReadyCount;
     174         121 : }
     175             : 
     176          83 : void AsynchronousSymbolQuery::handleFullyReady() {
     177             :   assert(QueryRegistrations.empty() &&
     178             :          "Query is still registered with some symbols");
     179             :   assert(!NotifySymbolsResolved && "Resolution not applied yet");
     180          83 :   NotifySymbolsReady(Error::success());
     181         166 :   NotifySymbolsReady = SymbolsReadyCallback();
     182          83 : }
     183             : 
     184           1 : bool AsynchronousSymbolQuery::canStillFail() {
     185           1 :   return (NotifySymbolsResolved || NotifySymbolsReady);
     186             : }
     187             : 
     188           2 : void AsynchronousSymbolQuery::handleFailed(Error Err) {
     189             :   assert(QueryRegistrations.empty() && ResolvedSymbols.empty() &&
     190             :          NotYetResolvedCount == 0 && NotYetReadyCount == 0 &&
     191             :          "Query should already have been abandoned");
     192           2 :   if (NotifySymbolsResolved)
     193           2 :     NotifySymbolsResolved(std::move(Err));
     194             :   else {
     195             :     assert(NotifySymbolsReady && "Failed after both callbacks issued?");
     196           0 :     NotifySymbolsReady(std::move(Err));
     197           0 :     NotifySymbolsReady = SymbolsReadyCallback();
     198             :   }
     199           2 : }
     200             : 
     201          35 : void AsynchronousSymbolQuery::addQueryDependence(VSO &V, SymbolStringPtr Name) {
     202          70 :   bool Added = QueryRegistrations[&V].insert(std::move(Name)).second;
     203             :   (void)Added;
     204             :   assert(Added && "Duplicate dependence notification?");
     205          35 : }
     206             : 
     207          33 : void AsynchronousSymbolQuery::removeQueryDependence(
     208             :     VSO &V, const SymbolStringPtr &Name) {
     209             :   auto QRI = QueryRegistrations.find(&V);
     210             :   assert(QRI != QueryRegistrations.end() && "No dependencies registered for V");
     211             :   assert(QRI->second.count(Name) && "No dependency on Name in V");
     212             :   QRI->second.erase(Name);
     213          33 :   if (QRI->second.empty())
     214             :     QueryRegistrations.erase(QRI);
     215          33 : }
     216             : 
     217           3 : void AsynchronousSymbolQuery::detach() {
     218             :   ResolvedSymbols.clear();
     219           3 :   NotYetResolvedCount = 0;
     220           3 :   NotYetReadyCount = 0;
     221           4 :   for (auto &KV : QueryRegistrations)
     222           1 :     KV.first->detachQueryHelper(*this, KV.second);
     223             :   QueryRegistrations.clear();
     224           3 : }
     225             : 
     226          33 : MaterializationResponsibility::MaterializationResponsibility(
     227          33 :     VSO &V, SymbolFlagsMap SymbolFlags)
     228          33 :     : V(V), SymbolFlags(std::move(SymbolFlags)) {
     229             :   assert(!this->SymbolFlags.empty() && "Materializing nothing?");
     230             : 
     231          69 :   for (auto &KV : this->SymbolFlags)
     232          36 :     KV.second |= JITSymbolFlags::Materializing;
     233          33 : }
     234             : 
     235         114 : MaterializationResponsibility::~MaterializationResponsibility() {
     236             :   assert(SymbolFlags.empty() &&
     237             :          "All symbols should have been explicitly materialized or failed");
     238          57 : }
     239             : 
     240           1 : SymbolNameSet MaterializationResponsibility::getRequestedSymbols() {
     241           1 :   return V.getRequestedSymbols(SymbolFlags);
     242             : }
     243             : 
     244          32 : void MaterializationResponsibility::resolve(const SymbolMap &Symbols) {
     245          66 :   for (auto &KV : Symbols) {
     246             :     auto I = SymbolFlags.find(KV.first);
     247             :     assert(I != SymbolFlags.end() &&
     248             :            "Resolving symbol outside this responsibility set");
     249             :     assert(I->second.isMaterializing() && "Duplicate resolution");
     250          34 :     I->second &= ~JITSymbolFlags::Materializing;
     251             :     assert(KV.second.getFlags() == I->second &&
     252             :            "Resolving symbol with incorrect flags");
     253             :   }
     254             : 
     255          32 :   V.resolve(Symbols);
     256          32 : }
     257             : 
     258          32 : void MaterializationResponsibility::finalize() {
     259             : #ifndef NDEBUG
     260             :   for (auto &KV : SymbolFlags)
     261             :     assert(!KV.second.isMaterializing() &&
     262             :            "Failed to resolve symbol before finalization");
     263             : #endif // NDEBUG
     264             : 
     265          32 :   V.finalize(SymbolFlags);
     266             :   SymbolFlags.clear();
     267          32 : }
     268             : 
     269           1 : Error MaterializationResponsibility::defineMaterializing(
     270             :     const SymbolFlagsMap &NewSymbolFlags) {
     271             :   // Add the given symbols to this responsibility object.
     272             :   // It's ok if we hit a duplicate here: In that case the new version will be
     273             :   // discarded, and the VSO::defineMaterializing method will return a duplicate
     274             :   // symbol error.
     275           2 :   for (auto &KV : NewSymbolFlags) {
     276             :     auto I = SymbolFlags.insert(KV).first;
     277           1 :     I->second |= JITSymbolFlags::Materializing;
     278             :   }
     279             : 
     280           1 :   return V.defineMaterializing(NewSymbolFlags);
     281             : }
     282             : 
     283           1 : void MaterializationResponsibility::failMaterialization() {
     284             : 
     285             :   SymbolNameSet FailedSymbols;
     286           3 :   for (auto &KV : SymbolFlags)
     287           2 :     FailedSymbols.insert(KV.first);
     288             : 
     289           1 :   V.notifyFailed(FailedSymbols);
     290             :   SymbolFlags.clear();
     291           1 : }
     292             : 
     293           1 : void MaterializationResponsibility::delegate(
     294             :     std::unique_ptr<MaterializationUnit> MU) {
     295           2 :   for (auto &KV : MU->getSymbols())
     296           1 :     SymbolFlags.erase(KV.first);
     297             : 
     298           3 :   V.replace(std::move(MU));
     299           1 : }
     300             : 
     301           6 : void MaterializationResponsibility::addDependencies(
     302             :     const SymbolDependenceMap &Dependencies) {
     303           6 :   V.addDependencies(SymbolFlags, Dependencies);
     304           6 : }
     305             : 
     306          10 : AbsoluteSymbolsMaterializationUnit::AbsoluteSymbolsMaterializationUnit(
     307          10 :     SymbolMap Symbols)
     308          30 :     : MaterializationUnit(extractFlags(Symbols)), Symbols(std::move(Symbols)) {}
     309             : 
     310           6 : void AbsoluteSymbolsMaterializationUnit::materialize(
     311             :     MaterializationResponsibility R) {
     312           6 :   R.resolve(Symbols);
     313           6 :   R.finalize();
     314           6 : }
     315             : 
     316           0 : void AbsoluteSymbolsMaterializationUnit::discard(const VSO &V,
     317             :                                                  SymbolStringPtr Name) {
     318             :   assert(Symbols.count(Name) && "Symbol is not part of this MU");
     319             :   Symbols.erase(Name);
     320           0 : }
     321             : 
     322             : SymbolFlagsMap
     323          10 : AbsoluteSymbolsMaterializationUnit::extractFlags(const SymbolMap &Symbols) {
     324             :   SymbolFlagsMap Flags;
     325          21 :   for (const auto &KV : Symbols)
     326          11 :     Flags[KV.first] = KV.second.getFlags();
     327          10 :   return Flags;
     328             : }
     329             : 
     330           1 : Error VSO::defineMaterializing(const SymbolFlagsMap &SymbolFlags) {
     331           2 :   return ES.runSessionLocked([&]() -> Error {
     332             :     std::vector<SymbolMap::iterator> AddedSyms;
     333             : 
     334           3 :     for (auto &KV : SymbolFlags) {
     335             :       SymbolMap::iterator EntryItr;
     336             :       bool Added;
     337             : 
     338           1 :       auto NewFlags = KV.second;
     339           1 :       NewFlags |= JITSymbolFlags::Materializing;
     340             : 
     341           1 :       std::tie(EntryItr, Added) = Symbols.insert(
     342           1 :           std::make_pair(KV.first, JITEvaluatedSymbol(0, NewFlags)));
     343             : 
     344           1 :       if (Added)
     345           1 :         AddedSyms.push_back(EntryItr);
     346             :       else {
     347             :         // Remove any symbols already added.
     348           0 :         for (auto &SI : AddedSyms)
     349             :           Symbols.erase(SI);
     350             : 
     351             :         // FIXME: Return all duplicates.
     352           0 :         return make_error<DuplicateDefinition>(*KV.first);
     353             :       }
     354             :     }
     355             : 
     356             :     return Error::success();
     357           2 :   });
     358             : }
     359             : 
     360           1 : void VSO::replace(std::unique_ptr<MaterializationUnit> MU) {
     361             :   assert(MU != nullptr && "Can not replace with a null MaterializationUnit");
     362             : 
     363             :   auto MustRunMU =
     364           4 :       ES.runSessionLocked([&, this]() -> std::unique_ptr<MaterializationUnit> {
     365             : 
     366             : #ifndef NDEBUG
     367             :         for (auto &KV : MU->getSymbols()) {
     368             :           auto SymI = Symbols.find(KV.first);
     369             :           assert(SymI != Symbols.end() && "Replacing unknown symbol");
     370             :           assert(!SymI->second.getFlags().isLazy() &&
     371             :                  SymI->second.getFlags().isMaterializing() &&
     372             :                  "Can not replace symbol that is not materializing");
     373             :           assert(UnmaterializedInfos.count(KV.first) == 0 &&
     374             :                  "Symbol being replaced should have no UnmaterializedInfo");
     375             :         }
     376             : #endif // NDEBUG
     377             : 
     378             :         // If any symbol has pending queries against it then we need to
     379             :         // materialize MU immediately.
     380           3 :         for (auto &KV : MU->getSymbols()) {
     381             :           auto MII = MaterializingInfos.find(KV.first);
     382           1 :           if (MII != MaterializingInfos.end()) {
     383           0 :             if (!MII->second.PendingQueries.empty())
     384             :               return std::move(MU);
     385             :           }
     386             :         }
     387             : 
     388             :         // Otherwise, make MU responsible for all the symbols.
     389             :         auto UMI = std::make_shared<UnmaterializedInfo>(std::move(MU));
     390           2 :         for (auto &KV : UMI->MU->getSymbols()) {
     391             :           assert(!KV.second.isLazy() &&
     392             :                  "Lazy flag should be managed internally.");
     393             :           assert(!KV.second.isMaterializing() &&
     394             :                  "Materializing flags should be managed internally.");
     395             : 
     396             :           auto SymI = Symbols.find(KV.first);
     397           1 :           JITSymbolFlags ReplaceFlags = KV.second;
     398           1 :           ReplaceFlags |= JITSymbolFlags::Lazy;
     399           1 :           SymI->second = JITEvaluatedSymbol(SymI->second.getAddress(),
     400             :                                             std::move(ReplaceFlags));
     401           1 :           UnmaterializedInfos[KV.first] = UMI;
     402             :         }
     403             : 
     404             :         return nullptr;
     405           2 :       });
     406             : 
     407           1 :   if (MustRunMU)
     408           0 :     ES.dispatchMaterialization(*this, std::move(MustRunMU));
     409           1 : }
     410             : 
     411           1 : SymbolNameSet VSO::getRequestedSymbols(const SymbolFlagsMap &SymbolFlags) {
     412           2 :   return ES.runSessionLocked([&]() {
     413             :     SymbolNameSet RequestedSymbols;
     414             : 
     415           4 :     for (auto &KV : SymbolFlags) {
     416             :       assert(Symbols.count(KV.first) && "VSO does not cover this symbol?");
     417             :       assert(Symbols[KV.first].getFlags().isMaterializing() &&
     418             :              "getRequestedSymbols can only be called for materializing "
     419             :              "symbols");
     420           2 :       auto I = MaterializingInfos.find(KV.first);
     421           2 :       if (I == MaterializingInfos.end())
     422             :         continue;
     423             : 
     424           1 :       if (!I->second.PendingQueries.empty())
     425           1 :         RequestedSymbols.insert(KV.first);
     426             :     }
     427             : 
     428           1 :     return RequestedSymbols;
     429           2 :   });
     430             : }
     431             : 
     432           6 : void VSO::addDependencies(const SymbolFlagsMap &Dependants,
     433             :                           const SymbolDependenceMap &Dependencies) {
     434          30 :   ES.runSessionLocked([&, this]() {
     435          18 :     for (auto &KV : Dependants) {
     436           6 :       const auto &Name = KV.first;
     437             :       assert(Symbols.count(Name) && "Name not in symbol table");
     438             :       assert((Symbols[Name].getFlags().isLazy() ||
     439             :               Symbols[Name].getFlags().isMaterializing()) &&
     440             :              "Symbol is not lazy or materializing");
     441             : 
     442           6 :       auto &MI = MaterializingInfos[Name];
     443             :       assert(!MI.IsFinalized && "Can not add dependencies to finalized symbol");
     444             : 
     445          18 :       for (auto &KV : Dependencies) {
     446             :         assert(KV.first && "Null VSO in dependency?");
     447           6 :         auto &OtherVSO = *KV.first;
     448           6 :         auto &DepsOnOtherVSO = MI.UnfinalizedDependencies[&OtherVSO];
     449             : 
     450          12 :         for (auto &OtherSymbol : KV.second) {
     451           6 :           auto &OtherMI = OtherVSO.MaterializingInfos[OtherSymbol];
     452             : 
     453           6 :           if (OtherMI.IsFinalized)
     454           0 :             transferFinalizedNodeDependencies(MI, Name, OtherMI);
     455          12 :           else if (&OtherVSO != this || OtherSymbol != Name) {
     456           6 :             OtherMI.Dependants[this].insert(Name);
     457             :             DepsOnOtherVSO.insert(OtherSymbol);
     458             :           }
     459             :         }
     460             :       }
     461             :     }
     462           6 :   });
     463           6 : }
     464             : 
     465          32 : void VSO::resolve(const SymbolMap &Resolved) {
     466          98 :   auto FullyResolvedQueries = ES.runSessionLocked([&, this]() {
     467             :     AsynchronousSymbolQuerySet FullyResolvedQueries;
     468          98 :     for (const auto &KV : Resolved) {
     469          34 :       auto &Name = KV.first;
     470          34 :       auto Sym = KV.second;
     471             :       JITSymbolFlags ResolvedFlags = Sym.getFlags();
     472          34 :       ResolvedFlags &= ~JITSymbolFlags::Weak;
     473             : 
     474             :       assert(!Sym.getFlags().isLazy() && !Sym.getFlags().isMaterializing() &&
     475             :              "Materializing flags should be managed internally");
     476             : 
     477             :       auto I = Symbols.find(Name);
     478             : 
     479             :       assert(I != Symbols.end() && "Symbol not found");
     480             :       assert(!I->second.getFlags().isLazy() &&
     481             :              I->second.getFlags().isMaterializing() &&
     482             :              "Symbol should be materializing");
     483             :       assert(I->second.getAddress() == 0 && "Symbol has already been resolved");
     484             : 
     485             :       assert(ResolvedFlags ==
     486             :                  JITSymbolFlags::stripTransientFlags(I->second.getFlags()) &&
     487             :              "Resolved flags should match the declared flags");
     488             : 
     489             :       // Once resolved, symbols can never be weak.
     490          34 :       ResolvedFlags |= JITSymbolFlags::Materializing;
     491          34 :       I->second = JITEvaluatedSymbol(Sym.getAddress(), ResolvedFlags);
     492             : 
     493          34 :       auto &MI = MaterializingInfos[Name];
     494          67 :       for (auto &Q : MI.PendingQueries) {
     495          33 :         Q->resolve(Name, Sym);
     496          33 :         if (Q->isFullyResolved())
     497             :           FullyResolvedQueries.insert(Q);
     498             :       }
     499             :     }
     500             : 
     501          32 :     return FullyResolvedQueries;
     502          64 :   });
     503             : 
     504          63 :   for (auto &Q : FullyResolvedQueries) {
     505             :     assert(Q->isFullyResolved() && "Q not fully resolved");
     506          31 :     Q->handleFullyResolved();
     507             :   }
     508          32 : }
     509             : 
     510          32 : void VSO::finalize(const SymbolFlagsMap &Finalized) {
     511         208 :   auto FullyReadyQueries = ES.runSessionLocked([&, this]() {
     512             :     AsynchronousSymbolQuerySet ReadyQueries;
     513             : 
     514          98 :     for (const auto &KV : Finalized) {
     515          34 :       const auto &Name = KV.first;
     516             : 
     517             :       auto MII = MaterializingInfos.find(Name);
     518             :       assert(MII != MaterializingInfos.end() &&
     519             :              "Missing MaterializingInfo entry");
     520             : 
     521          34 :       auto &MI = MII->second;
     522             : 
     523             :       // For each dependant, transfer this node's unfinalized dependencies to
     524             :       // it. If the dependant node is fully finalized then notify any pending
     525             :       // queries.
     526          37 :       for (auto &KV : MI.Dependants) {
     527           3 :         auto &DependantVSO = *KV.first;
     528           8 :         for (auto &DependantName : KV.second) {
     529             :           auto DependantMII =
     530             :               DependantVSO.MaterializingInfos.find(DependantName);
     531             :           assert(DependantMII != DependantVSO.MaterializingInfos.end() &&
     532             :                  "Dependant should have MaterializingInfo");
     533             : 
     534           5 :           auto &DependantMI = DependantMII->second;
     535             : 
     536             :           // Remove the dependant's dependency on this node.
     537             :           assert(DependantMI.UnfinalizedDependencies[this].count(Name) &&
     538             :                  "Dependant does not count this symbol as a dependency?");
     539          10 :           DependantMI.UnfinalizedDependencies[this].erase(Name);
     540          10 :           if (DependantMI.UnfinalizedDependencies[this].empty())
     541          10 :             DependantMI.UnfinalizedDependencies.erase(this);
     542             : 
     543             :           // Transfer unfinalized dependencies from this node to the dependant.
     544           5 :           DependantVSO.transferFinalizedNodeDependencies(DependantMI,
     545             :                                                          DependantName, MI);
     546             : 
     547             :           // If the dependant is finalized and this node was the last of its
     548             :           // unfinalized dependencies then notify any pending queries on the
     549             :           // dependant node.
     550           8 :           if (DependantMI.IsFinalized &&
     551             :               DependantMI.UnfinalizedDependencies.empty()) {
     552             :             assert(DependantMI.Dependants.empty() &&
     553             :                    "Dependants should be empty by now");
     554           4 :             for (auto &Q : DependantMI.PendingQueries) {
     555           2 :               Q->notifySymbolReady();
     556           2 :               if (Q->isFullyReady())
     557             :                 ReadyQueries.insert(Q);
     558           2 :               Q->removeQueryDependence(DependantVSO, DependantName);
     559             :             }
     560             : 
     561             :             // If this dependant node was fully finalized we can erase its
     562             :             // MaterializingInfo and update its materializing state.
     563             :             assert(DependantVSO.Symbols.count(DependantName) &&
     564             :                    "Dependant has no entry in the Symbols table");
     565           2 :             auto &DependantSym = DependantVSO.Symbols[DependantName];
     566             :             DependantSym.setFlags(static_cast<JITSymbolFlags::FlagNames>(
     567             :                 DependantSym.getFlags() & ~JITSymbolFlags::Materializing));
     568             :             DependantVSO.MaterializingInfos.erase(DependantMII);
     569             :           }
     570             :         }
     571             :       }
     572             :       MI.Dependants.clear();
     573          34 :       MI.IsFinalized = true;
     574             : 
     575          34 :       if (MI.UnfinalizedDependencies.empty()) {
     576          63 :         for (auto &Q : MI.PendingQueries) {
     577          31 :           Q->notifySymbolReady();
     578          31 :           if (Q->isFullyReady())
     579             :             ReadyQueries.insert(Q);
     580          31 :           Q->removeQueryDependence(*this, Name);
     581             :         }
     582             :         assert(Symbols.count(Name) &&
     583             :                "Symbol has no entry in the Symbols table");
     584          32 :         auto &Sym = Symbols[Name];
     585             :         Sym.setFlags(static_cast<JITSymbolFlags::FlagNames>(
     586             :             Sym.getFlags() & ~JITSymbolFlags::Materializing));
     587             :         MaterializingInfos.erase(MII);
     588             :       }
     589             :     }
     590             : 
     591          32 :     return ReadyQueries;
     592          64 :   });
     593             : 
     594          63 :   for (auto &Q : FullyReadyQueries) {
     595             :     assert(Q->isFullyReady() && "Q is not fully ready");
     596          31 :     Q->handleFullyReady();
     597             :   }
     598          32 : }
     599             : 
     600           1 : void VSO::notifyFailed(const SymbolNameSet &FailedSymbols) {
     601             : 
     602             :   // FIXME: This should fail any transitively dependant symbols too.
     603             : 
     604           8 :   auto FailedQueriesToNotify = ES.runSessionLocked([&, this]() {
     605             :     AsynchronousSymbolQuerySet FailedQueries;
     606             : 
     607           4 :     for (auto &Name : FailedSymbols) {
     608             :       auto I = Symbols.find(Name);
     609             :       assert(I != Symbols.end() && "Symbol not present in this VSO");
     610             :       Symbols.erase(I);
     611             : 
     612             :       auto MII = MaterializingInfos.find(Name);
     613             : 
     614             :       // If we have not created a MaterializingInfo for this symbol yet then
     615             :       // there is nobody to notify.
     616           2 :       if (MII == MaterializingInfos.end())
     617             :         continue;
     618             : 
     619             :       // Copy all the queries to the FailedQueries list, then abandon them.
     620             :       // This has to be a copy, and the copy has to come before the abandon
     621             :       // operation: Each Q.detach() call will reach back into this
     622             :       // PendingQueries list to remove Q.
     623           3 :       for (auto &Q : MII->second.PendingQueries)
     624             :         FailedQueries.insert(Q);
     625             : 
     626           4 :       for (auto &Q : FailedQueries)
     627           2 :         Q->detach();
     628             : 
     629             :       assert(MII->second.PendingQueries.empty() &&
     630             :              "Queries remain after symbol was failed");
     631             : 
     632             :       MaterializingInfos.erase(MII);
     633             :     }
     634             : 
     635           1 :     return FailedQueries;
     636           2 :   });
     637             : 
     638           2 :   for (auto &Q : FailedQueriesToNotify)
     639           2 :     Q->handleFailed(make_error<FailedToMaterialize>(FailedSymbols));
     640           1 : }
     641             : 
     642           3 : SymbolNameSet VSO::lookupFlags(SymbolFlagsMap &Flags,
     643             :                                const SymbolNameSet &Names) {
     644           9 :   return ES.runSessionLocked([&, this]() {
     645           3 :     auto Unresolved = lookupFlagsImpl(Flags, Names);
     646           3 :     if (FallbackDefinitionGenerator && !Unresolved.empty()) {
     647             :       auto FallbackDefs = FallbackDefinitionGenerator(*this, Unresolved);
     648           0 :       if (!FallbackDefs.empty()) {
     649           0 :         auto Unresolved2 = lookupFlagsImpl(Flags, FallbackDefs);
     650             :         (void)Unresolved2;
     651             :         assert(Unresolved2.empty() &&
     652             :                "All fallback defs should have been found by lookupFlagsImpl");
     653           0 :         for (auto &D : FallbackDefs)
     654             :           Unresolved.erase(D);
     655             :       }
     656             :     };
     657           3 :     return Unresolved;
     658           6 :   });
     659             : }
     660             : 
     661           3 : SymbolNameSet VSO::lookupFlagsImpl(SymbolFlagsMap &Flags,
     662             :                                    const SymbolNameSet &Names) {
     663             :   SymbolNameSet Unresolved;
     664             : 
     665          10 :   for (auto &Name : Names) {
     666             :     auto I = Symbols.find(Name);
     667             : 
     668           9 :     if (I == Symbols.end()) {
     669             :       Unresolved.insert(Name);
     670             :       continue;
     671             :     }
     672             : 
     673             :     assert(!Flags.count(Name) && "Symbol already present in Flags map");
     674           5 :     Flags[Name] = JITSymbolFlags::stripTransientFlags(I->second.getFlags());
     675             :   }
     676             : 
     677           3 :   return Unresolved;
     678             : }
     679             : 
     680          33 : SymbolNameSet VSO::lookup(std::shared_ptr<AsynchronousSymbolQuery> Q,
     681             :                           SymbolNameSet Names) {
     682             :   assert(Q && "Query can not be null");
     683             : 
     684          33 :   std::vector<std::unique_ptr<MaterializationUnit>> MUs;
     685             : 
     686             :   SymbolNameSet Unresolved = std::move(Names);
     687         133 :   ES.runSessionLocked([&, this]() {
     688          36 :     lookupImpl(Q, MUs, Unresolved);
     689          34 :     if (FallbackDefinitionGenerator && !Unresolved.empty()) {
     690             :       auto FallbackDefs = FallbackDefinitionGenerator(*this, Unresolved);
     691           1 :       if (!FallbackDefs.empty()) {
     692           2 :         for (auto &D : FallbackDefs)
     693             :           Unresolved.erase(D);
     694           1 :         lookupImpl(Q, MUs, FallbackDefs);
     695             :         assert(FallbackDefs.empty() &&
     696             :                "All fallback defs should have been found by lookupImpl");
     697             :       }
     698             :     }
     699          33 :   });
     700             : 
     701          33 :   if (Q->isFullyResolved())
     702           1 :     Q->handleFullyResolved();
     703             : 
     704          33 :   if (Q->isFullyReady())
     705           1 :     Q->handleFullyReady();
     706             : 
     707             :   // Dispatch any required MaterializationUnits for materialization.
     708          66 :   for (auto &MU : MUs)
     709          99 :     ES.dispatchMaterialization(*this, std::move(MU));
     710             : 
     711          33 :   return Unresolved;
     712             : }
     713             : 
     714          34 : void VSO::lookupImpl(std::shared_ptr<AsynchronousSymbolQuery> &Q,
     715             :                      std::vector<std::unique_ptr<MaterializationUnit>> &MUs,
     716             :                      SymbolNameSet &Unresolved) {
     717          72 :   for (auto I = Unresolved.begin(), E = Unresolved.end(); I != E;) {
     718             :     auto TmpI = I++;
     719             :     auto Name = *TmpI;
     720             : 
     721             :     // Search for the name in Symbols. Skip it if not found.
     722             :     auto SymI = Symbols.find(Name);
     723          38 :     if (SymI == Symbols.end())
     724           2 :       continue;
     725             : 
     726             :     // If we found Name in V, remove it frome the Unresolved set and add it
     727             :     // to the dependencies set.
     728             :     Unresolved.erase(TmpI);
     729             : 
     730             :     // If the symbol has an address then resolve it.
     731          36 :     if (SymI->second.getAddress() != 0)
     732           1 :       Q->resolve(Name, SymI->second);
     733             : 
     734             :     // If the symbol is lazy, get the MaterialiaztionUnit for it.
     735          36 :     if (SymI->second.getFlags().isLazy()) {
     736             :       assert(SymI->second.getAddress() == 0 &&
     737             :              "Lazy symbol should not have a resolved address");
     738             :       assert(!SymI->second.getFlags().isMaterializing() &&
     739             :              "Materializing and lazy should not both be set");
     740             :       auto UMII = UnmaterializedInfos.find(Name);
     741             :       assert(UMII != UnmaterializedInfos.end() &&
     742             :              "Lazy symbol should have UnmaterializedInfo");
     743             :       auto MU = std::move(UMII->second->MU);
     744             :       assert(MU != nullptr && "Materializer should not be null");
     745             : 
     746             :       // Kick all symbols associated with this MaterializationUnit into
     747             :       // materializing state.
     748          69 :       for (auto &KV : MU->getSymbols()) {
     749             :         auto SymK = Symbols.find(KV.first);
     750             :         auto Flags = SymK->second.getFlags();
     751             :         Flags &= ~JITSymbolFlags::Weak;
     752          36 :         Flags &= ~JITSymbolFlags::Lazy;
     753          36 :         Flags |= JITSymbolFlags::Materializing;
     754             :         SymK->second.setFlags(Flags);
     755          36 :         UnmaterializedInfos.erase(KV.first);
     756             :       }
     757             : 
     758             :       // Add MU to the list of MaterializationUnits to be materialized.
     759             :       MUs.push_back(std::move(MU));
     760           4 :     } else if (!SymI->second.getFlags().isMaterializing()) {
     761             :       // The symbol is neither lazy nor materializing. Finalize it and
     762             :       // continue.
     763           1 :       Q->notifySymbolReady();
     764           1 :       continue;
     765             :     }
     766             : 
     767             :     // Add the query to the PendingQueries list.
     768             :     assert(SymI->second.getFlags().isMaterializing() &&
     769             :            "By this line the symbol should be materializing");
     770          35 :     auto &MI = MaterializingInfos[Name];
     771          35 :     MI.PendingQueries.push_back(Q);
     772          70 :     Q->addQueryDependence(*this, Name);
     773             :   }
     774          34 : }
     775             : 
     776           0 : void VSO::dump(raw_ostream &OS) {
     777           0 :   ES.runSessionLocked([&, this]() {
     778           0 :     OS << "VSO \"" << VSOName
     779           0 :        << "\" (ES: " << format("0x%016x", reinterpret_cast<uintptr_t>(&ES))
     780           0 :        << "):\n"
     781           0 :        << "Symbol table:\n";
     782             : 
     783           0 :     for (auto &KV : Symbols) {
     784           0 :       OS << "    \"" << *KV.first << "\": " << KV.second.getAddress();
     785           0 :       if (KV.second.getFlags().isLazy() ||
     786             :           KV.second.getFlags().isMaterializing()) {
     787           0 :         OS << " (";
     788           0 :         if (KV.second.getFlags().isLazy()) {
     789             :           auto I = UnmaterializedInfos.find(KV.first);
     790             :           assert(I != UnmaterializedInfos.end() &&
     791             :                  "Lazy symbol should have UnmaterializedInfo");
     792           0 :           OS << " Lazy (MU=" << I->second->MU.get() << ")";
     793             :         }
     794           0 :         if (KV.second.getFlags().isMaterializing())
     795           0 :           OS << " Materializing";
     796           0 :         OS << " )\n";
     797             :       } else
     798           0 :         OS << "\n";
     799             :     }
     800             : 
     801           0 :     if (!MaterializingInfos.empty())
     802           0 :       OS << "  MaterializingInfos entries:\n";
     803           0 :     for (auto &KV : MaterializingInfos) {
     804           0 :       OS << "    \"" << *KV.first << "\":\n"
     805           0 :          << "      IsFinalized = " << (KV.second.IsFinalized ? "true" : "false")
     806           0 :          << "\n"
     807           0 :          << "      " << KV.second.PendingQueries.size() << " pending queries.\n"
     808           0 :          << "      Dependants:\n";
     809           0 :       for (auto &KV2 : KV.second.Dependants)
     810           0 :         OS << "        " << KV2.first->getName() << ": " << KV2.second << "\n";
     811           0 :       OS << "      Unfinalized Dependencies:\n";
     812           0 :       for (auto &KV2 : KV.second.UnfinalizedDependencies)
     813           0 :         OS << "        " << KV2.first->getName() << ": " << KV2.second << "\n";
     814             :     }
     815           0 :   });
     816           0 : }
     817             : 
     818          40 : Error VSO::defineImpl(MaterializationUnit &MU) {
     819             :   SymbolNameSet Duplicates;
     820             :   SymbolNameSet MUDefsOverridden;
     821             :   std::vector<SymbolMap::iterator> ExistingDefsOverridden;
     822          85 :   for (auto &KV : MU.getSymbols()) {
     823             :     assert(!KV.second.isLazy() && "Lazy flag should be managed internally.");
     824             :     assert(!KV.second.isMaterializing() &&
     825             :            "Materializing flags should be managed internally.");
     826             : 
     827             :     SymbolMap::iterator EntryItr;
     828             :     bool Added;
     829             : 
     830          45 :     auto NewFlags = KV.second;
     831          45 :     NewFlags |= JITSymbolFlags::Lazy;
     832             : 
     833             :     std::tie(EntryItr, Added) = Symbols.insert(
     834          45 :         std::make_pair(KV.first, JITEvaluatedSymbol(0, NewFlags)));
     835             : 
     836          45 :     if (!Added) {
     837             :       if (KV.second.isStrong()) {
     838             :         if (EntryItr->second.getFlags().isStrong())
     839           1 :           Duplicates.insert(KV.first);
     840             :         else
     841           3 :           ExistingDefsOverridden.push_back(EntryItr);
     842             :       } else
     843           0 :         MUDefsOverridden.insert(KV.first);
     844             :     }
     845             :   }
     846             : 
     847          40 :   if (!Duplicates.empty()) {
     848             :     // We need to remove the symbols we added.
     849           2 :     for (auto &KV : MU.getSymbols()) {
     850           1 :       if (Duplicates.count(KV.first) || Duplicates.count(KV.first))
     851           1 :         continue;
     852             : 
     853             :       bool Found = false;
     854           0 :       for (const auto &I : ExistingDefsOverridden)
     855           0 :         if (I->first == KV.first)
     856             :           Found = true;
     857             : 
     858           0 :       if (!Found)
     859           0 :         Symbols.erase(KV.first);
     860             :     }
     861             : 
     862             :     // FIXME: Return all duplicates.
     863           2 :     return make_error<DuplicateDefinition>(**Duplicates.begin());
     864             :   }
     865             : 
     866             :   // Update flags on existing defs and call discard on their materializers.
     867          42 :   for (auto &ExistingDefItr : ExistingDefsOverridden) {
     868             :     assert(ExistingDefItr->second.getFlags().isLazy() &&
     869             :            !ExistingDefItr->second.getFlags().isMaterializing() &&
     870             :            "Overridden existing def should be in the Lazy state");
     871             : 
     872             :     ExistingDefItr->second.getFlags() &= ~JITSymbolFlags::Weak;
     873             : 
     874             :     auto UMII = UnmaterializedInfos.find(ExistingDefItr->first);
     875             :     assert(UMII != UnmaterializedInfos.end() &&
     876             :            "Overridden existing def should have an UnmaterializedInfo");
     877             : 
     878           6 :     UMII->second->MU->doDiscard(*this, ExistingDefItr->first);
     879             :   }
     880             : 
     881             :   // Discard overridden symbols povided by MU.
     882          39 :   for (auto &Sym : MUDefsOverridden)
     883           0 :     MU.doDiscard(*this, Sym);
     884             : 
     885             :   return Error::success();
     886             : }
     887             : 
     888           1 : void VSO::detachQueryHelper(AsynchronousSymbolQuery &Q,
     889             :                             const SymbolNameSet &QuerySymbols) {
     890           3 :   for (auto &QuerySymbol : QuerySymbols) {
     891             :     assert(MaterializingInfos.count(QuerySymbol) &&
     892             :            "QuerySymbol does not have MaterializingInfo");
     893           2 :     auto &MI = MaterializingInfos[QuerySymbol];
     894             : 
     895             :     auto IdenticalQuery =
     896             :         [&](const std::shared_ptr<AsynchronousSymbolQuery> &R) {
     897           2 :           return R.get() == &Q;
     898             :         };
     899             : 
     900             :     auto I = std::find_if(MI.PendingQueries.begin(), MI.PendingQueries.end(),
     901             :                           IdenticalQuery);
     902             :     assert(I != MI.PendingQueries.end() &&
     903             :            "Query Q should be in the PendingQueries list for QuerySymbol");
     904           2 :     MI.PendingQueries.erase(I);
     905             :   }
     906           1 : }
     907             : 
     908           5 : void VSO::transferFinalizedNodeDependencies(
     909             :     MaterializingInfo &DependantMI, const SymbolStringPtr &DependantName,
     910             :     MaterializingInfo &FinalizedMI) {
     911           8 :   for (auto &KV : FinalizedMI.UnfinalizedDependencies) {
     912           3 :     auto &DependencyVSO = *KV.first;
     913             :     SymbolNameSet *UnfinalizedDependenciesOnDependencyVSO = nullptr;
     914             : 
     915           6 :     for (auto &DependencyName : KV.second) {
     916           3 :       auto &DependencyMI = DependencyVSO.MaterializingInfos[DependencyName];
     917             : 
     918             :       // Do not add self dependencies.
     919           3 :       if (&DependencyMI == &DependantMI)
     920           1 :         continue;
     921             : 
     922             :       // If we haven't looked up the dependencies for DependencyVSO yet, do it
     923             :       // now and cache the result.
     924           2 :       if (!UnfinalizedDependenciesOnDependencyVSO)
     925           2 :         UnfinalizedDependenciesOnDependencyVSO =
     926           4 :             &DependantMI.UnfinalizedDependencies[&DependencyVSO];
     927             : 
     928           4 :       DependencyMI.Dependants[this].insert(DependantName);
     929             :       UnfinalizedDependenciesOnDependencyVSO->insert(DependencyName);
     930             :     }
     931             :   }
     932           5 : }
     933             : 
     934          33 : VSO &ExecutionSession::createVSO(std::string Name) {
     935          99 :   return runSessionLocked([&, this]() -> VSO & {
     936         165 :       VSOs.push_back(std::unique_ptr<VSO>(new VSO(*this, std::move(Name))));
     937          33 :     return *VSOs.back();
     938          66 :   });
     939             : }
     940             : 
     941          73 : Expected<SymbolMap> blockingLookup(ExecutionSessionBase &ES,
     942             :                                    AsynchronousLookupFunction AsyncLookup,
     943             :                                    SymbolNameSet Names, bool WaitUntilReady,
     944             :                                    MaterializationResponsibility *MR) {
     945             : 
     946             : #if LLVM_ENABLE_THREADS
     947             :   // In the threaded case we use promises to return the results.
     948         146 :   std::promise<SymbolMap> PromisedResult;
     949          73 :   std::mutex ErrMutex;
     950             :   Error ResolutionError = Error::success();
     951         146 :   std::promise<void> PromisedReady;
     952             :   Error ReadyError = Error::success();
     953             :   auto OnResolve =
     954          73 :       [&](Expected<AsynchronousSymbolQuery::ResolutionResult> Result) {
     955          73 :         if (Result) {
     956          73 :           if (MR)
     957           0 :             MR->addDependencies(Result->Dependencies);
     958          73 :           PromisedResult.set_value(std::move(Result->Symbols));
     959             :         } else {
     960             :           {
     961           0 :             ErrorAsOutParameter _(&ResolutionError);
     962           0 :             std::lock_guard<std::mutex> Lock(ErrMutex);
     963             :             ResolutionError = Result.takeError();
     964             :           }
     965           0 :           PromisedResult.set_value(SymbolMap());
     966             :         }
     967         146 :       };
     968             : 
     969             :   std::function<void(Error)> OnReady;
     970          73 :   if (WaitUntilReady) {
     971          44 :     OnReady = [&](Error Err) {
     972          22 :       if (Err) {
     973           0 :         ErrorAsOutParameter _(&ReadyError);
     974           0 :         std::lock_guard<std::mutex> Lock(ErrMutex);
     975             :         ReadyError = std::move(Err);
     976             :       }
     977          22 :       PromisedReady.set_value();
     978          66 :     };
     979             :   } else {
     980         102 :     OnReady = [&](Error Err) {
     981          51 :       if (Err)
     982           0 :         ES.reportError(std::move(Err));
     983         153 :     };
     984             :   }
     985             : 
     986             : #else
     987             :   SymbolMap Result;
     988             :   Error ResolutionError = Error::success();
     989             :   Error ReadyError = Error::success();
     990             : 
     991             :   auto OnResolve = [&](Expected<AsynchronousSymbolQuery::ResolutionResult> R) {
     992             :     ErrorAsOutParameter _(&ResolutionError);
     993             :     if (R) {
     994             :       if (MR)
     995             :         MR->addDependencies(R->Dependencies);
     996             :       Result = std::move(R->Symbols);
     997             :     } else
     998             :       ResolutionError = R.takeError();
     999             :   };
    1000             : 
    1001             :   std::function<void(Error)> OnReady;
    1002             :   if (WaitUntilReady) {
    1003             :     OnReady = [&](Error Err) {
    1004             :       ErrorAsOutParameter _(&ReadyError);
    1005             :       if (Err)
    1006             :         ReadyError = std::move(Err);
    1007             :     };
    1008             :   } else {
    1009             :     OnReady = [&](Error Err) {
    1010             :       if (Err)
    1011             :         ES.reportError(std::move(Err));
    1012             :     };
    1013             :   }
    1014             : #endif
    1015             : 
    1016             :   auto Query = std::make_shared<AsynchronousSymbolQuery>(
    1017             :       Names, std::move(OnResolve), std::move(OnReady));
    1018             : 
    1019         146 :   SymbolNameSet UnresolvedSymbols = AsyncLookup(Query, std::move(Names));
    1020             : 
    1021             :   // If there are unresolved symbols then the query will never return.
    1022             :   // Fail it with ES.failQuery.
    1023          73 :   if (!UnresolvedSymbols.empty())
    1024           0 :     ES.failQuery(*Query,
    1025           0 :                  make_error<SymbolsNotFound>(std::move(UnresolvedSymbols)));
    1026             : 
    1027             : #if LLVM_ENABLE_THREADS
    1028             :   auto ResultFuture = PromisedResult.get_future();
    1029          73 :   auto Result = ResultFuture.get();
    1030             : 
    1031             :   {
    1032             :     std::lock_guard<std::mutex> Lock(ErrMutex);
    1033          73 :     if (ResolutionError) {
    1034             :       // ReadyError will never be assigned. Consume the success value.
    1035             :       cantFail(std::move(ReadyError));
    1036             :       return std::move(ResolutionError);
    1037             :     }
    1038             :   }
    1039             : 
    1040          73 :   if (WaitUntilReady) {
    1041             :     auto ReadyFuture = PromisedReady.get_future();
    1042          22 :     ReadyFuture.get();
    1043             : 
    1044             :     {
    1045             :       std::lock_guard<std::mutex> Lock(ErrMutex);
    1046          22 :       if (ReadyError)
    1047             :         return std::move(ReadyError);
    1048             :     }
    1049             :   } else
    1050             :     cantFail(std::move(ReadyError));
    1051             : 
    1052             :   return std::move(Result);
    1053             : 
    1054             : #else
    1055             :   if (ResolutionError) {
    1056             :     // ReadyError will never be assigned. Consume the success value.
    1057             :     cantFail(std::move(ReadyError));
    1058             :     return std::move(ResolutionError);
    1059             :   }
    1060             : 
    1061             :   if (ReadyError)
    1062             :     return std::move(ReadyError);
    1063             : 
    1064             :   return Result;
    1065             : #endif
    1066             : }
    1067             : 
    1068          22 : Expected<SymbolMap> lookup(const VSO::VSOList &VSOs, SymbolNameSet Names) {
    1069             : 
    1070          22 :   if (VSOs.empty())
    1071           0 :     return SymbolMap();
    1072             : 
    1073          22 :   auto &ES = (*VSOs.begin())->getExecutionSession();
    1074             : 
    1075             :   auto LookupFn = [&](std::shared_ptr<AsynchronousSymbolQuery> Q,
    1076          22 :                       SymbolNameSet Unresolved) {
    1077          22 :     for (auto *V : VSOs) {
    1078             :       assert(V && "VSOs entries must not be null");
    1079          22 :       if (Unresolved.empty())
    1080             :         break;
    1081          88 :       Unresolved = V->lookup(Q, std::move(Unresolved));
    1082             :     }
    1083          22 :     return Unresolved;
    1084             :   };
    1085             : 
    1086          66 :   return blockingLookup(ES, std::move(LookupFn), Names, true);
    1087             : }
    1088             : 
    1089             : /// Look up a symbol by searching a list of VSOs.
    1090          21 : Expected<JITEvaluatedSymbol> lookup(const VSO::VSOList &VSOs,
    1091             :                                     SymbolStringPtr Name) {
    1092          42 :   SymbolNameSet Names({Name});
    1093          84 :   if (auto ResultMap = lookup(VSOs, std::move(Names))) {
    1094             :     assert(ResultMap->size() == 1 && "Unexpected number of results");
    1095             :     assert(ResultMap->count(Name) && "Missing result for symbol");
    1096             :     return std::move(ResultMap->begin()->second);
    1097             :   } else
    1098             :     return ResultMap.takeError();
    1099             : }
    1100             : 
    1101             : } // End namespace orc.
    1102             : } // End namespace llvm.

Generated by: LCOV version 1.13