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 << " }";
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 WeakFlags = JITSymbolFlags::Weak | JITSymbolFlags::Common;
382  auto I = SymbolFlags.find(KV.first);
383  assert(I != SymbolFlags.end() &&
384  "Resolving symbol outside this responsibility set");
385  assert((KV.second.getFlags() & ~WeakFlags) == (I->second & ~WeakFlags) &&
386  "Resolving symbol with incorrect flags");
387  }
388 #endif
389 
390  return JD.resolve(Symbols);
391 }
392 
394 
395  LLVM_DEBUG({
396  dbgs() << "In " << JD.getName() << " emitting " << SymbolFlags << "\n";
397  });
398 
399  if (auto Err = JD.emit(SymbolFlags))
400  return Err;
401 
402  SymbolFlags.clear();
403  return Error::success();
404 }
405 
407  const SymbolFlagsMap &NewSymbolFlags) {
408  // Add the given symbols to this responsibility object.
409  // It's ok if we hit a duplicate here: In that case the new version will be
410  // discarded, and the JITDylib::defineMaterializing method will return a
411  // duplicate symbol error.
412  for (auto &KV : NewSymbolFlags)
413  SymbolFlags.insert(KV);
414 
415  return JD.defineMaterializing(NewSymbolFlags);
416 }
417 
419 
420  LLVM_DEBUG({
421  dbgs() << "In " << JD.getName() << " failing materialization for "
422  << SymbolFlags << "\n";
423  });
424 
425  JITDylib::FailedSymbolsWorklist Worklist;
426 
427  for (auto &KV : SymbolFlags)
428  Worklist.push_back(std::make_pair(&JD, KV.first));
429  SymbolFlags.clear();
430 
431  JD.notifyFailed(std::move(Worklist));
432 }
433 
435  std::unique_ptr<MaterializationUnit> MU) {
436  for (auto &KV : MU->getSymbols())
437  SymbolFlags.erase(KV.first);
438 
440  dbgs() << "In " << JD.getName() << " replacing symbols with " << *MU
441  << "\n";
442  }););
443 
444  JD.replace(std::move(MU));
445 }
446 
449  VModuleKey NewKey) {
450 
451  if (NewKey == VModuleKey())
452  NewKey = K;
453 
454  SymbolFlagsMap DelegatedFlags;
455 
456  for (auto &Name : Symbols) {
457  auto I = SymbolFlags.find(Name);
458  assert(I != SymbolFlags.end() &&
459  "Symbol is not tracked by this MaterializationResponsibility "
460  "instance");
461 
462  DelegatedFlags[Name] = std::move(I->second);
463  SymbolFlags.erase(I);
464  }
465 
466  return MaterializationResponsibility(JD, std::move(DelegatedFlags),
467  std::move(NewKey));
468 }
469 
471  const SymbolStringPtr &Name, const SymbolDependenceMap &Dependencies) {
472  assert(SymbolFlags.count(Name) &&
473  "Symbol not covered by this MaterializationResponsibility instance");
474  JD.addDependencies(Name, Dependencies);
475 }
476 
478  const SymbolDependenceMap &Dependencies) {
479  for (auto &KV : SymbolFlags)
480  JD.addDependencies(KV.first, Dependencies);
481 }
482 
484  SymbolMap Symbols, VModuleKey K)
485  : MaterializationUnit(extractFlags(Symbols), std::move(K)),
486  Symbols(std::move(Symbols)) {}
487 
489  return "<Absolute Symbols>";
490 }
491 
492 void AbsoluteSymbolsMaterializationUnit::materialize(
494  // No dependencies, so these calls can't fail.
495  cantFail(R.notifyResolved(Symbols));
496  cantFail(R.notifyEmitted());
497 }
498 
499 void AbsoluteSymbolsMaterializationUnit::discard(const JITDylib &JD,
500  const SymbolStringPtr &Name) {
501  assert(Symbols.count(Name) && "Symbol is not part of this MU");
502  Symbols.erase(Name);
503 }
504 
506 AbsoluteSymbolsMaterializationUnit::extractFlags(const SymbolMap &Symbols) {
507  SymbolFlagsMap Flags;
508  for (const auto &KV : Symbols)
509  Flags[KV.first] = KV.second.getFlags();
510  return Flags;
511 }
512 
514  JITDylib *SourceJD, bool MatchNonExported, SymbolAliasMap Aliases,
515  VModuleKey K)
516  : MaterializationUnit(extractFlags(Aliases), std::move(K)),
517  SourceJD(SourceJD), MatchNonExported(MatchNonExported),
518  Aliases(std::move(Aliases)) {}
519 
521  return "<Reexports>";
522 }
523 
524 void ReExportsMaterializationUnit::materialize(
526 
527  auto &ES = R.getTargetJITDylib().getExecutionSession();
528  JITDylib &TgtJD = R.getTargetJITDylib();
529  JITDylib &SrcJD = SourceJD ? *SourceJD : TgtJD;
530 
531  // Find the set of requested aliases and aliasees. Return any unrequested
532  // aliases back to the JITDylib so as to not prematurely materialize any
533  // aliasees.
534  auto RequestedSymbols = R.getRequestedSymbols();
535  SymbolAliasMap RequestedAliases;
536 
537  for (auto &Name : RequestedSymbols) {
538  auto I = Aliases.find(Name);
539  assert(I != Aliases.end() && "Symbol not found in aliases map?");
540  RequestedAliases[Name] = std::move(I->second);
541  Aliases.erase(I);
542  }
543 
544  LLVM_DEBUG({
545  ES.runSessionLocked([&]() {
546  dbgs() << "materializing reexports: target = " << TgtJD.getName()
547  << ", source = " << SrcJD.getName() << " " << RequestedAliases
548  << "\n";
549  });
550  });
551 
552  if (!Aliases.empty()) {
553  if (SourceJD)
554  R.replace(reexports(*SourceJD, std::move(Aliases), MatchNonExported));
555  else
556  R.replace(symbolAliases(std::move(Aliases)));
557  }
558 
559  // The OnResolveInfo struct will hold the aliases and responsibilty for each
560  // query in the list.
561  struct OnResolveInfo {
562  OnResolveInfo(MaterializationResponsibility R, SymbolAliasMap Aliases)
563  : R(std::move(R)), Aliases(std::move(Aliases)) {}
564 
566  SymbolAliasMap Aliases;
567  };
568 
569  // Build a list of queries to issue. In each round we build the largest set of
570  // aliases that we can resolve without encountering a chain definition of the
571  // form Foo -> Bar, Bar -> Baz. Such a form would deadlock as the query would
572  // be waitin on a symbol that it itself had to resolve. Usually this will just
573  // involve one round and a single query.
574 
575  std::vector<std::pair<SymbolNameSet, std::shared_ptr<OnResolveInfo>>>
576  QueryInfos;
577  while (!RequestedAliases.empty()) {
578  SymbolNameSet ResponsibilitySymbols;
579  SymbolNameSet QuerySymbols;
580  SymbolAliasMap QueryAliases;
581 
582  // Collect as many aliases as we can without including a chain.
583  for (auto &KV : RequestedAliases) {
584  // Chain detected. Skip this symbol for this round.
585  if (&SrcJD == &TgtJD && (QueryAliases.count(KV.second.Aliasee) ||
586  RequestedAliases.count(KV.second.Aliasee)))
587  continue;
588 
589  ResponsibilitySymbols.insert(KV.first);
590  QuerySymbols.insert(KV.second.Aliasee);
591  QueryAliases[KV.first] = std::move(KV.second);
592  }
593 
594  // Remove the aliases collected this round from the RequestedAliases map.
595  for (auto &KV : QueryAliases)
596  RequestedAliases.erase(KV.first);
597 
598  assert(!QuerySymbols.empty() && "Alias cycle detected!");
599 
600  auto QueryInfo = std::make_shared<OnResolveInfo>(
601  R.delegate(ResponsibilitySymbols), std::move(QueryAliases));
602  QueryInfos.push_back(
603  make_pair(std::move(QuerySymbols), std::move(QueryInfo)));
604  }
605 
606  // Issue the queries.
607  while (!QueryInfos.empty()) {
608  auto QuerySymbols = std::move(QueryInfos.back().first);
609  auto QueryInfo = std::move(QueryInfos.back().second);
610 
611  QueryInfos.pop_back();
612 
613  auto RegisterDependencies = [QueryInfo,
614  &SrcJD](const SymbolDependenceMap &Deps) {
615  // If there were no materializing symbols, just bail out.
616  if (Deps.empty())
617  return;
618 
619  // Otherwise the only deps should be on SrcJD.
620  assert(Deps.size() == 1 && Deps.count(&SrcJD) &&
621  "Unexpected dependencies for reexports");
622 
623  auto &SrcJDDeps = Deps.find(&SrcJD)->second;
624  SymbolDependenceMap PerAliasDepsMap;
625  auto &PerAliasDeps = PerAliasDepsMap[&SrcJD];
626 
627  for (auto &KV : QueryInfo->Aliases)
628  if (SrcJDDeps.count(KV.second.Aliasee)) {
629  PerAliasDeps = {KV.second.Aliasee};
630  QueryInfo->R.addDependencies(KV.first, PerAliasDepsMap);
631  }
632  };
633 
634  auto OnComplete = [QueryInfo](Expected<SymbolMap> Result) {
635  auto &ES = QueryInfo->R.getTargetJITDylib().getExecutionSession();
636  if (Result) {
637  SymbolMap ResolutionMap;
638  for (auto &KV : QueryInfo->Aliases) {
639  assert(Result->count(KV.second.Aliasee) &&
640  "Result map missing entry?");
641  ResolutionMap[KV.first] = JITEvaluatedSymbol(
642  (*Result)[KV.second.Aliasee].getAddress(), KV.second.AliasFlags);
643  }
644  if (auto Err = QueryInfo->R.notifyResolved(ResolutionMap)) {
645  ES.reportError(std::move(Err));
646  QueryInfo->R.failMaterialization();
647  return;
648  }
649  if (auto Err = QueryInfo->R.notifyEmitted()) {
650  ES.reportError(std::move(Err));
651  QueryInfo->R.failMaterialization();
652  return;
653  }
654  } else {
655  ES.reportError(Result.takeError());
656  QueryInfo->R.failMaterialization();
657  }
658  };
659 
660  ES.lookup(JITDylibSearchList({{&SrcJD, MatchNonExported}}), QuerySymbols,
661  SymbolState::Resolved, std::move(OnComplete),
662  std::move(RegisterDependencies));
663  }
664 }
665 
666 void ReExportsMaterializationUnit::discard(const JITDylib &JD,
667  const SymbolStringPtr &Name) {
668  assert(Aliases.count(Name) &&
669  "Symbol not covered by this MaterializationUnit");
670  Aliases.erase(Name);
671 }
672 
674 ReExportsMaterializationUnit::extractFlags(const SymbolAliasMap &Aliases) {
676  for (auto &KV : Aliases)
677  SymbolFlags[KV.first] = KV.second.AliasFlags;
678 
679  return SymbolFlags;
680 }
681 
684  auto Flags = SourceJD.lookupFlags(Symbols);
685 
686  if (!Flags)
687  return Flags.takeError();
688 
689  if (Flags->size() != Symbols.size()) {
690  SymbolNameSet Unresolved = Symbols;
691  for (auto &KV : *Flags)
692  Unresolved.erase(KV.first);
693  return make_error<SymbolsNotFound>(std::move(Unresolved));
694  }
695 
696  SymbolAliasMap Result;
697  for (auto &Name : Symbols) {
698  assert(Flags->count(Name) && "Missing entry in flags map");
699  Result[Name] = SymbolAliasMapEntry(Name, (*Flags)[Name]);
700  }
701 
702  return Result;
703 }
704 
706  bool MatchNonExported,
707  SymbolPredicate Allow)
708  : SourceJD(SourceJD), MatchNonExported(MatchNonExported),
709  Allow(std::move(Allow)) {}
710 
713  orc::SymbolNameSet Added;
714  orc::SymbolAliasMap AliasMap;
715 
716  auto Flags = SourceJD.lookupFlags(Names);
717 
718  if (!Flags)
719  return Flags.takeError();
720 
721  for (auto &KV : *Flags) {
722  if (Allow && !Allow(KV.first))
723  continue;
724  AliasMap[KV.first] = SymbolAliasMapEntry(KV.first, KV.second);
725  Added.insert(KV.first);
726  }
727 
728  if (!Added.empty())
729  cantFail(JD.define(reexports(SourceJD, AliasMap, MatchNonExported)));
730 
731  return Added;
732 }
733 
735 
737  ES.runSessionLocked([&]() {
738  auto I = std::find_if(DefGenerators.begin(), DefGenerators.end(),
739  [&](const std::unique_ptr<DefinitionGenerator> &H) {
740  return H.get() == &G;
741  });
742  assert(I != DefGenerators.end() && "Generator not found");
743  DefGenerators.erase(I);
744  });
745 }
746 
747 Error JITDylib::defineMaterializing(const SymbolFlagsMap &SymbolFlags) {
748  return ES.runSessionLocked([&]() -> Error {
749  std::vector<SymbolTable::iterator> AddedSyms;
750 
751  for (auto &KV : SymbolFlags) {
752  SymbolTable::iterator EntryItr;
753  bool Added;
754 
755  std::tie(EntryItr, Added) =
756  Symbols.insert(std::make_pair(KV.first, SymbolTableEntry(KV.second)));
757 
758  if (Added) {
759  AddedSyms.push_back(EntryItr);
760  EntryItr->second.setState(SymbolState::Materializing);
761  } else {
762  // Remove any symbols already added.
763  for (auto &SI : AddedSyms)
764  Symbols.erase(SI);
765 
766  // FIXME: Return all duplicates.
767  return make_error<DuplicateDefinition>(*KV.first);
768  }
769  }
770 
771  return Error::success();
772  });
773 }
774 
775 void JITDylib::replace(std::unique_ptr<MaterializationUnit> MU) {
776  assert(MU != nullptr && "Can not replace with a null MaterializationUnit");
777 
778  auto MustRunMU =
779  ES.runSessionLocked([&, this]() -> std::unique_ptr<MaterializationUnit> {
780 
781 #ifndef NDEBUG
782  for (auto &KV : MU->getSymbols()) {
783  auto SymI = Symbols.find(KV.first);
784  assert(SymI != Symbols.end() && "Replacing unknown symbol");
785  assert(SymI->second.isInMaterializationPhase() &&
786  "Can not call replace on a symbol that is not materializing");
787  assert(!SymI->second.hasMaterializerAttached() &&
788  "Symbol should not have materializer attached already");
789  assert(UnmaterializedInfos.count(KV.first) == 0 &&
790  "Symbol being replaced should have no UnmaterializedInfo");
791  }
792 #endif // NDEBUG
793 
794  // If any symbol has pending queries against it then we need to
795  // materialize MU immediately.
796  for (auto &KV : MU->getSymbols()) {
797  auto MII = MaterializingInfos.find(KV.first);
798  if (MII != MaterializingInfos.end()) {
799  if (MII->second.hasQueriesPending())
800  return std::move(MU);
801  }
802  }
803 
804  // Otherwise, make MU responsible for all the symbols.
805  auto UMI = std::make_shared<UnmaterializedInfo>(std::move(MU));
806  for (auto &KV : UMI->MU->getSymbols()) {
807  auto SymI = Symbols.find(KV.first);
808  assert(SymI->second.getState() == SymbolState::Materializing &&
809  "Can not replace a symbol that is not materializing");
810  assert(!SymI->second.hasMaterializerAttached() &&
811  "Can not replace a symbol that has a materializer attached");
812  assert(UnmaterializedInfos.count(KV.first) == 0 &&
813  "Unexpected materializer entry in map");
814  SymI->second.setAddress(SymI->second.getAddress());
815  SymI->second.setMaterializerAttached(true);
816  UnmaterializedInfos[KV.first] = UMI;
817  }
818 
819  return nullptr;
820  });
821 
822  if (MustRunMU)
823  ES.dispatchMaterialization(*this, std::move(MustRunMU));
824 }
825 
827 JITDylib::getRequestedSymbols(const SymbolFlagsMap &SymbolFlags) const {
828  return ES.runSessionLocked([&]() {
829  SymbolNameSet RequestedSymbols;
830 
831  for (auto &KV : SymbolFlags) {
832  assert(Symbols.count(KV.first) && "JITDylib does not cover this symbol?");
833  assert(Symbols.find(KV.first)->second.isInMaterializationPhase() &&
834  "getRequestedSymbols can only be called for symbols that have "
835  "started materializing");
836  auto I = MaterializingInfos.find(KV.first);
837  if (I == MaterializingInfos.end())
838  continue;
839 
840  if (I->second.hasQueriesPending())
841  RequestedSymbols.insert(KV.first);
842  }
843 
844  return RequestedSymbols;
845  });
846 }
847 
848 void JITDylib::addDependencies(const SymbolStringPtr &Name,
849  const SymbolDependenceMap &Dependencies) {
850  assert(Symbols.count(Name) && "Name not in symbol table");
851  assert(Symbols[Name].isInMaterializationPhase() &&
852  "Can not add dependencies for a symbol that is not materializing");
853 
854  // If Name is already in an error state then just bail out.
855  if (Symbols[Name].getFlags().hasError())
856  return;
857 
858  auto &MI = MaterializingInfos[Name];
859  assert(Symbols[Name].getState() != SymbolState::Emitted &&
860  "Can not add dependencies to an emitted symbol");
861 
862  bool DependsOnSymbolInErrorState = false;
863 
864  // Register dependencies, record whether any depenendency is in the error
865  // state.
866  for (auto &KV : Dependencies) {
867  assert(KV.first && "Null JITDylib in dependency?");
868  auto &OtherJITDylib = *KV.first;
869  auto &DepsOnOtherJITDylib = MI.UnemittedDependencies[&OtherJITDylib];
870 
871  for (auto &OtherSymbol : KV.second) {
872 
873  // Check the sym entry for the dependency.
874  auto OtherSymI = OtherJITDylib.Symbols.find(OtherSymbol);
875 
876 #ifndef NDEBUG
877  // Assert that this symbol exists and has not reached the ready state
878  // already.
879  assert(OtherSymI != OtherJITDylib.Symbols.end() &&
880  (OtherSymI->second.getState() != SymbolState::Ready &&
881  "Dependency on emitted/ready symbol"));
882 #endif
883 
884  auto &OtherSymEntry = OtherSymI->second;
885 
886  // If the dependency is in an error state then note this and continue,
887  // we will move this symbol to the error state below.
888  if (OtherSymEntry.getFlags().hasError()) {
889  DependsOnSymbolInErrorState = true;
890  continue;
891  }
892 
893  // If the dependency was not in the error state then add it to
894  // our list of dependencies.
895  assert(OtherJITDylib.MaterializingInfos.count(OtherSymbol) &&
896  "No MaterializingInfo for dependency");
897  auto &OtherMI = OtherJITDylib.MaterializingInfos[OtherSymbol];
898 
899  if (OtherSymEntry.getState() == SymbolState::Emitted)
900  transferEmittedNodeDependencies(MI, Name, OtherMI);
901  else if (&OtherJITDylib != this || OtherSymbol != Name) {
902  OtherMI.Dependants[this].insert(Name);
903  DepsOnOtherJITDylib.insert(OtherSymbol);
904  }
905  }
906 
907  if (DepsOnOtherJITDylib.empty())
908  MI.UnemittedDependencies.erase(&OtherJITDylib);
909  }
910 
911  // If this symbol dependended on any symbols in the error state then move
912  // this symbol to the error state too.
913  if (DependsOnSymbolInErrorState)
914  Symbols[Name].setFlags(Symbols[Name].getFlags() | JITSymbolFlags::HasError);
915 }
916 
917 Error JITDylib::resolve(const SymbolMap &Resolved) {
918  SymbolNameSet SymbolsInErrorState;
919  AsynchronousSymbolQuerySet CompletedQueries;
920 
921  ES.runSessionLocked([&, this]() {
922  struct WorklistEntry {
924  JITEvaluatedSymbol ResolvedSym;
925  };
926 
927  std::vector<WorklistEntry> Worklist;
928  Worklist.reserve(Resolved.size());
929 
930  // Build worklist and check for any symbols in the error state.
931  for (const auto &KV : Resolved) {
932 
933  assert(!KV.second.getFlags().hasError() &&
934  "Resolution result can not have error flag set");
935 
936  auto SymI = Symbols.find(KV.first);
937 
938  assert(SymI != Symbols.end() && "Symbol not found");
939  assert(!SymI->second.hasMaterializerAttached() &&
940  "Resolving symbol with materializer attached?");
941  assert(SymI->second.getState() == SymbolState::Materializing &&
942  "Symbol should be materializing");
943  assert(SymI->second.getAddress() == 0 &&
944  "Symbol has already been resolved");
945 
946  if (SymI->second.getFlags().hasError())
947  SymbolsInErrorState.insert(KV.first);
948  else {
949  auto Flags = KV.second.getFlags();
951  assert(Flags == (SymI->second.getFlags() &
953  "Resolved flags should match the declared flags");
954 
955  Worklist.push_back(
956  {SymI, JITEvaluatedSymbol(KV.second.getAddress(), Flags)});
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  SymI->second.setAddress(ResolvedSym.getAddress());
974  SymI->second.setFlags(ResolvedFlags);
975  SymI->second.setState(SymbolState::Resolved);
976 
977  auto &MI = MaterializingInfos[Name];
978  for (auto &Q : MI.takeQueriesMeeting(SymbolState::Resolved)) {
979  Q->notifySymbolMetRequiredState(Name, ResolvedSym);
980  Q->removeQueryDependence(*this, Name);
981  if (Q->isComplete())
982  CompletedQueries.insert(std::move(Q));
983  }
984  }
985  });
986 
987  assert((SymbolsInErrorState.empty() || CompletedQueries.empty()) &&
988  "Can't fail symbols and completed queries at the same time");
989 
990  // If we failed any symbols then return an error.
991  if (!SymbolsInErrorState.empty()) {
992  auto FailedSymbolsDepMap = std::make_shared<SymbolDependenceMap>();
993  (*FailedSymbolsDepMap)[this] = std::move(SymbolsInErrorState);
994  return make_error<FailedToMaterialize>(std::move(FailedSymbolsDepMap));
995  }
996 
997  // Otherwise notify all the completed queries.
998  for (auto &Q : CompletedQueries) {
999  assert(Q->isComplete() && "Q not completed");
1000  Q->handleComplete();
1001  }
1002 
1003  return Error::success();
1004 }
1005 
1006 Error JITDylib::emit(const SymbolFlagsMap &Emitted) {
1007  AsynchronousSymbolQuerySet CompletedQueries;
1008  SymbolNameSet SymbolsInErrorState;
1009 
1010  ES.runSessionLocked([&, this]() {
1011  std::vector<SymbolTable::iterator> Worklist;
1012 
1013  // Scan to build worklist, record any symbols in the erorr state.
1014  for (const auto &KV : Emitted) {
1015  auto &Name = KV.first;
1016 
1017  auto SymI = Symbols.find(Name);
1018  assert(SymI != Symbols.end() && "No symbol table entry for Name");
1019 
1020  if (SymI->second.getFlags().hasError())
1021  SymbolsInErrorState.insert(Name);
1022  else
1023  Worklist.push_back(SymI);
1024  }
1025 
1026  // If any symbols were in the error state then bail out.
1027  if (!SymbolsInErrorState.empty())
1028  return;
1029 
1030  // Otherwise update dependencies and move to the emitted state.
1031  while (!Worklist.empty()) {
1032  auto SymI = Worklist.back();
1033  Worklist.pop_back();
1034 
1035  auto &Name = SymI->first;
1036  auto &SymEntry = SymI->second;
1037 
1038  // Move symbol to the emitted state.
1039  assert(SymEntry.getState() == SymbolState::Resolved &&
1040  "Emitting from state other than Resolved");
1041  SymEntry.setState(SymbolState::Emitted);
1042 
1043  auto MII = MaterializingInfos.find(Name);
1044  assert(MII != MaterializingInfos.end() &&
1045  "Missing MaterializingInfo entry");
1046  auto &MI = MII->second;
1047 
1048  // For each dependant, transfer this node's emitted dependencies to
1049  // it. If the dependant node is ready (i.e. has no unemitted
1050  // dependencies) then notify any pending queries.
1051  for (auto &KV : MI.Dependants) {
1052  auto &DependantJD = *KV.first;
1053  for (auto &DependantName : KV.second) {
1054  auto DependantMII =
1055  DependantJD.MaterializingInfos.find(DependantName);
1056  assert(DependantMII != DependantJD.MaterializingInfos.end() &&
1057  "Dependant should have MaterializingInfo");
1058 
1059  auto &DependantMI = DependantMII->second;
1060 
1061  // Remove the dependant's dependency on this node.
1062  assert(DependantMI.UnemittedDependencies.count(this) &&
1063  "Dependant does not have an unemitted dependencies record for "
1064  "this JITDylib");
1065  assert(DependantMI.UnemittedDependencies[this].count(Name) &&
1066  "Dependant does not count this symbol as a dependency?");
1067 
1068  DependantMI.UnemittedDependencies[this].erase(Name);
1069  if (DependantMI.UnemittedDependencies[this].empty())
1070  DependantMI.UnemittedDependencies.erase(this);
1071 
1072  // Transfer unemitted dependencies from this node to the dependant.
1073  DependantJD.transferEmittedNodeDependencies(DependantMI,
1074  DependantName, MI);
1075 
1076  auto DependantSymI = DependantJD.Symbols.find(DependantName);
1077  assert(DependantSymI != DependantJD.Symbols.end() &&
1078  "Dependant has no entry in the Symbols table");
1079  auto &DependantSymEntry = DependantSymI->second;
1080 
1081  // If the dependant is emitted and this node was the last of its
1082  // unemitted dependencies then the dependant node is now ready, so
1083  // notify any pending queries on the dependant node.
1084  if (DependantSymEntry.getState() == SymbolState::Emitted &&
1085  DependantMI.UnemittedDependencies.empty()) {
1086  assert(DependantMI.Dependants.empty() &&
1087  "Dependants should be empty by now");
1088 
1089  // Since this dependant is now ready, we erase its MaterializingInfo
1090  // and update its materializing state.
1091  DependantSymEntry.setState(SymbolState::Ready);
1092 
1093  for (auto &Q : DependantMI.takeQueriesMeeting(SymbolState::Ready)) {
1094  Q->notifySymbolMetRequiredState(
1095  DependantName, DependantSymI->second.getSymbol());
1096  if (Q->isComplete())
1097  CompletedQueries.insert(Q);
1098  Q->removeQueryDependence(DependantJD, DependantName);
1099  }
1100 
1101  DependantJD.MaterializingInfos.erase(DependantMII);
1102  }
1103  }
1104  }
1105 
1106  MI.Dependants.clear();
1107  if (MI.UnemittedDependencies.empty()) {
1108  SymI->second.setState(SymbolState::Ready);
1109  for (auto &Q : MI.takeQueriesMeeting(SymbolState::Ready)) {
1110  Q->notifySymbolMetRequiredState(Name, SymI->second.getSymbol());
1111  if (Q->isComplete())
1112  CompletedQueries.insert(Q);
1113  Q->removeQueryDependence(*this, Name);
1114  }
1115  MaterializingInfos.erase(MII);
1116  }
1117  }
1118  });
1119 
1120  assert((SymbolsInErrorState.empty() || CompletedQueries.empty()) &&
1121  "Can't fail symbols and completed queries at the same time");
1122 
1123  // If we failed any symbols then return an error.
1124  if (!SymbolsInErrorState.empty()) {
1125  auto FailedSymbolsDepMap = std::make_shared<SymbolDependenceMap>();
1126  (*FailedSymbolsDepMap)[this] = std::move(SymbolsInErrorState);
1127  return make_error<FailedToMaterialize>(std::move(FailedSymbolsDepMap));
1128  }
1129 
1130  // Otherwise notify all the completed queries.
1131  for (auto &Q : CompletedQueries) {
1132  assert(Q->isComplete() && "Q is not complete");
1133  Q->handleComplete();
1134  }
1135 
1136  return Error::success();
1137 }
1138 
1139 void JITDylib::notifyFailed(FailedSymbolsWorklist Worklist) {
1140  AsynchronousSymbolQuerySet FailedQueries;
1141  auto FailedSymbolsMap = std::make_shared<SymbolDependenceMap>();
1142 
1143  // Failing no symbols is a no-op.
1144  if (Worklist.empty())
1145  return;
1146 
1147  auto &ES = Worklist.front().first->getExecutionSession();
1148 
1149  ES.runSessionLocked([&]() {
1150  while (!Worklist.empty()) {
1151  assert(Worklist.back().first && "Failed JITDylib can not be null");
1152  auto &JD = *Worklist.back().first;
1153  auto Name = std::move(Worklist.back().second);
1154  Worklist.pop_back();
1155 
1156  (*FailedSymbolsMap)[&JD].insert(Name);
1157 
1158  assert(JD.Symbols.count(Name) && "No symbol table entry for Name");
1159  auto &Sym = JD.Symbols[Name];
1160 
1161  // Move the symbol into the error state.
1162  // Note that this may be redundant: The symbol might already have been
1163  // moved to this state in response to the failure of a dependence.
1164  Sym.setFlags(Sym.getFlags() | JITSymbolFlags::HasError);
1165 
1166  // FIXME: Come up with a sane mapping of state to
1167  // presence-of-MaterializingInfo so that we can assert presence / absence
1168  // here, rather than testing it.
1169  auto MII = JD.MaterializingInfos.find(Name);
1170 
1171  if (MII == JD.MaterializingInfos.end())
1172  continue;
1173 
1174  auto &MI = MII->second;
1175 
1176  // Move all dependants to the error state and disconnect from them.
1177  for (auto &KV : MI.Dependants) {
1178  auto &DependantJD = *KV.first;
1179  for (auto &DependantName : KV.second) {
1180  assert(DependantJD.Symbols.count(DependantName) &&
1181  "No symbol table entry for DependantName");
1182  auto &DependantSym = DependantJD.Symbols[DependantName];
1183  DependantSym.setFlags(DependantSym.getFlags() |
1185 
1186  assert(DependantJD.MaterializingInfos.count(DependantName) &&
1187  "No MaterializingInfo for dependant");
1188  auto &DependantMI = DependantJD.MaterializingInfos[DependantName];
1189 
1190  auto UnemittedDepI = DependantMI.UnemittedDependencies.find(&JD);
1191  assert(UnemittedDepI != DependantMI.UnemittedDependencies.end() &&
1192  "No UnemittedDependencies entry for this JITDylib");
1193  assert(UnemittedDepI->second.count(Name) &&
1194  "No UnemittedDependencies entry for this symbol");
1195  UnemittedDepI->second.erase(Name);
1196  if (UnemittedDepI->second.empty())
1197  DependantMI.UnemittedDependencies.erase(UnemittedDepI);
1198 
1199  // If this symbol is already in the emitted state then we need to
1200  // take responsibility for failing its queries, so add it to the
1201  // worklist.
1202  if (DependantSym.getState() == SymbolState::Emitted) {
1203  assert(DependantMI.Dependants.empty() &&
1204  "Emitted symbol should not have dependants");
1205  Worklist.push_back(std::make_pair(&DependantJD, DependantName));
1206  }
1207  }
1208  }
1209  MI.Dependants.clear();
1210 
1211  // Disconnect from all unemitted depenencies.
1212  for (auto &KV : MI.UnemittedDependencies) {
1213  auto &UnemittedDepJD = *KV.first;
1214  for (auto &UnemittedDepName : KV.second) {
1215  auto UnemittedDepMII =
1216  UnemittedDepJD.MaterializingInfos.find(UnemittedDepName);
1217  assert(UnemittedDepMII != UnemittedDepJD.MaterializingInfos.end() &&
1218  "Missing MII for unemitted dependency");
1219  assert(UnemittedDepMII->second.Dependants.count(&JD) &&
1220  "JD not listed as a dependant of unemitted dependency");
1221  assert(UnemittedDepMII->second.Dependants[&JD].count(Name) &&
1222  "Name is not listed as a dependant of unemitted dependency");
1223  UnemittedDepMII->second.Dependants[&JD].erase(Name);
1224  if (UnemittedDepMII->second.Dependants[&JD].empty())
1225  UnemittedDepMII->second.Dependants.erase(&JD);
1226  }
1227  }
1228  MI.UnemittedDependencies.clear();
1229 
1230  // Collect queries to be failed for this MII.
1231  for (auto &Q : MII->second.pendingQueries()) {
1232  // Add the query to the list to be failed and detach it.
1233  FailedQueries.insert(Q);
1234  Q->detach();
1235  }
1236 
1237  assert(MI.Dependants.empty() &&
1238  "Can not delete MaterializingInfo with dependants still attached");
1239  assert(MI.UnemittedDependencies.empty() &&
1240  "Can not delete MaterializingInfo with unemitted dependencies "
1241  "still attached");
1242  assert(!MI.hasQueriesPending() &&
1243  "Can not delete MaterializingInfo with queries pending");
1244  JD.MaterializingInfos.erase(MII);
1245  }
1246  });
1247 
1248  for (auto &Q : FailedQueries)
1249  Q->handleFailed(make_error<FailedToMaterialize>(FailedSymbolsMap));
1250 }
1251 
1253  bool SearchThisJITDylibFirst,
1254  bool MatchNonExportedInThisDylib) {
1255  if (SearchThisJITDylibFirst) {
1256  if (NewSearchOrder.empty() || NewSearchOrder.front().first != this)
1257  NewSearchOrder.insert(NewSearchOrder.begin(),
1258  {this, MatchNonExportedInThisDylib});
1259  }
1260 
1261  ES.runSessionLocked([&]() { SearchOrder = std::move(NewSearchOrder); });
1262 }
1263 
1264 void JITDylib::addToSearchOrder(JITDylib &JD, bool MatchNonExported) {
1265  ES.runSessionLocked([&]() {
1266  SearchOrder.push_back({&JD, MatchNonExported});
1267  });
1268 }
1269 
1271  bool MatchNonExported) {
1272  ES.runSessionLocked([&]() {
1273  auto I = std::find_if(SearchOrder.begin(), SearchOrder.end(),
1274  [&](const JITDylibSearchList::value_type &KV) {
1275  return KV.first == &OldJD;
1276  });
1277 
1278  if (I != SearchOrder.end())
1279  *I = {&NewJD, MatchNonExported};
1280  });
1281 }
1282 
1284  ES.runSessionLocked([&]() {
1285  auto I = std::find_if(SearchOrder.begin(), SearchOrder.end(),
1286  [&](const JITDylibSearchList::value_type &KV) {
1287  return KV.first == &JD;
1288  });
1289  if (I != SearchOrder.end())
1290  SearchOrder.erase(I);
1291  });
1292 }
1293 
1295  return ES.runSessionLocked([&]() -> Error {
1296  using SymbolMaterializerItrPair =
1297  std::pair<SymbolTable::iterator, UnmaterializedInfosMap::iterator>;
1298  std::vector<SymbolMaterializerItrPair> SymbolsToRemove;
1299  SymbolNameSet Missing;
1301 
1302  for (auto &Name : Names) {
1303  auto I = Symbols.find(Name);
1304 
1305  // Note symbol missing.
1306  if (I == Symbols.end()) {
1307  Missing.insert(Name);
1308  continue;
1309  }
1310 
1311  // Note symbol materializing.
1312  if (I->second.isInMaterializationPhase()) {
1313  Materializing.insert(Name);
1314  continue;
1315  }
1316 
1317  auto UMII = I->second.hasMaterializerAttached()
1318  ? UnmaterializedInfos.find(Name)
1319  : UnmaterializedInfos.end();
1320  SymbolsToRemove.push_back(std::make_pair(I, UMII));
1321  }
1322 
1323  // If any of the symbols are not defined, return an error.
1324  if (!Missing.empty())
1325  return make_error<SymbolsNotFound>(std::move(Missing));
1326 
1327  // If any of the symbols are currently materializing, return an error.
1328  if (!Materializing.empty())
1329  return make_error<SymbolsCouldNotBeRemoved>(std::move(Materializing));
1330 
1331  // Remove the symbols.
1332  for (auto &SymbolMaterializerItrPair : SymbolsToRemove) {
1333  auto UMII = SymbolMaterializerItrPair.second;
1334 
1335  // If there is a materializer attached, call discard.
1336  if (UMII != UnmaterializedInfos.end()) {
1337  UMII->second->MU->doDiscard(*this, UMII->first);
1338  UnmaterializedInfos.erase(UMII);
1339  }
1340 
1341  auto SymI = SymbolMaterializerItrPair.first;
1342  Symbols.erase(SymI);
1343  }
1344 
1345  return Error::success();
1346  });
1347 }
1348 
1350  return ES.runSessionLocked([&, this]() -> Expected<SymbolFlagsMap> {
1351  SymbolFlagsMap Result;
1352  auto Unresolved = lookupFlagsImpl(Result, Names);
1353  if (!Unresolved)
1354  return Unresolved.takeError();
1355 
1356  /// Run any definition generators.
1357  for (auto &DG : DefGenerators) {
1358 
1359  // Bail out early if we've resolved everything.
1360  if (Unresolved->empty())
1361  break;
1362 
1363  // Run this generator.
1364  auto NewDefs = DG->tryToGenerate(*this, *Unresolved);
1365  if (!NewDefs)
1366  return NewDefs.takeError();
1367 
1368  if (!NewDefs->empty()) {
1369  auto Unresolved2 = lookupFlagsImpl(Result, *NewDefs);
1370  if (!Unresolved2)
1371  return Unresolved2.takeError();
1372  (void)Unresolved2;
1373  assert(Unresolved2->empty() &&
1374  "All fallback defs should have been found by lookupFlagsImpl");
1375  }
1376 
1377  for (auto &Name : *NewDefs)
1378  Unresolved->erase(Name);
1379  }
1380  return Result;
1381  });
1382 }
1383 
1384 Expected<SymbolNameSet> JITDylib::lookupFlagsImpl(SymbolFlagsMap &Flags,
1385  const SymbolNameSet &Names) {
1386  SymbolNameSet Unresolved;
1387 
1388  for (auto &Name : Names) {
1389  auto I = Symbols.find(Name);
1390  if (I != Symbols.end()) {
1391  assert(!Flags.count(Name) && "Symbol already present in Flags map");
1392  Flags[Name] = I->second.getFlags();
1393  } else
1394  Unresolved.insert(Name);
1395  }
1396 
1397  return Unresolved;
1398 }
1399 
1400 Error JITDylib::lodgeQuery(std::shared_ptr<AsynchronousSymbolQuery> &Q,
1401  SymbolNameSet &Unresolved, bool MatchNonExported,
1402  MaterializationUnitList &MUs) {
1403  assert(Q && "Query can not be null");
1404 
1405  if (auto Err = lodgeQueryImpl(Q, Unresolved, MatchNonExported, MUs))
1406  return Err;
1407 
1408  // Run any definition generators.
1409  for (auto &DG : DefGenerators) {
1410 
1411  // Bail out early if we have resolved everything.
1412  if (Unresolved.empty())
1413  break;
1414 
1415  // Run the generator.
1416  auto NewDefs = DG->tryToGenerate(*this, Unresolved);
1417 
1418  // If the generator returns an error then bail out.
1419  if (!NewDefs)
1420  return NewDefs.takeError();
1421 
1422  // If the generator was able to generate new definitions for any of the
1423  // unresolved symbols then lodge the query against them.
1424  if (!NewDefs->empty()) {
1425  for (auto &D : *NewDefs)
1426  Unresolved.erase(D);
1427 
1428  // Lodge query. This can not fail as any new definitions were added
1429  // by the generator under the session locked. Since they can't have
1430  // started materializing yet the can not have failed.
1431  cantFail(lodgeQueryImpl(Q, *NewDefs, MatchNonExported, MUs));
1432 
1433  assert(NewDefs->empty() &&
1434  "All fallback defs should have been found by lookupImpl");
1435  }
1436  }
1437 
1438  return Error::success();
1439 }
1440 
1441 Error JITDylib::lodgeQueryImpl(
1442  std::shared_ptr<AsynchronousSymbolQuery> &Q, SymbolNameSet &Unresolved,
1443  bool MatchNonExported,
1444  std::vector<std::unique_ptr<MaterializationUnit>> &MUs) {
1445 
1446  std::vector<SymbolStringPtr> ToRemove;
1447  for (auto Name : Unresolved) {
1448 
1449  // Search for the name in Symbols. Skip it if not found.
1450  auto SymI = Symbols.find(Name);
1451  if (SymI == Symbols.end())
1452  continue;
1453 
1454  // If this is a non exported symbol and we're skipping those then skip it.
1455  if (!SymI->second.getFlags().isExported() && !MatchNonExported)
1456  continue;
1457 
1458  // If we matched against Name in JD, mark it to be removed from the
1459  // Unresolved set.
1460  ToRemove.push_back(Name);
1461 
1462  // If we matched against this symbol but it is in the error state then
1463  // bail out and treat it as a failure to materialize.
1464  if (SymI->second.getFlags().hasError()) {
1465  auto FailedSymbolsMap = std::make_shared<SymbolDependenceMap>();
1466  (*FailedSymbolsMap)[this] = {Name};
1467  return make_error<FailedToMaterialize>(std::move(FailedSymbolsMap));
1468  }
1469 
1470  // If this symbol already meets the required state for then notify the
1471  // query and continue.
1472  if (SymI->second.getState() >= Q->getRequiredState()) {
1473  Q->notifySymbolMetRequiredState(Name, SymI->second.getSymbol());
1474  continue;
1475  }
1476 
1477  // Otherwise this symbol does not yet meet the required state. Check whether
1478  // it has a materializer attached, and if so prepare to run it.
1479  if (SymI->second.hasMaterializerAttached()) {
1480  assert(SymI->second.getAddress() == 0 &&
1481  "Symbol not resolved but already has address?");
1482  auto UMII = UnmaterializedInfos.find(Name);
1483  assert(UMII != UnmaterializedInfos.end() &&
1484  "Lazy symbol should have UnmaterializedInfo");
1485  auto MU = std::move(UMII->second->MU);
1486  assert(MU != nullptr && "Materializer should not be null");
1487 
1488  // Move all symbols associated with this MaterializationUnit into
1489  // materializing state.
1490  for (auto &KV : MU->getSymbols()) {
1491  auto SymK = Symbols.find(KV.first);
1492  SymK->second.setMaterializerAttached(false);
1493  SymK->second.setState(SymbolState::Materializing);
1494  UnmaterializedInfos.erase(KV.first);
1495  }
1496 
1497  // Add MU to the list of MaterializationUnits to be materialized.
1498  MUs.push_back(std::move(MU));
1499  }
1500 
1501  // Add the query to the PendingQueries list.
1502  assert(SymI->second.isInMaterializationPhase() &&
1503  "By this line the symbol should be materializing");
1504  auto &MI = MaterializingInfos[Name];
1505  MI.addQuery(Q);
1506  Q->addQueryDependence(*this, Name);
1507  }
1508 
1509  // Remove any symbols that we found.
1510  for (auto &Name : ToRemove)
1511  Unresolved.erase(Name);
1512 
1513  return Error::success();
1514 }
1515 
1517 JITDylib::legacyLookup(std::shared_ptr<AsynchronousSymbolQuery> Q,
1518  SymbolNameSet Names) {
1519  assert(Q && "Query can not be null");
1520 
1521  ES.runOutstandingMUs();
1522 
1523  bool QueryComplete = false;
1524  std::vector<std::unique_ptr<MaterializationUnit>> MUs;
1525 
1526  SymbolNameSet Unresolved = std::move(Names);
1527  auto Err = ES.runSessionLocked([&, this]() -> Error {
1528  QueryComplete = lookupImpl(Q, MUs, Unresolved);
1529 
1530  // Run any definition generators.
1531  for (auto &DG : DefGenerators) {
1532 
1533  // Bail out early if we have resolved everything.
1534  if (Unresolved.empty())
1535  break;
1536 
1537  assert(!QueryComplete && "query complete but unresolved symbols remain?");
1538  auto NewDefs = DG->tryToGenerate(*this, Unresolved);
1539  if (!NewDefs)
1540  return NewDefs.takeError();
1541  if (!NewDefs->empty()) {
1542  for (auto &D : *NewDefs)
1543  Unresolved.erase(D);
1544  QueryComplete = lookupImpl(Q, MUs, *NewDefs);
1545  assert(NewDefs->empty() &&
1546  "All fallback defs should have been found by lookupImpl");
1547  }
1548  }
1549  return Error::success();
1550  });
1551 
1552  if (Err)
1553  return std::move(Err);
1554 
1555  assert((MUs.empty() || !QueryComplete) &&
1556  "If action flags are set, there should be no work to do (so no MUs)");
1557 
1558  if (QueryComplete)
1559  Q->handleComplete();
1560 
1561  // FIXME: Swap back to the old code below once RuntimeDyld works with
1562  // callbacks from asynchronous queries.
1563  // Add MUs to the OutstandingMUs list.
1564  {
1565  std::lock_guard<std::recursive_mutex> Lock(ES.OutstandingMUsMutex);
1566  for (auto &MU : MUs)
1567  ES.OutstandingMUs.push_back(make_pair(this, std::move(MU)));
1568  }
1569  ES.runOutstandingMUs();
1570 
1571  // Dispatch any required MaterializationUnits for materialization.
1572  // for (auto &MU : MUs)
1573  // ES.dispatchMaterialization(*this, std::move(MU));
1574 
1575  return Unresolved;
1576 }
1577 
1578 bool JITDylib::lookupImpl(
1579  std::shared_ptr<AsynchronousSymbolQuery> &Q,
1580  std::vector<std::unique_ptr<MaterializationUnit>> &MUs,
1581  SymbolNameSet &Unresolved) {
1582  bool QueryComplete = false;
1583 
1584  std::vector<SymbolStringPtr> ToRemove;
1585  for (auto Name : Unresolved) {
1586 
1587  // Search for the name in Symbols. Skip it if not found.
1588  auto SymI = Symbols.find(Name);
1589  if (SymI == Symbols.end())
1590  continue;
1591 
1592  // If we found Name, mark it to be removed from the Unresolved set.
1593  ToRemove.push_back(Name);
1594 
1595  if (SymI->second.getState() >= Q->getRequiredState()) {
1596  Q->notifySymbolMetRequiredState(Name, SymI->second.getSymbol());
1597  if (Q->isComplete())
1598  QueryComplete = true;
1599  continue;
1600  }
1601 
1602  // If the symbol is lazy, get the MaterialiaztionUnit for it.
1603  if (SymI->second.hasMaterializerAttached()) {
1604  assert(SymI->second.getAddress() == 0 &&
1605  "Lazy symbol should not have a resolved address");
1606  auto UMII = UnmaterializedInfos.find(Name);
1607  assert(UMII != UnmaterializedInfos.end() &&
1608  "Lazy symbol should have UnmaterializedInfo");
1609  auto MU = std::move(UMII->second->MU);
1610  assert(MU != nullptr && "Materializer should not be null");
1611 
1612  // Kick all symbols associated with this MaterializationUnit into
1613  // materializing state.
1614  for (auto &KV : MU->getSymbols()) {
1615  auto SymK = Symbols.find(KV.first);
1616  assert(SymK != Symbols.end() && "Missing symbol table entry");
1617  SymK->second.setState(SymbolState::Materializing);
1618  SymK->second.setMaterializerAttached(false);
1619  UnmaterializedInfos.erase(KV.first);
1620  }
1621 
1622  // Add MU to the list of MaterializationUnits to be materialized.
1623  MUs.push_back(std::move(MU));
1624  }
1625 
1626  // Add the query to the PendingQueries list.
1627  assert(SymI->second.isInMaterializationPhase() &&
1628  "By this line the symbol should be materializing");
1629  auto &MI = MaterializingInfos[Name];
1630  MI.addQuery(Q);
1631  Q->addQueryDependence(*this, Name);
1632  }
1633 
1634  // Remove any marked symbols from the Unresolved set.
1635  for (auto &Name : ToRemove)
1636  Unresolved.erase(Name);
1637 
1638  return QueryComplete;
1639 }
1640 
1642  ES.runSessionLocked([&, this]() {
1643  OS << "JITDylib \"" << JITDylibName << "\" (ES: "
1644  << format("0x%016" PRIx64, reinterpret_cast<uintptr_t>(&ES)) << "):\n"
1645  << "Search order: [";
1646  for (auto &KV : SearchOrder)
1647  OS << " (\"" << KV.first->getName() << "\", "
1648  << (KV.second ? "all" : "exported only") << ")";
1649  OS << " ]\n"
1650  << "Symbol table:\n";
1651 
1652  for (auto &KV : Symbols) {
1653  OS << " \"" << *KV.first << "\": ";
1654  if (auto Addr = KV.second.getAddress())
1655  OS << format("0x%016" PRIx64, Addr) << ", " << KV.second.getFlags()
1656  << " ";
1657  else
1658  OS << "<not resolved> ";
1659 
1660  OS << KV.second.getState();
1661 
1662  if (KV.second.hasMaterializerAttached()) {
1663  OS << " (Materializer ";
1664  auto I = UnmaterializedInfos.find(KV.first);
1665  assert(I != UnmaterializedInfos.end() &&
1666  "Lazy symbol should have UnmaterializedInfo");
1667  OS << I->second->MU.get() << ")\n";
1668  } else
1669  OS << "\n";
1670  }
1671 
1672  if (!MaterializingInfos.empty())
1673  OS << " MaterializingInfos entries:\n";
1674  for (auto &KV : MaterializingInfos) {
1675  OS << " \"" << *KV.first << "\":\n"
1676  << " " << KV.second.pendingQueries().size()
1677  << " pending queries: { ";
1678  for (const auto &Q : KV.second.pendingQueries())
1679  OS << Q.get() << " (" << Q->getRequiredState() << ") ";
1680  OS << "}\n Dependants:\n";
1681  for (auto &KV2 : KV.second.Dependants)
1682  OS << " " << KV2.first->getName() << ": " << KV2.second << "\n";
1683  OS << " Unemitted Dependencies:\n";
1684  for (auto &KV2 : KV.second.UnemittedDependencies)
1685  OS << " " << KV2.first->getName() << ": " << KV2.second << "\n";
1686  }
1687  });
1688 }
1689 
1690 void JITDylib::MaterializingInfo::addQuery(
1691  std::shared_ptr<AsynchronousSymbolQuery> Q) {
1692 
1693  auto I = std::lower_bound(
1694  PendingQueries.rbegin(), PendingQueries.rend(), Q->getRequiredState(),
1695  [](const std::shared_ptr<AsynchronousSymbolQuery> &V, SymbolState S) {
1696  return V->getRequiredState() <= S;
1697  });
1698  PendingQueries.insert(I.base(), std::move(Q));
1699 }
1700 
1701 void JITDylib::MaterializingInfo::removeQuery(
1702  const AsynchronousSymbolQuery &Q) {
1703  // FIXME: Implement 'find_as' for shared_ptr<T>/T*.
1704  auto I =
1705  std::find_if(PendingQueries.begin(), PendingQueries.end(),
1706  [&Q](const std::shared_ptr<AsynchronousSymbolQuery> &V) {
1707  return V.get() == &Q;
1708  });
1709  assert(I != PendingQueries.end() &&
1710  "Query is not attached to this MaterializingInfo");
1711  PendingQueries.erase(I);
1712 }
1713 
1714 JITDylib::AsynchronousSymbolQueryList
1715 JITDylib::MaterializingInfo::takeQueriesMeeting(SymbolState RequiredState) {
1716  AsynchronousSymbolQueryList Result;
1717  while (!PendingQueries.empty()) {
1718  if (PendingQueries.back()->getRequiredState() > RequiredState)
1719  break;
1720 
1721  Result.push_back(std::move(PendingQueries.back()));
1722  PendingQueries.pop_back();
1723  }
1724 
1725  return Result;
1726 }
1727 
1728 JITDylib::JITDylib(ExecutionSession &ES, std::string Name)
1729  : ES(ES), JITDylibName(std::move(Name)) {
1730  SearchOrder.push_back({this, true});
1731 }
1732 
1733 Error JITDylib::defineImpl(MaterializationUnit &MU) {
1734  SymbolNameSet Duplicates;
1735  std::vector<SymbolStringPtr> ExistingDefsOverridden;
1736  std::vector<SymbolStringPtr> MUDefsOverridden;
1737 
1738  for (const auto &KV : MU.getSymbols()) {
1739  auto I = Symbols.find(KV.first);
1740 
1741  if (I != Symbols.end()) {
1742  if (KV.second.isStrong()) {
1743  if (I->second.getFlags().isStrong() ||
1744  I->second.getState() > SymbolState::NeverSearched)
1745  Duplicates.insert(KV.first);
1746  else {
1747  assert(I->second.getState() == SymbolState::NeverSearched &&
1748  "Overridden existing def should be in the never-searched "
1749  "state");
1750  ExistingDefsOverridden.push_back(KV.first);
1751  }
1752  } else
1753  MUDefsOverridden.push_back(KV.first);
1754  }
1755  }
1756 
1757  // If there were any duplicate definitions then bail out.
1758  if (!Duplicates.empty())
1759  return make_error<DuplicateDefinition>(**Duplicates.begin());
1760 
1761  // Discard any overridden defs in this MU.
1762  for (auto &S : MUDefsOverridden)
1763  MU.doDiscard(*this, S);
1764 
1765  // Discard existing overridden defs.
1766  for (auto &S : ExistingDefsOverridden) {
1767 
1768  auto UMII = UnmaterializedInfos.find(S);
1769  assert(UMII != UnmaterializedInfos.end() &&
1770  "Overridden existing def should have an UnmaterializedInfo");
1771  UMII->second->MU->doDiscard(*this, S);
1772  }
1773 
1774  // Finally, add the defs from this MU.
1775  for (auto &KV : MU.getSymbols()) {
1776  auto &SymEntry = Symbols[KV.first];
1777  SymEntry.setFlags(KV.second);
1778  SymEntry.setState(SymbolState::NeverSearched);
1779  SymEntry.setMaterializerAttached(true);
1780  }
1781 
1782  return Error::success();
1783 }
1784 
1785 void JITDylib::detachQueryHelper(AsynchronousSymbolQuery &Q,
1786  const SymbolNameSet &QuerySymbols) {
1787  for (auto &QuerySymbol : QuerySymbols) {
1788  assert(MaterializingInfos.count(QuerySymbol) &&
1789  "QuerySymbol does not have MaterializingInfo");
1790  auto &MI = MaterializingInfos[QuerySymbol];
1791  MI.removeQuery(Q);
1792  }
1793 }
1794 
1795 void JITDylib::transferEmittedNodeDependencies(
1796  MaterializingInfo &DependantMI, const SymbolStringPtr &DependantName,
1797  MaterializingInfo &EmittedMI) {
1798  for (auto &KV : EmittedMI.UnemittedDependencies) {
1799  auto &DependencyJD = *KV.first;
1800  SymbolNameSet *UnemittedDependenciesOnDependencyJD = nullptr;
1801 
1802  for (auto &DependencyName : KV.second) {
1803  auto &DependencyMI = DependencyJD.MaterializingInfos[DependencyName];
1804 
1805  // Do not add self dependencies.
1806  if (&DependencyMI == &DependantMI)
1807  continue;
1808 
1809  // If we haven't looked up the dependencies for DependencyJD yet, do it
1810  // now and cache the result.
1811  if (!UnemittedDependenciesOnDependencyJD)
1812  UnemittedDependenciesOnDependencyJD =
1813  &DependantMI.UnemittedDependencies[&DependencyJD];
1814 
1815  DependencyMI.Dependants[this].insert(DependantName);
1816  UnemittedDependenciesOnDependencyJD->insert(DependencyName);
1817  }
1818  }
1819 }
1820 
1821 ExecutionSession::ExecutionSession(std::shared_ptr<SymbolStringPool> SSP)
1822  : SSP(SSP ? std::move(SSP) : std::make_shared<SymbolStringPool>()) {
1823  // Construct the main dylib.
1824  JDs.push_back(std::unique_ptr<JITDylib>(new JITDylib(*this, "<main>")));
1825 }
1826 
1828  return runSessionLocked([this]() -> JITDylib & { return *JDs.front(); });
1829 }
1830 
1832  return runSessionLocked([&, this]() -> JITDylib * {
1833  for (auto &JD : JDs)
1834  if (JD->getName() == Name)
1835  return JD.get();
1836  return nullptr;
1837  });
1838 }
1839 
1841  bool AddToMainDylibSearchOrder) {
1842  assert(!getJITDylibByName(Name) && "JITDylib with that name already exists");
1843  return runSessionLocked([&, this]() -> JITDylib & {
1844  JDs.push_back(
1845  std::unique_ptr<JITDylib>(new JITDylib(*this, std::move(Name))));
1846  if (AddToMainDylibSearchOrder)
1847  JDs.front()->addToSearchOrder(*JDs.back());
1848  return *JDs.back();
1849  });
1850 }
1851 
1853  assert(!!Err && "Error should be in failure state");
1854 
1855  bool SendErrorToQuery;
1856  runSessionLocked([&]() {
1857  Q.detach();
1858  SendErrorToQuery = Q.canStillFail();
1859  });
1860 
1861  if (SendErrorToQuery)
1862  Q.handleFailed(std::move(Err));
1863  else
1864  reportError(std::move(Err));
1865 }
1866 
1868  LegacyAsyncLookupFunction AsyncLookup, SymbolNameSet Names,
1869  SymbolState RequiredState,
1870  RegisterDependenciesFunction RegisterDependencies) {
1871 #if LLVM_ENABLE_THREADS
1872  // In the threaded case we use promises to return the results.
1873  std::promise<SymbolMap> PromisedResult;
1874  Error ResolutionError = Error::success();
1875  auto NotifyComplete = [&](Expected<SymbolMap> R) {
1876  if (R)
1877  PromisedResult.set_value(std::move(*R));
1878  else {
1879  ErrorAsOutParameter _(&ResolutionError);
1880  ResolutionError = R.takeError();
1881  PromisedResult.set_value(SymbolMap());
1882  }
1883  };
1884 #else
1885  SymbolMap Result;
1886  Error ResolutionError = Error::success();
1887 
1888  auto NotifyComplete = [&](Expected<SymbolMap> R) {
1889  ErrorAsOutParameter _(&ResolutionError);
1890  if (R)
1891  Result = std::move(*R);
1892  else
1893  ResolutionError = R.takeError();
1894  };
1895 #endif
1896 
1897  auto Query = std::make_shared<AsynchronousSymbolQuery>(
1898  Names, RequiredState, std::move(NotifyComplete));
1899  // FIXME: This should be run session locked along with the registration code
1900  // and error reporting below.
1901  SymbolNameSet UnresolvedSymbols = AsyncLookup(Query, std::move(Names));
1902 
1903  // If the query was lodged successfully then register the dependencies,
1904  // otherwise fail it with an error.
1905  if (UnresolvedSymbols.empty())
1906  RegisterDependencies(Query->QueryRegistrations);
1907  else {
1908  bool DeliverError = runSessionLocked([&]() {
1909  Query->detach();
1910  return Query->canStillFail();
1911  });
1912  auto Err = make_error<SymbolsNotFound>(std::move(UnresolvedSymbols));
1913  if (DeliverError)
1914  Query->handleFailed(std::move(Err));
1915  else
1916  reportError(std::move(Err));
1917  }
1918 
1919 #if LLVM_ENABLE_THREADS
1920  auto ResultFuture = PromisedResult.get_future();
1921  auto Result = ResultFuture.get();
1922  if (ResolutionError)
1923  return std::move(ResolutionError);
1924  return std::move(Result);
1925 
1926 #else
1927  if (ResolutionError)
1928  return std::move(ResolutionError);
1929 
1930  return Result;
1931 #endif
1932 }
1933 
1935  const JITDylibSearchList &SearchOrder, SymbolNameSet Symbols,
1936  SymbolState RequiredState, SymbolsResolvedCallback NotifyComplete,
1937  RegisterDependenciesFunction RegisterDependencies) {
1938 
1939  LLVM_DEBUG({
1940  runSessionLocked([&]() {
1941  dbgs() << "Looking up " << Symbols << " in " << SearchOrder
1942  << " (required state: " << RequiredState << ")\n";
1943  });
1944  });
1945 
1946  // lookup can be re-entered recursively if running on a single thread. Run any
1947  // outstanding MUs in case this query depends on them, otherwise this lookup
1948  // will starve waiting for a result from an MU that is stuck in the queue.
1949  runOutstandingMUs();
1950 
1951  auto Unresolved = std::move(Symbols);
1952  std::map<JITDylib *, MaterializationUnitList> CollectedMUsMap;
1953  auto Q = std::make_shared<AsynchronousSymbolQuery>(Unresolved, RequiredState,
1954  std::move(NotifyComplete));
1955  bool QueryComplete = false;
1956 
1957  auto LodgingErr = runSessionLocked([&]() -> Error {
1958  auto LodgeQuery = [&]() -> Error {
1959  for (auto &KV : SearchOrder) {
1960  assert(KV.first && "JITDylibList entries must not be null");
1961  assert(!CollectedMUsMap.count(KV.first) &&
1962  "JITDylibList should not contain duplicate entries");
1963 
1964  auto &JD = *KV.first;
1965  auto MatchNonExported = KV.second;
1966  if (auto Err = JD.lodgeQuery(Q, Unresolved, MatchNonExported,
1967  CollectedMUsMap[&JD]))
1968  return Err;
1969  }
1970 
1971  if (!Unresolved.empty())
1972  return make_error<SymbolsNotFound>(std::move(Unresolved));
1973 
1974  return Error::success();
1975  };
1976 
1977  if (auto Err = LodgeQuery()) {
1978  // Query failed.
1979 
1980  // Disconnect the query from its dependencies.
1981  Q->detach();
1982 
1983  // Replace the MUs.
1984  for (auto &KV : CollectedMUsMap)
1985  for (auto &MU : KV.second)
1986  KV.first->replace(std::move(MU));
1987 
1988  return Err;
1989  }
1990 
1991  // Query lodged successfully.
1992 
1993  // Record whether this query is fully ready / resolved. We will use
1994  // this to call handleFullyResolved/handleFullyReady outside the session
1995  // lock.
1996  QueryComplete = Q->isComplete();
1997 
1998  // Call the register dependencies function.
1999  if (RegisterDependencies && !Q->QueryRegistrations.empty())
2000  RegisterDependencies(Q->QueryRegistrations);
2001 
2002  return Error::success();
2003  });
2004 
2005  if (LodgingErr) {
2006  Q->handleFailed(std::move(LodgingErr));
2007  return;
2008  }
2009 
2010  if (QueryComplete)
2011  Q->handleComplete();
2012 
2013  // Move the MUs to the OutstandingMUs list, then materialize.
2014  {
2015  std::lock_guard<std::recursive_mutex> Lock(OutstandingMUsMutex);
2016 
2017  for (auto &KV : CollectedMUsMap)
2018  for (auto &MU : KV.second)
2019  OutstandingMUs.push_back(std::make_pair(KV.first, std::move(MU)));
2020  }
2021 
2022  runOutstandingMUs();
2023 }
2024 
2027  const SymbolNameSet &Symbols,
2028  SymbolState RequiredState,
2029  RegisterDependenciesFunction RegisterDependencies) {
2030 #if LLVM_ENABLE_THREADS
2031  // In the threaded case we use promises to return the results.
2032  std::promise<SymbolMap> PromisedResult;
2033  Error ResolutionError = Error::success();
2034 
2035  auto NotifyComplete = [&](Expected<SymbolMap> R) {
2036  if (R)
2037  PromisedResult.set_value(std::move(*R));
2038  else {
2039  ErrorAsOutParameter _(&ResolutionError);
2040  ResolutionError = R.takeError();
2041  PromisedResult.set_value(SymbolMap());
2042  }
2043  };
2044 
2045 #else
2046  SymbolMap Result;
2047  Error ResolutionError = Error::success();
2048 
2049  auto NotifyComplete = [&](Expected<SymbolMap> R) {
2050  ErrorAsOutParameter _(&ResolutionError);
2051  if (R)
2052  Result = std::move(*R);
2053  else
2054  ResolutionError = R.takeError();
2055  };
2056 #endif
2057 
2058  // Perform the asynchronous lookup.
2059  lookup(SearchOrder, Symbols, RequiredState, NotifyComplete,
2060  RegisterDependencies);
2061 
2062 #if LLVM_ENABLE_THREADS
2063  auto ResultFuture = PromisedResult.get_future();
2064  auto Result = ResultFuture.get();
2065 
2066  if (ResolutionError)
2067  return std::move(ResolutionError);
2068 
2069  return std::move(Result);
2070 
2071 #else
2072  if (ResolutionError)
2073  return std::move(ResolutionError);
2074 
2075  return Result;
2076 #endif
2077 }
2078 
2081  SymbolStringPtr Name) {
2082  SymbolNameSet Names({Name});
2083 
2084  if (auto ResultMap = lookup(SearchOrder, std::move(Names), SymbolState::Ready,
2085  NoDependenciesToRegister)) {
2086  assert(ResultMap->size() == 1 && "Unexpected number of results");
2087  assert(ResultMap->count(Name) && "Missing result for symbol");
2088  return std::move(ResultMap->begin()->second);
2089  } else
2090  return ResultMap.takeError();
2091 }
2092 
2095  SymbolStringPtr Name) {
2096  SymbolNameSet Names({Name});
2097 
2098  JITDylibSearchList FullSearchOrder;
2099  FullSearchOrder.reserve(SearchOrder.size());
2100  for (auto *JD : SearchOrder)
2101  FullSearchOrder.push_back({JD, false});
2102 
2103  return lookup(FullSearchOrder, Name);
2104 }
2105 
2108  return lookup(SearchOrder, intern(Name));
2109 }
2110 
2112  runSessionLocked([this, &OS]() {
2113  for (auto &JD : JDs)
2114  JD->dump(OS);
2115  });
2116 }
2117 
2118 void ExecutionSession::runOutstandingMUs() {
2119  while (1) {
2120  std::pair<JITDylib *, std::unique_ptr<MaterializationUnit>> JITDylibAndMU;
2121 
2122  {
2123  std::lock_guard<std::recursive_mutex> Lock(OutstandingMUsMutex);
2124  if (!OutstandingMUs.empty()) {
2125  JITDylibAndMU = std::move(OutstandingMUs.back());
2126  OutstandingMUs.pop_back();
2127  }
2128  }
2129 
2130  if (JITDylibAndMU.first) {
2131  assert(JITDylibAndMU.second && "JITDylib, but no MU?");
2132  dispatchMaterialization(*JITDylibAndMU.first,
2133  std::move(JITDylibAndMU.second));
2134  } else
2135  break;
2136  }
2137 }
2138 
2140  : ES(ES), DL(DL) {}
2141 
2143  std::string MangledName;
2144  {
2145  raw_string_ostream MangledNameStream(MangledName);
2146  Mangler::getNameWithPrefix(MangledNameStream, Name, DL);
2147  }
2148  return ES.intern(MangledName);
2149 }
2150 
2151 } // End namespace orc.
2152 } // 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:393
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:406
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:434
~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:1294
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:470
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:2111
std::set< std::shared_ptr< AsynchronousSymbolQuery > > AsynchronousSymbolQuerySet
Definition: Core.h:508
SymbolStringPtr operator()(StringRef Name)
Definition: Core.cpp:2142
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:1852
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:736
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:1283
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:683
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:1252
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:1349
#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:1517
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:1270
#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:1867
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:2139
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:448
JITDylib & createJITDylib(std::string Name, bool AddToMainDylibSearchOrder=true)
Add a new JITDylib to this ExecutionSession.
Definition: Core.cpp:1840
void addDependenciesForAll(const SymbolDependenceMap &Dependencies)
Add dependencies that apply to all symbols covered by this instance.
Definition: Core.cpp:477
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:1055
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:483
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:705
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:1934
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:488
JITDylib * getJITDylibByName(StringRef Name)
Return a pointer to the "name" JITDylib.
Definition: Core.cpp:1831
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:712
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:1264
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:1827
void failMaterialization()
Notify all not-yet-emitted covered by this MaterializationResponsibility instance that an error has o...
Definition: Core.cpp:418
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:513
#define LLVM_DEBUG(X)
Definition: Debug.h:122
StringRef getName() const override
Return the name of this materialization unit.
Definition: Core.cpp:520
ExecutionSession(std::shared_ptr< SymbolStringPool > SSP=nullptr)
Construct an ExecutionSession.
Definition: Core.cpp:1821
#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:1641
virtual StringRef getName() const =0
Return the name of this materialization unit.