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