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