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