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

Generated by: LCOV version 1.13