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