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