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::delegate(
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 void MaterializationResponsibility::addDependencies(
321     const SymbolDependenceMap &Dependencies) {
322   V.addDependencies(SymbolFlags, Dependencies);
323 }
324 
325 AbsoluteSymbolsMaterializationUnit::AbsoluteSymbolsMaterializationUnit(
326     SymbolMap Symbols)
327     : MaterializationUnit(extractFlags(Symbols)), Symbols(std::move(Symbols)) {}
328 
329 void AbsoluteSymbolsMaterializationUnit::materialize(
330     MaterializationResponsibility R) {
331   R.resolve(Symbols);
332   R.finalize();
333 }
334 
335 void AbsoluteSymbolsMaterializationUnit::discard(const VSO &V,
336                                                  SymbolStringPtr Name) {
337   assert(Symbols.count(Name) && "Symbol is not part of this MU");
338   Symbols.erase(Name);
339 }
340 
341 SymbolFlagsMap
342 AbsoluteSymbolsMaterializationUnit::extractFlags(const SymbolMap &Symbols) {
343   SymbolFlagsMap Flags;
344   for (const auto &KV : Symbols)
345     Flags[KV.first] = KV.second.getFlags();
346   return Flags;
347 }
348 
349 SymbolAliasesMaterializationUnit::SymbolAliasesMaterializationUnit(
350     SymbolAliasMap Aliases)
351     : MaterializationUnit(extractFlags(Aliases)), Aliases(std::move(Aliases)) {}
352 
353 void SymbolAliasesMaterializationUnit::materialize(
354     MaterializationResponsibility R) {
355   auto &V = R.getTargetVSO();
356   auto &ES = V.getExecutionSession();
357 
358   // FIXME: Use a unique_ptr when we move to C++14 and have generalized lambda
359   // capture.
360   auto SharedR = std::make_shared<MaterializationResponsibility>(std::move(R));
361 
362   auto OnResolve = [this, SharedR](
363                        Expected<AsynchronousSymbolQuery::ResolutionResult> RR) {
364     if (RR) {
365       SymbolMap ResolutionMap;
366       for (auto &KV : Aliases) {
367         assert(RR->Symbols.count(KV.second.Aliasee) &&
368                "Result map missing entry?");
369         ResolutionMap[KV.first] = JITEvaluatedSymbol(
370             RR->Symbols[KV.second.Aliasee].getAddress(), KV.second.AliasFlags);
371       }
372 
373       SharedR->resolve(ResolutionMap);
374       SharedR->finalize();
375     } else {
376       auto &ES = SharedR->getTargetVSO().getExecutionSession();
377       ES.reportError(RR.takeError());
378       SharedR->failMaterialization();
379     }
380   };
381 
382   auto OnReady = [&ES](Error Err) { ES.reportError(std::move(Err)); };
383 
384   SymbolNameSet Aliasees;
385   for (auto &KV : Aliases)
386     Aliasees.insert(KV.second.Aliasee);
387 
388   auto Q = std::make_shared<AsynchronousSymbolQuery>(
389       Aliasees, std::move(OnResolve), std::move(OnReady));
390   auto Unresolved = V.lookup(Q, Aliasees);
391 
392   if (!Unresolved.empty())
393     ES.failQuery(*Q, make_error<SymbolsNotFound>(std::move(Unresolved)));
394 }
395 
396 void SymbolAliasesMaterializationUnit::discard(const VSO &V,
397                                                SymbolStringPtr Name) {
398   assert(Aliases.count(Name) &&
399          "Symbol not covered by this MaterializationUnit");
400   Aliases.erase(Name);
401 }
402 
403 SymbolFlagsMap
404 SymbolAliasesMaterializationUnit::extractFlags(const SymbolAliasMap &Aliases) {
405   SymbolFlagsMap SymbolFlags;
406   for (auto &KV : Aliases)
407     SymbolFlags[KV.first] = KV.second.AliasFlags;
408 
409   return SymbolFlags;
410 }
411 
412 Error VSO::defineMaterializing(const SymbolFlagsMap &SymbolFlags) {
413   return ES.runSessionLocked([&]() -> Error {
414     std::vector<SymbolMap::iterator> AddedSyms;
415 
416     for (auto &KV : SymbolFlags) {
417       SymbolMap::iterator EntryItr;
418       bool Added;
419 
420       auto NewFlags = KV.second;
421       NewFlags |= JITSymbolFlags::Materializing;
422 
423       std::tie(EntryItr, Added) = Symbols.insert(
424           std::make_pair(KV.first, JITEvaluatedSymbol(0, NewFlags)));
425 
426       if (Added)
427         AddedSyms.push_back(EntryItr);
428       else {
429         // Remove any symbols already added.
430         for (auto &SI : AddedSyms)
431           Symbols.erase(SI);
432 
433         // FIXME: Return all duplicates.
434         return make_error<DuplicateDefinition>(*KV.first);
435       }
436     }
437 
438     return Error::success();
439   });
440 }
441 
442 void VSO::replace(std::unique_ptr<MaterializationUnit> MU) {
443   assert(MU != nullptr && "Can not replace with a null MaterializationUnit");
444 
445   auto MustRunMU =
446       ES.runSessionLocked([&, this]() -> std::unique_ptr<MaterializationUnit> {
447 
448 #ifndef NDEBUG
449         for (auto &KV : MU->getSymbols()) {
450           auto SymI = Symbols.find(KV.first);
451           assert(SymI != Symbols.end() && "Replacing unknown symbol");
452           assert(!SymI->second.getFlags().isLazy() &&
453                  SymI->second.getFlags().isMaterializing() &&
454                  "Can not replace symbol that is not materializing");
455           assert(UnmaterializedInfos.count(KV.first) == 0 &&
456                  "Symbol being replaced should have no UnmaterializedInfo");
457         }
458 #endif // NDEBUG
459 
460         // If any symbol has pending queries against it then we need to
461         // materialize MU immediately.
462         for (auto &KV : MU->getSymbols()) {
463           auto MII = MaterializingInfos.find(KV.first);
464           if (MII != MaterializingInfos.end()) {
465             if (!MII->second.PendingQueries.empty())
466               return std::move(MU);
467           }
468         }
469 
470         // Otherwise, make MU responsible for all the symbols.
471         auto UMI = std::make_shared<UnmaterializedInfo>(std::move(MU));
472         for (auto &KV : UMI->MU->getSymbols()) {
473           assert(!KV.second.isLazy() &&
474                  "Lazy flag should be managed internally.");
475           assert(!KV.second.isMaterializing() &&
476                  "Materializing flags should be managed internally.");
477 
478           auto SymI = Symbols.find(KV.first);
479           JITSymbolFlags ReplaceFlags = KV.second;
480           ReplaceFlags |= JITSymbolFlags::Lazy;
481           SymI->second = JITEvaluatedSymbol(SymI->second.getAddress(),
482                                             std::move(ReplaceFlags));
483           UnmaterializedInfos[KV.first] = UMI;
484         }
485 
486         return nullptr;
487       });
488 
489   if (MustRunMU)
490     ES.dispatchMaterialization(*this, std::move(MustRunMU));
491 }
492 
493 SymbolNameSet VSO::getRequestedSymbols(const SymbolFlagsMap &SymbolFlags) {
494   return ES.runSessionLocked([&]() {
495     SymbolNameSet RequestedSymbols;
496 
497     for (auto &KV : SymbolFlags) {
498       assert(Symbols.count(KV.first) && "VSO does not cover this symbol?");
499       assert(Symbols[KV.first].getFlags().isMaterializing() &&
500              "getRequestedSymbols can only be called for materializing "
501              "symbols");
502       auto I = MaterializingInfos.find(KV.first);
503       if (I == MaterializingInfos.end())
504         continue;
505 
506       if (!I->second.PendingQueries.empty())
507         RequestedSymbols.insert(KV.first);
508     }
509 
510     return RequestedSymbols;
511   });
512 }
513 
514 void VSO::addDependencies(const SymbolFlagsMap &Dependants,
515                           const SymbolDependenceMap &Dependencies) {
516   ES.runSessionLocked([&, this]() {
517     for (auto &KV : Dependants) {
518       const auto &Name = KV.first;
519       assert(Symbols.count(Name) && "Name not in symbol table");
520       assert((Symbols[Name].getFlags().isLazy() ||
521               Symbols[Name].getFlags().isMaterializing()) &&
522              "Symbol is not lazy or materializing");
523 
524       auto &MI = MaterializingInfos[Name];
525       assert(!MI.IsFinalized && "Can not add dependencies to finalized symbol");
526 
527       for (auto &KV : Dependencies) {
528         assert(KV.first && "Null VSO in dependency?");
529         auto &OtherVSO = *KV.first;
530         auto &DepsOnOtherVSO = MI.UnfinalizedDependencies[&OtherVSO];
531 
532         for (auto &OtherSymbol : KV.second) {
533           auto &OtherMI = OtherVSO.MaterializingInfos[OtherSymbol];
534 
535           if (OtherMI.IsFinalized)
536             transferFinalizedNodeDependencies(MI, Name, OtherMI);
537           else if (&OtherVSO != this || OtherSymbol != Name) {
538             OtherMI.Dependants[this].insert(Name);
539             DepsOnOtherVSO.insert(OtherSymbol);
540           }
541         }
542 
543         if (DepsOnOtherVSO.empty())
544           MI.UnfinalizedDependencies.erase(&OtherVSO);
545       }
546     }
547   });
548 }
549 
550 void VSO::resolve(const SymbolMap &Resolved) {
551   auto FullyResolvedQueries = ES.runSessionLocked([&, this]() {
552     AsynchronousSymbolQuerySet FullyResolvedQueries;
553     for (const auto &KV : Resolved) {
554       auto &Name = KV.first;
555       auto Sym = KV.second;
556 
557       assert(!Sym.getFlags().isLazy() && !Sym.getFlags().isMaterializing() &&
558              "Materializing flags should be managed internally");
559 
560       auto I = Symbols.find(Name);
561 
562       assert(I != Symbols.end() && "Symbol not found");
563       assert(!I->second.getFlags().isLazy() &&
564              I->second.getFlags().isMaterializing() &&
565              "Symbol should be materializing");
566       assert(I->second.getAddress() == 0 && "Symbol has already been resolved");
567 
568       assert((Sym.getFlags() & ~JITSymbolFlags::Weak) ==
569                  (JITSymbolFlags::stripTransientFlags(I->second.getFlags()) &
570                   ~JITSymbolFlags::Weak) &&
571              "Resolved flags should match the declared flags");
572 
573       // Once resolved, symbols can never be weak.
574       JITSymbolFlags ResolvedFlags = Sym.getFlags();
575       ResolvedFlags &= ~JITSymbolFlags::Weak;
576       ResolvedFlags |= JITSymbolFlags::Materializing;
577       I->second = JITEvaluatedSymbol(Sym.getAddress(), ResolvedFlags);
578 
579       auto &MI = MaterializingInfos[Name];
580       for (auto &Q : MI.PendingQueries) {
581         Q->resolve(Name, Sym);
582         if (Q->isFullyResolved())
583           FullyResolvedQueries.insert(Q);
584       }
585     }
586 
587     return FullyResolvedQueries;
588   });
589 
590   for (auto &Q : FullyResolvedQueries) {
591     assert(Q->isFullyResolved() && "Q not fully resolved");
592     Q->handleFullyResolved();
593   }
594 }
595 
596 void VSO::finalize(const SymbolFlagsMap &Finalized) {
597   auto FullyReadyQueries = ES.runSessionLocked([&, this]() {
598     AsynchronousSymbolQuerySet ReadyQueries;
599 
600     for (const auto &KV : Finalized) {
601       const auto &Name = KV.first;
602 
603       auto MII = MaterializingInfos.find(Name);
604       assert(MII != MaterializingInfos.end() &&
605              "Missing MaterializingInfo entry");
606 
607       auto &MI = MII->second;
608 
609       // For each dependant, transfer this node's unfinalized dependencies to
610       // it. If the dependant node is fully finalized then notify any pending
611       // queries.
612       for (auto &KV : MI.Dependants) {
613         auto &DependantVSO = *KV.first;
614         for (auto &DependantName : KV.second) {
615           auto DependantMII =
616               DependantVSO.MaterializingInfos.find(DependantName);
617           assert(DependantMII != DependantVSO.MaterializingInfos.end() &&
618                  "Dependant should have MaterializingInfo");
619 
620           auto &DependantMI = DependantMII->second;
621 
622           // Remove the dependant's dependency on this node.
623           assert(DependantMI.UnfinalizedDependencies[this].count(Name) &&
624                  "Dependant does not count this symbol as a dependency?");
625           DependantMI.UnfinalizedDependencies[this].erase(Name);
626           if (DependantMI.UnfinalizedDependencies[this].empty())
627             DependantMI.UnfinalizedDependencies.erase(this);
628 
629           // Transfer unfinalized dependencies from this node to the dependant.
630           DependantVSO.transferFinalizedNodeDependencies(DependantMI,
631                                                          DependantName, MI);
632 
633           // If the dependant is finalized and this node was the last of its
634           // unfinalized dependencies then notify any pending queries on the
635           // dependant node.
636           if (DependantMI.IsFinalized &&
637               DependantMI.UnfinalizedDependencies.empty()) {
638             assert(DependantMI.Dependants.empty() &&
639                    "Dependants should be empty by now");
640             for (auto &Q : DependantMI.PendingQueries) {
641               Q->notifySymbolReady();
642               if (Q->isFullyReady())
643                 ReadyQueries.insert(Q);
644               Q->removeQueryDependence(DependantVSO, DependantName);
645             }
646 
647             // If this dependant node was fully finalized we can erase its
648             // MaterializingInfo and update its materializing state.
649             assert(DependantVSO.Symbols.count(DependantName) &&
650                    "Dependant has no entry in the Symbols table");
651             auto &DependantSym = DependantVSO.Symbols[DependantName];
652             DependantSym.setFlags(static_cast<JITSymbolFlags::FlagNames>(
653                 DependantSym.getFlags() & ~JITSymbolFlags::Materializing));
654             DependantVSO.MaterializingInfos.erase(DependantMII);
655           }
656         }
657       }
658       MI.Dependants.clear();
659       MI.IsFinalized = true;
660 
661       if (MI.UnfinalizedDependencies.empty()) {
662         for (auto &Q : MI.PendingQueries) {
663           Q->notifySymbolReady();
664           if (Q->isFullyReady())
665             ReadyQueries.insert(Q);
666           Q->removeQueryDependence(*this, Name);
667         }
668         assert(Symbols.count(Name) &&
669                "Symbol has no entry in the Symbols table");
670         auto &Sym = Symbols[Name];
671         Sym.setFlags(static_cast<JITSymbolFlags::FlagNames>(
672             Sym.getFlags() & ~JITSymbolFlags::Materializing));
673         MaterializingInfos.erase(MII);
674       }
675     }
676 
677     return ReadyQueries;
678   });
679 
680   for (auto &Q : FullyReadyQueries) {
681     assert(Q->isFullyReady() && "Q is not fully ready");
682     Q->handleFullyReady();
683   }
684 }
685 
686 void VSO::notifyFailed(const SymbolNameSet &FailedSymbols) {
687 
688   // FIXME: This should fail any transitively dependant symbols too.
689 
690   auto FailedQueriesToNotify = ES.runSessionLocked([&, this]() {
691     AsynchronousSymbolQuerySet FailedQueries;
692 
693     for (auto &Name : FailedSymbols) {
694       auto I = Symbols.find(Name);
695       assert(I != Symbols.end() && "Symbol not present in this VSO");
696       Symbols.erase(I);
697 
698       auto MII = MaterializingInfos.find(Name);
699 
700       // If we have not created a MaterializingInfo for this symbol yet then
701       // there is nobody to notify.
702       if (MII == MaterializingInfos.end())
703         continue;
704 
705       // Copy all the queries to the FailedQueries list, then abandon them.
706       // This has to be a copy, and the copy has to come before the abandon
707       // operation: Each Q.detach() call will reach back into this
708       // PendingQueries list to remove Q.
709       for (auto &Q : MII->second.PendingQueries)
710         FailedQueries.insert(Q);
711 
712       for (auto &Q : FailedQueries)
713         Q->detach();
714 
715       assert(MII->second.PendingQueries.empty() &&
716              "Queries remain after symbol was failed");
717 
718       MaterializingInfos.erase(MII);
719     }
720 
721     return FailedQueries;
722   });
723 
724   for (auto &Q : FailedQueriesToNotify)
725     Q->handleFailed(make_error<FailedToMaterialize>(FailedSymbols));
726 }
727 
728 void VSO::runOutstandingMUs() {
729   while (1) {
730     std::unique_ptr<MaterializationUnit> MU;
731 
732     {
733       std::lock_guard<std::recursive_mutex> Lock(OutstandingMUsMutex);
734       if (!OutstandingMUs.empty()) {
735         MU = std::move(OutstandingMUs.back());
736         OutstandingMUs.pop_back();
737       }
738     }
739 
740     if (MU)
741       ES.dispatchMaterialization(*this, std::move(MU));
742     else
743       break;
744   }
745 }
746 
747 SymbolNameSet VSO::lookupFlags(SymbolFlagsMap &Flags,
748                                const SymbolNameSet &Names) {
749   return ES.runSessionLocked([&, this]() {
750     auto Unresolved = lookupFlagsImpl(Flags, Names);
751     if (FallbackDefinitionGenerator && !Unresolved.empty()) {
752       auto FallbackDefs = FallbackDefinitionGenerator(*this, Unresolved);
753       if (!FallbackDefs.empty()) {
754         auto Unresolved2 = lookupFlagsImpl(Flags, FallbackDefs);
755         (void)Unresolved2;
756         assert(Unresolved2.empty() &&
757                "All fallback defs should have been found by lookupFlagsImpl");
758         for (auto &D : FallbackDefs)
759           Unresolved.erase(D);
760       }
761     };
762     return Unresolved;
763   });
764 }
765 
766 SymbolNameSet VSO::lookupFlagsImpl(SymbolFlagsMap &Flags,
767                                    const SymbolNameSet &Names) {
768   SymbolNameSet Unresolved;
769 
770   for (auto &Name : Names) {
771     auto I = Symbols.find(Name);
772 
773     if (I == Symbols.end()) {
774       Unresolved.insert(Name);
775       continue;
776     }
777 
778     assert(!Flags.count(Name) && "Symbol already present in Flags map");
779     Flags[Name] = JITSymbolFlags::stripTransientFlags(I->second.getFlags());
780   }
781 
782   return Unresolved;
783 }
784 
785 SymbolNameSet VSO::lookup(std::shared_ptr<AsynchronousSymbolQuery> Q,
786                           SymbolNameSet Names) {
787   assert(Q && "Query can not be null");
788 
789   runOutstandingMUs();
790 
791   LookupImplActionFlags ActionFlags = None;
792   std::vector<std::unique_ptr<MaterializationUnit>> MUs;
793 
794   SymbolNameSet Unresolved = std::move(Names);
795   ES.runSessionLocked([&, this]() {
796     ActionFlags = lookupImpl(Q, MUs, Unresolved);
797     if (FallbackDefinitionGenerator && !Unresolved.empty()) {
798       assert(ActionFlags == None &&
799              "ActionFlags set but unresolved symbols remain?");
800       auto FallbackDefs = FallbackDefinitionGenerator(*this, Unresolved);
801       if (!FallbackDefs.empty()) {
802         for (auto &D : FallbackDefs)
803           Unresolved.erase(D);
804         ActionFlags = lookupImpl(Q, MUs, FallbackDefs);
805         assert(FallbackDefs.empty() &&
806                "All fallback defs should have been found by lookupImpl");
807       }
808     }
809   });
810 
811   assert((MUs.empty() || ActionFlags == None) &&
812          "If action flags are set, there should be no work to do (so no MUs)");
813 
814   if (ActionFlags & NotifyFullyResolved)
815     Q->handleFullyResolved();
816 
817   if (ActionFlags & NotifyFullyReady)
818     Q->handleFullyReady();
819 
820   // FIXME: Swap back to the old code below once RuntimeDyld works with
821   //        callbacks from asynchronous queries.
822   // Add MUs to the OutstandingMUs list.
823   {
824     std::lock_guard<std::recursive_mutex> Lock(OutstandingMUsMutex);
825     for (auto &MU : MUs)
826       OutstandingMUs.push_back(std::move(MU));
827   }
828   runOutstandingMUs();
829 
830   // Dispatch any required MaterializationUnits for materialization.
831   // for (auto &MU : MUs)
832   //  ES.dispatchMaterialization(*this, std::move(MU));
833 
834   return Unresolved;
835 }
836 
837 VSO::LookupImplActionFlags
838 VSO::lookupImpl(std::shared_ptr<AsynchronousSymbolQuery> &Q,
839                 std::vector<std::unique_ptr<MaterializationUnit>> &MUs,
840                 SymbolNameSet &Unresolved) {
841   LookupImplActionFlags ActionFlags = None;
842 
843   for (auto I = Unresolved.begin(), E = Unresolved.end(); I != E;) {
844     auto TmpI = I++;
845     auto Name = *TmpI;
846 
847     // Search for the name in Symbols. Skip it if not found.
848     auto SymI = Symbols.find(Name);
849     if (SymI == Symbols.end())
850       continue;
851 
852     // If we found Name in V, remove it frome the Unresolved set and add it
853     // to the dependencies set.
854     Unresolved.erase(TmpI);
855 
856     // If the symbol has an address then resolve it.
857     if (SymI->second.getAddress() != 0) {
858       Q->resolve(Name, SymI->second);
859       if (Q->isFullyResolved())
860         ActionFlags |= NotifyFullyResolved;
861     }
862 
863     // If the symbol is lazy, get the MaterialiaztionUnit for it.
864     if (SymI->second.getFlags().isLazy()) {
865       assert(SymI->second.getAddress() == 0 &&
866              "Lazy symbol should not have a resolved address");
867       assert(!SymI->second.getFlags().isMaterializing() &&
868              "Materializing and lazy should not both be set");
869       auto UMII = UnmaterializedInfos.find(Name);
870       assert(UMII != UnmaterializedInfos.end() &&
871              "Lazy symbol should have UnmaterializedInfo");
872       auto MU = std::move(UMII->second->MU);
873       assert(MU != nullptr && "Materializer should not be null");
874 
875       // Kick all symbols associated with this MaterializationUnit into
876       // materializing state.
877       for (auto &KV : MU->getSymbols()) {
878         auto SymK = Symbols.find(KV.first);
879         auto Flags = SymK->second.getFlags();
880         Flags &= ~JITSymbolFlags::Lazy;
881         Flags |= JITSymbolFlags::Materializing;
882         SymK->second.setFlags(Flags);
883         UnmaterializedInfos.erase(KV.first);
884       }
885 
886       // Add MU to the list of MaterializationUnits to be materialized.
887       MUs.push_back(std::move(MU));
888     } else if (!SymI->second.getFlags().isMaterializing()) {
889       // The symbol is neither lazy nor materializing. Finalize it and
890       // continue.
891       Q->notifySymbolReady();
892       if (Q->isFullyReady())
893         ActionFlags |= NotifyFullyReady;
894       continue;
895     }
896 
897     // Add the query to the PendingQueries list.
898     assert(SymI->second.getFlags().isMaterializing() &&
899            "By this line the symbol should be materializing");
900     auto &MI = MaterializingInfos[Name];
901     MI.PendingQueries.push_back(Q);
902     Q->addQueryDependence(*this, Name);
903   }
904 
905   return ActionFlags;
906 }
907 
908 void VSO::dump(raw_ostream &OS) {
909   ES.runSessionLocked([&, this]() {
910     OS << "VSO \"" << VSOName
911        << "\" (ES: " << format("0x%016x", reinterpret_cast<uintptr_t>(&ES))
912        << "):\n"
913        << "Symbol table:\n";
914 
915     for (auto &KV : Symbols) {
916       OS << "    \"" << *KV.first
917          << "\": " << format("0x%016x", KV.second.getAddress());
918       if (KV.second.getFlags().isLazy() ||
919           KV.second.getFlags().isMaterializing()) {
920         OS << " (";
921         if (KV.second.getFlags().isLazy()) {
922           auto I = UnmaterializedInfos.find(KV.first);
923           assert(I != UnmaterializedInfos.end() &&
924                  "Lazy symbol should have UnmaterializedInfo");
925           OS << " Lazy (MU=" << I->second->MU.get() << ")";
926         }
927         if (KV.second.getFlags().isMaterializing())
928           OS << " Materializing";
929         OS << " )\n";
930       } else
931         OS << "\n";
932     }
933 
934     if (!MaterializingInfos.empty())
935       OS << "  MaterializingInfos entries:\n";
936     for (auto &KV : MaterializingInfos) {
937       OS << "    \"" << *KV.first << "\":\n"
938          << "      IsFinalized = " << (KV.second.IsFinalized ? "true" : "false")
939          << "\n"
940          << "      " << KV.second.PendingQueries.size()
941          << " pending queries: { ";
942       for (auto &Q : KV.second.PendingQueries)
943         OS << Q.get() << " ";
944       OS << "}\n      Dependants:\n";
945       for (auto &KV2 : KV.second.Dependants)
946         OS << "        " << KV2.first->getName() << ": " << KV2.second << "\n";
947       OS << "      Unfinalized Dependencies:\n";
948       for (auto &KV2 : KV.second.UnfinalizedDependencies)
949         OS << "        " << KV2.first->getName() << ": " << KV2.second << "\n";
950     }
951   });
952 }
953 
954 Error VSO::defineImpl(MaterializationUnit &MU) {
955   SymbolNameSet Duplicates;
956   SymbolNameSet MUDefsOverridden;
957 
958   struct ExistingDefOverriddenEntry {
959     SymbolMap::iterator ExistingDefItr;
960     JITSymbolFlags NewFlags;
961   };
962   std::vector<ExistingDefOverriddenEntry> ExistingDefsOverridden;
963 
964   for (auto &KV : MU.getSymbols()) {
965     assert(!KV.second.isLazy() && "Lazy flag should be managed internally.");
966     assert(!KV.second.isMaterializing() &&
967            "Materializing flags should be managed internally.");
968 
969     SymbolMap::iterator EntryItr;
970     bool Added;
971 
972     auto NewFlags = KV.second;
973     NewFlags |= JITSymbolFlags::Lazy;
974 
975     std::tie(EntryItr, Added) = Symbols.insert(
976         std::make_pair(KV.first, JITEvaluatedSymbol(0, NewFlags)));
977 
978     if (!Added) {
979       if (KV.second.isStrong()) {
980         if (EntryItr->second.getFlags().isStrong() ||
981             (EntryItr->second.getFlags() & JITSymbolFlags::Materializing))
982           Duplicates.insert(KV.first);
983         else
984           ExistingDefsOverridden.push_back({EntryItr, NewFlags});
985       } else
986         MUDefsOverridden.insert(KV.first);
987     }
988   }
989 
990   if (!Duplicates.empty()) {
991     // We need to remove the symbols we added.
992     for (auto &KV : MU.getSymbols()) {
993       if (Duplicates.count(KV.first))
994         continue;
995 
996       bool Found = false;
997       for (const auto &EDO : ExistingDefsOverridden)
998         if (EDO.ExistingDefItr->first == KV.first)
999           Found = true;
1000 
1001       if (!Found)
1002         Symbols.erase(KV.first);
1003     }
1004 
1005     // FIXME: Return all duplicates.
1006     return make_error<DuplicateDefinition>(**Duplicates.begin());
1007   }
1008 
1009   // Update flags on existing defs and call discard on their materializers.
1010   for (auto &EDO : ExistingDefsOverridden) {
1011     assert(EDO.ExistingDefItr->second.getFlags().isLazy() &&
1012            !EDO.ExistingDefItr->second.getFlags().isMaterializing() &&
1013            "Overridden existing def should be in the Lazy state");
1014 
1015     EDO.ExistingDefItr->second.setFlags(EDO.NewFlags);
1016 
1017     auto UMII = UnmaterializedInfos.find(EDO.ExistingDefItr->first);
1018     assert(UMII != UnmaterializedInfos.end() &&
1019            "Overridden existing def should have an UnmaterializedInfo");
1020 
1021     UMII->second->MU->doDiscard(*this, EDO.ExistingDefItr->first);
1022   }
1023 
1024   // Discard overridden symbols povided by MU.
1025   for (auto &Sym : MUDefsOverridden)
1026     MU.doDiscard(*this, Sym);
1027 
1028   return Error::success();
1029 }
1030 
1031 void VSO::detachQueryHelper(AsynchronousSymbolQuery &Q,
1032                             const SymbolNameSet &QuerySymbols) {
1033   for (auto &QuerySymbol : QuerySymbols) {
1034     assert(MaterializingInfos.count(QuerySymbol) &&
1035            "QuerySymbol does not have MaterializingInfo");
1036     auto &MI = MaterializingInfos[QuerySymbol];
1037 
1038     auto IdenticalQuery =
1039         [&](const std::shared_ptr<AsynchronousSymbolQuery> &R) {
1040           return R.get() == &Q;
1041         };
1042 
1043     auto I = std::find_if(MI.PendingQueries.begin(), MI.PendingQueries.end(),
1044                           IdenticalQuery);
1045     assert(I != MI.PendingQueries.end() &&
1046            "Query Q should be in the PendingQueries list for QuerySymbol");
1047     MI.PendingQueries.erase(I);
1048   }
1049 }
1050 
1051 void VSO::transferFinalizedNodeDependencies(
1052     MaterializingInfo &DependantMI, const SymbolStringPtr &DependantName,
1053     MaterializingInfo &FinalizedMI) {
1054   for (auto &KV : FinalizedMI.UnfinalizedDependencies) {
1055     auto &DependencyVSO = *KV.first;
1056     SymbolNameSet *UnfinalizedDependenciesOnDependencyVSO = nullptr;
1057 
1058     for (auto &DependencyName : KV.second) {
1059       auto &DependencyMI = DependencyVSO.MaterializingInfos[DependencyName];
1060 
1061       // Do not add self dependencies.
1062       if (&DependencyMI == &DependantMI)
1063         continue;
1064 
1065       // If we haven't looked up the dependencies for DependencyVSO yet, do it
1066       // now and cache the result.
1067       if (!UnfinalizedDependenciesOnDependencyVSO)
1068         UnfinalizedDependenciesOnDependencyVSO =
1069             &DependantMI.UnfinalizedDependencies[&DependencyVSO];
1070 
1071       DependencyMI.Dependants[this].insert(DependantName);
1072       UnfinalizedDependenciesOnDependencyVSO->insert(DependencyName);
1073     }
1074   }
1075 }
1076 
1077 VSO &ExecutionSession::createVSO(std::string Name) {
1078   return runSessionLocked([&, this]() -> VSO & {
1079       VSOs.push_back(std::unique_ptr<VSO>(new VSO(*this, std::move(Name))));
1080     return *VSOs.back();
1081   });
1082 }
1083 
1084 Expected<SymbolMap> blockingLookup(ExecutionSessionBase &ES,
1085                                    AsynchronousLookupFunction AsyncLookup,
1086                                    SymbolNameSet Names, bool WaitUntilReady,
1087                                    MaterializationResponsibility *MR) {
1088 
1089 #if LLVM_ENABLE_THREADS
1090   // In the threaded case we use promises to return the results.
1091   std::promise<SymbolMap> PromisedResult;
1092   std::mutex ErrMutex;
1093   Error ResolutionError = Error::success();
1094   std::promise<void> PromisedReady;
1095   Error ReadyError = Error::success();
1096   auto OnResolve =
1097       [&](Expected<AsynchronousSymbolQuery::ResolutionResult> Result) {
1098         if (Result) {
1099           if (MR)
1100             MR->addDependencies(Result->Dependencies);
1101           PromisedResult.set_value(std::move(Result->Symbols));
1102         } else {
1103           {
1104             ErrorAsOutParameter _(&ResolutionError);
1105             std::lock_guard<std::mutex> Lock(ErrMutex);
1106             ResolutionError = Result.takeError();
1107           }
1108           PromisedResult.set_value(SymbolMap());
1109         }
1110       };
1111 
1112   std::function<void(Error)> OnReady;
1113   if (WaitUntilReady) {
1114     OnReady = [&](Error Err) {
1115       if (Err) {
1116         ErrorAsOutParameter _(&ReadyError);
1117         std::lock_guard<std::mutex> Lock(ErrMutex);
1118         ReadyError = std::move(Err);
1119       }
1120       PromisedReady.set_value();
1121     };
1122   } else {
1123     OnReady = [&](Error Err) {
1124       if (Err)
1125         ES.reportError(std::move(Err));
1126     };
1127   }
1128 
1129 #else
1130   SymbolMap Result;
1131   Error ResolutionError = Error::success();
1132   Error ReadyError = Error::success();
1133 
1134   auto OnResolve = [&](Expected<AsynchronousSymbolQuery::ResolutionResult> R) {
1135     ErrorAsOutParameter _(&ResolutionError);
1136     if (R) {
1137       if (MR)
1138         MR->addDependencies(R->Dependencies);
1139       Result = std::move(R->Symbols);
1140     } else
1141       ResolutionError = R.takeError();
1142   };
1143 
1144   std::function<void(Error)> OnReady;
1145   if (WaitUntilReady) {
1146     OnReady = [&](Error Err) {
1147       ErrorAsOutParameter _(&ReadyError);
1148       if (Err)
1149         ReadyError = std::move(Err);
1150     };
1151   } else {
1152     OnReady = [&](Error Err) {
1153       if (Err)
1154         ES.reportError(std::move(Err));
1155     };
1156   }
1157 #endif
1158 
1159   auto Query = std::make_shared<AsynchronousSymbolQuery>(
1160       Names, std::move(OnResolve), std::move(OnReady));
1161 
1162   SymbolNameSet UnresolvedSymbols = AsyncLookup(Query, std::move(Names));
1163 
1164   // If there are unresolved symbols then the query will never return.
1165   // Fail it with ES.failQuery.
1166   if (!UnresolvedSymbols.empty())
1167     ES.failQuery(*Query,
1168                  make_error<SymbolsNotFound>(std::move(UnresolvedSymbols)));
1169 
1170 #if LLVM_ENABLE_THREADS
1171   auto ResultFuture = PromisedResult.get_future();
1172   auto Result = ResultFuture.get();
1173 
1174   {
1175     std::lock_guard<std::mutex> Lock(ErrMutex);
1176     if (ResolutionError) {
1177       // ReadyError will never be assigned. Consume the success value.
1178       cantFail(std::move(ReadyError));
1179       return std::move(ResolutionError);
1180     }
1181   }
1182 
1183   if (WaitUntilReady) {
1184     auto ReadyFuture = PromisedReady.get_future();
1185     ReadyFuture.get();
1186 
1187     {
1188       std::lock_guard<std::mutex> Lock(ErrMutex);
1189       if (ReadyError)
1190         return std::move(ReadyError);
1191     }
1192   } else
1193     cantFail(std::move(ReadyError));
1194 
1195   return std::move(Result);
1196 
1197 #else
1198   if (ResolutionError) {
1199     // ReadyError will never be assigned. Consume the success value.
1200     cantFail(std::move(ReadyError));
1201     return std::move(ResolutionError);
1202   }
1203 
1204   if (ReadyError)
1205     return std::move(ReadyError);
1206 
1207   return Result;
1208 #endif
1209 }
1210 
1211 Expected<SymbolMap> lookup(const VSOList &VSOs, SymbolNameSet Names) {
1212 
1213   if (VSOs.empty())
1214     return SymbolMap();
1215 
1216   auto &ES = (*VSOs.begin())->getExecutionSession();
1217 
1218   auto LookupFn = [&](std::shared_ptr<AsynchronousSymbolQuery> Q,
1219                       SymbolNameSet Unresolved) {
1220     for (auto *V : VSOs) {
1221       assert(V && "VSOs entries must not be null");
1222       if (Unresolved.empty())
1223         break;
1224       Unresolved = V->lookup(Q, std::move(Unresolved));
1225     }
1226     return Unresolved;
1227   };
1228 
1229   return blockingLookup(ES, std::move(LookupFn), Names, true);
1230 }
1231 
1232 /// Look up a symbol by searching a list of VSOs.
1233 Expected<JITEvaluatedSymbol> lookup(const VSOList &VSOs, SymbolStringPtr Name) {
1234   SymbolNameSet Names({Name});
1235   if (auto ResultMap = lookup(VSOs, std::move(Names))) {
1236     assert(ResultMap->size() == 1 && "Unexpected number of results");
1237     assert(ResultMap->count(Name) && "Missing result for symbol");
1238     return std::move(ResultMap->begin()->second);
1239   } else
1240     return ResultMap.takeError();
1241 }
1242 
1243 MangleAndInterner::MangleAndInterner(ExecutionSessionBase &ES,
1244                                      const DataLayout &DL)
1245     : ES(ES), DL(DL) {}
1246 
1247 SymbolStringPtr MangleAndInterner::operator()(StringRef Name) {
1248   std::string MangledName;
1249   {
1250     raw_string_ostream MangledNameStream(MangledName);
1251     Mangler::getNameWithPrefix(MangledNameStream, Name, DL);
1252   }
1253   return ES.getSymbolStringPool().intern(MangledName);
1254 }
1255 
1256 } // End namespace orc.
1257 } // End namespace llvm.
1258