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