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