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