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