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