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