LCOV - code coverage report
Current view: top level - lib/ExecutionEngine/Orc - Core.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 357 480 74.4 %
Date: 2018-09-23 13:06:45 Functions: 62 82 75.6 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===--- Core.cpp - Core ORC APIs (MaterializationUnit, JITDylib, 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/IR/Mangler.h"
      14             : #include "llvm/Support/Debug.h"
      15             : #include "llvm/Support/Format.h"
      16             : 
      17             : #if LLVM_ENABLE_THREADS
      18             : #include <future>
      19             : #endif
      20             : 
      21             : namespace llvm {
      22             : namespace orc {
      23             : 
      24             : char FailedToMaterialize::ID = 0;
      25             : char SymbolsNotFound::ID = 0;
      26             : 
      27             : RegisterDependenciesFunction NoDependenciesToRegister =
      28             :     RegisterDependenciesFunction();
      29             : 
      30           0 : void MaterializationUnit::anchor() {}
      31             : 
      32           0 : raw_ostream &operator<<(raw_ostream &OS, const JITSymbolFlags &Flags) {
      33           0 :   if (Flags.isCallable())
      34           0 :     OS << "[Callable]";
      35             :   else
      36           0 :     OS << "[Data]";
      37           0 :   if (Flags.isWeak())
      38           0 :     OS << "[Weak]";
      39           0 :   else if (Flags.isCommon())
      40           0 :     OS << "[Common]";
      41             : 
      42           0 :   if (!Flags.isExported())
      43           0 :     OS << "[Hidden]";
      44             : 
      45           0 :   return OS;
      46             : }
      47             : 
      48           0 : raw_ostream &operator<<(raw_ostream &OS, const JITEvaluatedSymbol &Sym) {
      49           0 :   OS << format("0x%016x", Sym.getAddress()) << " " << Sym.getFlags();
      50           0 :   return OS;
      51             : }
      52             : 
      53           0 : raw_ostream &operator<<(raw_ostream &OS, const SymbolMap::value_type &KV) {
      54           0 :   OS << "\"" << *KV.first << "\": " << KV.second;
      55           0 :   return OS;
      56             : }
      57             : 
      58           0 : raw_ostream &operator<<(raw_ostream &OS, const SymbolNameSet &Symbols) {
      59           0 :   OS << "{";
      60           0 :   if (!Symbols.empty()) {
      61           0 :     OS << " \"" << **Symbols.begin() << "\"";
      62           0 :     for (auto &Sym : make_range(std::next(Symbols.begin()), Symbols.end()))
      63           0 :       OS << ", \"" << *Sym << "\"";
      64             :   }
      65           0 :   OS << " }";
      66           0 :   return OS;
      67             : }
      68             : 
      69           0 : raw_ostream &operator<<(raw_ostream &OS, const SymbolMap &Symbols) {
      70           0 :   OS << "{";
      71           0 :   if (!Symbols.empty()) {
      72           0 :     OS << " {" << *Symbols.begin() << "}";
      73           0 :     for (auto &Sym : make_range(std::next(Symbols.begin()), Symbols.end()))
      74           0 :       OS << ", {" << Sym << "}";
      75             :   }
      76           0 :   OS << " }";
      77           0 :   return OS;
      78             : }
      79             : 
      80           0 : raw_ostream &operator<<(raw_ostream &OS, const SymbolFlagsMap &SymbolFlags) {
      81           0 :   OS << "{";
      82           0 :   if (!SymbolFlags.empty()) {
      83           0 :     OS << " {\"" << *SymbolFlags.begin()->first
      84           0 :        << "\": " << SymbolFlags.begin()->second << "}";
      85             :     for (auto &KV :
      86           0 :          make_range(std::next(SymbolFlags.begin()), SymbolFlags.end()))
      87           0 :       OS << ", {\"" << *KV.first << "\": " << KV.second << "}";
      88             :   }
      89           0 :   OS << " }";
      90           0 :   return OS;
      91             : }
      92             : 
      93           0 : raw_ostream &operator<<(raw_ostream &OS, const SymbolDependenceMap &Deps) {
      94           0 :   OS << "{";
      95           0 :   if (!Deps.empty()) {
      96           0 :     OS << " { " << Deps.begin()->first->getName() << ": "
      97           0 :        << Deps.begin()->second << " }";
      98           0 :     for (auto &KV : make_range(std::next(Deps.begin()), Deps.end()))
      99           0 :       OS << ", { " << KV.first->getName() << ": " << KV.second << " }";
     100             :   }
     101           0 :   OS << " }";
     102           0 :   return OS;
     103             : }
     104             : 
     105           0 : raw_ostream &operator<<(raw_ostream &OS, const JITDylibList &JDs) {
     106           0 :   OS << "[";
     107           0 :   if (!JDs.empty()) {
     108             :     assert(JDs.front() && "JITDylibList entries must not be null");
     109           0 :     OS << " " << JDs.front()->getName();
     110           0 :     for (auto *JD : make_range(std::next(JDs.begin()), JDs.end())) {
     111             :       assert(JD && "JITDylibList entries must not be null");
     112           0 :       OS << ", " << JD->getName();
     113             :     }
     114             :   }
     115           0 :   OS << " ]";
     116           0 :   return OS;
     117             : }
     118             : 
     119           1 : FailedToMaterialize::FailedToMaterialize(SymbolNameSet Symbols)
     120           1 :     : Symbols(std::move(Symbols)) {
     121             :   assert(!this->Symbols.empty() && "Can not fail to resolve an empty set");
     122           1 : }
     123             : 
     124           0 : std::error_code FailedToMaterialize::convertToErrorCode() const {
     125           0 :   return orcError(OrcErrorCode::UnknownORCError);
     126             : }
     127             : 
     128           0 : void FailedToMaterialize::log(raw_ostream &OS) const {
     129           0 :   OS << "Failed to materialize symbols: " << Symbols;
     130           0 : }
     131             : 
     132           0 : SymbolsNotFound::SymbolsNotFound(SymbolNameSet Symbols)
     133           0 :     : Symbols(std::move(Symbols)) {
     134             :   assert(!this->Symbols.empty() && "Can not fail to resolve an empty set");
     135           0 : }
     136             : 
     137           0 : std::error_code SymbolsNotFound::convertToErrorCode() const {
     138           0 :   return orcError(OrcErrorCode::UnknownORCError);
     139             : }
     140             : 
     141           0 : void SymbolsNotFound::log(raw_ostream &OS) const {
     142           0 :   OS << "Symbols not found: " << Symbols;
     143           0 : }
     144             : 
     145         156 : AsynchronousSymbolQuery::AsynchronousSymbolQuery(
     146             :     const SymbolNameSet &Symbols, SymbolsResolvedCallback NotifySymbolsResolved,
     147         156 :     SymbolsReadyCallback NotifySymbolsReady)
     148             :     : NotifySymbolsResolved(std::move(NotifySymbolsResolved)),
     149         156 :       NotifySymbolsReady(std::move(NotifySymbolsReady)) {
     150         156 :   NotYetResolvedCount = NotYetReadyCount = Symbols.size();
     151             : 
     152         337 :   for (auto &S : Symbols)
     153         181 :     ResolvedSymbols[S] = nullptr;
     154         156 : }
     155             : 
     156         178 : void AsynchronousSymbolQuery::resolve(const SymbolStringPtr &Name,
     157             :                                       JITEvaluatedSymbol Sym) {
     158             :   auto I = ResolvedSymbols.find(Name);
     159             :   assert(I != ResolvedSymbols.end() &&
     160             :          "Resolving symbol outside the requested set");
     161             :   assert(I->second.getAddress() == 0 && "Redundantly resolving symbol Name");
     162         178 :   I->second = std::move(Sym);
     163         178 :   --NotYetResolvedCount;
     164         178 : }
     165             : 
     166         154 : void AsynchronousSymbolQuery::handleFullyResolved() {
     167             :   assert(NotYetResolvedCount == 0 && "Not fully resolved?");
     168             : 
     169         154 :   if (!NotifySymbolsResolved) {
     170             :     // handleFullyResolved may be called by handleFullyReady (see comments in
     171             :     // that method), in which case this is a no-op, so bail out.
     172             :     assert(!NotifySymbolsReady &&
     173             :            "NotifySymbolsResolved already called or an error occurred");
     174           0 :     return;
     175             :   }
     176             : 
     177         154 :   auto TmpNotifySymbolsResolved = std::move(NotifySymbolsResolved);
     178         308 :   NotifySymbolsResolved = SymbolsResolvedCallback();
     179         154 :   TmpNotifySymbolsResolved(std::move(ResolvedSymbols));
     180             : }
     181             : 
     182         178 : void AsynchronousSymbolQuery::notifySymbolReady() {
     183             :   assert(NotYetReadyCount != 0 && "All symbols already emitted");
     184         178 :   --NotYetReadyCount;
     185         178 : }
     186             : 
     187         154 : void AsynchronousSymbolQuery::handleFullyReady() {
     188             :   assert(NotifySymbolsReady &&
     189             :          "NotifySymbolsReady already called or an error occurred");
     190             : 
     191         154 :   auto TmpNotifySymbolsReady = std::move(NotifySymbolsReady);
     192         154 :   NotifySymbolsReady = SymbolsReadyCallback();
     193             : 
     194         154 :   if (NotYetResolvedCount == 0 && NotifySymbolsResolved) {
     195             :     // The NotifyResolved callback of one query must have caused this query to
     196             :     // become ready (i.e. there is still a handleFullyResolved callback waiting
     197             :     // to be made back up the stack). Fold the handleFullyResolved call into
     198             :     // this one before proceeding. This will cause the call further up the
     199             :     // stack to become a no-op.
     200           0 :     handleFullyResolved();
     201             :   }
     202             : 
     203             :   assert(QueryRegistrations.empty() &&
     204             :          "Query is still registered with some symbols");
     205             :   assert(!NotifySymbolsResolved && "Resolution not applied yet");
     206         154 :   TmpNotifySymbolsReady(Error::success());
     207         154 : }
     208             : 
     209           1 : bool AsynchronousSymbolQuery::canStillFail() {
     210           1 :   return (NotifySymbolsResolved || NotifySymbolsReady);
     211             : }
     212             : 
     213           2 : void AsynchronousSymbolQuery::handleFailed(Error Err) {
     214             :   assert(QueryRegistrations.empty() && ResolvedSymbols.empty() &&
     215             :          NotYetResolvedCount == 0 && NotYetReadyCount == 0 &&
     216             :          "Query should already have been abandoned");
     217           2 :   if (NotifySymbolsResolved) {
     218           2 :     NotifySymbolsResolved(std::move(Err));
     219           4 :     NotifySymbolsResolved = SymbolsResolvedCallback();
     220             :   } else {
     221             :     assert(NotifySymbolsReady && "Failed after both callbacks issued?");
     222           0 :     NotifySymbolsReady(std::move(Err));
     223             :   }
     224           2 :   NotifySymbolsReady = SymbolsReadyCallback();
     225           2 : }
     226             : 
     227          96 : void AsynchronousSymbolQuery::addQueryDependence(JITDylib &JD,
     228             :                                                  SymbolStringPtr Name) {
     229          96 :   bool Added = QueryRegistrations[&JD].insert(std::move(Name)).second;
     230             :   (void)Added;
     231             :   assert(Added && "Duplicate dependence notification?");
     232          96 : }
     233             : 
     234          94 : void AsynchronousSymbolQuery::removeQueryDependence(
     235             :     JITDylib &JD, const SymbolStringPtr &Name) {
     236          94 :   auto QRI = QueryRegistrations.find(&JD);
     237             :   assert(QRI != QueryRegistrations.end() &&
     238             :          "No dependencies registered for JD");
     239             :   assert(QRI->second.count(Name) && "No dependency on Name in JD");
     240             :   QRI->second.erase(Name);
     241          94 :   if (QRI->second.empty())
     242             :     QueryRegistrations.erase(QRI);
     243          94 : }
     244             : 
     245           3 : void AsynchronousSymbolQuery::detach() {
     246             :   ResolvedSymbols.clear();
     247           3 :   NotYetResolvedCount = 0;
     248           3 :   NotYetReadyCount = 0;
     249           4 :   for (auto &KV : QueryRegistrations)
     250           1 :     KV.first->detachQueryHelper(*this, KV.second);
     251             :   QueryRegistrations.clear();
     252           3 : }
     253             : 
     254          98 : MaterializationResponsibility::MaterializationResponsibility(
     255          98 :     JITDylib &JD, SymbolFlagsMap SymbolFlags)
     256          98 :     : JD(JD), SymbolFlags(std::move(SymbolFlags)) {
     257             :   assert(!this->SymbolFlags.empty() && "Materializing nothing?");
     258             : 
     259             : #ifndef NDEBUG
     260             :   for (auto &KV : this->SymbolFlags)
     261             :     KV.second |= JITSymbolFlags::Materializing;
     262             : #endif
     263          98 : }
     264             : 
     265         265 : MaterializationResponsibility::~MaterializationResponsibility() {
     266             :   assert(SymbolFlags.empty() &&
     267             :          "All symbols should have been explicitly materialized or failed");
     268         265 : }
     269             : 
     270          25 : SymbolNameSet MaterializationResponsibility::getRequestedSymbols() {
     271          25 :   return JD.getRequestedSymbols(SymbolFlags);
     272             : }
     273             : 
     274         100 : void MaterializationResponsibility::resolve(const SymbolMap &Symbols) {
     275             : #ifndef NDEBUG
     276             :   for (auto &KV : Symbols) {
     277             :     auto I = SymbolFlags.find(KV.first);
     278             :     assert(I != SymbolFlags.end() &&
     279             :            "Resolving symbol outside this responsibility set");
     280             :     assert(I->second.isMaterializing() && "Duplicate resolution");
     281             :     I->second &= ~JITSymbolFlags::Materializing;
     282             :     if (I->second.isWeak())
     283             :       assert(I->second == (KV.second.getFlags() | JITSymbolFlags::Weak) &&
     284             :              "Resolving symbol with incorrect flags");
     285             :     else
     286             :       assert(I->second == KV.second.getFlags() &&
     287             :              "Resolving symbol with incorrect flags");
     288             :   }
     289             : #endif
     290             : 
     291         100 :   JD.resolve(Symbols);
     292         100 : }
     293             : 
     294          90 : void MaterializationResponsibility::emit() {
     295             : #ifndef NDEBUG
     296             :   for (auto &KV : SymbolFlags)
     297             :     assert(!KV.second.isMaterializing() &&
     298             :            "Failed to resolve symbol before emission");
     299             : #endif // NDEBUG
     300             : 
     301          90 :   JD.emit(SymbolFlags);
     302             :   SymbolFlags.clear();
     303          90 : }
     304             : 
     305           2 : Error MaterializationResponsibility::defineMaterializing(
     306             :     const SymbolFlagsMap &NewSymbolFlags) {
     307             :   // Add the given symbols to this responsibility object.
     308             :   // It's ok if we hit a duplicate here: In that case the new version will be
     309             :   // discarded, and the JITDylib::defineMaterializing method will return a
     310             :   // duplicate symbol error.
     311           4 :   for (auto &KV : NewSymbolFlags) {
     312             :     auto I = SymbolFlags.insert(KV).first;
     313             :     (void)I;
     314             : #ifndef NDEBUG
     315             :     I->second |= JITSymbolFlags::Materializing;
     316             : #endif
     317             :   }
     318             : 
     319           2 :   return JD.defineMaterializing(NewSymbolFlags);
     320             : }
     321             : 
     322           1 : void MaterializationResponsibility::failMaterialization() {
     323             : 
     324             :   SymbolNameSet FailedSymbols;
     325           3 :   for (auto &KV : SymbolFlags)
     326           2 :     FailedSymbols.insert(KV.first);
     327             : 
     328           1 :   JD.notifyFailed(FailedSymbols);
     329             :   SymbolFlags.clear();
     330           1 : }
     331             : 
     332          21 : void MaterializationResponsibility::replace(
     333             :     std::unique_ptr<MaterializationUnit> MU) {
     334          37 :   for (auto &KV : MU->getSymbols())
     335          16 :     SymbolFlags.erase(KV.first);
     336             : 
     337          42 :   JD.replace(std::move(MU));
     338          21 : }
     339             : 
     340             : MaterializationResponsibility
     341           9 : MaterializationResponsibility::delegate(const SymbolNameSet &Symbols) {
     342             :   SymbolFlagsMap DelegatedFlags;
     343             : 
     344          18 :   for (auto &Name : Symbols) {
     345             :     auto I = SymbolFlags.find(Name);
     346             :     assert(I != SymbolFlags.end() &&
     347             :            "Symbol is not tracked by this MaterializationResponsibility "
     348             :            "instance");
     349             : 
     350           9 :     DelegatedFlags[Name] = std::move(I->second);
     351             :     SymbolFlags.erase(I);
     352             :   }
     353             : 
     354          18 :   return MaterializationResponsibility(JD, std::move(DelegatedFlags));
     355             : }
     356             : 
     357           6 : void MaterializationResponsibility::addDependencies(
     358             :     const SymbolStringPtr &Name, const SymbolDependenceMap &Dependencies) {
     359             :   assert(SymbolFlags.count(Name) &&
     360             :          "Symbol not covered by this MaterializationResponsibility instance");
     361           6 :   JD.addDependencies(Name, Dependencies);
     362           6 : }
     363             : 
     364          14 : void MaterializationResponsibility::addDependenciesForAll(
     365             :     const SymbolDependenceMap &Dependencies) {
     366          33 :   for (auto &KV : SymbolFlags)
     367          19 :     JD.addDependencies(KV.first, Dependencies);
     368          14 : }
     369             : 
     370          28 : AbsoluteSymbolsMaterializationUnit::AbsoluteSymbolsMaterializationUnit(
     371          28 :     SymbolMap Symbols)
     372          56 :     : MaterializationUnit(extractFlags(Symbols)), Symbols(std::move(Symbols)) {}
     373             : 
     374          15 : void AbsoluteSymbolsMaterializationUnit::materialize(
     375             :     MaterializationResponsibility R) {
     376          15 :   R.resolve(Symbols);
     377          15 :   R.emit();
     378          15 : }
     379             : 
     380           0 : void AbsoluteSymbolsMaterializationUnit::discard(const JITDylib &JD,
     381             :                                                  SymbolStringPtr Name) {
     382             :   assert(Symbols.count(Name) && "Symbol is not part of this MU");
     383             :   Symbols.erase(Name);
     384           0 : }
     385             : 
     386             : SymbolFlagsMap
     387          28 : AbsoluteSymbolsMaterializationUnit::extractFlags(const SymbolMap &Symbols) {
     388             :   SymbolFlagsMap Flags;
     389          69 :   for (const auto &KV : Symbols)
     390          41 :     Flags[KV.first] = KV.second.getFlags();
     391          28 :   return Flags;
     392             : }
     393             : 
     394          17 : ReExportsMaterializationUnit::ReExportsMaterializationUnit(
     395          17 :     JITDylib *SourceJD, SymbolAliasMap Aliases)
     396          17 :     : MaterializationUnit(extractFlags(Aliases)), SourceJD(SourceJD),
     397          17 :       Aliases(std::move(Aliases)) {}
     398             : 
     399           7 : void ReExportsMaterializationUnit::materialize(
     400             :     MaterializationResponsibility R) {
     401             : 
     402           7 :   auto &ES = R.getTargetJITDylib().getExecutionSession();
     403             :   JITDylib &TgtJD = R.getTargetJITDylib();
     404           7 :   JITDylib &SrcJD = SourceJD ? *SourceJD : TgtJD;
     405             : 
     406             :   // Find the set of requested aliases and aliasees. Return any unrequested
     407             :   // aliases back to the JITDylib so as to not prematurely materialize any
     408             :   // aliasees.
     409           7 :   auto RequestedSymbols = R.getRequestedSymbols();
     410             :   SymbolAliasMap RequestedAliases;
     411             : 
     412          15 :   for (auto &Name : RequestedSymbols) {
     413             :     auto I = Aliases.find(Name);
     414             :     assert(I != Aliases.end() && "Symbol not found in aliases map?");
     415           8 :     RequestedAliases[Name] = std::move(I->second);
     416             :     Aliases.erase(I);
     417             :   }
     418             : 
     419           7 :   if (!Aliases.empty()) {
     420           2 :     if (SourceJD)
     421           2 :       R.replace(reexports(*SourceJD, std::move(Aliases)));
     422             :     else
     423           2 :       R.replace(symbolAliases(std::move(Aliases)));
     424             :   }
     425             : 
     426             :   // The OnResolveInfo struct will hold the aliases and responsibilty for each
     427             :   // query in the list.
     428           8 :   struct OnResolveInfo {
     429           8 :     OnResolveInfo(MaterializationResponsibility R, SymbolAliasMap Aliases)
     430           8 :         : R(std::move(R)), Aliases(std::move(Aliases)) {}
     431             : 
     432             :     MaterializationResponsibility R;
     433             :     SymbolAliasMap Aliases;
     434             :   };
     435             : 
     436             :   // Build a list of queries to issue. In each round we build the largest set of
     437             :   // aliases that we can resolve without encountering a chain definition of the
     438             :   // form Foo -> Bar, Bar -> Baz. Such a form would deadlock as the query would
     439             :   // be waitin on a symbol that it itself had to resolve. Usually this will just
     440             :   // involve one round and a single query.
     441             : 
     442             :   std::vector<std::pair<SymbolNameSet, std::shared_ptr<OnResolveInfo>>>
     443           7 :       QueryInfos;
     444          15 :   while (!RequestedAliases.empty()) {
     445             :     SymbolNameSet ResponsibilitySymbols;
     446             :     SymbolNameSet QuerySymbols;
     447             :     SymbolAliasMap QueryAliases;
     448             : 
     449             :     for (auto I = RequestedAliases.begin(), E = RequestedAliases.end();
     450          17 :          I != E;) {
     451             :       auto Tmp = I++;
     452             : 
     453             :       // Chain detected. Skip this symbol for this round.
     454           9 :       if (&SrcJD == &TgtJD && (QueryAliases.count(Tmp->second.Aliasee) ||
     455             :                                RequestedAliases.count(Tmp->second.Aliasee)))
     456             :         continue;
     457             : 
     458           8 :       ResponsibilitySymbols.insert(Tmp->first);
     459           8 :       QuerySymbols.insert(Tmp->second.Aliasee);
     460           8 :       QueryAliases[Tmp->first] = std::move(Tmp->second);
     461             :       RequestedAliases.erase(Tmp);
     462             :     }
     463             :     assert(!QuerySymbols.empty() && "Alias cycle detected!");
     464             : 
     465             :     auto QueryInfo = std::make_shared<OnResolveInfo>(
     466          16 :         R.delegate(ResponsibilitySymbols), std::move(QueryAliases));
     467             :     QueryInfos.push_back(
     468           8 :         make_pair(std::move(QuerySymbols), std::move(QueryInfo)));
     469             :   }
     470             : 
     471             :   // Issue the queries.
     472          15 :   while (!QueryInfos.empty()) {
     473             :     auto QuerySymbols = std::move(QueryInfos.back().first);
     474             :     auto QueryInfo = std::move(QueryInfos.back().second);
     475             : 
     476             :     QueryInfos.pop_back();
     477             : 
     478             :     auto RegisterDependencies = [QueryInfo,
     479          16 :                                  &SrcJD](const SymbolDependenceMap &Deps) {
     480             :       // If there were no materializing symbols, just bail out.
     481             :       if (Deps.empty())
     482             :         return;
     483             : 
     484             :       // Otherwise the only deps should be on SrcJD.
     485             :       assert(Deps.size() == 1 && Deps.count(&SrcJD) &&
     486             :              "Unexpected dependencies for reexports");
     487             : 
     488             :       auto &SrcJDDeps = Deps.find(&SrcJD)->second;
     489             :       SymbolDependenceMap PerAliasDepsMap;
     490             :       auto &PerAliasDeps = PerAliasDepsMap[&SrcJD];
     491             : 
     492             :       for (auto &KV : QueryInfo->Aliases)
     493             :         if (SrcJDDeps.count(KV.second.Aliasee)) {
     494             :           PerAliasDeps = {KV.second.Aliasee};
     495             :           QueryInfo->R.addDependencies(KV.first, PerAliasDepsMap);
     496             :         }
     497           8 :     };
     498             : 
     499           8 :     auto OnResolve = [QueryInfo](Expected<SymbolMap> Result) {
     500             :       if (Result) {
     501             :         SymbolMap ResolutionMap;
     502             :         for (auto &KV : QueryInfo->Aliases) {
     503             :           assert(Result->count(KV.second.Aliasee) &&
     504             :                  "Result map missing entry?");
     505             :           ResolutionMap[KV.first] = JITEvaluatedSymbol(
     506             :               (*Result)[KV.second.Aliasee].getAddress(), KV.second.AliasFlags);
     507             :         }
     508             :         QueryInfo->R.resolve(ResolutionMap);
     509             :         QueryInfo->R.emit();
     510             :       } else {
     511             :         auto &ES = QueryInfo->R.getTargetJITDylib().getExecutionSession();
     512             :         ES.reportError(Result.takeError());
     513             :         QueryInfo->R.failMaterialization();
     514             :       }
     515             :     };
     516             : 
     517             :     auto OnReady = [&ES](Error Err) { ES.reportError(std::move(Err)); };
     518             : 
     519          32 :     ES.lookup({&SrcJD}, QuerySymbols, std::move(OnResolve), std::move(OnReady),
     520             :               std::move(RegisterDependencies));
     521             :   }
     522           7 : }
     523             : 
     524           1 : void ReExportsMaterializationUnit::discard(const JITDylib &JD,
     525             :                                            SymbolStringPtr Name) {
     526             :   assert(Aliases.count(Name) &&
     527             :          "Symbol not covered by this MaterializationUnit");
     528             :   Aliases.erase(Name);
     529           1 : }
     530             : 
     531             : SymbolFlagsMap
     532          17 : ReExportsMaterializationUnit::extractFlags(const SymbolAliasMap &Aliases) {
     533             :   SymbolFlagsMap SymbolFlags;
     534          29 :   for (auto &KV : Aliases)
     535          12 :     SymbolFlags[KV.first] = KV.second.AliasFlags;
     536             : 
     537          17 :   return SymbolFlags;
     538             : }
     539             : 
     540             : Expected<SymbolAliasMap>
     541           0 : buildSimpleReexportsAliasMap(JITDylib &SourceJD, const SymbolNameSet &Symbols) {
     542           0 :   auto Flags = SourceJD.lookupFlags(Symbols);
     543             : 
     544           0 :   if (Flags.size() != Symbols.size()) {
     545             :     SymbolNameSet Unresolved = Symbols;
     546           0 :     for (auto &KV : Flags)
     547           0 :       Unresolved.erase(KV.first);
     548             :     return make_error<SymbolsNotFound>(std::move(Unresolved));
     549             :   }
     550             : 
     551             :   SymbolAliasMap Result;
     552           0 :   for (auto &Name : Symbols) {
     553             :     assert(Flags.count(Name) && "Missing entry in flags map");
     554           0 :     Result[Name] = SymbolAliasMapEntry(Name, Flags[Name]);
     555             :   }
     556             : 
     557             :   return Result;
     558             : }
     559             : 
     560           1 : ReexportsFallbackDefinitionGenerator::ReexportsFallbackDefinitionGenerator(
     561           1 :     JITDylib &BackingJD, SymbolPredicate Allow)
     562           2 :     : BackingJD(BackingJD), Allow(std::move(Allow)) {}
     563             : 
     564           1 : SymbolNameSet ReexportsFallbackDefinitionGenerator::
     565             : operator()(JITDylib &JD, const SymbolNameSet &Names) {
     566             :   orc::SymbolNameSet Added;
     567             :   orc::SymbolAliasMap AliasMap;
     568             : 
     569           1 :   auto Flags = BackingJD.lookupFlags(Names);
     570             : 
     571           3 :   for (auto &KV : Flags) {
     572           2 :     if (!Allow(KV.first))
     573             :       continue;
     574           1 :     AliasMap[KV.first] = SymbolAliasMapEntry(KV.first, KV.second);
     575             :     Added.insert(KV.first);
     576             :   }
     577             : 
     578           1 :   if (!Added.empty())
     579           2 :     cantFail(JD.define(reexports(BackingJD, AliasMap)));
     580             : 
     581           1 :   return Added;
     582             : }
     583             : 
     584           2 : Error JITDylib::defineMaterializing(const SymbolFlagsMap &SymbolFlags) {
     585           2 :   return ES.runSessionLocked([&]() -> Error {
     586             :     std::vector<SymbolMap::iterator> AddedSyms;
     587             : 
     588             :     for (auto &KV : SymbolFlags) {
     589             :       SymbolMap::iterator EntryItr;
     590             :       bool Added;
     591             : 
     592             :       auto NewFlags = KV.second;
     593             :       NewFlags |= JITSymbolFlags::Materializing;
     594             : 
     595             :       std::tie(EntryItr, Added) = Symbols.insert(
     596             :           std::make_pair(KV.first, JITEvaluatedSymbol(0, NewFlags)));
     597             : 
     598             :       if (Added)
     599             :         AddedSyms.push_back(EntryItr);
     600             :       else {
     601             :         // Remove any symbols already added.
     602             :         for (auto &SI : AddedSyms)
     603             :           Symbols.erase(SI);
     604             : 
     605             :         // FIXME: Return all duplicates.
     606             :         return make_error<DuplicateDefinition>(*KV.first);
     607             :       }
     608             :     }
     609             : 
     610             :     return Error::success();
     611           2 :   });
     612             : }
     613             : 
     614          21 : void JITDylib::replace(std::unique_ptr<MaterializationUnit> MU) {
     615             :   assert(MU != nullptr && "Can not replace with a null MaterializationUnit");
     616             : 
     617             :   auto MustRunMU =
     618          21 :       ES.runSessionLocked([&, this]() -> std::unique_ptr<MaterializationUnit> {
     619             : 
     620             : #ifndef NDEBUG
     621             :         for (auto &KV : MU->getSymbols()) {
     622             :           auto SymI = Symbols.find(KV.first);
     623             :           assert(SymI != Symbols.end() && "Replacing unknown symbol");
     624             :           assert(!SymI->second.getFlags().isLazy() &&
     625             :                  SymI->second.getFlags().isMaterializing() &&
     626             :                  "Can not replace symbol that is not materializing");
     627             :           assert(UnmaterializedInfos.count(KV.first) == 0 &&
     628             :                  "Symbol being replaced should have no UnmaterializedInfo");
     629             :         }
     630             : #endif // NDEBUG
     631             : 
     632             :         // If any symbol has pending queries against it then we need to
     633             :         // materialize MU immediately.
     634             :         for (auto &KV : MU->getSymbols()) {
     635             :           auto MII = MaterializingInfos.find(KV.first);
     636             :           if (MII != MaterializingInfos.end()) {
     637             :             if (!MII->second.PendingQueries.empty())
     638             :               return std::move(MU);
     639             :           }
     640             :         }
     641             : 
     642             :         // Otherwise, make MU responsible for all the symbols.
     643             :         auto UMI = std::make_shared<UnmaterializedInfo>(std::move(MU));
     644             :         for (auto &KV : UMI->MU->getSymbols()) {
     645             :           assert(!KV.second.isLazy() &&
     646             :                  "Lazy flag should be managed internally.");
     647             :           assert(!KV.second.isMaterializing() &&
     648             :                  "Materializing flags should be managed internally.");
     649             : 
     650             :           auto SymI = Symbols.find(KV.first);
     651             :           JITSymbolFlags ReplaceFlags = KV.second;
     652             :           ReplaceFlags |= JITSymbolFlags::Lazy;
     653             :           SymI->second = JITEvaluatedSymbol(SymI->second.getAddress(),
     654             :                                             std::move(ReplaceFlags));
     655             :           UnmaterializedInfos[KV.first] = UMI;
     656             :         }
     657             : 
     658             :         return nullptr;
     659          21 :       });
     660             : 
     661          21 :   if (MustRunMU)
     662           0 :     ES.dispatchMaterialization(*this, std::move(MustRunMU));
     663          21 : }
     664             : 
     665          25 : SymbolNameSet JITDylib::getRequestedSymbols(const SymbolFlagsMap &SymbolFlags) {
     666          25 :   return ES.runSessionLocked([&]() {
     667             :     SymbolNameSet RequestedSymbols;
     668             : 
     669             :     for (auto &KV : SymbolFlags) {
     670             :       assert(Symbols.count(KV.first) && "JITDylib does not cover this symbol?");
     671             :       assert(Symbols[KV.first].getFlags().isMaterializing() &&
     672             :              "getRequestedSymbols can only be called for materializing "
     673             :              "symbols");
     674             :       auto I = MaterializingInfos.find(KV.first);
     675             :       if (I == MaterializingInfos.end())
     676             :         continue;
     677             : 
     678             :       if (!I->second.PendingQueries.empty())
     679             :         RequestedSymbols.insert(KV.first);
     680             :     }
     681             : 
     682             :     return RequestedSymbols;
     683          25 :   });
     684             : }
     685             : 
     686          25 : void JITDylib::addDependencies(const SymbolStringPtr &Name,
     687             :                                const SymbolDependenceMap &Dependencies) {
     688             :   assert(Symbols.count(Name) && "Name not in symbol table");
     689             :   assert((Symbols[Name].getFlags().isLazy() ||
     690             :           Symbols[Name].getFlags().isMaterializing()) &&
     691             :          "Symbol is not lazy or materializing");
     692             : 
     693          25 :   auto &MI = MaterializingInfos[Name];
     694             :   assert(!MI.IsEmitted && "Can not add dependencies to an emitted symbol");
     695             : 
     696          50 :   for (auto &KV : Dependencies) {
     697             :     assert(KV.first && "Null JITDylib in dependency?");
     698          25 :     auto &OtherJITDylib = *KV.first;
     699          25 :     auto &DepsOnOtherJITDylib = MI.UnemittedDependencies[&OtherJITDylib];
     700             : 
     701          53 :     for (auto &OtherSymbol : KV.second) {
     702             : #ifndef NDEBUG
     703             :       // Assert that this symbol exists and has not been emitted already.
     704             :       auto SymI = OtherJITDylib.Symbols.find(OtherSymbol);
     705             :       assert(SymI != OtherJITDylib.Symbols.end() &&
     706             :              (SymI->second.getFlags().isLazy() ||
     707             :               SymI->second.getFlags().isMaterializing()) &&
     708             :              "Dependency on emitted symbol");
     709             : #endif
     710             : 
     711          28 :       auto &OtherMI = OtherJITDylib.MaterializingInfos[OtherSymbol];
     712             : 
     713          28 :       if (OtherMI.IsEmitted)
     714           0 :         transferEmittedNodeDependencies(MI, Name, OtherMI);
     715          28 :       else if (&OtherJITDylib != this || OtherSymbol != Name) {
     716          48 :         OtherMI.Dependants[this].insert(Name);
     717             :         DepsOnOtherJITDylib.insert(OtherSymbol);
     718             :       }
     719             :     }
     720             : 
     721          25 :     if (DepsOnOtherJITDylib.empty())
     722           1 :       MI.UnemittedDependencies.erase(&OtherJITDylib);
     723             :   }
     724          25 : }
     725             : 
     726         100 : void JITDylib::resolve(const SymbolMap &Resolved) {
     727         100 :   auto FullyResolvedQueries = ES.runSessionLocked([&, this]() {
     728             :     AsynchronousSymbolQuerySet FullyResolvedQueries;
     729             :     for (const auto &KV : Resolved) {
     730             :       auto &Name = KV.first;
     731             :       auto Sym = KV.second;
     732             : 
     733             :       assert(!Sym.getFlags().isLazy() && !Sym.getFlags().isMaterializing() &&
     734             :              "Materializing flags should be managed internally");
     735             : 
     736             :       auto I = Symbols.find(Name);
     737             : 
     738             :       assert(I != Symbols.end() && "Symbol not found");
     739             :       assert(!I->second.getFlags().isLazy() &&
     740             :              I->second.getFlags().isMaterializing() &&
     741             :              "Symbol should be materializing");
     742             :       assert(I->second.getAddress() == 0 && "Symbol has already been resolved");
     743             : 
     744             :       assert((Sym.getFlags() & ~JITSymbolFlags::Weak) ==
     745             :                  (JITSymbolFlags::stripTransientFlags(I->second.getFlags()) &
     746             :                   ~JITSymbolFlags::Weak) &&
     747             :              "Resolved flags should match the declared flags");
     748             : 
     749             :       // Once resolved, symbols can never be weak.
     750             :       JITSymbolFlags ResolvedFlags = Sym.getFlags();
     751             :       ResolvedFlags &= ~JITSymbolFlags::Weak;
     752             :       ResolvedFlags |= JITSymbolFlags::Materializing;
     753             :       I->second = JITEvaluatedSymbol(Sym.getAddress(), ResolvedFlags);
     754             : 
     755             :       auto &MI = MaterializingInfos[Name];
     756             :       for (auto &Q : MI.PendingQueries) {
     757             :         Q->resolve(Name, Sym);
     758             :         if (Q->isFullyResolved())
     759             :           FullyResolvedQueries.insert(Q);
     760             :       }
     761             :     }
     762             : 
     763             :     return FullyResolvedQueries;
     764         100 :   });
     765             : 
     766         185 :   for (auto &Q : FullyResolvedQueries) {
     767             :     assert(Q->isFullyResolved() && "Q not fully resolved");
     768          85 :     Q->handleFullyResolved();
     769             :   }
     770         100 : }
     771             : 
     772          90 : void JITDylib::emit(const SymbolFlagsMap &Emitted) {
     773          90 :   auto FullyReadyQueries = ES.runSessionLocked([&, this]() {
     774             :     AsynchronousSymbolQuerySet ReadyQueries;
     775             : 
     776             :     for (const auto &KV : Emitted) {
     777             :       const auto &Name = KV.first;
     778             : 
     779             :       auto MII = MaterializingInfos.find(Name);
     780             :       assert(MII != MaterializingInfos.end() &&
     781             :              "Missing MaterializingInfo entry");
     782             : 
     783             :       auto &MI = MII->second;
     784             : 
     785             :       // For each dependant, transfer this node's emitted dependencies to
     786             :       // it. If the dependant node is ready (i.e. has no unemitted
     787             :       // dependencies) then notify any pending queries.
     788             :       for (auto &KV : MI.Dependants) {
     789             :         auto &DependantJD = *KV.first;
     790             :         for (auto &DependantName : KV.second) {
     791             :           auto DependantMII =
     792             :               DependantJD.MaterializingInfos.find(DependantName);
     793             :           assert(DependantMII != DependantJD.MaterializingInfos.end() &&
     794             :                  "Dependant should have MaterializingInfo");
     795             : 
     796             :           auto &DependantMI = DependantMII->second;
     797             : 
     798             :           // Remove the dependant's dependency on this node.
     799             :           assert(DependantMI.UnemittedDependencies[this].count(Name) &&
     800             :                  "Dependant does not count this symbol as a dependency?");
     801             :           DependantMI.UnemittedDependencies[this].erase(Name);
     802             :           if (DependantMI.UnemittedDependencies[this].empty())
     803             :             DependantMI.UnemittedDependencies.erase(this);
     804             : 
     805             :           // Transfer unemitted dependencies from this node to the dependant.
     806             :           DependantJD.transferEmittedNodeDependencies(DependantMI,
     807             :                                                       DependantName, MI);
     808             : 
     809             :           // If the dependant is emitted and this node was the last of its
     810             :           // unemitted dependencies then the dependant node is now ready, so
     811             :           // notify any pending queries on the dependant node.
     812             :           if (DependantMI.IsEmitted &&
     813             :               DependantMI.UnemittedDependencies.empty()) {
     814             :             assert(DependantMI.Dependants.empty() &&
     815             :                    "Dependants should be empty by now");
     816             :             for (auto &Q : DependantMI.PendingQueries) {
     817             :               Q->notifySymbolReady();
     818             :               if (Q->isFullyReady())
     819             :                 ReadyQueries.insert(Q);
     820             :               Q->removeQueryDependence(DependantJD, DependantName);
     821             :             }
     822             : 
     823             :             // Since this dependant is now ready, we erase its MaterializingInfo
     824             :             // and update its materializing state.
     825             :             assert(DependantJD.Symbols.count(DependantName) &&
     826             :                    "Dependant has no entry in the Symbols table");
     827             :             auto &DependantSym = DependantJD.Symbols[DependantName];
     828             :             DependantSym.setFlags(DependantSym.getFlags() &
     829             :                                   ~JITSymbolFlags::Materializing);
     830             :             DependantJD.MaterializingInfos.erase(DependantMII);
     831             :           }
     832             :         }
     833             :       }
     834             :       MI.Dependants.clear();
     835             :       MI.IsEmitted = true;
     836             : 
     837             :       if (MI.UnemittedDependencies.empty()) {
     838             :         for (auto &Q : MI.PendingQueries) {
     839             :           Q->notifySymbolReady();
     840             :           if (Q->isFullyReady())
     841             :             ReadyQueries.insert(Q);
     842             :           Q->removeQueryDependence(*this, Name);
     843             :         }
     844             :         assert(Symbols.count(Name) &&
     845             :                "Symbol has no entry in the Symbols table");
     846             :         auto &Sym = Symbols[Name];
     847             :         Sym.setFlags(Sym.getFlags() & ~JITSymbolFlags::Materializing);
     848             :         MaterializingInfos.erase(MII);
     849             :       }
     850             :     }
     851             : 
     852             :     return ReadyQueries;
     853          90 :   });
     854             : 
     855         176 :   for (auto &Q : FullyReadyQueries) {
     856             :     assert(Q->isFullyReady() && "Q is not fully ready");
     857          86 :     Q->handleFullyReady();
     858             :   }
     859          90 : }
     860             : 
     861           1 : void JITDylib::notifyFailed(const SymbolNameSet &FailedSymbols) {
     862             : 
     863             :   // FIXME: This should fail any transitively dependant symbols too.
     864             : 
     865           1 :   auto FailedQueriesToNotify = ES.runSessionLocked([&, this]() {
     866             :     AsynchronousSymbolQuerySet FailedQueries;
     867             : 
     868             :     for (auto &Name : FailedSymbols) {
     869             :       auto I = Symbols.find(Name);
     870             :       assert(I != Symbols.end() && "Symbol not present in this JITDylib");
     871             :       Symbols.erase(I);
     872             : 
     873             :       auto MII = MaterializingInfos.find(Name);
     874             : 
     875             :       // If we have not created a MaterializingInfo for this symbol yet then
     876             :       // there is nobody to notify.
     877             :       if (MII == MaterializingInfos.end())
     878             :         continue;
     879             : 
     880             :       // Copy all the queries to the FailedQueries list, then abandon them.
     881             :       // This has to be a copy, and the copy has to come before the abandon
     882             :       // operation: Each Q.detach() call will reach back into this
     883             :       // PendingQueries list to remove Q.
     884             :       for (auto &Q : MII->second.PendingQueries)
     885             :         FailedQueries.insert(Q);
     886             : 
     887             :       for (auto &Q : FailedQueries)
     888             :         Q->detach();
     889             : 
     890             :       assert(MII->second.PendingQueries.empty() &&
     891             :              "Queries remain after symbol was failed");
     892             : 
     893             :       MaterializingInfos.erase(MII);
     894             :     }
     895             : 
     896             :     return FailedQueries;
     897           1 :   });
     898             : 
     899           2 :   for (auto &Q : FailedQueriesToNotify)
     900           2 :     Q->handleFailed(make_error<FailedToMaterialize>(FailedSymbols));
     901           1 : }
     902             : 
     903           0 : void JITDylib::setSearchOrder(JITDylibList NewSearchOrder,
     904             :                               bool SearchThisJITDylibFirst) {
     905           0 :   if (SearchThisJITDylibFirst && NewSearchOrder.front() != this)
     906           0 :     NewSearchOrder.insert(NewSearchOrder.begin(), this);
     907             : 
     908           0 :   ES.runSessionLocked([&]() { SearchOrder = std::move(NewSearchOrder); });
     909           0 : }
     910             : 
     911          66 : void JITDylib::addToSearchOrder(JITDylib &JD) {
     912         132 :   ES.runSessionLocked([&]() { SearchOrder.push_back(&JD); });
     913          66 : }
     914             : 
     915           0 : void JITDylib::replaceInSearchOrder(JITDylib &OldJD, JITDylib &NewJD) {
     916           0 :   ES.runSessionLocked([&]() {
     917             :     auto I = std::find(SearchOrder.begin(), SearchOrder.end(), &OldJD);
     918             : 
     919             :     if (I != SearchOrder.end())
     920             :       *I = &NewJD;
     921             :   });
     922           0 : }
     923             : 
     924           0 : void JITDylib::removeFromSearchOrder(JITDylib &JD) {
     925           0 :   ES.runSessionLocked([&]() {
     926             :     auto I = std::find(SearchOrder.begin(), SearchOrder.end(), &JD);
     927             :     if (I != SearchOrder.end())
     928             :       SearchOrder.erase(I);
     929             :   });
     930           0 : }
     931             : 
     932           4 : SymbolFlagsMap JITDylib::lookupFlags(const SymbolNameSet &Names) {
     933           4 :   return ES.runSessionLocked([&, this]() {
     934             :     SymbolFlagsMap Result;
     935             :     auto Unresolved = lookupFlagsImpl(Result, Names);
     936             :     if (FallbackDefinitionGenerator && !Unresolved.empty()) {
     937             :       auto FallbackDefs = FallbackDefinitionGenerator(*this, Unresolved);
     938             :       if (!FallbackDefs.empty()) {
     939             :         auto Unresolved2 = lookupFlagsImpl(Result, FallbackDefs);
     940             :         (void)Unresolved2;
     941             :         assert(Unresolved2.empty() &&
     942             :                "All fallback defs should have been found by lookupFlagsImpl");
     943             :       }
     944             :     };
     945             :     return Result;
     946           4 :   });
     947             : }
     948             : 
     949           5 : SymbolNameSet JITDylib::lookupFlagsImpl(SymbolFlagsMap &Flags,
     950             :                                         const SymbolNameSet &Names) {
     951             :   SymbolNameSet Unresolved;
     952             : 
     953          17 :   for (auto &Name : Names) {
     954             :     auto I = Symbols.find(Name);
     955             : 
     956          12 :     if (I == Symbols.end()) {
     957             :       Unresolved.insert(Name);
     958             :       continue;
     959             :     }
     960             : 
     961             :     assert(!Flags.count(Name) && "Symbol already present in Flags map");
     962           6 :     Flags[Name] = JITSymbolFlags::stripTransientFlags(I->second.getFlags());
     963             :   }
     964             : 
     965           5 :   return Unresolved;
     966             : }
     967             : 
     968         113 : void JITDylib::lodgeQuery(std::shared_ptr<AsynchronousSymbolQuery> &Q,
     969             :                           SymbolNameSet &Unresolved,
     970             :                           MaterializationUnitList &MUs) {
     971             :   assert(Q && "Query can not be null");
     972             : 
     973         113 :   lodgeQueryImpl(Q, Unresolved, MUs);
     974         113 :   if (FallbackDefinitionGenerator && !Unresolved.empty()) {
     975             :     auto FallbackDefs = FallbackDefinitionGenerator(*this, Unresolved);
     976           3 :     if (!FallbackDefs.empty()) {
     977           6 :       for (auto &D : FallbackDefs)
     978             :         Unresolved.erase(D);
     979           3 :       lodgeQueryImpl(Q, FallbackDefs, MUs);
     980             :       assert(FallbackDefs.empty() &&
     981             :              "All fallback defs should have been found by lookupImpl");
     982             :     }
     983             :   }
     984         113 : }
     985             : 
     986         116 : void JITDylib::lodgeQueryImpl(
     987             :     std::shared_ptr<AsynchronousSymbolQuery> &Q, SymbolNameSet &Unresolved,
     988             :     std::vector<std::unique_ptr<MaterializationUnit>> &MUs) {
     989         229 :   for (auto I = Unresolved.begin(), E = Unresolved.end(); I != E;) {
     990             :     auto TmpI = I++;
     991             :     auto Name = *TmpI;
     992             : 
     993             :     // Search for the name in Symbols. Skip it if not found.
     994             :     auto SymI = Symbols.find(Name);
     995         113 :     if (SymI == Symbols.end())
     996             :       continue;
     997             : 
     998             :     // If we found Name in JD, remove it frome the Unresolved set and add it
     999             :     // to the added set.
    1000             :     Unresolved.erase(TmpI);
    1001             : 
    1002             :     // If the symbol has an address then resolve it.
    1003         110 :     if (SymI->second.getAddress() != 0)
    1004          18 :       Q->resolve(Name, SymI->second);
    1005             : 
    1006             :     // If the symbol is lazy, get the MaterialiaztionUnit for it.
    1007         110 :     if (SymI->second.getFlags().isLazy()) {
    1008             :       assert(SymI->second.getAddress() == 0 &&
    1009             :              "Lazy symbol should not have a resolved address");
    1010             :       assert(!SymI->second.getFlags().isMaterializing() &&
    1011             :              "Materializing and lazy should not both be set");
    1012             :       auto UMII = UnmaterializedInfos.find(Name);
    1013             :       assert(UMII != UnmaterializedInfos.end() &&
    1014             :              "Lazy symbol should have UnmaterializedInfo");
    1015             :       auto MU = std::move(UMII->second->MU);
    1016             :       assert(MU != nullptr && "Materializer should not be null");
    1017             : 
    1018             :       // Move all symbols associated with this MaterializationUnit into
    1019             :       // materializing state.
    1020         212 :       for (auto &KV : MU->getSymbols()) {
    1021             :         auto SymK = Symbols.find(KV.first);
    1022             :         auto Flags = SymK->second.getFlags();
    1023             :         Flags &= ~JITSymbolFlags::Lazy;
    1024             :         Flags |= JITSymbolFlags::Materializing;
    1025             :         SymK->second.setFlags(Flags);
    1026         125 :         UnmaterializedInfos.erase(KV.first);
    1027             :       }
    1028             : 
    1029             :       // Add MU to the list of MaterializationUnits to be materialized.
    1030             :       MUs.push_back(std::move(MU));
    1031          23 :     } else if (!SymI->second.getFlags().isMaterializing()) {
    1032             :       // The symbol is neither lazy nor materializing, so it must be
    1033             :       // ready. Notify the query and continue.
    1034          17 :       Q->notifySymbolReady();
    1035          17 :       continue;
    1036             :     }
    1037             : 
    1038             :     // Add the query to the PendingQueries list.
    1039             :     assert(SymI->second.getFlags().isMaterializing() &&
    1040             :            "By this line the symbol should be materializing");
    1041          93 :     auto &MI = MaterializingInfos[Name];
    1042          93 :     MI.PendingQueries.push_back(Q);
    1043         186 :     Q->addQueryDependence(*this, Name);
    1044             :   }
    1045         116 : }
    1046             : 
    1047           3 : SymbolNameSet JITDylib::legacyLookup(std::shared_ptr<AsynchronousSymbolQuery> Q,
    1048             :                                      SymbolNameSet Names) {
    1049             :   assert(Q && "Query can not be null");
    1050             : 
    1051           3 :   ES.runOutstandingMUs();
    1052             : 
    1053           3 :   LookupImplActionFlags ActionFlags = None;
    1054           3 :   std::vector<std::unique_ptr<MaterializationUnit>> MUs;
    1055             : 
    1056             :   SymbolNameSet Unresolved = std::move(Names);
    1057           3 :   ES.runSessionLocked([&, this]() {
    1058             :     ActionFlags = lookupImpl(Q, MUs, Unresolved);
    1059             :     if (FallbackDefinitionGenerator && !Unresolved.empty()) {
    1060             :       assert(ActionFlags == None &&
    1061             :              "ActionFlags set but unresolved symbols remain?");
    1062             :       auto FallbackDefs = FallbackDefinitionGenerator(*this, Unresolved);
    1063             :       if (!FallbackDefs.empty()) {
    1064             :         for (auto &D : FallbackDefs)
    1065             :           Unresolved.erase(D);
    1066             :         ActionFlags = lookupImpl(Q, MUs, FallbackDefs);
    1067             :         assert(FallbackDefs.empty() &&
    1068             :                "All fallback defs should have been found by lookupImpl");
    1069             :       }
    1070             :     }
    1071             :   });
    1072             : 
    1073             :   assert((MUs.empty() || ActionFlags == None) &&
    1074             :          "If action flags are set, there should be no work to do (so no MUs)");
    1075             : 
    1076           6 :   if (ActionFlags & NotifyFullyResolved)
    1077           0 :     Q->handleFullyResolved();
    1078             : 
    1079           6 :   if (ActionFlags & NotifyFullyReady)
    1080           0 :     Q->handleFullyReady();
    1081             : 
    1082             :   // FIXME: Swap back to the old code below once RuntimeDyld works with
    1083             :   //        callbacks from asynchronous queries.
    1084             :   // Add MUs to the OutstandingMUs list.
    1085             :   {
    1086           3 :     std::lock_guard<std::recursive_mutex> Lock(ES.OutstandingMUsMutex);
    1087           5 :     for (auto &MU : MUs)
    1088           4 :       ES.OutstandingMUs.push_back(make_pair(this, std::move(MU)));
    1089             :   }
    1090           3 :   ES.runOutstandingMUs();
    1091             : 
    1092             :   // Dispatch any required MaterializationUnits for materialization.
    1093             :   // for (auto &MU : MUs)
    1094             :   //  ES.dispatchMaterialization(*this, std::move(MU));
    1095             : 
    1096           3 :   return Unresolved;
    1097             : }
    1098             : 
    1099             : JITDylib::LookupImplActionFlags
    1100           3 : JITDylib::lookupImpl(std::shared_ptr<AsynchronousSymbolQuery> &Q,
    1101             :                      std::vector<std::unique_ptr<MaterializationUnit>> &MUs,
    1102             :                      SymbolNameSet &Unresolved) {
    1103             :   LookupImplActionFlags ActionFlags = None;
    1104             : 
    1105           7 :   for (auto I = Unresolved.begin(), E = Unresolved.end(); I != E;) {
    1106             :     auto TmpI = I++;
    1107             :     auto Name = *TmpI;
    1108             : 
    1109             :     // Search for the name in Symbols. Skip it if not found.
    1110             :     auto SymI = Symbols.find(Name);
    1111           4 :     if (SymI == Symbols.end())
    1112             :       continue;
    1113             : 
    1114             :     // If we found Name, remove it frome the Unresolved set and add it
    1115             :     // to the dependencies set.
    1116             :     Unresolved.erase(TmpI);
    1117             : 
    1118             :     // If the symbol has an address then resolve it.
    1119           3 :     if (SymI->second.getAddress() != 0) {
    1120           0 :       Q->resolve(Name, SymI->second);
    1121           0 :       if (Q->isFullyResolved())
    1122             :         ActionFlags |= NotifyFullyResolved;
    1123             :     }
    1124             : 
    1125             :     // If the symbol is lazy, get the MaterialiaztionUnit for it.
    1126           3 :     if (SymI->second.getFlags().isLazy()) {
    1127             :       assert(SymI->second.getAddress() == 0 &&
    1128             :              "Lazy symbol should not have a resolved address");
    1129             :       assert(!SymI->second.getFlags().isMaterializing() &&
    1130             :              "Materializing and lazy should not both be set");
    1131             :       auto UMII = UnmaterializedInfos.find(Name);
    1132             :       assert(UMII != UnmaterializedInfos.end() &&
    1133             :              "Lazy symbol should have UnmaterializedInfo");
    1134             :       auto MU = std::move(UMII->second->MU);
    1135             :       assert(MU != nullptr && "Materializer should not be null");
    1136             : 
    1137             :       // Kick all symbols associated with this MaterializationUnit into
    1138             :       // materializing state.
    1139           5 :       for (auto &KV : MU->getSymbols()) {
    1140             :         auto SymK = Symbols.find(KV.first);
    1141             :         auto Flags = SymK->second.getFlags();
    1142             :         Flags &= ~JITSymbolFlags::Lazy;
    1143             :         Flags |= JITSymbolFlags::Materializing;
    1144             :         SymK->second.setFlags(Flags);
    1145           3 :         UnmaterializedInfos.erase(KV.first);
    1146             :       }
    1147             : 
    1148             :       // Add MU to the list of MaterializationUnits to be materialized.
    1149             :       MUs.push_back(std::move(MU));
    1150           1 :     } else if (!SymI->second.getFlags().isMaterializing()) {
    1151             :       // The symbol is neither lazy nor materializing, so it must be ready.
    1152             :       // Notify the query and continue.
    1153           0 :       Q->notifySymbolReady();
    1154           0 :       if (Q->isFullyReady())
    1155             :         ActionFlags |= NotifyFullyReady;
    1156           0 :       continue;
    1157             :     }
    1158             : 
    1159             :     // Add the query to the PendingQueries list.
    1160             :     assert(SymI->second.getFlags().isMaterializing() &&
    1161             :            "By this line the symbol should be materializing");
    1162           3 :     auto &MI = MaterializingInfos[Name];
    1163           3 :     MI.PendingQueries.push_back(Q);
    1164           6 :     Q->addQueryDependence(*this, Name);
    1165             :   }
    1166             : 
    1167           3 :   return ActionFlags;
    1168             : }
    1169             : 
    1170           0 : void JITDylib::dump(raw_ostream &OS) {
    1171           0 :   ES.runSessionLocked([&, this]() {
    1172             :     OS << "JITDylib \"" << JITDylibName
    1173             :        << "\" (ES: " << format("0x%016x", reinterpret_cast<uintptr_t>(&ES))
    1174             :        << "):\n"
    1175             :        << "Symbol table:\n";
    1176             : 
    1177             :     for (auto &KV : Symbols) {
    1178             :       OS << "    \"" << *KV.first << "\": ";
    1179             :       if (auto Addr = KV.second.getAddress())
    1180             :         OS << format("0x%016x", Addr);
    1181             :       else
    1182             :         OS << "<not resolved>";
    1183             :       if (KV.second.getFlags().isLazy() ||
    1184             :           KV.second.getFlags().isMaterializing()) {
    1185             :         OS << " (";
    1186             :         if (KV.second.getFlags().isLazy()) {
    1187             :           auto I = UnmaterializedInfos.find(KV.first);
    1188             :           assert(I != UnmaterializedInfos.end() &&
    1189             :                  "Lazy symbol should have UnmaterializedInfo");
    1190             :           OS << " Lazy (MU=" << I->second->MU.get() << ")";
    1191             :         }
    1192             :         if (KV.second.getFlags().isMaterializing())
    1193             :           OS << " Materializing";
    1194             :         OS << " )\n";
    1195             :       } else
    1196             :         OS << "\n";
    1197             :     }
    1198             : 
    1199             :     if (!MaterializingInfos.empty())
    1200             :       OS << "  MaterializingInfos entries:\n";
    1201             :     for (auto &KV : MaterializingInfos) {
    1202             :       OS << "    \"" << *KV.first << "\":\n"
    1203             :          << "      IsEmitted = " << (KV.second.IsEmitted ? "true" : "false")
    1204             :          << "\n"
    1205             :          << "      " << KV.second.PendingQueries.size()
    1206             :          << " pending queries: { ";
    1207             :       for (auto &Q : KV.second.PendingQueries)
    1208             :         OS << Q.get() << " ";
    1209             :       OS << "}\n      Dependants:\n";
    1210             :       for (auto &KV2 : KV.second.Dependants)
    1211             :         OS << "        " << KV2.first->getName() << ": " << KV2.second << "\n";
    1212             :       OS << "      Unemitted Dependencies:\n";
    1213             :       for (auto &KV2 : KV.second.UnemittedDependencies)
    1214             :         OS << "        " << KV2.first->getName() << ": " << KV2.second << "\n";
    1215             :     }
    1216             :   });
    1217           0 : }
    1218             : 
    1219         224 : JITDylib::JITDylib(ExecutionSession &ES, std::string Name)
    1220         448 :     : ES(ES), JITDylibName(std::move(Name)) {
    1221         224 :   SearchOrder.push_back(this);
    1222         224 : }
    1223             : 
    1224          99 : Error JITDylib::defineImpl(MaterializationUnit &MU) {
    1225             :   SymbolNameSet Duplicates;
    1226             :   SymbolNameSet MUDefsOverridden;
    1227             : 
    1228             :   struct ExistingDefOverriddenEntry {
    1229             :     SymbolMap::iterator ExistingDefItr;
    1230             :     JITSymbolFlags NewFlags;
    1231             :   };
    1232             :   std::vector<ExistingDefOverriddenEntry> ExistingDefsOverridden;
    1233             : 
    1234         247 :   for (auto &KV : MU.getSymbols()) {
    1235             :     assert(!KV.second.isLazy() && "Lazy flag should be managed internally.");
    1236             :     assert(!KV.second.isMaterializing() &&
    1237             :            "Materializing flags should be managed internally.");
    1238             : 
    1239             :     SymbolMap::iterator EntryItr;
    1240             :     bool Added;
    1241             : 
    1242         148 :     auto NewFlags = KV.second;
    1243             :     NewFlags |= JITSymbolFlags::Lazy;
    1244             : 
    1245         148 :     std::tie(EntryItr, Added) = Symbols.insert(
    1246         296 :         std::make_pair(KV.first, JITEvaluatedSymbol(0, NewFlags)));
    1247             : 
    1248         148 :     if (!Added) {
    1249             :       if (KV.second.isStrong()) {
    1250           5 :         if (EntryItr->second.getFlags().isStrong() ||
    1251             :             (EntryItr->second.getFlags() & JITSymbolFlags::Materializing))
    1252           1 :           Duplicates.insert(KV.first);
    1253             :         else
    1254           4 :           ExistingDefsOverridden.push_back({EntryItr, NewFlags});
    1255             :       } else
    1256           3 :         MUDefsOverridden.insert(KV.first);
    1257             :     }
    1258             :   }
    1259             : 
    1260          99 :   if (!Duplicates.empty()) {
    1261             :     // We need to remove the symbols we added.
    1262           2 :     for (auto &KV : MU.getSymbols()) {
    1263             :       if (Duplicates.count(KV.first))
    1264             :         continue;
    1265             : 
    1266             :       bool Found = false;
    1267           0 :       for (const auto &EDO : ExistingDefsOverridden)
    1268           0 :         if (EDO.ExistingDefItr->first == KV.first)
    1269             :           Found = true;
    1270             : 
    1271           0 :       if (!Found)
    1272           0 :         Symbols.erase(KV.first);
    1273             :     }
    1274             : 
    1275             :     // FIXME: Return all duplicates.
    1276           2 :     return make_error<DuplicateDefinition>(**Duplicates.begin());
    1277             :   }
    1278             : 
    1279             :   // Update flags on existing defs and call discard on their materializers.
    1280         102 :   for (auto &EDO : ExistingDefsOverridden) {
    1281             :     assert(EDO.ExistingDefItr->second.getFlags().isLazy() &&
    1282             :            !EDO.ExistingDefItr->second.getFlags().isMaterializing() &&
    1283             :            "Overridden existing def should be in the Lazy state");
    1284             : 
    1285           4 :     EDO.ExistingDefItr->second.setFlags(EDO.NewFlags);
    1286             : 
    1287             :     auto UMII = UnmaterializedInfos.find(EDO.ExistingDefItr->first);
    1288             :     assert(UMII != UnmaterializedInfos.end() &&
    1289             :            "Overridden existing def should have an UnmaterializedInfo");
    1290             : 
    1291           8 :     UMII->second->MU->doDiscard(*this, EDO.ExistingDefItr->first);
    1292             :   }
    1293             : 
    1294             :   // Discard overridden symbols povided by MU.
    1295         101 :   for (auto &Sym : MUDefsOverridden)
    1296           6 :     MU.doDiscard(*this, Sym);
    1297             : 
    1298             :   return Error::success();
    1299             : }
    1300             : 
    1301           1 : void JITDylib::detachQueryHelper(AsynchronousSymbolQuery &Q,
    1302             :                                  const SymbolNameSet &QuerySymbols) {
    1303           3 :   for (auto &QuerySymbol : QuerySymbols) {
    1304             :     assert(MaterializingInfos.count(QuerySymbol) &&
    1305             :            "QuerySymbol does not have MaterializingInfo");
    1306           2 :     auto &MI = MaterializingInfos[QuerySymbol];
    1307             : 
    1308             :     auto IdenticalQuery =
    1309             :         [&](const std::shared_ptr<AsynchronousSymbolQuery> &R) {
    1310           0 :           return R.get() == &Q;
    1311             :         };
    1312             : 
    1313             :     auto I = std::find_if(MI.PendingQueries.begin(), MI.PendingQueries.end(),
    1314             :                           IdenticalQuery);
    1315             :     assert(I != MI.PendingQueries.end() &&
    1316             :            "Query Q should be in the PendingQueries list for QuerySymbol");
    1317           2 :     MI.PendingQueries.erase(I);
    1318             :   }
    1319           1 : }
    1320             : 
    1321          27 : void JITDylib::transferEmittedNodeDependencies(
    1322             :     MaterializingInfo &DependantMI, const SymbolStringPtr &DependantName,
    1323             :     MaterializingInfo &EmittedMI) {
    1324          31 :   for (auto &KV : EmittedMI.UnemittedDependencies) {
    1325           4 :     auto &DependencyJD = *KV.first;
    1326             :     SymbolNameSet *UnemittedDependenciesOnDependencyJD = nullptr;
    1327             : 
    1328           8 :     for (auto &DependencyName : KV.second) {
    1329           4 :       auto &DependencyMI = DependencyJD.MaterializingInfos[DependencyName];
    1330             : 
    1331             :       // Do not add self dependencies.
    1332           4 :       if (&DependencyMI == &DependantMI)
    1333             :         continue;
    1334             : 
    1335             :       // If we haven't looked up the dependencies for DependencyJD yet, do it
    1336             :       // now and cache the result.
    1337           3 :       if (!UnemittedDependenciesOnDependencyJD)
    1338             :         UnemittedDependenciesOnDependencyJD =
    1339           3 :             &DependantMI.UnemittedDependencies[&DependencyJD];
    1340             : 
    1341           6 :       DependencyMI.Dependants[this].insert(DependantName);
    1342             :       UnemittedDependenciesOnDependencyJD->insert(DependencyName);
    1343             :     }
    1344             :   }
    1345          27 : }
    1346             : 
    1347         158 : ExecutionSession::ExecutionSession(std::shared_ptr<SymbolStringPool> SSP)
    1348         474 :     : SSP(SSP ? std::move(SSP) : std::make_shared<SymbolStringPool>()) {
    1349             :   // Construct the main dylib.
    1350         316 :   JDs.push_back(std::unique_ptr<JITDylib>(new JITDylib(*this, "<main>")));
    1351         158 : }
    1352             : 
    1353           2 : JITDylib &ExecutionSession::getMainJITDylib() {
    1354           2 :   return runSessionLocked([this]() -> JITDylib & { return *JDs.front(); });
    1355             : }
    1356             : 
    1357          66 : JITDylib &ExecutionSession::createJITDylib(std::string Name,
    1358             :                                            bool AddToMainDylibSearchOrder) {
    1359             :   return runSessionLocked([&, this]() -> JITDylib & {
    1360             :     JDs.push_back(
    1361             :         std::unique_ptr<JITDylib>(new JITDylib(*this, std::move(Name))));
    1362             :     if (AddToMainDylibSearchOrder)
    1363             :       JDs.front()->addToSearchOrder(*JDs.back());
    1364             :     return *JDs.back();
    1365          66 :   });
    1366             : }
    1367             : 
    1368           1 : void ExecutionSession::legacyFailQuery(AsynchronousSymbolQuery &Q, Error Err) {
    1369             :   assert(!!Err && "Error should be in failure state");
    1370             : 
    1371             :   bool SendErrorToQuery;
    1372           1 :   runSessionLocked([&]() {
    1373             :     Q.detach();
    1374             :     SendErrorToQuery = Q.canStillFail();
    1375             :   });
    1376             : 
    1377           1 :   if (SendErrorToQuery)
    1378           2 :     Q.handleFailed(std::move(Err));
    1379             :   else
    1380           0 :     reportError(std::move(Err));
    1381           1 : }
    1382             : 
    1383          40 : Expected<SymbolMap> ExecutionSession::legacyLookup(
    1384             :     LegacyAsyncLookupFunction AsyncLookup, SymbolNameSet Names,
    1385             :     bool WaitUntilReady, RegisterDependenciesFunction RegisterDependencies) {
    1386             : #if LLVM_ENABLE_THREADS
    1387             :   // In the threaded case we use promises to return the results.
    1388          80 :   std::promise<SymbolMap> PromisedResult;
    1389          40 :   std::mutex ErrMutex;
    1390             :   Error ResolutionError = Error::success();
    1391          80 :   std::promise<void> PromisedReady;
    1392             :   Error ReadyError = Error::success();
    1393             :   auto OnResolve = [&](Expected<SymbolMap> R) {
    1394             :     if (R)
    1395             :       PromisedResult.set_value(std::move(*R));
    1396             :     else {
    1397             :       {
    1398             :         ErrorAsOutParameter _(&ResolutionError);
    1399             :         std::lock_guard<std::mutex> Lock(ErrMutex);
    1400             :         ResolutionError = R.takeError();
    1401             :       }
    1402             :       PromisedResult.set_value(SymbolMap());
    1403             :     }
    1404          40 :   };
    1405             : 
    1406             :   std::function<void(Error)> OnReady;
    1407          40 :   if (WaitUntilReady) {
    1408             :     OnReady = [&](Error Err) {
    1409             :       if (Err) {
    1410             :         ErrorAsOutParameter _(&ReadyError);
    1411             :         std::lock_guard<std::mutex> Lock(ErrMutex);
    1412             :         ReadyError = std::move(Err);
    1413             :       }
    1414             :       PromisedReady.set_value();
    1415           0 :     };
    1416             :   } else {
    1417             :     OnReady = [&](Error Err) {
    1418             :       if (Err)
    1419             :         reportError(std::move(Err));
    1420          40 :     };
    1421             :   }
    1422             : 
    1423             : #else
    1424             :   SymbolMap Result;
    1425             :   Error ResolutionError = Error::success();
    1426             :   Error ReadyError = Error::success();
    1427             : 
    1428             :   auto OnResolve = [&](Expected<SymbolMap> R) {
    1429             :     ErrorAsOutParameter _(&ResolutionError);
    1430             :     if (R)
    1431             :       Result = std::move(*R);
    1432             :     else
    1433             :       ResolutionError = R.takeError();
    1434             :   };
    1435             : 
    1436             :   std::function<void(Error)> OnReady;
    1437             :   if (WaitUntilReady) {
    1438             :     OnReady = [&](Error Err) {
    1439             :       ErrorAsOutParameter _(&ReadyError);
    1440             :       if (Err)
    1441             :         ReadyError = std::move(Err);
    1442             :     };
    1443             :   } else {
    1444             :     OnReady = [&](Error Err) {
    1445             :       if (Err)
    1446             :         reportError(std::move(Err));
    1447             :     };
    1448             :   }
    1449             : #endif
    1450             : 
    1451             :   auto Query = std::make_shared<AsynchronousSymbolQuery>(
    1452             :       Names, std::move(OnResolve), std::move(OnReady));
    1453             :   // FIXME: This should be run session locked along with the registration code
    1454             :   // and error reporting below.
    1455          40 :   SymbolNameSet UnresolvedSymbols = AsyncLookup(Query, std::move(Names));
    1456             : 
    1457             :   // If the query was lodged successfully then register the dependencies,
    1458             :   // otherwise fail it with an error.
    1459          40 :   if (UnresolvedSymbols.empty())
    1460          40 :     RegisterDependencies(Query->QueryRegistrations);
    1461             :   else {
    1462           0 :     bool DeliverError = runSessionLocked([&]() {
    1463             :       Query->detach();
    1464             :       return Query->canStillFail();
    1465             :     });
    1466             :     auto Err = make_error<SymbolsNotFound>(std::move(UnresolvedSymbols));
    1467           0 :     if (DeliverError)
    1468           0 :       Query->handleFailed(std::move(Err));
    1469             :     else
    1470           0 :       reportError(std::move(Err));
    1471             :   }
    1472             : 
    1473             : #if LLVM_ENABLE_THREADS
    1474             :   auto ResultFuture = PromisedResult.get_future();
    1475          40 :   auto Result = ResultFuture.get();
    1476             : 
    1477             :   {
    1478             :     std::lock_guard<std::mutex> Lock(ErrMutex);
    1479          40 :     if (ResolutionError) {
    1480             :       // ReadyError will never be assigned. Consume the success value.
    1481             :       cantFail(std::move(ReadyError));
    1482             :       return std::move(ResolutionError);
    1483             :     }
    1484             :   }
    1485             : 
    1486          40 :   if (WaitUntilReady) {
    1487             :     auto ReadyFuture = PromisedReady.get_future();
    1488           0 :     ReadyFuture.get();
    1489             : 
    1490             :     {
    1491             :       std::lock_guard<std::mutex> Lock(ErrMutex);
    1492           0 :       if (ReadyError)
    1493             :         return std::move(ReadyError);
    1494             :     }
    1495             :   } else
    1496             :     cantFail(std::move(ReadyError));
    1497             : 
    1498             :   return std::move(Result);
    1499             : 
    1500             : #else
    1501             :   if (ResolutionError) {
    1502             :     // ReadyError will never be assigned. Consume the success value.
    1503             :     cantFail(std::move(ReadyError));
    1504             :     return std::move(ResolutionError);
    1505             :   }
    1506             : 
    1507             :   if (ReadyError)
    1508             :     return std::move(ReadyError);
    1509             : 
    1510             :   return Result;
    1511             : #endif
    1512             : }
    1513             : 
    1514         112 : void ExecutionSession::lookup(
    1515             :     const JITDylibList &JDs, const SymbolNameSet &Symbols,
    1516             :     SymbolsResolvedCallback OnResolve, SymbolsReadyCallback OnReady,
    1517             :     RegisterDependenciesFunction RegisterDependencies) {
    1518             : 
    1519             :   // lookup can be re-entered recursively if running on a single thread. Run any
    1520             :   // outstanding MUs in case this query depends on them, otherwise the main
    1521             :   // thread will starve waiting for a result from an MU that it failed to run.
    1522         112 :   runOutstandingMUs();
    1523             : 
    1524             :   auto Unresolved = std::move(Symbols);
    1525             :   std::map<JITDylib *, MaterializationUnitList> MUsMap;
    1526             :   auto Q = std::make_shared<AsynchronousSymbolQuery>(
    1527             :       Symbols, std::move(OnResolve), std::move(OnReady));
    1528         112 :   bool QueryIsFullyResolved = false;
    1529         112 :   bool QueryIsFullyReady = false;
    1530         112 :   bool QueryFailed = false;
    1531             : 
    1532         112 :   runSessionLocked([&]() {
    1533             :     for (auto *JD : JDs) {
    1534             :       assert(JD && "JITDylibList entries must not be null");
    1535             :       assert(!MUsMap.count(JD) &&
    1536             :              "JITDylibList should not contain duplicate entries");
    1537             :       JD->lodgeQuery(Q, Unresolved, MUsMap[JD]);
    1538             :     }
    1539             : 
    1540             :     if (Unresolved.empty()) {
    1541             :       // Query lodged successfully.
    1542             : 
    1543             :       // Record whether this query is fully ready / resolved. We will use
    1544             :       // this to call handleFullyResolved/handleFullyReady outside the session
    1545             :       // lock.
    1546             :       QueryIsFullyResolved = Q->isFullyResolved();
    1547             :       QueryIsFullyReady = Q->isFullyReady();
    1548             : 
    1549             :       // Call the register dependencies function.
    1550             :       if (RegisterDependencies && !Q->QueryRegistrations.empty())
    1551             :         RegisterDependencies(Q->QueryRegistrations);
    1552             :     } else {
    1553             :       // Query failed due to unresolved symbols.
    1554             :       QueryFailed = true;
    1555             : 
    1556             :       // Disconnect the query from its dependencies.
    1557             :       Q->detach();
    1558             : 
    1559             :       // Replace the MUs.
    1560             :       for (auto &KV : MUsMap)
    1561             :         for (auto &MU : KV.second)
    1562             :           KV.first->replace(std::move(MU));
    1563             :     }
    1564             :   });
    1565             : 
    1566         112 :   if (QueryFailed) {
    1567           0 :     Q->handleFailed(make_error<SymbolsNotFound>(std::move(Unresolved)));
    1568             :     return;
    1569             :   } else {
    1570         112 :     if (QueryIsFullyResolved)
    1571          28 :       Q->handleFullyResolved();
    1572         112 :     if (QueryIsFullyReady)
    1573          27 :       Q->handleFullyReady();
    1574             :   }
    1575             : 
    1576             :   // Move the MUs to the OutstandingMUs list, then materialize.
    1577             :   {
    1578         112 :     std::lock_guard<std::recursive_mutex> Lock(OutstandingMUsMutex);
    1579             : 
    1580         225 :     for (auto &KV : MUsMap)
    1581         200 :       for (auto &MU : KV.second)
    1582         174 :         OutstandingMUs.push_back(std::make_pair(KV.first, std::move(MU)));
    1583             :   }
    1584             : 
    1585         112 :   runOutstandingMUs();
    1586             : }
    1587             : 
    1588             : Expected<SymbolMap>
    1589          91 : ExecutionSession::lookup(const JITDylibList &JDs, const SymbolNameSet &Symbols,
    1590             :                          RegisterDependenciesFunction RegisterDependencies,
    1591             :                          bool WaitUntilReady) {
    1592             : #if LLVM_ENABLE_THREADS
    1593             :   // In the threaded case we use promises to return the results.
    1594         182 :   std::promise<SymbolMap> PromisedResult;
    1595          91 :   std::mutex ErrMutex;
    1596             :   Error ResolutionError = Error::success();
    1597         182 :   std::promise<void> PromisedReady;
    1598             :   Error ReadyError = Error::success();
    1599             :   auto OnResolve = [&](Expected<SymbolMap> R) {
    1600             :     if (R)
    1601             :       PromisedResult.set_value(std::move(*R));
    1602             :     else {
    1603             :       {
    1604             :         ErrorAsOutParameter _(&ResolutionError);
    1605             :         std::lock_guard<std::mutex> Lock(ErrMutex);
    1606             :         ResolutionError = R.takeError();
    1607             :       }
    1608             :       PromisedResult.set_value(SymbolMap());
    1609             :     }
    1610             :   };
    1611             : 
    1612             :   std::function<void(Error)> OnReady;
    1613          91 :   if (WaitUntilReady) {
    1614             :     OnReady = [&](Error Err) {
    1615             :       if (Err) {
    1616             :         ErrorAsOutParameter _(&ReadyError);
    1617             :         std::lock_guard<std::mutex> Lock(ErrMutex);
    1618             :         ReadyError = std::move(Err);
    1619             :       }
    1620             :       PromisedReady.set_value();
    1621          78 :     };
    1622             :   } else {
    1623             :     OnReady = [&](Error Err) {
    1624             :       if (Err)
    1625             :         reportError(std::move(Err));
    1626          13 :     };
    1627             :   }
    1628             : 
    1629             : #else
    1630             :   SymbolMap Result;
    1631             :   Error ResolutionError = Error::success();
    1632             :   Error ReadyError = Error::success();
    1633             : 
    1634             :   auto OnResolve = [&](Expected<SymbolMap> R) {
    1635             :     ErrorAsOutParameter _(&ResolutionError);
    1636             :     if (R)
    1637             :       Result = std::move(*R);
    1638             :     else
    1639             :       ResolutionError = R.takeError();
    1640             :   };
    1641             : 
    1642             :   std::function<void(Error)> OnReady;
    1643             :   if (WaitUntilReady) {
    1644             :     OnReady = [&](Error Err) {
    1645             :       ErrorAsOutParameter _(&ReadyError);
    1646             :       if (Err)
    1647             :         ReadyError = std::move(Err);
    1648             :     };
    1649             :   } else {
    1650             :     OnReady = [&](Error Err) {
    1651             :       if (Err)
    1652             :         reportError(std::move(Err));
    1653             :     };
    1654             :   }
    1655             : #endif
    1656             : 
    1657             :   // Perform the asynchronous lookup.
    1658         195 :   lookup(JDs, Symbols, OnResolve, OnReady, RegisterDependencies);
    1659             : 
    1660             : #if LLVM_ENABLE_THREADS
    1661             :   auto ResultFuture = PromisedResult.get_future();
    1662          91 :   auto Result = ResultFuture.get();
    1663             : 
    1664             :   {
    1665             :     std::lock_guard<std::mutex> Lock(ErrMutex);
    1666          91 :     if (ResolutionError) {
    1667             :       // ReadyError will never be assigned. Consume the success value.
    1668             :       cantFail(std::move(ReadyError));
    1669             :       return std::move(ResolutionError);
    1670             :     }
    1671             :   }
    1672             : 
    1673          90 :   if (WaitUntilReady) {
    1674             :     auto ReadyFuture = PromisedReady.get_future();
    1675          77 :     ReadyFuture.get();
    1676             : 
    1677             :     {
    1678             :       std::lock_guard<std::mutex> Lock(ErrMutex);
    1679          77 :       if (ReadyError)
    1680             :         return std::move(ReadyError);
    1681             :     }
    1682             :   } else
    1683             :     cantFail(std::move(ReadyError));
    1684             : 
    1685             :   return std::move(Result);
    1686             : 
    1687             : #else
    1688             :   if (ResolutionError) {
    1689             :     // ReadyError will never be assigned. Consume the success value.
    1690             :     cantFail(std::move(ReadyError));
    1691             :     return std::move(ResolutionError);
    1692             :   }
    1693             : 
    1694             :   if (ReadyError)
    1695             :     return std::move(ReadyError);
    1696             : 
    1697             :   return Result;
    1698             : #endif
    1699             : }
    1700             : 
    1701         230 : void ExecutionSession::runOutstandingMUs() {
    1702             :   while (1) {
    1703             :     std::pair<JITDylib *, std::unique_ptr<MaterializationUnit>> JITDylibAndMU;
    1704             : 
    1705             :     {
    1706         319 :       std::lock_guard<std::recursive_mutex> Lock(OutstandingMUsMutex);
    1707         319 :       if (!OutstandingMUs.empty()) {
    1708             :         JITDylibAndMU = std::move(OutstandingMUs.back());
    1709             :         OutstandingMUs.pop_back();
    1710             :       }
    1711             :     }
    1712             : 
    1713         319 :     if (JITDylibAndMU.first) {
    1714             :       assert(JITDylibAndMU.second && "JITDylib, but no MU?");
    1715         178 :       dispatchMaterialization(*JITDylibAndMU.first,
    1716             :                               std::move(JITDylibAndMU.second));
    1717             :     } else
    1718             :       break;
    1719             :   }
    1720         230 : }
    1721             : 
    1722          77 : Expected<SymbolMap> lookup(const JITDylibList &JDs, SymbolNameSet Names) {
    1723             : 
    1724          77 :   if (JDs.empty())
    1725           0 :     return SymbolMap();
    1726             : 
    1727          77 :   auto &ES = (*JDs.begin())->getExecutionSession();
    1728             : 
    1729         154 :   return ES.lookup(JDs, Names, NoDependenciesToRegister, true);
    1730             : }
    1731             : 
    1732             : /// Look up a symbol by searching a list of JDs.
    1733          54 : Expected<JITEvaluatedSymbol> lookup(const JITDylibList &JDs,
    1734             :                                     SymbolStringPtr Name) {
    1735         108 :   SymbolNameSet Names({Name});
    1736         216 :   if (auto ResultMap = lookup(JDs, std::move(Names))) {
    1737             :     assert(ResultMap->size() == 1 && "Unexpected number of results");
    1738             :     assert(ResultMap->count(Name) && "Missing result for symbol");
    1739             :     return std::move(ResultMap->begin()->second);
    1740             :   } else
    1741             :     return ResultMap.takeError();
    1742             : }
    1743             : 
    1744          44 : MangleAndInterner::MangleAndInterner(ExecutionSession &ES, const DataLayout &DL)
    1745          44 :     : ES(ES), DL(DL) {}
    1746             : 
    1747         110 : SymbolStringPtr MangleAndInterner::operator()(StringRef Name) {
    1748             :   std::string MangledName;
    1749             :   {
    1750         110 :     raw_string_ostream MangledNameStream(MangledName);
    1751         220 :     Mangler::getNameWithPrefix(MangledNameStream, Name, DL);
    1752             :   }
    1753         220 :   return ES.getSymbolStringPool().intern(MangledName);
    1754             : }
    1755             : 
    1756             : } // End namespace orc.
    1757             : } // End namespace llvm.

Generated by: LCOV version 1.13