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   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 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   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   SetPrinter(const Set &S, Pred ShouldPrint = Pred())
86       : S(S), ShouldPrint(std::move(ShouldPrint)) {}
87 
88   void printTo(llvm::raw_ostream &OS) const {
89     bool PrintComma = false;
90     OS << "{";
91     for (auto &E : S) {
92       if (ShouldPrint(E)) {
93         if (PrintComma)
94           OS << ',';
95         OS << ' ' << E;
96         PrintComma = true;
97       }
98     }
99     OS << " }";
100   }
101 
102 private:
103   const Set &S;
104   mutable Pred ShouldPrint;
105 };
106 
107 template <typename Set, typename Pred>
108 SetPrinter<Set, Pred> printSet(const Set &S, Pred P = Pred()) {
109   return SetPrinter<Set, Pred>(S, std::move(P));
110 }
111 
112 // Render a SetPrinter by delegating to its printTo method.
113 template <typename Set, typename Pred>
114 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
115                               const SetPrinter<Set, Pred> &Printer) {
116   Printer.printTo(OS);
117   return OS;
118 }
119 
120 struct PrintSymbolFlagsMapElemsMatchingCLOpts {
121   bool operator()(const orc::SymbolFlagsMap::value_type &KV) {
122     return flagsMatchCLOpts(KV.second);
123   }
124 };
125 
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 
134 namespace llvm {
135 namespace orc {
136 
137   SymbolStringPool::PoolMapEntry SymbolStringPtr::Tombstone(0);
138 
139 char FailedToMaterialize::ID = 0;
140 char SymbolsNotFound::ID = 0;
141 char SymbolsCouldNotBeRemoved::ID = 0;
142 
143 RegisterDependenciesFunction NoDependenciesToRegister =
144     RegisterDependenciesFunction();
145 
146 void MaterializationUnit::anchor() {}
147 
148 raw_ostream &operator<<(raw_ostream &OS, const SymbolStringPtr &Sym) {
149   return OS << *Sym;
150 }
151 
152 raw_ostream &operator<<(raw_ostream &OS, const SymbolNameSet &Symbols) {
153   return OS << printSet(Symbols, PrintAll<SymbolStringPtr>());
154 }
155 
156 raw_ostream &operator<<(raw_ostream &OS, const JITSymbolFlags &Flags) {
157   if (Flags.isCallable())
158     OS << "[Callable]";
159   else
160     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 
169   return OS;
170 }
171 
172 raw_ostream &operator<<(raw_ostream &OS, const JITEvaluatedSymbol &Sym) {
173   return OS << format("0x%016x", Sym.getAddress()) << " " << Sym.getFlags();
174 }
175 
176 raw_ostream &operator<<(raw_ostream &OS, const SymbolFlagsMap::value_type &KV) {
177   return OS << "(\"" << KV.first << "\", " << KV.second << ")";
178 }
179 
180 raw_ostream &operator<<(raw_ostream &OS, const SymbolMap::value_type &KV) {
181   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 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                         const SymbolDependenceMap::value_type &KV) {
194   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 }
200 
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   OS << " ]";
219   return OS;
220 }
221 
222 FailedToMaterialize::FailedToMaterialize(SymbolNameSet Symbols)
223     : Symbols(std::move(Symbols)) {
224   assert(!this->Symbols.empty() && "Can not fail to resolve an empty set");
225 }
226 
227 std::error_code FailedToMaterialize::convertToErrorCode() const {
228   return orcError(OrcErrorCode::UnknownORCError);
229 }
230 
231 void FailedToMaterialize::log(raw_ostream &OS) const {
232   OS << "Failed to materialize symbols: " << Symbols;
233 }
234 
235 SymbolsNotFound::SymbolsNotFound(SymbolNameSet Symbols)
236     : Symbols(std::move(Symbols)) {
237   assert(!this->Symbols.empty() && "Can not fail to resolve an empty set");
238 }
239 
240 std::error_code SymbolsNotFound::convertToErrorCode() const {
241   return orcError(OrcErrorCode::UnknownORCError);
242 }
243 
244 void SymbolsNotFound::log(raw_ostream &OS) const {
245   OS << "Symbols not found: " << Symbols;
246 }
247 
248 SymbolsCouldNotBeRemoved::SymbolsCouldNotBeRemoved(SymbolNameSet Symbols)
249     : Symbols(std::move(Symbols)) {
250   assert(!this->Symbols.empty() && "Can not fail to resolve an empty set");
251 }
252 
253 std::error_code SymbolsCouldNotBeRemoved::convertToErrorCode() const {
254   return orcError(OrcErrorCode::UnknownORCError);
255 }
256 
257 void SymbolsCouldNotBeRemoved::log(raw_ostream &OS) const {
258   OS << "Symbols could not be removed: " << Symbols;
259 }
260 
261 AsynchronousSymbolQuery::AsynchronousSymbolQuery(
262     const SymbolNameSet &Symbols, SymbolsResolvedCallback NotifySymbolsResolved,
263     SymbolsReadyCallback NotifySymbolsReady)
264     : NotifySymbolsResolved(std::move(NotifySymbolsResolved)),
265       NotifySymbolsReady(std::move(NotifySymbolsReady)) {
266   NotYetResolvedCount = NotYetReadyCount = Symbols.size();
267 
268   for (auto &S : Symbols)
269     ResolvedSymbols[S] = nullptr;
270 }
271 
272 void AsynchronousSymbolQuery::resolve(const SymbolStringPtr &Name,
273                                       JITEvaluatedSymbol Sym) {
274   auto I = ResolvedSymbols.find(Name);
275   assert(I != ResolvedSymbols.end() &&
276          "Resolving symbol outside the requested set");
277   assert(I->second.getAddress() == 0 && "Redundantly resolving symbol Name");
278   I->second = std::move(Sym);
279   --NotYetResolvedCount;
280 }
281 
282 void AsynchronousSymbolQuery::handleFullyResolved() {
283   assert(NotYetResolvedCount == 0 && "Not fully resolved?");
284 
285   if (!NotifySymbolsResolved) {
286     // handleFullyResolved may be called by handleFullyReady (see comments in
287     // 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     return;
291   }
292 
293   auto TmpNotifySymbolsResolved = std::move(NotifySymbolsResolved);
294   NotifySymbolsResolved = SymbolsResolvedCallback();
295   TmpNotifySymbolsResolved(std::move(ResolvedSymbols));
296 }
297 
298 void AsynchronousSymbolQuery::notifySymbolReady() {
299   assert(NotYetReadyCount != 0 && "All symbols already emitted");
300   --NotYetReadyCount;
301 }
302 
303 void AsynchronousSymbolQuery::handleFullyReady() {
304   assert(NotifySymbolsReady &&
305          "NotifySymbolsReady already called or an error occurred");
306 
307   auto TmpNotifySymbolsReady = std::move(NotifySymbolsReady);
308   NotifySymbolsReady = SymbolsReadyCallback();
309 
310   if (NotYetResolvedCount == 0 && NotifySymbolsResolved) {
311     // The NotifyResolved callback of one query must have caused this query to
312     // become ready (i.e. there is still a handleFullyResolved callback waiting
313     // 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     handleFullyResolved();
317   }
318 
319   assert(QueryRegistrations.empty() &&
320          "Query is still registered with some symbols");
321   assert(!NotifySymbolsResolved && "Resolution not applied yet");
322   TmpNotifySymbolsReady(Error::success());
323 }
324 
325 bool AsynchronousSymbolQuery::canStillFail() {
326   return (NotifySymbolsResolved || NotifySymbolsReady);
327 }
328 
329 void AsynchronousSymbolQuery::handleFailed(Error Err) {
330   assert(QueryRegistrations.empty() && ResolvedSymbols.empty() &&
331          NotYetResolvedCount == 0 && NotYetReadyCount == 0 &&
332          "Query should already have been abandoned");
333   if (NotifySymbolsResolved) {
334     NotifySymbolsResolved(std::move(Err));
335     NotifySymbolsResolved = SymbolsResolvedCallback();
336   } else {
337     assert(NotifySymbolsReady && "Failed after both callbacks issued?");
338     NotifySymbolsReady(std::move(Err));
339   }
340   NotifySymbolsReady = SymbolsReadyCallback();
341 }
342 
343 void AsynchronousSymbolQuery::addQueryDependence(JITDylib &JD,
344                                                  SymbolStringPtr Name) {
345   bool Added = QueryRegistrations[&JD].insert(std::move(Name)).second;
346   (void)Added;
347   assert(Added && "Duplicate dependence notification?");
348 }
349 
350 void AsynchronousSymbolQuery::removeQueryDependence(
351     JITDylib &JD, const SymbolStringPtr &Name) {
352   auto QRI = QueryRegistrations.find(&JD);
353   assert(QRI != QueryRegistrations.end() &&
354          "No dependencies registered for JD");
355   assert(QRI->second.count(Name) && "No dependency on Name in JD");
356   QRI->second.erase(Name);
357   if (QRI->second.empty())
358     QueryRegistrations.erase(QRI);
359 }
360 
361 void AsynchronousSymbolQuery::detach() {
362   ResolvedSymbols.clear();
363   NotYetResolvedCount = 0;
364   NotYetReadyCount = 0;
365   for (auto &KV : QueryRegistrations)
366     KV.first->detachQueryHelper(*this, KV.second);
367   QueryRegistrations.clear();
368 }
369 
370 MaterializationResponsibility::MaterializationResponsibility(
371     JITDylib &JD, SymbolFlagsMap SymbolFlags, VModuleKey K)
372     : JD(JD), SymbolFlags(std::move(SymbolFlags)), K(std::move(K)) {
373   assert(!this->SymbolFlags.empty() && "Materializing nothing?");
374 
375 #ifndef NDEBUG
376   for (auto &KV : this->SymbolFlags)
377     KV.second |= JITSymbolFlags::Materializing;
378 #endif
379 }
380 
381 MaterializationResponsibility::~MaterializationResponsibility() {
382   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 }
389 
390 void MaterializationResponsibility::resolve(const SymbolMap &Symbols) {
391   LLVM_DEBUG(dbgs() << "In " << JD.getName() << " resolving " << Symbols
392                     << "\n");
393 #ifndef NDEBUG
394   for (auto &KV : Symbols) {
395     auto I = SymbolFlags.find(KV.first);
396     assert(I != SymbolFlags.end() &&
397            "Resolving symbol outside this responsibility set");
398     assert(I->second.isMaterializing() && "Duplicate resolution");
399     I->second &= ~JITSymbolFlags::Materializing;
400     if (I->second.isWeak())
401       assert(I->second == (KV.second.getFlags() | JITSymbolFlags::Weak) &&
402              "Resolving symbol with incorrect flags");
403     else
404       assert(I->second == KV.second.getFlags() &&
405              "Resolving symbol with incorrect flags");
406   }
407 #endif
408 
409   JD.resolve(Symbols);
410 }
411 
412 void MaterializationResponsibility::emit() {
413 #ifndef NDEBUG
414   for (auto &KV : SymbolFlags)
415     assert(!KV.second.isMaterializing() &&
416            "Failed to resolve symbol before emission");
417 #endif // NDEBUG
418 
419   JD.emit(SymbolFlags);
420   SymbolFlags.clear();
421 }
422 
423 Error MaterializationResponsibility::defineMaterializing(
424     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   for (auto &KV : NewSymbolFlags) {
430     auto I = SymbolFlags.insert(KV).first;
431     (void)I;
432 #ifndef NDEBUG
433     I->second |= JITSymbolFlags::Materializing;
434 #endif
435   }
436 
437   return JD.defineMaterializing(NewSymbolFlags);
438 }
439 
440 void MaterializationResponsibility::failMaterialization() {
441 
442   SymbolNameSet FailedSymbols;
443   for (auto &KV : SymbolFlags)
444     FailedSymbols.insert(KV.first);
445 
446   JD.notifyFailed(FailedSymbols);
447   SymbolFlags.clear();
448 }
449 
450 void MaterializationResponsibility::replace(
451     std::unique_ptr<MaterializationUnit> MU) {
452   for (auto &KV : MU->getSymbols())
453     SymbolFlags.erase(KV.first);
454 
455   LLVM_DEBUG(JD.getExecutionSession().runSessionLocked([&]() {
456     dbgs() << "In " << JD.getName() << " replacing symbols with " << *MU
457            << "\n";
458   }););
459 
460   JD.replace(std::move(MU));
461 }
462 
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 
482   return MaterializationResponsibility(JD, std::move(DelegatedFlags),
483                                        std::move(NewKey));
484 }
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 }
492 
493 void MaterializationResponsibility::addDependenciesForAll(
494     const SymbolDependenceMap &Dependencies) {
495   for (auto &KV : SymbolFlags)
496     JD.addDependencies(KV.first, Dependencies);
497 }
498 
499 AbsoluteSymbolsMaterializationUnit::AbsoluteSymbolsMaterializationUnit(
500     SymbolMap Symbols, VModuleKey K)
501     : MaterializationUnit(extractFlags(Symbols), std::move(K)),
502       Symbols(std::move(Symbols)) {}
503 
504 StringRef AbsoluteSymbolsMaterializationUnit::getName() const {
505   return "<Absolute Symbols>";
506 }
507 
508 void AbsoluteSymbolsMaterializationUnit::materialize(
509     MaterializationResponsibility R) {
510   R.resolve(Symbols);
511   R.emit();
512 }
513 
514 void AbsoluteSymbolsMaterializationUnit::discard(const JITDylib &JD,
515                                                  const SymbolStringPtr &Name) {
516   assert(Symbols.count(Name) && "Symbol is not part of this MU");
517   Symbols.erase(Name);
518 }
519 
520 SymbolFlagsMap
521 AbsoluteSymbolsMaterializationUnit::extractFlags(const SymbolMap &Symbols) {
522   SymbolFlagsMap Flags;
523   for (const auto &KV : Symbols)
524     Flags[KV.first] = KV.second.getFlags();
525   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 
533 StringRef ReExportsMaterializationUnit::getName() const {
534   return "<Reexports>";
535 }
536 
537 void ReExportsMaterializationUnit::materialize(
538     MaterializationResponsibility R) {
539 
540   auto &ES = R.getTargetJITDylib().getExecutionSession();
541   JITDylib &TgtJD = R.getTargetJITDylib();
542   JITDylib &SrcJD = SourceJD ? *SourceJD : TgtJD;
543 
544   // Find the set of requested aliases and aliasees. Return any unrequested
545   // aliases back to the JITDylib so as to not prematurely materialize any
546   // aliasees.
547   auto RequestedSymbols = R.getRequestedSymbols();
548   SymbolAliasMap RequestedAliases;
549 
550   for (auto &Name : RequestedSymbols) {
551     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   }
556 
557   if (!Aliases.empty()) {
558     if (SourceJD)
559       R.replace(reexports(*SourceJD, std::move(Aliases)));
560     else
561       R.replace(symbolAliases(std::move(Aliases)));
562   }
563 
564   // The OnResolveInfo struct will hold the aliases and responsibilty for each
565   // query in the list.
566   struct OnResolveInfo {
567     OnResolveInfo(MaterializationResponsibility R, SymbolAliasMap Aliases)
568         : R(std::move(R)), Aliases(std::move(Aliases)) {}
569 
570     MaterializationResponsibility R;
571     SymbolAliasMap Aliases;
572   };
573 
574   // 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   // form Foo -> Bar, Bar -> Baz. Such a form would deadlock as the query would
577   // 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   std::vector<std::pair<SymbolNameSet, std::shared_ptr<OnResolveInfo>>>
581       QueryInfos;
582   while (!RequestedAliases.empty()) {
583     SymbolNameSet ResponsibilitySymbols;
584     SymbolNameSet QuerySymbols;
585     SymbolAliasMap QueryAliases;
586 
587     // Collect as many aliases as we can without including a chain.
588     for (auto &KV : RequestedAliases) {
589       // Chain detected. Skip this symbol for this round.
590       if (&SrcJD == &TgtJD && (QueryAliases.count(KV.second.Aliasee) ||
591                                RequestedAliases.count(KV.second.Aliasee)))
592         continue;
593 
594       ResponsibilitySymbols.insert(KV.first);
595       QuerySymbols.insert(KV.second.Aliasee);
596       QueryAliases[KV.first] = std::move(KV.second);
597     }
598 
599     // Remove the aliases collected this round from the RequestedAliases map.
600     for (auto &KV : QueryAliases)
601       RequestedAliases.erase(KV.first);
602 
603     assert(!QuerySymbols.empty() && "Alias cycle detected!");
604 
605     auto QueryInfo = std::make_shared<OnResolveInfo>(
606         R.delegate(ResponsibilitySymbols), std::move(QueryAliases));
607     QueryInfos.push_back(
608         make_pair(std::move(QuerySymbols), std::move(QueryInfo)));
609   }
610 
611   // Issue the queries.
612   while (!QueryInfos.empty()) {
613     auto QuerySymbols = std::move(QueryInfos.back().first);
614     auto QueryInfo = std::move(QueryInfos.back().second);
615 
616     QueryInfos.pop_back();
617 
618     auto RegisterDependencies = [QueryInfo,
619                                  &SrcJD](const SymbolDependenceMap &Deps) {
620       // If there were no materializing symbols, just bail out.
621       if (Deps.empty())
622         return;
623 
624       // Otherwise the only deps should be on SrcJD.
625       assert(Deps.size() == 1 && Deps.count(&SrcJD) &&
626              "Unexpected dependencies for reexports");
627 
628       auto &SrcJDDeps = Deps.find(&SrcJD)->second;
629       SymbolDependenceMap PerAliasDepsMap;
630       auto &PerAliasDeps = PerAliasDepsMap[&SrcJD];
631 
632       for (auto &KV : QueryInfo->Aliases)
633         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       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         QueryInfo->R.failMaterialization();
654       }
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               std::move(RegisterDependencies), nullptr, true);
661   }
662 }
663 
664 void ReExportsMaterializationUnit::discard(const JITDylib &JD,
665                                            const SymbolStringPtr &Name) {
666   assert(Aliases.count(Name) &&
667          "Symbol not covered by this MaterializationUnit");
668   Aliases.erase(Name);
669 }
670 
671 SymbolFlagsMap
672 ReExportsMaterializationUnit::extractFlags(const SymbolAliasMap &Aliases) {
673   SymbolFlagsMap SymbolFlags;
674   for (auto &KV : Aliases)
675     SymbolFlags[KV.first] = KV.second.AliasFlags;
676 
677   return SymbolFlags;
678 }
679 
680 Expected<SymbolAliasMap>
681 buildSimpleReexportsAliasMap(JITDylib &SourceJD, const SymbolNameSet &Symbols) {
682   auto Flags = SourceJD.lookupFlags(Symbols);
683 
684   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   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   auto Flags = SourceJD.lookupFlags(Names);
710 
711   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 
732       auto NewFlags = KV.second;
733       NewFlags |= JITSymbolFlags::Materializing;
734 
735       std::tie(EntryItr, Added) = Symbols.insert(
736           std::make_pair(KV.first, JITEvaluatedSymbol(0, NewFlags)));
737 
738       if (Added)
739         AddedSyms.push_back(EntryItr);
740       else {
741         // Remove any symbols already added.
742         for (auto &SI : AddedSyms)
743           Symbols.erase(SI);
744 
745         // FIXME: Return all duplicates.
746         return make_error<DuplicateDefinition>(*KV.first);
747       }
748     }
749 
750     return Error::success();
751   });
752 }
753 
754 void JITDylib::replace(std::unique_ptr<MaterializationUnit> MU) {
755   assert(MU != nullptr && "Can not replace with a null MaterializationUnit");
756 
757   auto MustRunMU =
758       ES.runSessionLocked([&, this]() -> std::unique_ptr<MaterializationUnit> {
759 
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           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         // If any symbol has pending queries against it then we need to
773         // materialize MU immediately.
774         for (auto &KV : MU->getSymbols()) {
775           auto MII = MaterializingInfos.find(KV.first);
776           if (MII != MaterializingInfos.end()) {
777             if (!MII->second.PendingQueries.empty())
778               return std::move(MU);
779           }
780         }
781 
782         // Otherwise, make MU responsible for all the symbols.
783         auto UMI = std::make_shared<UnmaterializedInfo>(std::move(MU));
784         for (auto &KV : UMI->MU->getSymbols()) {
785           assert(!KV.second.isLazy() &&
786                  "Lazy flag should be managed internally.");
787           assert(!KV.second.isMaterializing() &&
788                  "Materializing flags should be managed internally.");
789 
790           auto SymI = Symbols.find(KV.first);
791           JITSymbolFlags ReplaceFlags = KV.second;
792           ReplaceFlags |= JITSymbolFlags::Lazy;
793           SymI->second = JITEvaluatedSymbol(SymI->second.getAddress(),
794                                             std::move(ReplaceFlags));
795           UnmaterializedInfos[KV.first] = UMI;
796         }
797 
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     return RequestedSymbols;
824   });
825 }
826 
827 void JITDylib::addDependencies(const SymbolStringPtr &Name,
828                                const SymbolDependenceMap &Dependencies) {
829   assert(Symbols.count(Name) && "Name not in symbol table");
830   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       auto &Name = KV.first;
872       auto Sym = KV.second;
873 
874       assert(!Sym.getFlags().isLazy() && !Sym.getFlags().isMaterializing() &&
875              "Materializing flags should be managed internally");
876 
877       auto I = Symbols.find(Name);
878 
879       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       auto &MI = MaterializingInfos[Name];
897       for (auto &Q : MI.PendingQueries) {
898         Q->resolve(Name, Sym);
899         if (Q->isFullyResolved())
900           FullyResolvedQueries.insert(Q);
901       }
902     }
903 
904     return FullyResolvedQueries;
905   });
906 
907   for (auto &Q : FullyResolvedQueries) {
908     assert(Q->isFullyResolved() && "Q not fully resolved");
909     Q->handleFullyResolved();
910   }
911 }
912 
913 void JITDylib::emit(const SymbolFlagsMap &Emitted) {
914   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       auto &MI = MII->second;
925 
926       // For each dependant, transfer this node's emitted dependencies to
927       // it. If the dependant node is ready (i.e. has no unemitted
928       // dependencies) then notify any pending queries.
929       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           assert(DependantMII != DependantJD.MaterializingInfos.end() &&
935                  "Dependant should have MaterializingInfo");
936 
937           auto &DependantMI = DependantMII->second;
938 
939           // Remove the dependant's dependency on this node.
940           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 
978       if (MI.UnemittedDependencies.empty()) {
979         for (auto &Q : MI.PendingQueries) {
980           Q->notifySymbolReady();
981           if (Q->isFullyReady())
982             ReadyQueries.insert(Q);
983           Q->removeQueryDependence(*this, Name);
984         }
985         assert(Symbols.count(Name) &&
986                "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   ES.runSessionLocked([&]() {
1067     auto I = std::find(SearchOrder.begin(), SearchOrder.end(), &JD);
1068     if (I != SearchOrder.end())
1069       SearchOrder.erase(I);
1070   });
1071 }
1072 
1073 Error JITDylib::remove(const SymbolNameSet &Names) {
1074   return ES.runSessionLocked([&]() -> Error {
1075     using SymbolMaterializerItrPair =
1076         std::pair<SymbolMap::iterator, UnmaterializedInfosMap::iterator>;
1077     std::vector<SymbolMaterializerItrPair> SymbolsToRemove;
1078     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     for (auto &SymbolMaterializerItrPair : SymbolsToRemove) {
1111       auto UMII = SymbolMaterializerItrPair.second;
1112 
1113       // If there is a materializer attached, call discard.
1114       if (UMII != UnmaterializedInfos.end()) {
1115         UMII->second->MU->doDiscard(*this, UMII->first);
1116         UnmaterializedInfos.erase(UMII);
1117       }
1118 
1119       auto SymI = SymbolMaterializerItrPair.first;
1120       Symbols.erase(SymI);
1121     }
1122 
1123     return Error::success();
1124   });
1125 }
1126 
1127 SymbolFlagsMap JITDylib::lookupFlags(const SymbolNameSet &Names) {
1128   return ES.runSessionLocked([&, this]() {
1129     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         (void)Unresolved2;
1136         assert(Unresolved2.empty() &&
1137                "All fallback defs should have been found by lookupFlagsImpl");
1138       }
1139     };
1140     return Result;
1141   });
1142 }
1143 
1144 SymbolNameSet JITDylib::lookupFlagsImpl(SymbolFlagsMap &Flags,
1145                                         const SymbolNameSet &Names) {
1146   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     // against this symbol.
1197     if (!SymI->second.getFlags().isExported())
1198       if (!MatchNonExported && MatchNonExportedInJD != this)
1199         continue;
1200 
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       assert(!SymI->second.getFlags().isMaterializing() &&
1214              "Materializing and lazy should not both be set");
1215       auto UMII = UnmaterializedInfos.find(Name);
1216       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 
1221       // Move all symbols associated with this MaterializationUnit into
1222       // materializing state.
1223       for (auto &KV : MU->getSymbols()) {
1224         auto SymK = Symbols.find(KV.first);
1225         auto Flags = SymK->second.getFlags();
1226         Flags &= ~JITSymbolFlags::Lazy;
1227         Flags |= JITSymbolFlags::Materializing;
1228         SymK->second.setFlags(Flags);
1229         UnmaterializedInfos.erase(KV.first);
1230       }
1231 
1232       // 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       // 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     // Add the query to the PendingQueries list.
1242     assert(SymI->second.getFlags().isMaterializing() &&
1243            "By this line the symbol should be materializing");
1244     auto &MI = MaterializingInfos[Name];
1245     MI.PendingQueries.push_back(Q);
1246     Q->addQueryDependence(*this, Name);
1247   }
1248 
1249   // Remove any symbols that we found.
1250   for (auto &Name : ToRemove)
1251     Unresolved.erase(Name);
1252 }
1253 
1254 SymbolNameSet JITDylib::legacyLookup(std::shared_ptr<AsynchronousSymbolQuery> Q,
1255                                      SymbolNameSet Names) {
1256   assert(Q && "Query can not be null");
1257 
1258   ES.runOutstandingMUs();
1259 
1260   LookupImplActionFlags ActionFlags = None;
1261   std::vector<std::unique_ptr<MaterializationUnit>> MUs;
1262 
1263   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       auto NewDefs = DefGenerator(*this, Unresolved);
1270       if (!NewDefs.empty()) {
1271         for (auto &D : NewDefs)
1272           Unresolved.erase(D);
1273         ActionFlags = lookupImpl(Q, MUs, NewDefs);
1274         assert(NewDefs.empty() &&
1275                "All fallback defs should have been found by lookupImpl");
1276       }
1277     }
1278   });
1279 
1280   assert((MUs.empty() || ActionFlags == None) &&
1281          "If action flags are set, there should be no work to do (so no MUs)");
1282 
1283   if (ActionFlags & NotifyFullyResolved)
1284     Q->handleFullyResolved();
1285 
1286   if (ActionFlags & NotifyFullyReady)
1287     Q->handleFullyReady();
1288 
1289   // FIXME: Swap back to the old code below once RuntimeDyld works with
1290   //        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       ES.OutstandingMUs.push_back(make_pair(this, std::move(MU)));
1296   }
1297   ES.runOutstandingMUs();
1298 
1299   // Dispatch any required MaterializationUnits for materialization.
1300   // for (auto &MU : MUs)
1301   //  ES.dispatchMaterialization(*this, std::move(MU));
1302 
1303   return Unresolved;
1304 }
1305 
1306 JITDylib::LookupImplActionFlags
1307 JITDylib::lookupImpl(std::shared_ptr<AsynchronousSymbolQuery> &Q,
1308                      std::vector<std::unique_ptr<MaterializationUnit>> &MUs,
1309                      SymbolNameSet &Unresolved) {
1310   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     auto SymI = Symbols.find(Name);
1317     if (SymI == Symbols.end())
1318       continue;
1319 
1320     // If we found Name, mark it to be removed from the Unresolved set.
1321     ToRemove.push_back(Name);
1322 
1323     // If the symbol has an address then resolve it.
1324     if (SymI->second.getAddress() != 0) {
1325       Q->resolve(Name, SymI->second);
1326       if (Q->isFullyResolved())
1327         ActionFlags |= NotifyFullyResolved;
1328     }
1329 
1330     // If the symbol is lazy, get the MaterialiaztionUnit for it.
1331     if (SymI->second.getFlags().isLazy()) {
1332       assert(SymI->second.getAddress() == 0 &&
1333              "Lazy symbol should not have a resolved address");
1334       assert(!SymI->second.getFlags().isMaterializing() &&
1335              "Materializing and lazy should not both be set");
1336       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     } else if (!SymI->second.getFlags().isMaterializing()) {
1356       // The symbol is neither lazy nor materializing, so it must be ready.
1357       // Notify the query and continue.
1358       Q->notifySymbolReady();
1359       if (Q->isFullyReady())
1360         ActionFlags |= NotifyFullyReady;
1361       continue;
1362     }
1363 
1364     // Add the query to the PendingQueries list.
1365     assert(SymI->second.getFlags().isMaterializing() &&
1366            "By this line the symbol should be materializing");
1367     auto &MI = MaterializingInfos[Name];
1368     MI.PendingQueries.push_back(Q);
1369     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 
1376   return ActionFlags;
1377 }
1378 
1379 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        << "):\n"
1384        << "Symbol table:\n";
1385 
1386     for (auto &KV : Symbols) {
1387       OS << "    \"" << *KV.first << "\": ";
1388       if (auto Addr = KV.second.getAddress())
1389         OS << format("0x%016x", Addr);
1390       else
1391         OS << "<not resolved>";
1392       if (KV.second.getFlags().isLazy() ||
1393           KV.second.getFlags().isMaterializing()) {
1394         OS << " (";
1395         if (KV.second.getFlags().isLazy()) {
1396           auto I = UnmaterializedInfos.find(KV.first);
1397           assert(I != UnmaterializedInfos.end() &&
1398                  "Lazy symbol should have UnmaterializedInfo");
1399           OS << " Lazy (MU=" << I->second->MU.get() << ")";
1400         }
1401         if (KV.second.getFlags().isMaterializing())
1402           OS << " Materializing";
1403         OS << " )\n";
1404       } else
1405         OS << "\n";
1406     }
1407 
1408     if (!MaterializingInfos.empty())
1409       OS << "  MaterializingInfos entries:\n";
1410     for (auto &KV : MaterializingInfos) {
1411       OS << "    \"" << *KV.first << "\":\n"
1412          << "      IsEmitted = " << (KV.second.IsEmitted ? "true" : "false")
1413          << "\n"
1414          << "      " << KV.second.PendingQueries.size()
1415          << " pending queries: { ";
1416       for (auto &Q : KV.second.PendingQueries)
1417         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       for (auto &KV2 : KV.second.UnemittedDependencies)
1423         OS << "        " << KV2.first->getName() << ": " << KV2.second << "\n";
1424     }
1425   });
1426 }
1427 
1428 JITDylib::JITDylib(ExecutionSession &ES, std::string Name)
1429     : ES(ES), JITDylibName(std::move(Name)) {
1430   SearchOrder.push_back(this);
1431 }
1432 
1433 Error JITDylib::defineImpl(MaterializationUnit &MU) {
1434   SymbolNameSet Duplicates;
1435   SymbolNameSet MUDefsOverridden;
1436 
1437   struct ExistingDefOverriddenEntry {
1438     SymbolMap::iterator ExistingDefItr;
1439     JITSymbolFlags NewFlags;
1440   };
1441   std::vector<ExistingDefOverriddenEntry> ExistingDefsOverridden;
1442 
1443   for (auto &KV : MU.getSymbols()) {
1444     assert(!KV.second.isLazy() && "Lazy flag should be managed internally.");
1445     assert(!KV.second.isMaterializing() &&
1446            "Materializing flags should be managed internally.");
1447 
1448     SymbolMap::iterator EntryItr;
1449     bool Added;
1450 
1451     auto NewFlags = KV.second;
1452     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            "Overridden existing def should have an UnmaterializedInfo");
1499 
1500     UMII->second->MU->doDiscard(*this, EDO.ExistingDefItr->first);
1501   }
1502 
1503   // Discard overridden symbols povided by MU.
1504   for (auto &Sym : MUDefsOverridden)
1505     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     auto &MI = MaterializingInfos[QuerySymbol];
1516 
1517     auto IdenticalQuery =
1518         [&](const std::shared_ptr<AsynchronousSymbolQuery> &R) {
1519           return R.get() == &Q;
1520         };
1521 
1522     auto I = std::find_if(MI.PendingQueries.begin(), MI.PendingQueries.end(),
1523                           IdenticalQuery);
1524     assert(I != MI.PendingQueries.end() &&
1525            "Query Q should be in the PendingQueries list for QuerySymbol");
1526     MI.PendingQueries.erase(I);
1527   }
1528 }
1529 
1530 void JITDylib::transferEmittedNodeDependencies(
1531     MaterializingInfo &DependantMI, const SymbolStringPtr &DependantName,
1532     MaterializingInfo &EmittedMI) {
1533   for (auto &KV : EmittedMI.UnemittedDependencies) {
1534     auto &DependencyJD = *KV.first;
1535     SymbolNameSet *UnemittedDependenciesOnDependencyJD = nullptr;
1536 
1537     for (auto &DependencyName : KV.second) {
1538       auto &DependencyMI = DependencyJD.MaterializingInfos[DependencyName];
1539 
1540       // Do not add self dependencies.
1541       if (&DependencyMI == &DependantMI)
1542         continue;
1543 
1544       // If we haven't looked up the dependencies for DependencyJD yet, do it
1545       // now and cache the result.
1546       if (!UnemittedDependenciesOnDependencyJD)
1547         UnemittedDependenciesOnDependencyJD =
1548             &DependantMI.UnemittedDependencies[&DependencyJD];
1549 
1550       DependencyMI.Dependants[this].insert(DependantName);
1551       UnemittedDependenciesOnDependencyJD->insert(DependencyName);
1552     }
1553   }
1554 }
1555 
1556 ExecutionSession::ExecutionSession(std::shared_ptr<SymbolStringPool> SSP)
1557     : 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 
1562 JITDylib &ExecutionSession::getMainJITDylib() {
1563   return runSessionLocked([this]() -> JITDylib & { return *JDs.front(); });
1564 }
1565 
1566 JITDylib &ExecutionSession::createJITDylib(std::string Name,
1567                                            bool AddToMainDylibSearchOrder) {
1568   return runSessionLocked([&, this]() -> JITDylib & {
1569     JDs.push_back(
1570         std::unique_ptr<JITDylib>(new JITDylib(*this, std::move(Name))));
1571     if (AddToMainDylibSearchOrder)
1572       JDs.front()->addToSearchOrder(*JDs.back());
1573     return *JDs.back();
1574   });
1575 }
1576 
1577 void ExecutionSession::legacyFailQuery(AsynchronousSymbolQuery &Q, Error Err) {
1578   assert(!!Err && "Error should be in failure state");
1579 
1580   bool SendErrorToQuery;
1581   runSessionLocked([&]() {
1582     Q.detach();
1583     SendErrorToQuery = Q.canStillFail();
1584   });
1585 
1586   if (SendErrorToQuery)
1587     Q.handleFailed(std::move(Err));
1588   else
1589     reportError(std::move(Err));
1590 }
1591 
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   std::mutex ErrMutex;
1599   Error ResolutionError = Error::success();
1600   std::promise<void> PromisedReady;
1601   Error ReadyError = Error::success();
1602   auto OnResolve = [&](Expected<SymbolMap> R) {
1603     if (R)
1604       PromisedResult.set_value(std::move(*R));
1605     else {
1606       {
1607         ErrorAsOutParameter _(&ResolutionError);
1608         std::lock_guard<std::mutex> Lock(ErrMutex);
1609         ResolutionError = R.takeError();
1610       }
1611       PromisedResult.set_value(SymbolMap());
1612     }
1613   };
1614 
1615   std::function<void(Error)> OnReady;
1616   if (WaitUntilReady) {
1617     OnReady = [&](Error Err) {
1618       if (Err) {
1619         ErrorAsOutParameter _(&ReadyError);
1620         std::lock_guard<std::mutex> Lock(ErrMutex);
1621         ReadyError = std::move(Err);
1622       }
1623       PromisedReady.set_value();
1624     };
1625   } else {
1626     OnReady = [&](Error Err) {
1627       if (Err)
1628         reportError(std::move(Err));
1629     };
1630   }
1631 
1632 #else
1633   SymbolMap Result;
1634   Error ResolutionError = Error::success();
1635   Error ReadyError = Error::success();
1636 
1637   auto OnResolve = [&](Expected<SymbolMap> R) {
1638     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   if (WaitUntilReady) {
1647     OnReady = [&](Error Err) {
1648       ErrorAsOutParameter _(&ReadyError);
1649       if (Err)
1650         ReadyError = std::move(Err);
1651     };
1652   } else {
1653     OnReady = [&](Error Err) {
1654       if (Err)
1655         reportError(std::move(Err));
1656     };
1657   }
1658 #endif
1659 
1660   auto Query = std::make_shared<AsynchronousSymbolQuery>(
1661       Names, std::move(OnResolve), std::move(OnReady));
1662   // FIXME: This should be run session locked along with the registration code
1663   // and error reporting below.
1664   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     RegisterDependencies(Query->QueryRegistrations);
1670   else {
1671     bool DeliverError = runSessionLocked([&]() {
1672       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 
1686   {
1687     std::lock_guard<std::mutex> Lock(ErrMutex);
1688     if (ResolutionError) {
1689       // ReadyError will never be assigned. Consume the success value.
1690       cantFail(std::move(ReadyError));
1691       return std::move(ResolutionError);
1692     }
1693   }
1694 
1695   if (WaitUntilReady) {
1696     auto ReadyFuture = PromisedReady.get_future();
1697     ReadyFuture.get();
1698 
1699     {
1700       std::lock_guard<std::mutex> Lock(ErrMutex);
1701       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   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   bool QueryIsFullyReady = false;
1741   bool QueryFailed = false;
1742 
1743   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       JD->lodgeQuery(Q, Unresolved, MatchNonExportedInJD, MatchNonExported,
1749                      CollectedMUsMap[JD]);
1750     }
1751 
1752     if (Unresolved.empty()) {
1753       // Query lodged successfully.
1754 
1755       // Record whether this query is fully ready / resolved. We will use
1756       // this to call handleFullyResolved/handleFullyReady outside the session
1757       // lock.
1758       QueryIsFullyResolved = Q->isFullyResolved();
1759       QueryIsFullyReady = Q->isFullyReady();
1760 
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 
1768       // Disconnect the query from its dependencies.
1769       Q->detach();
1770 
1771       // Replace the MUs.
1772       for (auto &KV : CollectedMUsMap)
1773         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   }
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 #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   Error ReadyError = Error::success();
1812   auto OnResolve = [&](Expected<SymbolMap> R) {
1813     if (R)
1814       PromisedResult.set_value(std::move(*R));
1815     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       Result = std::move(*R);
1851     else
1852       ResolutionError = R.takeError();
1853   };
1854 
1855   std::function<void(Error)> OnReady;
1856   if (WaitUntilReady) {
1857     OnReady = [&](Error Err) {
1858       ErrorAsOutParameter _(&ReadyError);
1859       if (Err)
1860         ReadyError = std::move(Err);
1861     };
1862   } else {
1863     OnReady = [&](Error Err) {
1864       if (Err)
1865         reportError(std::move(Err));
1866     };
1867   }
1868 #endif
1869 
1870   // Perform the asynchronous lookup.
1871   lookup(JDs, Symbols, OnResolve, OnReady, RegisterDependencies,
1872          MatchNonExportedInJD, MatchNonExported);
1873 
1874 #if LLVM_ENABLE_THREADS
1875   auto ResultFuture = PromisedResult.get_future();
1876   auto Result = ResultFuture.get();
1877 
1878   {
1879     std::lock_guard<std::mutex> Lock(ErrMutex);
1880     if (ResolutionError) {
1881       // ReadyError will never be assigned. Consume the success value.
1882       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 
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   }
1907 
1908   if (ReadyError)
1909     return std::move(ReadyError);
1910 
1911   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 void ExecutionSession::runOutstandingMUs() {
1944   while (1) {
1945     std::pair<JITDylib *, std::unique_ptr<MaterializationUnit>> JITDylibAndMU;
1946 
1947     {
1948       std::lock_guard<std::recursive_mutex> Lock(OutstandingMUsMutex);
1949       if (!OutstandingMUs.empty()) {
1950         JITDylibAndMU = std::move(OutstandingMUs.back());
1951         OutstandingMUs.pop_back();
1952       }
1953     }
1954 
1955     if (JITDylibAndMU.first) {
1956       assert(JITDylibAndMU.second && "JITDylib, but no MU?");
1957       dispatchMaterialization(*JITDylibAndMU.first,
1958                               std::move(JITDylibAndMU.second));
1959     } else
1960       break;
1961   }
1962 }
1963 
1964 MangleAndInterner::MangleAndInterner(ExecutionSession &ES, const DataLayout &DL)
1965     : 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.
1978