LLVM  13.0.0git
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 
11 #include "llvm/ADT/STLExtras.h"
12 #include "llvm/Config/llvm-config.h"
17 
18 #include <condition_variable>
19 #include <future>
20 
21 #define DEBUG_TYPE "orc"
22 
23 namespace llvm {
24 namespace orc {
25 
28 char SymbolsNotFound::ID = 0;
32 char Task::ID = 0;
34 
37 
38 void MaterializationUnit::anchor() {}
39 
41  assert((reinterpret_cast<uintptr_t>(JD.get()) & 0x1) == 0 &&
42  "JITDylib must be two byte aligned");
43  JD->Retain();
44  JDAndFlag.store(reinterpret_cast<uintptr_t>(JD.get()));
45 }
46 
48  getJITDylib().getExecutionSession().destroyResourceTracker(*this);
49  getJITDylib().Release();
50 }
51 
53  return getJITDylib().getExecutionSession().removeResourceTracker(*this);
54 }
55 
57  getJITDylib().getExecutionSession().transferResourceTracker(DstRT, *this);
58 }
59 
60 void ResourceTracker::makeDefunct() {
61  uintptr_t Val = JDAndFlag.load();
62  Val |= 0x1U;
63  JDAndFlag.store(Val);
64 }
65 
67 
69  : RT(std::move(RT)) {}
70 
73 }
74 
76  OS << "Resource tracker " << (void *)RT.get() << " became defunct";
77 }
78 
80  std::shared_ptr<SymbolDependenceMap> Symbols)
81  : Symbols(std::move(Symbols)) {
82  assert(!this->Symbols->empty() && "Can not fail to resolve an empty set");
83 }
84 
85 std::error_code FailedToMaterialize::convertToErrorCode() const {
87 }
88 
90  OS << "Failed to materialize symbols: " << *Symbols;
91 }
92 
94  for (auto &Sym : Symbols)
95  this->Symbols.push_back(Sym);
96  assert(!this->Symbols.empty() && "Can not fail to resolve an empty set");
97 }
98 
100  : Symbols(std::move(Symbols)) {
101  assert(!this->Symbols.empty() && "Can not fail to resolve an empty set");
102 }
103 
104 std::error_code SymbolsNotFound::convertToErrorCode() const {
106 }
107 
109  OS << "Symbols not found: " << Symbols;
110 }
111 
113  : Symbols(std::move(Symbols)) {
114  assert(!this->Symbols.empty() && "Can not fail to resolve an empty set");
115 }
116 
119 }
120 
122  OS << "Symbols could not be removed: " << Symbols;
123 }
124 
127 }
128 
130  OS << "Missing definitions in module " << ModuleName
131  << ": " << Symbols;
132 }
133 
136 }
137 
139  OS << "Unexpected definitions in module " << ModuleName
140  << ": " << Symbols;
141 }
142 
144  const SymbolLookupSet &Symbols, SymbolState RequiredState,
145  SymbolsResolvedCallback NotifyComplete)
146  : NotifyComplete(std::move(NotifyComplete)), RequiredState(RequiredState) {
147  assert(RequiredState >= SymbolState::Resolved &&
148  "Cannot query for a symbols that have not reached the resolve state "
149  "yet");
150 
151  OutstandingSymbolsCount = Symbols.size();
152 
153  for (auto &KV : Symbols)
154  ResolvedSymbols[KV.first] = nullptr;
155 }
156 
159  auto I = ResolvedSymbols.find(Name);
160  assert(I != ResolvedSymbols.end() &&
161  "Resolving symbol outside the requested set");
162  assert(I->second.getAddress() == 0 && "Redundantly resolving symbol Name");
163 
164  // If this is a materialization-side-effects-only symbol then drop it,
165  // otherwise update its map entry with its resolved address.
167  ResolvedSymbols.erase(I);
168  else
169  I->second = std::move(Sym);
170  --OutstandingSymbolsCount;
171 }
172 
173 void AsynchronousSymbolQuery::handleComplete(ExecutionSession &ES) {
174  assert(OutstandingSymbolsCount == 0 &&
175  "Symbols remain, handleComplete called prematurely");
176 
177  class RunQueryCompleteTask : public Task {
178  public:
179  RunQueryCompleteTask(SymbolMap ResolvedSymbols,
180  SymbolsResolvedCallback NotifyComplete)
181  : ResolvedSymbols(std::move(ResolvedSymbols)),
182  NotifyComplete(std::move(NotifyComplete)) {}
183  void printDescription(raw_ostream &OS) override {
184  OS << "Execute query complete callback for " << ResolvedSymbols;
185  }
186  void run() override { NotifyComplete(std::move(ResolvedSymbols)); }
187 
188  private:
189  SymbolMap ResolvedSymbols;
190  SymbolsResolvedCallback NotifyComplete;
191  };
192 
193  auto T = std::make_unique<RunQueryCompleteTask>(std::move(ResolvedSymbols),
194  std::move(NotifyComplete));
195  NotifyComplete = SymbolsResolvedCallback();
196  ES.dispatchTask(std::move(T));
197 }
198 
199 void AsynchronousSymbolQuery::handleFailed(Error Err) {
200  assert(QueryRegistrations.empty() && ResolvedSymbols.empty() &&
201  OutstandingSymbolsCount == 0 &&
202  "Query should already have been abandoned");
203  NotifyComplete(std::move(Err));
204  NotifyComplete = SymbolsResolvedCallback();
205 }
206 
207 void AsynchronousSymbolQuery::addQueryDependence(JITDylib &JD,
208  SymbolStringPtr Name) {
209  bool Added = QueryRegistrations[&JD].insert(std::move(Name)).second;
210  (void)Added;
211  assert(Added && "Duplicate dependence notification?");
212 }
213 
214 void AsynchronousSymbolQuery::removeQueryDependence(
215  JITDylib &JD, const SymbolStringPtr &Name) {
216  auto QRI = QueryRegistrations.find(&JD);
217  assert(QRI != QueryRegistrations.end() &&
218  "No dependencies registered for JD");
219  assert(QRI->second.count(Name) && "No dependency on Name in JD");
220  QRI->second.erase(Name);
221  if (QRI->second.empty())
222  QueryRegistrations.erase(QRI);
223 }
224 
225 void AsynchronousSymbolQuery::dropSymbol(const SymbolStringPtr &Name) {
226  auto I = ResolvedSymbols.find(Name);
227  assert(I != ResolvedSymbols.end() &&
228  "Redundant removal of weakly-referenced symbol");
229  ResolvedSymbols.erase(I);
230  --OutstandingSymbolsCount;
231 }
232 
233 void AsynchronousSymbolQuery::detach() {
234  ResolvedSymbols.clear();
235  OutstandingSymbolsCount = 0;
236  for (auto &KV : QueryRegistrations)
237  KV.first->detachQueryHelper(*this, KV.second);
238  QueryRegistrations.clear();
239 }
240 
242  SymbolMap Symbols)
243  : MaterializationUnit(extractFlags(Symbols), nullptr),
244  Symbols(std::move(Symbols)) {}
245 
247  return "<Absolute Symbols>";
248 }
249 
250 void AbsoluteSymbolsMaterializationUnit::materialize(
251  std::unique_ptr<MaterializationResponsibility> R) {
252  // No dependencies, so these calls can't fail.
253  cantFail(R->notifyResolved(Symbols));
254  cantFail(R->notifyEmitted());
255 }
256 
257 void AbsoluteSymbolsMaterializationUnit::discard(const JITDylib &JD,
258  const SymbolStringPtr &Name) {
259  assert(Symbols.count(Name) && "Symbol is not part of this MU");
260  Symbols.erase(Name);
261 }
262 
264 AbsoluteSymbolsMaterializationUnit::extractFlags(const SymbolMap &Symbols) {
265  SymbolFlagsMap Flags;
266  for (const auto &KV : Symbols)
267  Flags[KV.first] = KV.second.getFlags();
268  return Flags;
269 }
270 
272  JITDylib *SourceJD, JITDylibLookupFlags SourceJDLookupFlags,
273  SymbolAliasMap Aliases)
274  : MaterializationUnit(extractFlags(Aliases), nullptr), SourceJD(SourceJD),
275  SourceJDLookupFlags(SourceJDLookupFlags), Aliases(std::move(Aliases)) {}
276 
278  return "<Reexports>";
279 }
280 
281 void ReExportsMaterializationUnit::materialize(
282  std::unique_ptr<MaterializationResponsibility> R) {
283 
284  auto &ES = R->getTargetJITDylib().getExecutionSession();
285  JITDylib &TgtJD = R->getTargetJITDylib();
286  JITDylib &SrcJD = SourceJD ? *SourceJD : TgtJD;
287 
288  // Find the set of requested aliases and aliasees. Return any unrequested
289  // aliases back to the JITDylib so as to not prematurely materialize any
290  // aliasees.
291  auto RequestedSymbols = R->getRequestedSymbols();
292  SymbolAliasMap RequestedAliases;
293 
294  for (auto &Name : RequestedSymbols) {
295  auto I = Aliases.find(Name);
296  assert(I != Aliases.end() && "Symbol not found in aliases map?");
297  RequestedAliases[Name] = std::move(I->second);
298  Aliases.erase(I);
299  }
300 
301  LLVM_DEBUG({
302  ES.runSessionLocked([&]() {
303  dbgs() << "materializing reexports: target = " << TgtJD.getName()
304  << ", source = " << SrcJD.getName() << " " << RequestedAliases
305  << "\n";
306  });
307  });
308 
309  if (!Aliases.empty()) {
310  auto Err = SourceJD ? R->replace(reexports(*SourceJD, std::move(Aliases),
311  SourceJDLookupFlags))
312  : R->replace(symbolAliases(std::move(Aliases)));
313 
314  if (Err) {
315  // FIXME: Should this be reported / treated as failure to materialize?
316  // Or should this be treated as a sanctioned bailing-out?
317  ES.reportError(std::move(Err));
318  R->failMaterialization();
319  return;
320  }
321  }
322 
323  // The OnResolveInfo struct will hold the aliases and responsibilty for each
324  // query in the list.
325  struct OnResolveInfo {
326  OnResolveInfo(std::unique_ptr<MaterializationResponsibility> R,
327  SymbolAliasMap Aliases)
328  : R(std::move(R)), Aliases(std::move(Aliases)) {}
329 
330  std::unique_ptr<MaterializationResponsibility> R;
331  SymbolAliasMap Aliases;
332  };
333 
334  // Build a list of queries to issue. In each round we build a query for the
335  // largest set of aliases that we can resolve without encountering a chain of
336  // aliases (e.g. Foo -> Bar, Bar -> Baz). Such a chain would deadlock as the
337  // query would be waiting on a symbol that it itself had to resolve. Creating
338  // a new query for each link in such a chain eliminates the possibility of
339  // deadlock. In practice chains are likely to be rare, and this algorithm will
340  // usually result in a single query to issue.
341 
342  std::vector<std::pair<SymbolLookupSet, std::shared_ptr<OnResolveInfo>>>
343  QueryInfos;
344  while (!RequestedAliases.empty()) {
345  SymbolNameSet ResponsibilitySymbols;
346  SymbolLookupSet QuerySymbols;
347  SymbolAliasMap QueryAliases;
348 
349  // Collect as many aliases as we can without including a chain.
350  for (auto &KV : RequestedAliases) {
351  // Chain detected. Skip this symbol for this round.
352  if (&SrcJD == &TgtJD && (QueryAliases.count(KV.second.Aliasee) ||
353  RequestedAliases.count(KV.second.Aliasee)))
354  continue;
355 
356  ResponsibilitySymbols.insert(KV.first);
357  QuerySymbols.add(KV.second.Aliasee,
358  KV.second.AliasFlags.hasMaterializationSideEffectsOnly()
361  QueryAliases[KV.first] = std::move(KV.second);
362  }
363 
364  // Remove the aliases collected this round from the RequestedAliases map.
365  for (auto &KV : QueryAliases)
366  RequestedAliases.erase(KV.first);
367 
368  assert(!QuerySymbols.empty() && "Alias cycle detected!");
369 
370  auto NewR = R->delegate(ResponsibilitySymbols);
371  if (!NewR) {
372  ES.reportError(NewR.takeError());
373  R->failMaterialization();
374  return;
375  }
376 
377  auto QueryInfo = std::make_shared<OnResolveInfo>(std::move(*NewR),
378  std::move(QueryAliases));
379  QueryInfos.push_back(
380  make_pair(std::move(QuerySymbols), std::move(QueryInfo)));
381  }
382 
383  // Issue the queries.
384  while (!QueryInfos.empty()) {
385  auto QuerySymbols = std::move(QueryInfos.back().first);
386  auto QueryInfo = std::move(QueryInfos.back().second);
387 
388  QueryInfos.pop_back();
389 
390  auto RegisterDependencies = [QueryInfo,
391  &SrcJD](const SymbolDependenceMap &Deps) {
392  // If there were no materializing symbols, just bail out.
393  if (Deps.empty())
394  return;
395 
396  // Otherwise the only deps should be on SrcJD.
397  assert(Deps.size() == 1 && Deps.count(&SrcJD) &&
398  "Unexpected dependencies for reexports");
399 
400  auto &SrcJDDeps = Deps.find(&SrcJD)->second;
401  SymbolDependenceMap PerAliasDepsMap;
402  auto &PerAliasDeps = PerAliasDepsMap[&SrcJD];
403 
404  for (auto &KV : QueryInfo->Aliases)
405  if (SrcJDDeps.count(KV.second.Aliasee)) {
406  PerAliasDeps = {KV.second.Aliasee};
407  QueryInfo->R->addDependencies(KV.first, PerAliasDepsMap);
408  }
409  };
410 
411  auto OnComplete = [QueryInfo](Expected<SymbolMap> Result) {
412  auto &ES = QueryInfo->R->getTargetJITDylib().getExecutionSession();
413  if (Result) {
414  SymbolMap ResolutionMap;
415  for (auto &KV : QueryInfo->Aliases) {
416  assert((KV.second.AliasFlags.hasMaterializationSideEffectsOnly() ||
417  Result->count(KV.second.Aliasee)) &&
418  "Result map missing entry?");
419  // Don't try to resolve materialization-side-effects-only symbols.
420  if (KV.second.AliasFlags.hasMaterializationSideEffectsOnly())
421  continue;
422 
423  ResolutionMap[KV.first] = JITEvaluatedSymbol(
424  (*Result)[KV.second.Aliasee].getAddress(), KV.second.AliasFlags);
425  }
426  if (auto Err = QueryInfo->R->notifyResolved(ResolutionMap)) {
427  ES.reportError(std::move(Err));
428  QueryInfo->R->failMaterialization();
429  return;
430  }
431  if (auto Err = QueryInfo->R->notifyEmitted()) {
432  ES.reportError(std::move(Err));
433  QueryInfo->R->failMaterialization();
434  return;
435  }
436  } else {
437  ES.reportError(Result.takeError());
438  QueryInfo->R->failMaterialization();
439  }
440  };
441 
443  JITDylibSearchOrder({{&SrcJD, SourceJDLookupFlags}}),
444  QuerySymbols, SymbolState::Resolved, std::move(OnComplete),
445  std::move(RegisterDependencies));
446  }
447 }
448 
449 void ReExportsMaterializationUnit::discard(const JITDylib &JD,
450  const SymbolStringPtr &Name) {
451  assert(Aliases.count(Name) &&
452  "Symbol not covered by this MaterializationUnit");
453  Aliases.erase(Name);
454 }
455 
457 ReExportsMaterializationUnit::extractFlags(const SymbolAliasMap &Aliases) {
459  for (auto &KV : Aliases)
460  SymbolFlags[KV.first] = KV.second.AliasFlags;
461 
462  return SymbolFlags;
463 }
464 
466  SymbolNameSet Symbols) {
467  SymbolLookupSet LookupSet(Symbols);
468  auto Flags = SourceJD.getExecutionSession().lookupFlags(
470  SymbolLookupSet(std::move(Symbols)));
471 
472  if (!Flags)
473  return Flags.takeError();
474 
475  SymbolAliasMap Result;
476  for (auto &Name : Symbols) {
477  assert(Flags->count(Name) && "Missing entry in flags map");
478  Result[Name] = SymbolAliasMapEntry(Name, (*Flags)[Name]);
479  }
480 
481  return Result;
482 }
483 
485 public:
491  }
493  virtual void complete(std::unique_ptr<InProgressLookupState> IPLS) = 0;
494  virtual void fail(Error Err) = 0;
495 
500 
501  std::unique_lock<std::mutex> GeneratorLock;
503  bool NewJITDylib = true;
506  std::vector<std::weak_ptr<DefinitionGenerator>> CurDefGeneratorStack;
507 };
508 
510 public:
513  unique_function<void(Expected<SymbolFlagsMap>)> OnComplete)
516  OnComplete(std::move(OnComplete)) {}
517 
518  void complete(std::unique_ptr<InProgressLookupState> IPLS) override {
519  GeneratorLock = {}; // Unlock and release.
520  auto &ES = SearchOrder.front().first->getExecutionSession();
521  ES.OL_completeLookupFlags(std::move(IPLS), std::move(OnComplete));
522  }
523 
524  void fail(Error Err) override {
525  GeneratorLock = {}; // Unlock and release.
526  OnComplete(std::move(Err));
527  }
528 
529 private:
530  unique_function<void(Expected<SymbolFlagsMap>)> OnComplete;
531 };
532 
534 public:
538  std::shared_ptr<AsynchronousSymbolQuery> Q,
539  RegisterDependenciesFunction RegisterDependencies)
541  RequiredState),
542  Q(std::move(Q)), RegisterDependencies(std::move(RegisterDependencies)) {
543  }
544 
545  void complete(std::unique_ptr<InProgressLookupState> IPLS) override {
546  GeneratorLock = {}; // Unlock and release.
547  auto &ES = SearchOrder.front().first->getExecutionSession();
548  ES.OL_completeLookup(std::move(IPLS), std::move(Q),
549  std::move(RegisterDependencies));
550  }
551 
552  void fail(Error Err) override {
553  GeneratorLock = {};
554  Q->detach();
555  Q->handleFailed(std::move(Err));
556  }
557 
558 private:
559  std::shared_ptr<AsynchronousSymbolQuery> Q;
560  RegisterDependenciesFunction RegisterDependencies;
561 };
562 
564  JITDylibLookupFlags SourceJDLookupFlags,
566  : SourceJD(SourceJD), SourceJDLookupFlags(SourceJDLookupFlags),
567  Allow(std::move(Allow)) {}
568 
570  JITDylib &JD,
571  JITDylibLookupFlags JDLookupFlags,
572  const SymbolLookupSet &LookupSet) {
573  assert(&JD != &SourceJD && "Cannot re-export from the same dylib");
574 
575  // Use lookupFlags to find the subset of symbols that match our lookup.
576  auto Flags = JD.getExecutionSession().lookupFlags(
577  K, {{&SourceJD, JDLookupFlags}}, LookupSet);
578  if (!Flags)
579  return Flags.takeError();
580 
581  // Create an alias map.
582  orc::SymbolAliasMap AliasMap;
583  for (auto &KV : *Flags)
584  if (!Allow || Allow(KV.first))
585  AliasMap[KV.first] = SymbolAliasMapEntry(KV.first, KV.second);
586 
587  if (AliasMap.empty())
588  return Error::success();
589 
590  // Define the re-exports.
591  return JD.define(reexports(SourceJD, AliasMap, SourceJDLookupFlags));
592 }
593 
594 LookupState::LookupState(std::unique_ptr<InProgressLookupState> IPLS)
595  : IPLS(std::move(IPLS)) {}
596 
597 void LookupState::reset(InProgressLookupState *IPLS) { this->IPLS.reset(IPLS); }
598 
599 LookupState::LookupState() = default;
600 LookupState::LookupState(LookupState &&) = default;
601 LookupState &LookupState::operator=(LookupState &&) = default;
602 LookupState::~LookupState() = default;
603 
605  assert(IPLS && "Cannot call continueLookup on empty LookupState");
606  auto &ES = IPLS->SearchOrder.begin()->first->getExecutionSession();
607  ES.OL_applyQueryPhase1(std::move(IPLS), std::move(Err));
608 }
609 
611 
613  std::vector<ResourceTrackerSP> TrackersToRemove;
614  ES.runSessionLocked([&]() {
615  for (auto &KV : TrackerSymbols)
616  TrackersToRemove.push_back(KV.first);
617  TrackersToRemove.push_back(getDefaultResourceTracker());
618  });
619 
620  Error Err = Error::success();
621  for (auto &RT : TrackersToRemove)
622  Err = joinErrors(std::move(Err), RT->remove());
623  return Err;
624 }
625 
627  return ES.runSessionLocked([this] {
628  if (!DefaultTracker)
629  DefaultTracker = new ResourceTracker(this);
630  return DefaultTracker;
631  });
632 }
633 
635  return ES.runSessionLocked([this] {
636  ResourceTrackerSP RT = new ResourceTracker(this);
637  return RT;
638  });
639 }
640 
642  std::lock_guard<std::mutex> Lock(GeneratorsMutex);
643  auto I = llvm::find_if(DefGenerators,
644  [&](const std::shared_ptr<DefinitionGenerator> &H) {
645  return H.get() == &G;
646  });
647  assert(I != DefGenerators.end() && "Generator not found");
648  DefGenerators.erase(I);
649 }
650 
652 JITDylib::defineMaterializing(SymbolFlagsMap SymbolFlags) {
653 
654  return ES.runSessionLocked([&]() -> Expected<SymbolFlagsMap> {
655  std::vector<SymbolTable::iterator> AddedSyms;
656  std::vector<SymbolFlagsMap::iterator> RejectedWeakDefs;
657 
658  for (auto SFItr = SymbolFlags.begin(), SFEnd = SymbolFlags.end();
659  SFItr != SFEnd; ++SFItr) {
660 
661  auto &Name = SFItr->first;
662  auto &Flags = SFItr->second;
663 
664  auto EntryItr = Symbols.find(Name);
665 
666  // If the entry already exists...
667  if (EntryItr != Symbols.end()) {
668 
669  // If this is a strong definition then error out.
670  if (!Flags.isWeak()) {
671  // Remove any symbols already added.
672  for (auto &SI : AddedSyms)
673  Symbols.erase(SI);
674 
675  // FIXME: Return all duplicates.
676  return make_error<DuplicateDefinition>(std::string(*Name));
677  }
678 
679  // Otherwise just make a note to discard this symbol after the loop.
680  RejectedWeakDefs.push_back(SFItr);
681  continue;
682  } else
683  EntryItr =
684  Symbols.insert(std::make_pair(Name, SymbolTableEntry(Flags))).first;
685 
686  AddedSyms.push_back(EntryItr);
687  EntryItr->second.setState(SymbolState::Materializing);
688  }
689 
690  // Remove any rejected weak definitions from the SymbolFlags map.
691  while (!RejectedWeakDefs.empty()) {
692  SymbolFlags.erase(RejectedWeakDefs.back());
693  RejectedWeakDefs.pop_back();
694  }
695 
696  return SymbolFlags;
697  });
698 }
699 
700 Error JITDylib::replace(MaterializationResponsibility &FromMR,
701  std::unique_ptr<MaterializationUnit> MU) {
702  assert(MU != nullptr && "Can not replace with a null MaterializationUnit");
703  std::unique_ptr<MaterializationUnit> MustRunMU;
704  std::unique_ptr<MaterializationResponsibility> MustRunMR;
705 
706  auto Err =
707  ES.runSessionLocked([&, this]() -> Error {
708  auto RT = getTracker(FromMR);
709 
710  if (RT->isDefunct())
711  return make_error<ResourceTrackerDefunct>(std::move(RT));
712 
713 #ifndef NDEBUG
714  for (auto &KV : MU->getSymbols()) {
715  auto SymI = Symbols.find(KV.first);
716  assert(SymI != Symbols.end() && "Replacing unknown symbol");
717  assert(SymI->second.getState() == SymbolState::Materializing &&
718  "Can not replace a symbol that ha is not materializing");
719  assert(!SymI->second.hasMaterializerAttached() &&
720  "Symbol should not have materializer attached already");
721  assert(UnmaterializedInfos.count(KV.first) == 0 &&
722  "Symbol being replaced should have no UnmaterializedInfo");
723  }
724 #endif // NDEBUG
725 
726  // If the tracker is defunct we need to bail out immediately.
727 
728  // If any symbol has pending queries against it then we need to
729  // materialize MU immediately.
730  for (auto &KV : MU->getSymbols()) {
731  auto MII = MaterializingInfos.find(KV.first);
732  if (MII != MaterializingInfos.end()) {
733  if (MII->second.hasQueriesPending()) {
734  MustRunMR = ES.createMaterializationResponsibility(
735  *RT, std::move(MU->SymbolFlags), std::move(MU->InitSymbol));
736  MustRunMU = std::move(MU);
737  return Error::success();
738  }
739  }
740  }
741 
742  // Otherwise, make MU responsible for all the symbols.
743  auto RTI = MRTrackers.find(&FromMR);
744  assert(RTI != MRTrackers.end() && "No tracker for FromMR");
745  auto UMI =
746  std::make_shared<UnmaterializedInfo>(std::move(MU), RTI->second);
747  for (auto &KV : UMI->MU->getSymbols()) {
748  auto SymI = Symbols.find(KV.first);
749  assert(SymI->second.getState() == SymbolState::Materializing &&
750  "Can not replace a symbol that is not materializing");
751  assert(!SymI->second.hasMaterializerAttached() &&
752  "Can not replace a symbol that has a materializer attached");
753  assert(UnmaterializedInfos.count(KV.first) == 0 &&
754  "Unexpected materializer entry in map");
755  SymI->second.setAddress(SymI->second.getAddress());
756  SymI->second.setMaterializerAttached(true);
757 
758  auto &UMIEntry = UnmaterializedInfos[KV.first];
759  assert((!UMIEntry || !UMIEntry->MU) &&
760  "Replacing symbol with materializer still attached");
761  UMIEntry = UMI;
762  }
763 
764  return Error::success();
765  });
766 
767  if (Err)
768  return Err;
769 
770  if (MustRunMU) {
771  assert(MustRunMR && "MustRunMU set implies MustRunMR set");
772  ES.dispatchTask(std::make_unique<MaterializationTask>(
773  std::move(MustRunMU), std::move(MustRunMR)));
774  } else {
775  assert(!MustRunMR && "MustRunMU unset implies MustRunMR unset");
776  }
777 
778  return Error::success();
779 }
780 
781 Expected<std::unique_ptr<MaterializationResponsibility>>
782 JITDylib::delegate(MaterializationResponsibility &FromMR,
783  SymbolFlagsMap SymbolFlags, SymbolStringPtr InitSymbol) {
784 
785  return ES.runSessionLocked(
786  [&]() -> Expected<std::unique_ptr<MaterializationResponsibility>> {
787  auto RT = getTracker(FromMR);
788 
789  if (RT->isDefunct())
790  return make_error<ResourceTrackerDefunct>(std::move(RT));
791 
792  return ES.createMaterializationResponsibility(
793  *RT, std::move(SymbolFlags), std::move(InitSymbol));
794  });
795 }
796 
798 JITDylib::getRequestedSymbols(const SymbolFlagsMap &SymbolFlags) const {
799  return ES.runSessionLocked([&]() {
800  SymbolNameSet RequestedSymbols;
801 
802  for (auto &KV : SymbolFlags) {
803  assert(Symbols.count(KV.first) && "JITDylib does not cover this symbol?");
804  assert(Symbols.find(KV.first)->second.getState() !=
805  SymbolState::NeverSearched &&
806  Symbols.find(KV.first)->second.getState() != SymbolState::Ready &&
807  "getRequestedSymbols can only be called for symbols that have "
808  "started materializing");
809  auto I = MaterializingInfos.find(KV.first);
810  if (I == MaterializingInfos.end())
811  continue;
812 
813  if (I->second.hasQueriesPending())
814  RequestedSymbols.insert(KV.first);
815  }
816 
817  return RequestedSymbols;
818  });
819 }
820 
821 void JITDylib::addDependencies(const SymbolStringPtr &Name,
822  const SymbolDependenceMap &Dependencies) {
823  ES.runSessionLocked([&]() {
824  assert(Symbols.count(Name) && "Name not in symbol table");
825  assert(Symbols[Name].getState() < SymbolState::Emitted &&
826  "Can not add dependencies for a symbol that is not materializing");
827 
828  LLVM_DEBUG({
829  dbgs() << "In " << getName() << " adding dependencies for " << *Name
830  << ": " << Dependencies << "\n";
831  });
832 
833  // If Name is already in an error state then just bail out.
834  if (Symbols[Name].getFlags().hasError())
835  return;
836 
837  auto &MI = MaterializingInfos[Name];
838  assert(Symbols[Name].getState() != SymbolState::Emitted &&
839  "Can not add dependencies to an emitted symbol");
840 
841  bool DependsOnSymbolInErrorState = false;
842 
843  // Register dependencies, record whether any depenendency is in the error
844  // state.
845  for (auto &KV : Dependencies) {
846  assert(KV.first && "Null JITDylib in dependency?");
847  auto &OtherJITDylib = *KV.first;
848  auto &DepsOnOtherJITDylib = MI.UnemittedDependencies[&OtherJITDylib];
849 
850  for (auto &OtherSymbol : KV.second) {
851 
852  // Check the sym entry for the dependency.
853  auto OtherSymI = OtherJITDylib.Symbols.find(OtherSymbol);
854 
855  // Assert that this symbol exists and has not reached the ready state
856  // already.
857  assert(OtherSymI != OtherJITDylib.Symbols.end() &&
858  "Dependency on unknown symbol");
859 
860  auto &OtherSymEntry = OtherSymI->second;
861 
862  // If the other symbol is already in the Ready state then there's no
863  // dependency to add.
864  if (OtherSymEntry.getState() == SymbolState::Ready)
865  continue;
866 
867  // If the dependency is in an error state then note this and continue,
868  // we will move this symbol to the error state below.
869  if (OtherSymEntry.getFlags().hasError()) {
870  DependsOnSymbolInErrorState = true;
871  continue;
872  }
873 
874  // If the dependency was not in the error state then add it to
875  // our list of dependencies.
876  auto &OtherMI = OtherJITDylib.MaterializingInfos[OtherSymbol];
877 
878  if (OtherSymEntry.getState() == SymbolState::Emitted)
879  transferEmittedNodeDependencies(MI, Name, OtherMI);
880  else if (&OtherJITDylib != this || OtherSymbol != Name) {
881  OtherMI.Dependants[this].insert(Name);
882  DepsOnOtherJITDylib.insert(OtherSymbol);
883  }
884  }
885 
886  if (DepsOnOtherJITDylib.empty())
887  MI.UnemittedDependencies.erase(&OtherJITDylib);
888  }
889 
890  // If this symbol dependended on any symbols in the error state then move
891  // this symbol to the error state too.
892  if (DependsOnSymbolInErrorState)
893  Symbols[Name].setFlags(Symbols[Name].getFlags() |
895  });
896 }
897 
898 Error JITDylib::resolve(MaterializationResponsibility &MR,
899  const SymbolMap &Resolved) {
900  AsynchronousSymbolQuerySet CompletedQueries;
901 
902  if (auto Err = ES.runSessionLocked([&, this]() -> Error {
903  auto RTI = MRTrackers.find(&MR);
904  assert(RTI != MRTrackers.end() && "No resource tracker for MR?");
905  if (RTI->second->isDefunct())
906  return make_error<ResourceTrackerDefunct>(RTI->second);
907 
908  struct WorklistEntry {
909  SymbolTable::iterator SymI;
910  JITEvaluatedSymbol ResolvedSym;
911  };
912 
913  SymbolNameSet SymbolsInErrorState;
914  std::vector<WorklistEntry> Worklist;
915  Worklist.reserve(Resolved.size());
916 
917  // Build worklist and check for any symbols in the error state.
918  for (const auto &KV : Resolved) {
919 
920  assert(!KV.second.getFlags().hasError() &&
921  "Resolution result can not have error flag set");
922 
923  auto SymI = Symbols.find(KV.first);
924 
925  assert(SymI != Symbols.end() && "Symbol not found");
926  assert(!SymI->second.hasMaterializerAttached() &&
927  "Resolving symbol with materializer attached?");
928  assert(SymI->second.getState() == SymbolState::Materializing &&
929  "Symbol should be materializing");
930  assert(SymI->second.getAddress() == 0 &&
931  "Symbol has already been resolved");
932 
933  if (SymI->second.getFlags().hasError())
934  SymbolsInErrorState.insert(KV.first);
935  else {
936  auto Flags = KV.second.getFlags();
938  assert(Flags ==
939  (SymI->second.getFlags() &
941  "Resolved flags should match the declared flags");
942 
943  Worklist.push_back(
944  {SymI, JITEvaluatedSymbol(KV.second.getAddress(), Flags)});
945  }
946  }
947 
948  // If any symbols were in the error state then bail out.
949  if (!SymbolsInErrorState.empty()) {
950  auto FailedSymbolsDepMap = std::make_shared<SymbolDependenceMap>();
951  (*FailedSymbolsDepMap)[this] = std::move(SymbolsInErrorState);
952  return make_error<FailedToMaterialize>(
953  std::move(FailedSymbolsDepMap));
954  }
955 
956  while (!Worklist.empty()) {
957  auto SymI = Worklist.back().SymI;
958  auto ResolvedSym = Worklist.back().ResolvedSym;
959  Worklist.pop_back();
960 
961  auto &Name = SymI->first;
962 
963  // Resolved symbols can not be weak: discard the weak flag.
964  JITSymbolFlags ResolvedFlags = ResolvedSym.getFlags();
965  SymI->second.setAddress(ResolvedSym.getAddress());
966  SymI->second.setFlags(ResolvedFlags);
967  SymI->second.setState(SymbolState::Resolved);
968 
969  auto MII = MaterializingInfos.find(Name);
970  if (MII == MaterializingInfos.end())
971  continue;
972 
973  auto &MI = MII->second;
974  for (auto &Q : MI.takeQueriesMeeting(SymbolState::Resolved)) {
975  Q->notifySymbolMetRequiredState(Name, ResolvedSym);
976  Q->removeQueryDependence(*this, Name);
977  if (Q->isComplete())
978  CompletedQueries.insert(std::move(Q));
979  }
980  }
981 
982  return Error::success();
983  }))
984  return Err;
985 
986  // Otherwise notify all the completed queries.
987  for (auto &Q : CompletedQueries) {
988  assert(Q->isComplete() && "Q not completed");
989  Q->handleComplete(ES);
990  }
991 
992  return Error::success();
993 }
994 
995 Error JITDylib::emit(MaterializationResponsibility &MR,
996  const SymbolFlagsMap &Emitted) {
997  AsynchronousSymbolQuerySet CompletedQueries;
998  DenseMap<JITDylib *, SymbolNameVector> ReadySymbols;
999 
1000  if (auto Err = ES.runSessionLocked([&, this]() -> Error {
1001  auto RTI = MRTrackers.find(&MR);
1002  assert(RTI != MRTrackers.end() && "No resource tracker for MR?");
1003  if (RTI->second->isDefunct())
1004  return make_error<ResourceTrackerDefunct>(RTI->second);
1005 
1006  SymbolNameSet SymbolsInErrorState;
1007  std::vector<SymbolTable::iterator> Worklist;
1008 
1009  // Scan to build worklist, record any symbols in the erorr state.
1010  for (const auto &KV : Emitted) {
1011  auto &Name = KV.first;
1012 
1013  auto SymI = Symbols.find(Name);
1014  assert(SymI != Symbols.end() && "No symbol table entry for Name");
1015 
1016  if (SymI->second.getFlags().hasError())
1017  SymbolsInErrorState.insert(Name);
1018  else
1019  Worklist.push_back(SymI);
1020  }
1021 
1022  // If any symbols were in the error state then bail out.
1023  if (!SymbolsInErrorState.empty()) {
1024  auto FailedSymbolsDepMap = std::make_shared<SymbolDependenceMap>();
1025  (*FailedSymbolsDepMap)[this] = std::move(SymbolsInErrorState);
1026  return make_error<FailedToMaterialize>(
1027  std::move(FailedSymbolsDepMap));
1028  }
1029 
1030  // Otherwise update dependencies and move to the emitted state.
1031  while (!Worklist.empty()) {
1032  auto SymI = Worklist.back();
1033  Worklist.pop_back();
1034 
1035  auto &Name = SymI->first;
1036  auto &SymEntry = SymI->second;
1037 
1038  // Move symbol to the emitted state.
1039  assert(((SymEntry.getFlags().hasMaterializationSideEffectsOnly() &&
1040  SymEntry.getState() == SymbolState::Materializing) ||
1041  SymEntry.getState() == SymbolState::Resolved) &&
1042  "Emitting from state other than Resolved");
1043  SymEntry.setState(SymbolState::Emitted);
1044 
1045  auto MII = MaterializingInfos.find(Name);
1046 
1047  // If this symbol has no MaterializingInfo then it's trivially ready.
1048  // Update its state and continue.
1049  if (MII == MaterializingInfos.end()) {
1050  SymEntry.setState(SymbolState::Ready);
1051  continue;
1052  }
1053 
1054  auto &MI = MII->second;
1055 
1056  // For each dependant, transfer this node's emitted dependencies to
1057  // it. If the dependant node is ready (i.e. has no unemitted
1058  // dependencies) then notify any pending queries.
1059  for (auto &KV : MI.Dependants) {
1060  auto &DependantJD = *KV.first;
1061  auto &DependantJDReadySymbols = ReadySymbols[&DependantJD];
1062  for (auto &DependantName : KV.second) {
1063  auto DependantMII =
1064  DependantJD.MaterializingInfos.find(DependantName);
1065  assert(DependantMII != DependantJD.MaterializingInfos.end() &&
1066  "Dependant should have MaterializingInfo");
1067 
1068  auto &DependantMI = DependantMII->second;
1069 
1070  // Remove the dependant's dependency on this node.
1071  assert(DependantMI.UnemittedDependencies.count(this) &&
1072  "Dependant does not have an unemitted dependencies record "
1073  "for "
1074  "this JITDylib");
1075  assert(DependantMI.UnemittedDependencies[this].count(Name) &&
1076  "Dependant does not count this symbol as a dependency?");
1077 
1078  DependantMI.UnemittedDependencies[this].erase(Name);
1079  if (DependantMI.UnemittedDependencies[this].empty())
1080  DependantMI.UnemittedDependencies.erase(this);
1081 
1082  // Transfer unemitted dependencies from this node to the
1083  // dependant.
1084  DependantJD.transferEmittedNodeDependencies(DependantMI,
1085  DependantName, MI);
1086 
1087  auto DependantSymI = DependantJD.Symbols.find(DependantName);
1088  assert(DependantSymI != DependantJD.Symbols.end() &&
1089  "Dependant has no entry in the Symbols table");
1090  auto &DependantSymEntry = DependantSymI->second;
1091 
1092  // If the dependant is emitted and this node was the last of its
1093  // unemitted dependencies then the dependant node is now ready, so
1094  // notify any pending queries on the dependant node.
1095  if (DependantSymEntry.getState() == SymbolState::Emitted &&
1096  DependantMI.UnemittedDependencies.empty()) {
1097  assert(DependantMI.Dependants.empty() &&
1098  "Dependants should be empty by now");
1099 
1100  // Since this dependant is now ready, we erase its
1101  // MaterializingInfo and update its materializing state.
1102  DependantSymEntry.setState(SymbolState::Ready);
1103  DependantJDReadySymbols.push_back(DependantName);
1104 
1105  for (auto &Q :
1106  DependantMI.takeQueriesMeeting(SymbolState::Ready)) {
1107  Q->notifySymbolMetRequiredState(
1108  DependantName, DependantSymI->second.getSymbol());
1109  if (Q->isComplete())
1110  CompletedQueries.insert(Q);
1111  Q->removeQueryDependence(DependantJD, DependantName);
1112  }
1113  DependantJD.MaterializingInfos.erase(DependantMII);
1114  }
1115  }
1116  }
1117 
1118  auto &ThisJDReadySymbols = ReadySymbols[this];
1119  MI.Dependants.clear();
1120  if (MI.UnemittedDependencies.empty()) {
1121  SymI->second.setState(SymbolState::Ready);
1122  ThisJDReadySymbols.push_back(Name);
1123  for (auto &Q : MI.takeQueriesMeeting(SymbolState::Ready)) {
1124  Q->notifySymbolMetRequiredState(Name, SymI->second.getSymbol());
1125  if (Q->isComplete())
1126  CompletedQueries.insert(Q);
1127  Q->removeQueryDependence(*this, Name);
1128  }
1129  MaterializingInfos.erase(MII);
1130  }
1131  }
1132 
1133  return Error::success();
1134  }))
1135  return Err;
1136 
1137  // Otherwise notify all the completed queries.
1138  for (auto &Q : CompletedQueries) {
1139  assert(Q->isComplete() && "Q is not complete");
1140  Q->handleComplete(ES);
1141  }
1142 
1143  return Error::success();
1144 }
1145 
1146 void JITDylib::unlinkMaterializationResponsibility(
1147  MaterializationResponsibility &MR) {
1148  ES.runSessionLocked([&]() {
1149  auto I = MRTrackers.find(&MR);
1150  assert(I != MRTrackers.end() && "MaterializationResponsibility not linked");
1151  MRTrackers.erase(I);
1152  });
1153 }
1154 
1155 std::pair<JITDylib::AsynchronousSymbolQuerySet,
1156  std::shared_ptr<SymbolDependenceMap>>
1157 JITDylib::failSymbols(FailedSymbolsWorklist Worklist) {
1158  AsynchronousSymbolQuerySet FailedQueries;
1159  auto FailedSymbolsMap = std::make_shared<SymbolDependenceMap>();
1160 
1161  while (!Worklist.empty()) {
1162  assert(Worklist.back().first && "Failed JITDylib can not be null");
1163  auto &JD = *Worklist.back().first;
1164  auto Name = std::move(Worklist.back().second);
1165  Worklist.pop_back();
1166 
1167  (*FailedSymbolsMap)[&JD].insert(Name);
1168 
1169  assert(JD.Symbols.count(Name) && "No symbol table entry for Name");
1170  auto &Sym = JD.Symbols[Name];
1171 
1172  // Move the symbol into the error state.
1173  // Note that this may be redundant: The symbol might already have been
1174  // moved to this state in response to the failure of a dependence.
1175  Sym.setFlags(Sym.getFlags() | JITSymbolFlags::HasError);
1176 
1177  // FIXME: Come up with a sane mapping of state to
1178  // presence-of-MaterializingInfo so that we can assert presence / absence
1179  // here, rather than testing it.
1180  auto MII = JD.MaterializingInfos.find(Name);
1181 
1182  if (MII == JD.MaterializingInfos.end())
1183  continue;
1184 
1185  auto &MI = MII->second;
1186 
1187  // Move all dependants to the error state and disconnect from them.
1188  for (auto &KV : MI.Dependants) {
1189  auto &DependantJD = *KV.first;
1190  for (auto &DependantName : KV.second) {
1191  assert(DependantJD.Symbols.count(DependantName) &&
1192  "No symbol table entry for DependantName");
1193  auto &DependantSym = DependantJD.Symbols[DependantName];
1194  DependantSym.setFlags(DependantSym.getFlags() |
1195  JITSymbolFlags::HasError);
1196 
1197  assert(DependantJD.MaterializingInfos.count(DependantName) &&
1198  "No MaterializingInfo for dependant");
1199  auto &DependantMI = DependantJD.MaterializingInfos[DependantName];
1200 
1201  auto UnemittedDepI = DependantMI.UnemittedDependencies.find(&JD);
1202  assert(UnemittedDepI != DependantMI.UnemittedDependencies.end() &&
1203  "No UnemittedDependencies entry for this JITDylib");
1204  assert(UnemittedDepI->second.count(Name) &&
1205  "No UnemittedDependencies entry for this symbol");
1206  UnemittedDepI->second.erase(Name);
1207  if (UnemittedDepI->second.empty())
1208  DependantMI.UnemittedDependencies.erase(UnemittedDepI);
1209 
1210  // If this symbol is already in the emitted state then we need to
1211  // take responsibility for failing its queries, so add it to the
1212  // worklist.
1213  if (DependantSym.getState() == SymbolState::Emitted) {
1214  assert(DependantMI.Dependants.empty() &&
1215  "Emitted symbol should not have dependants");
1216  Worklist.push_back(std::make_pair(&DependantJD, DependantName));
1217  }
1218  }
1219  }
1220  MI.Dependants.clear();
1221 
1222  // Disconnect from all unemitted depenencies.
1223  for (auto &KV : MI.UnemittedDependencies) {
1224  auto &UnemittedDepJD = *KV.first;
1225  for (auto &UnemittedDepName : KV.second) {
1226  auto UnemittedDepMII =
1227  UnemittedDepJD.MaterializingInfos.find(UnemittedDepName);
1228  assert(UnemittedDepMII != UnemittedDepJD.MaterializingInfos.end() &&
1229  "Missing MII for unemitted dependency");
1230  assert(UnemittedDepMII->second.Dependants.count(&JD) &&
1231  "JD not listed as a dependant of unemitted dependency");
1232  assert(UnemittedDepMII->second.Dependants[&JD].count(Name) &&
1233  "Name is not listed as a dependant of unemitted dependency");
1234  UnemittedDepMII->second.Dependants[&JD].erase(Name);
1235  if (UnemittedDepMII->second.Dependants[&JD].empty())
1236  UnemittedDepMII->second.Dependants.erase(&JD);
1237  }
1238  }
1239  MI.UnemittedDependencies.clear();
1240 
1241  // Collect queries to be failed for this MII.
1242  AsynchronousSymbolQueryList ToDetach;
1243  for (auto &Q : MII->second.pendingQueries()) {
1244  // Add the query to the list to be failed and detach it.
1245  FailedQueries.insert(Q);
1246  ToDetach.push_back(Q);
1247  }
1248  for (auto &Q : ToDetach)
1249  Q->detach();
1250 
1251  assert(MI.Dependants.empty() &&
1252  "Can not delete MaterializingInfo with dependants still attached");
1253  assert(MI.UnemittedDependencies.empty() &&
1254  "Can not delete MaterializingInfo with unemitted dependencies "
1255  "still attached");
1256  assert(!MI.hasQueriesPending() &&
1257  "Can not delete MaterializingInfo with queries pending");
1258  JD.MaterializingInfos.erase(MII);
1259  }
1260 
1261  return std::make_pair(std::move(FailedQueries), std::move(FailedSymbolsMap));
1262 }
1263 
1264 void JITDylib::setLinkOrder(JITDylibSearchOrder NewLinkOrder,
1265  bool LinkAgainstThisJITDylibFirst) {
1266  ES.runSessionLocked([&]() {
1267  if (LinkAgainstThisJITDylibFirst) {
1268  LinkOrder.clear();
1269  if (NewLinkOrder.empty() || NewLinkOrder.front().first != this)
1270  LinkOrder.push_back(
1271  std::make_pair(this, JITDylibLookupFlags::MatchAllSymbols));
1272  llvm::append_range(LinkOrder, NewLinkOrder);
1273  } else
1274  LinkOrder = std::move(NewLinkOrder);
1275  });
1276 }
1277 
1278 void JITDylib::addToLinkOrder(JITDylib &JD, JITDylibLookupFlags JDLookupFlags) {
1279  ES.runSessionLocked([&]() { LinkOrder.push_back({&JD, JDLookupFlags}); });
1280 }
1281 
1282 void JITDylib::replaceInLinkOrder(JITDylib &OldJD, JITDylib &NewJD,
1283  JITDylibLookupFlags JDLookupFlags) {
1284  ES.runSessionLocked([&]() {
1285  for (auto &KV : LinkOrder)
1286  if (KV.first == &OldJD) {
1287  KV = {&NewJD, JDLookupFlags};
1288  break;
1289  }
1290  });
1291 }
1292 
1293 void JITDylib::removeFromLinkOrder(JITDylib &JD) {
1294  ES.runSessionLocked([&]() {
1295  auto I = llvm::find_if(LinkOrder,
1296  [&](const JITDylibSearchOrder::value_type &KV) {
1297  return KV.first == &JD;
1298  });
1299  if (I != LinkOrder.end())
1300  LinkOrder.erase(I);
1301  });
1302 }
1303 
1305  return ES.runSessionLocked([&]() -> Error {
1306  using SymbolMaterializerItrPair =
1307  std::pair<SymbolTable::iterator, UnmaterializedInfosMap::iterator>;
1308  std::vector<SymbolMaterializerItrPair> SymbolsToRemove;
1309  SymbolNameSet Missing;
1311 
1312  for (auto &Name : Names) {
1313  auto I = Symbols.find(Name);
1314 
1315  // Note symbol missing.
1316  if (I == Symbols.end()) {
1317  Missing.insert(Name);
1318  continue;
1319  }
1320 
1321  // Note symbol materializing.
1322  if (I->second.getState() != SymbolState::NeverSearched &&
1323  I->second.getState() != SymbolState::Ready) {
1324  Materializing.insert(Name);
1325  continue;
1326  }
1327 
1328  auto UMII = I->second.hasMaterializerAttached()
1329  ? UnmaterializedInfos.find(Name)
1330  : UnmaterializedInfos.end();
1331  SymbolsToRemove.push_back(std::make_pair(I, UMII));
1332  }
1333 
1334  // If any of the symbols are not defined, return an error.
1335  if (!Missing.empty())
1336  return make_error<SymbolsNotFound>(std::move(Missing));
1337 
1338  // If any of the symbols are currently materializing, return an error.
1339  if (!Materializing.empty())
1340  return make_error<SymbolsCouldNotBeRemoved>(std::move(Materializing));
1341 
1342  // Remove the symbols.
1343  for (auto &SymbolMaterializerItrPair : SymbolsToRemove) {
1344  auto UMII = SymbolMaterializerItrPair.second;
1345 
1346  // If there is a materializer attached, call discard.
1347  if (UMII != UnmaterializedInfos.end()) {
1348  UMII->second->MU->doDiscard(*this, UMII->first);
1349  UnmaterializedInfos.erase(UMII);
1350  }
1351 
1352  auto SymI = SymbolMaterializerItrPair.first;
1353  Symbols.erase(SymI);
1354  }
1355 
1356  return Error::success();
1357  });
1358 }
1359 
1361  ES.runSessionLocked([&, this]() {
1362  OS << "JITDylib \"" << JITDylibName << "\" (ES: "
1363  << format("0x%016" PRIx64, reinterpret_cast<uintptr_t>(&ES)) << "):\n"
1364  << "Link order: " << LinkOrder << "\n"
1365  << "Symbol table:\n";
1366 
1367  for (auto &KV : Symbols) {
1368  OS << " \"" << *KV.first << "\": ";
1369  if (auto Addr = KV.second.getAddress())
1370  OS << format("0x%016" PRIx64, Addr) << ", " << KV.second.getFlags()
1371  << " ";
1372  else
1373  OS << "<not resolved> ";
1374 
1375  OS << KV.second.getFlags() << " " << KV.second.getState();
1376 
1377  if (KV.second.hasMaterializerAttached()) {
1378  OS << " (Materializer ";
1379  auto I = UnmaterializedInfos.find(KV.first);
1380  assert(I != UnmaterializedInfos.end() &&
1381  "Lazy symbol should have UnmaterializedInfo");
1382  OS << I->second->MU.get() << ", " << I->second->MU->getName() << ")\n";
1383  } else
1384  OS << "\n";
1385  }
1386 
1387  if (!MaterializingInfos.empty())
1388  OS << " MaterializingInfos entries:\n";
1389  for (auto &KV : MaterializingInfos) {
1390  OS << " \"" << *KV.first << "\":\n"
1391  << " " << KV.second.pendingQueries().size()
1392  << " pending queries: { ";
1393  for (const auto &Q : KV.second.pendingQueries())
1394  OS << Q.get() << " (" << Q->getRequiredState() << ") ";
1395  OS << "}\n Dependants:\n";
1396  for (auto &KV2 : KV.second.Dependants)
1397  OS << " " << KV2.first->getName() << ": " << KV2.second << "\n";
1398  OS << " Unemitted Dependencies:\n";
1399  for (auto &KV2 : KV.second.UnemittedDependencies)
1400  OS << " " << KV2.first->getName() << ": " << KV2.second << "\n";
1401  assert((Symbols[KV.first].getState() != SymbolState::Ready ||
1402  !KV.second.pendingQueries().empty() ||
1403  !KV.second.Dependants.empty() ||
1404  !KV.second.UnemittedDependencies.empty()) &&
1405  "Stale materializing info entry");
1406  }
1407  });
1408 }
1409 
1410 void JITDylib::MaterializingInfo::addQuery(
1411  std::shared_ptr<AsynchronousSymbolQuery> Q) {
1412 
1413  auto I = std::lower_bound(
1414  PendingQueries.rbegin(), PendingQueries.rend(), Q->getRequiredState(),
1415  [](const std::shared_ptr<AsynchronousSymbolQuery> &V, SymbolState S) {
1416  return V->getRequiredState() <= S;
1417  });
1418  PendingQueries.insert(I.base(), std::move(Q));
1419 }
1420 
1421 void JITDylib::MaterializingInfo::removeQuery(
1422  const AsynchronousSymbolQuery &Q) {
1423  // FIXME: Implement 'find_as' for shared_ptr<T>/T*.
1424  auto I = llvm::find_if(
1425  PendingQueries, [&Q](const std::shared_ptr<AsynchronousSymbolQuery> &V) {
1426  return V.get() == &Q;
1427  });
1428  assert(I != PendingQueries.end() &&
1429  "Query is not attached to this MaterializingInfo");
1430  PendingQueries.erase(I);
1431 }
1432 
1433 JITDylib::AsynchronousSymbolQueryList
1434 JITDylib::MaterializingInfo::takeQueriesMeeting(SymbolState RequiredState) {
1435  AsynchronousSymbolQueryList Result;
1436  while (!PendingQueries.empty()) {
1437  if (PendingQueries.back()->getRequiredState() > RequiredState)
1438  break;
1439 
1440  Result.push_back(std::move(PendingQueries.back()));
1441  PendingQueries.pop_back();
1442  }
1443 
1444  return Result;
1445 }
1446 
1447 JITDylib::JITDylib(ExecutionSession &ES, std::string Name)
1448  : ES(ES), JITDylibName(std::move(Name)) {
1449  LinkOrder.push_back({this, JITDylibLookupFlags::MatchAllSymbols});
1450 }
1451 
1452 ResourceTrackerSP JITDylib::getTracker(MaterializationResponsibility &MR) {
1453  auto I = MRTrackers.find(&MR);
1454  assert(I != MRTrackers.end() && "MR is not linked");
1455  assert(I->second && "Linked tracker is null");
1456  return I->second;
1457 }
1458 
1460  std::shared_ptr<SymbolDependenceMap>>
1461 JITDylib::removeTracker(ResourceTracker &RT) {
1462  // Note: Should be called under the session lock.
1463 
1464  SymbolNameVector SymbolsToRemove;
1465  std::vector<std::pair<JITDylib *, SymbolStringPtr>> SymbolsToFail;
1466 
1467  if (&RT == DefaultTracker.get()) {
1468  SymbolNameSet TrackedSymbols;
1469  for (auto &KV : TrackerSymbols)
1470  for (auto &Sym : KV.second)
1471  TrackedSymbols.insert(Sym);
1472 
1473  for (auto &KV : Symbols) {
1474  auto &Sym = KV.first;
1475  if (!TrackedSymbols.count(Sym))
1476  SymbolsToRemove.push_back(Sym);
1477  }
1478 
1479  DefaultTracker.reset();
1480  } else {
1481  /// Check for a non-default tracker.
1482  auto I = TrackerSymbols.find(&RT);
1483  if (I != TrackerSymbols.end()) {
1484  SymbolsToRemove = std::move(I->second);
1485  TrackerSymbols.erase(I);
1486  }
1487  // ... if not found this tracker was already defunct. Nothing to do.
1488  }
1489 
1490  for (auto &Sym : SymbolsToRemove) {
1491  assert(Symbols.count(Sym) && "Symbol not in symbol table");
1492 
1493  // If there is a MaterializingInfo then collect any queries to fail.
1494  auto MII = MaterializingInfos.find(Sym);
1495  if (MII != MaterializingInfos.end())
1496  SymbolsToFail.push_back({this, Sym});
1497  }
1498 
1499  AsynchronousSymbolQuerySet QueriesToFail;
1500  auto Result = failSymbols(std::move(SymbolsToFail));
1501 
1502  // Removed symbols should be taken out of the table altogether.
1503  for (auto &Sym : SymbolsToRemove) {
1504  auto I = Symbols.find(Sym);
1505  assert(I != Symbols.end() && "Symbol not present in table");
1506 
1507  // Remove Materializer if present.
1508  if (I->second.hasMaterializerAttached()) {
1509  // FIXME: Should this discard the symbols?
1510  UnmaterializedInfos.erase(Sym);
1511  } else {
1512  assert(!UnmaterializedInfos.count(Sym) &&
1513  "Symbol has materializer attached");
1514  }
1515 
1516  Symbols.erase(I);
1517  }
1518 
1519  return Result;
1520 }
1521 
1522 void JITDylib::transferTracker(ResourceTracker &DstRT, ResourceTracker &SrcRT) {
1523  assert(&DstRT != &SrcRT && "No-op transfers shouldn't call transferTracker");
1524  assert(&DstRT.getJITDylib() == this && "DstRT is not for this JITDylib");
1525  assert(&SrcRT.getJITDylib() == this && "SrcRT is not for this JITDylib");
1526 
1527  // Update trackers for any not-yet materialized units.
1528  for (auto &KV : UnmaterializedInfos) {
1529  if (KV.second->RT == &SrcRT)
1530  KV.second->RT = &DstRT;
1531  }
1532 
1533  // Update trackers for any active materialization responsibilities.
1534  for (auto &KV : MRTrackers) {
1535  if (KV.second == &SrcRT)
1536  KV.second = &DstRT;
1537  }
1538 
1539  // If we're transfering to the default tracker we just need to delete the
1540  // tracked symbols for the source tracker.
1541  if (&DstRT == DefaultTracker.get()) {
1542  TrackerSymbols.erase(&SrcRT);
1543  return;
1544  }
1545 
1546  // If we're transferring from the default tracker we need to find all
1547  // currently untracked symbols.
1548  if (&SrcRT == DefaultTracker.get()) {
1549  assert(!TrackerSymbols.count(&SrcRT) &&
1550  "Default tracker should not appear in TrackerSymbols");
1551 
1552  SymbolNameVector SymbolsToTrack;
1553 
1554  SymbolNameSet CurrentlyTrackedSymbols;
1555  for (auto &KV : TrackerSymbols)
1556  for (auto &Sym : KV.second)
1557  CurrentlyTrackedSymbols.insert(Sym);
1558 
1559  for (auto &KV : Symbols) {
1560  auto &Sym = KV.first;
1561  if (!CurrentlyTrackedSymbols.count(Sym))
1562  SymbolsToTrack.push_back(Sym);
1563  }
1564 
1565  TrackerSymbols[&DstRT] = std::move(SymbolsToTrack);
1566  return;
1567  }
1568 
1569  auto &DstTrackedSymbols = TrackerSymbols[&DstRT];
1570 
1571  // Finally if neither SrtRT or DstRT are the default tracker then
1572  // just append DstRT's tracked symbols to SrtRT's.
1573  auto SI = TrackerSymbols.find(&SrcRT);
1574  if (SI == TrackerSymbols.end())
1575  return;
1576 
1577  DstTrackedSymbols.reserve(DstTrackedSymbols.size() + SI->second.size());
1578  for (auto &Sym : SI->second)
1579  DstTrackedSymbols.push_back(std::move(Sym));
1580  TrackerSymbols.erase(SI);
1581 }
1582 
1583 Error JITDylib::defineImpl(MaterializationUnit &MU) {
1584 
1585  LLVM_DEBUG({ dbgs() << " " << MU.getSymbols() << "\n"; });
1586 
1587  SymbolNameSet Duplicates;
1588  std::vector<SymbolStringPtr> ExistingDefsOverridden;
1589  std::vector<SymbolStringPtr> MUDefsOverridden;
1590 
1591  for (const auto &KV : MU.getSymbols()) {
1592  auto I = Symbols.find(KV.first);
1593 
1594  if (I != Symbols.end()) {
1595  if (KV.second.isStrong()) {
1596  if (I->second.getFlags().isStrong() ||
1597  I->second.getState() > SymbolState::NeverSearched)
1598  Duplicates.insert(KV.first);
1599  else {
1600  assert(I->second.getState() == SymbolState::NeverSearched &&
1601  "Overridden existing def should be in the never-searched "
1602  "state");
1603  ExistingDefsOverridden.push_back(KV.first);
1604  }
1605  } else
1606  MUDefsOverridden.push_back(KV.first);
1607  }
1608  }
1609 
1610  // If there were any duplicate definitions then bail out.
1611  if (!Duplicates.empty()) {
1612  LLVM_DEBUG(
1613  { dbgs() << " Error: Duplicate symbols " << Duplicates << "\n"; });
1614  return make_error<DuplicateDefinition>(std::string(**Duplicates.begin()));
1615  }
1616 
1617  // Discard any overridden defs in this MU.
1618  LLVM_DEBUG({
1619  if (!MUDefsOverridden.empty())
1620  dbgs() << " Defs in this MU overridden: " << MUDefsOverridden << "\n";
1621  });
1622  for (auto &S : MUDefsOverridden)
1623  MU.doDiscard(*this, S);
1624 
1625  // Discard existing overridden defs.
1626  LLVM_DEBUG({
1627  if (!ExistingDefsOverridden.empty())
1628  dbgs() << " Existing defs overridden by this MU: " << MUDefsOverridden
1629  << "\n";
1630  });
1631  for (auto &S : ExistingDefsOverridden) {
1632 
1633  auto UMII = UnmaterializedInfos.find(S);
1634  assert(UMII != UnmaterializedInfos.end() &&
1635  "Overridden existing def should have an UnmaterializedInfo");
1636  UMII->second->MU->doDiscard(*this, S);
1637  }
1638 
1639  // Finally, add the defs from this MU.
1640  for (auto &KV : MU.getSymbols()) {
1641  auto &SymEntry = Symbols[KV.first];
1642  SymEntry.setFlags(KV.second);
1643  SymEntry.setState(SymbolState::NeverSearched);
1644  SymEntry.setMaterializerAttached(true);
1645  }
1646 
1647  return Error::success();
1648 }
1649 
1650 void JITDylib::installMaterializationUnit(
1651  std::unique_ptr<MaterializationUnit> MU, ResourceTracker &RT) {
1652 
1653  /// defineImpl succeeded.
1654  if (&RT != DefaultTracker.get()) {
1655  auto &TS = TrackerSymbols[&RT];
1656  TS.reserve(TS.size() + MU->getSymbols().size());
1657  for (auto &KV : MU->getSymbols())
1658  TS.push_back(KV.first);
1659  }
1660 
1661  auto UMI = std::make_shared<UnmaterializedInfo>(std::move(MU), &RT);
1662  for (auto &KV : UMI->MU->getSymbols())
1663  UnmaterializedInfos[KV.first] = UMI;
1664 }
1665 
1666 void JITDylib::detachQueryHelper(AsynchronousSymbolQuery &Q,
1667  const SymbolNameSet &QuerySymbols) {
1668  for (auto &QuerySymbol : QuerySymbols) {
1669  assert(MaterializingInfos.count(QuerySymbol) &&
1670  "QuerySymbol does not have MaterializingInfo");
1671  auto &MI = MaterializingInfos[QuerySymbol];
1672  MI.removeQuery(Q);
1673  }
1674 }
1675 
1676 void JITDylib::transferEmittedNodeDependencies(
1677  MaterializingInfo &DependantMI, const SymbolStringPtr &DependantName,
1678  MaterializingInfo &EmittedMI) {
1679  for (auto &KV : EmittedMI.UnemittedDependencies) {
1680  auto &DependencyJD = *KV.first;
1681  SymbolNameSet *UnemittedDependenciesOnDependencyJD = nullptr;
1682 
1683  for (auto &DependencyName : KV.second) {
1684  auto &DependencyMI = DependencyJD.MaterializingInfos[DependencyName];
1685 
1686  // Do not add self dependencies.
1687  if (&DependencyMI == &DependantMI)
1688  continue;
1689 
1690  // If we haven't looked up the dependencies for DependencyJD yet, do it
1691  // now and cache the result.
1692  if (!UnemittedDependenciesOnDependencyJD)
1693  UnemittedDependenciesOnDependencyJD =
1694  &DependantMI.UnemittedDependencies[&DependencyJD];
1695 
1696  DependencyMI.Dependants[this].insert(DependantName);
1697  UnemittedDependenciesOnDependencyJD->insert(DependencyName);
1698  }
1699  }
1700 }
1701 
1703 
1705  ExecutionSession &ES,
1706  const DenseMap<JITDylib *, SymbolLookupSet> &InitSyms) {
1707 
1708  DenseMap<JITDylib *, SymbolMap> CompoundResult;
1709  Error CompoundErr = Error::success();
1710  std::mutex LookupMutex;
1711  std::condition_variable CV;
1712  uint64_t Count = InitSyms.size();
1713 
1714  LLVM_DEBUG({
1715  dbgs() << "Issuing init-symbol lookup:\n";
1716  for (auto &KV : InitSyms)
1717  dbgs() << " " << KV.first->getName() << ": " << KV.second << "\n";
1718  });
1719 
1720  for (auto &KV : InitSyms) {
1721  auto *JD = KV.first;
1722  auto Names = std::move(KV.second);
1723  ES.lookup(
1726  std::move(Names), SymbolState::Ready,
1727  [&, JD](Expected<SymbolMap> Result) {
1728  {
1729  std::lock_guard<std::mutex> Lock(LookupMutex);
1730  --Count;
1731  if (Result) {
1732  assert(!CompoundResult.count(JD) &&
1733  "Duplicate JITDylib in lookup?");
1734  CompoundResult[JD] = std::move(*Result);
1735  } else
1736  CompoundErr =
1737  joinErrors(std::move(CompoundErr), Result.takeError());
1738  }
1739  CV.notify_one();
1740  },
1742  }
1743 
1744  std::unique_lock<std::mutex> Lock(LookupMutex);
1745  CV.wait(Lock, [&] { return Count == 0 || CompoundErr; });
1746 
1747  if (CompoundErr)
1748  return std::move(CompoundErr);
1749 
1750  return std::move(CompoundResult);
1751 }
1752 
1753 void Task::anchor() {}
1754 
1756  OS << "Materialization task: " << MU->getName() << " in "
1757  << MR->getTargetJITDylib().getName();
1758 }
1759 
1760 void MaterializationTask::run() { MU->materialize(std::move(MR)); }
1761 
1762 ExecutionSession::ExecutionSession(std::shared_ptr<SymbolStringPool> SSP)
1763  : SSP(SSP ? std::move(SSP) : std::make_shared<SymbolStringPool>()) {}
1764 
1766  LLVM_DEBUG(dbgs() << "Ending ExecutionSession " << this << "\n");
1767 
1768  std::vector<JITDylibSP> JITDylibsToClose = runSessionLocked([&] {
1769  SessionOpen = false;
1770  return std::move(JDs);
1771  });
1772 
1773  // TODO: notifiy platform? run static deinits?
1774 
1775  Error Err = Error::success();
1776  for (auto &JD : JITDylibsToClose)
1777  Err = joinErrors(std::move(Err), JD->clear());
1778  return Err;
1779 }
1780 
1782  runSessionLocked([&] { ResourceManagers.push_back(&RM); });
1783 }
1784 
1786  runSessionLocked([&] {
1787  assert(!ResourceManagers.empty() && "No managers registered");
1788  if (ResourceManagers.back() == &RM)
1789  ResourceManagers.pop_back();
1790  else {
1791  auto I = llvm::find(ResourceManagers, &RM);
1792  assert(I != ResourceManagers.end() && "RM not registered");
1793  ResourceManagers.erase(I);
1794  }
1795  });
1796 }
1797 
1799  return runSessionLocked([&, this]() -> JITDylib * {
1800  for (auto &JD : JDs)
1801  if (JD->getName() == Name)
1802  return JD.get();
1803  return nullptr;
1804  });
1805 }
1806 
1808  assert(!getJITDylibByName(Name) && "JITDylib with that name already exists");
1809  return runSessionLocked([&, this]() -> JITDylib & {
1810  JDs.push_back(new JITDylib(*this, std::move(Name)));
1811  return *JDs.back();
1812  });
1813 }
1814 
1816  auto &JD = createBareJITDylib(Name);
1817  if (P)
1818  if (auto Err = P->setupJITDylib(JD))
1819  return std::move(Err);
1820  return JD;
1821 }
1822 
1823 std::vector<JITDylibSP> JITDylib::getDFSLinkOrder(ArrayRef<JITDylibSP> JDs) {
1824  if (JDs.empty())
1825  return {};
1826 
1827  auto &ES = JDs.front()->getExecutionSession();
1828  return ES.runSessionLocked([&]() {
1829  DenseSet<JITDylib *> Visited;
1830  std::vector<JITDylibSP> Result;
1831 
1832  for (auto &JD : JDs) {
1833 
1834  if (Visited.count(JD.get()))
1835  continue;
1836 
1837  SmallVector<JITDylibSP, 64> WorkStack;
1838  WorkStack.push_back(JD);
1839  Visited.insert(JD.get());
1840 
1841  while (!WorkStack.empty()) {
1842  Result.push_back(std::move(WorkStack.back()));
1843  WorkStack.pop_back();
1844 
1845  for (auto &KV : llvm::reverse(Result.back()->LinkOrder)) {
1846  auto &JD = *KV.first;
1847  if (Visited.count(&JD))
1848  continue;
1849  Visited.insert(&JD);
1850  WorkStack.push_back(&JD);
1851  }
1852  }
1853  }
1854  return Result;
1855  });
1856 }
1857 
1858 std::vector<JITDylibSP>
1860  auto Tmp = getDFSLinkOrder(JDs);
1861  std::reverse(Tmp.begin(), Tmp.end());
1862  return Tmp;
1863 }
1864 
1865 std::vector<JITDylibSP> JITDylib::getDFSLinkOrder() {
1866  return getDFSLinkOrder({this});
1867 }
1868 
1869 std::vector<JITDylibSP> JITDylib::getReverseDFSLinkOrder() {
1870  return getReverseDFSLinkOrder({this});
1871 }
1872 
1874  LookupKind K, JITDylibSearchOrder SearchOrder, SymbolLookupSet LookupSet,
1875  unique_function<void(Expected<SymbolFlagsMap>)> OnComplete) {
1876 
1877  OL_applyQueryPhase1(std::make_unique<InProgressLookupFlagsState>(
1878  K, std::move(SearchOrder), std::move(LookupSet),
1879  std::move(OnComplete)),
1880  Error::success());
1881 }
1882 
1885  SymbolLookupSet LookupSet) {
1886 
1887  std::promise<MSVCPExpected<SymbolFlagsMap>> ResultP;
1888  OL_applyQueryPhase1(std::make_unique<InProgressLookupFlagsState>(
1889  K, std::move(SearchOrder), std::move(LookupSet),
1890  [&ResultP](Expected<SymbolFlagsMap> Result) {
1891  ResultP.set_value(std::move(Result));
1892  }),
1893  Error::success());
1894 
1895  auto ResultF = ResultP.get_future();
1896  return ResultF.get();
1897 }
1898 
1900  LookupKind K, const JITDylibSearchOrder &SearchOrder,
1901  SymbolLookupSet Symbols, SymbolState RequiredState,
1902  SymbolsResolvedCallback NotifyComplete,
1903  RegisterDependenciesFunction RegisterDependencies) {
1904 
1905  LLVM_DEBUG({
1906  runSessionLocked([&]() {
1907  dbgs() << "Looking up " << Symbols << " in " << SearchOrder
1908  << " (required state: " << RequiredState << ")\n";
1909  });
1910  });
1911 
1912  // lookup can be re-entered recursively if running on a single thread. Run any
1913  // outstanding MUs in case this query depends on them, otherwise this lookup
1914  // will starve waiting for a result from an MU that is stuck in the queue.
1915  dispatchOutstandingMUs();
1916 
1917  auto Unresolved = std::move(Symbols);
1918  auto Q = std::make_shared<AsynchronousSymbolQuery>(Unresolved, RequiredState,
1919  std::move(NotifyComplete));
1920 
1921  auto IPLS = std::make_unique<InProgressFullLookupState>(
1922  K, SearchOrder, std::move(Unresolved), RequiredState, std::move(Q),
1923  std::move(RegisterDependencies));
1924 
1925  OL_applyQueryPhase1(std::move(IPLS), Error::success());
1926 }
1927 
1930  const SymbolLookupSet &Symbols, LookupKind K,
1931  SymbolState RequiredState,
1932  RegisterDependenciesFunction RegisterDependencies) {
1933 #if LLVM_ENABLE_THREADS
1934  // In the threaded case we use promises to return the results.
1935  std::promise<SymbolMap> PromisedResult;
1936  Error ResolutionError = Error::success();
1937 
1938  auto NotifyComplete = [&](Expected<SymbolMap> R) {
1939  if (R)
1940  PromisedResult.set_value(std::move(*R));
1941  else {
1942  ErrorAsOutParameter _(&ResolutionError);
1943  ResolutionError = R.takeError();
1944  PromisedResult.set_value(SymbolMap());
1945  }
1946  };
1947 
1948 #else
1949  SymbolMap Result;
1950  Error ResolutionError = Error::success();
1951 
1952  auto NotifyComplete = [&](Expected<SymbolMap> R) {
1953  ErrorAsOutParameter _(&ResolutionError);
1954  if (R)
1955  Result = std::move(*R);
1956  else
1957  ResolutionError = R.takeError();
1958  };
1959 #endif
1960 
1961  // Perform the asynchronous lookup.
1962  lookup(K, SearchOrder, Symbols, RequiredState, NotifyComplete,
1963  RegisterDependencies);
1964 
1965 #if LLVM_ENABLE_THREADS
1966  auto ResultFuture = PromisedResult.get_future();
1967  auto Result = ResultFuture.get();
1968 
1969  if (ResolutionError)
1970  return std::move(ResolutionError);
1971 
1972  return std::move(Result);
1973 
1974 #else
1975  if (ResolutionError)
1976  return std::move(ResolutionError);
1977 
1978  return Result;
1979 #endif
1980 }
1981 
1984  SymbolStringPtr Name, SymbolState RequiredState) {
1985  SymbolLookupSet Names({Name});
1986 
1987  if (auto ResultMap = lookup(SearchOrder, std::move(Names), LookupKind::Static,
1988  RequiredState, NoDependenciesToRegister)) {
1989  assert(ResultMap->size() == 1 && "Unexpected number of results");
1990  assert(ResultMap->count(Name) && "Missing result for symbol");
1991  return std::move(ResultMap->begin()->second);
1992  } else
1993  return ResultMap.takeError();
1994 }
1995 
1998  SymbolState RequiredState) {
1999  return lookup(makeJITDylibSearchOrder(SearchOrder), Name, RequiredState);
2000 }
2001 
2004  SymbolState RequiredState) {
2005  return lookup(SearchOrder, intern(Name), RequiredState);
2006 }
2007 
2009  runSessionLocked([this, &OS]() {
2010  for (auto &JD : JDs)
2011  JD->dump(OS);
2012  });
2013 }
2014 
2015 void ExecutionSession::dispatchOutstandingMUs() {
2016  LLVM_DEBUG(dbgs() << "Dispatching MaterializationUnits...\n");
2017  while (1) {
2019  std::unique_ptr<MaterializationResponsibility>>>
2020  JMU;
2021 
2022  {
2023  std::lock_guard<std::recursive_mutex> Lock(OutstandingMUsMutex);
2024  if (!OutstandingMUs.empty()) {
2025  JMU.emplace(std::move(OutstandingMUs.back()));
2026  OutstandingMUs.pop_back();
2027  }
2028  }
2029 
2030  if (!JMU)
2031  break;
2032 
2033  assert(JMU->first && "No MU?");
2034  LLVM_DEBUG(dbgs() << " Dispatching \"" << JMU->first->getName() << "\"\n");
2035  dispatchTask(std::make_unique<MaterializationTask>(std::move(JMU->first),
2036  std::move(JMU->second)));
2037  }
2038  LLVM_DEBUG(dbgs() << "Done dispatching MaterializationUnits.\n");
2039 }
2040 
2041 Error ExecutionSession::removeResourceTracker(ResourceTracker &RT) {
2042  LLVM_DEBUG({
2043  dbgs() << "In " << RT.getJITDylib().getName() << " removing tracker "
2044  << formatv("{0:x}", RT.getKeyUnsafe()) << "\n";
2045  });
2046  std::vector<ResourceManager *> CurrentResourceManagers;
2047 
2049  std::shared_ptr<SymbolDependenceMap> FailedSymbols;
2050 
2051  runSessionLocked([&] {
2052  CurrentResourceManagers = ResourceManagers;
2053  RT.makeDefunct();
2054  std::tie(QueriesToFail, FailedSymbols) = RT.getJITDylib().removeTracker(RT);
2055  });
2056 
2057  Error Err = Error::success();
2058 
2059  for (auto *L : reverse(CurrentResourceManagers))
2060  Err =
2061  joinErrors(std::move(Err), L->handleRemoveResources(RT.getKeyUnsafe()));
2062 
2063  for (auto &Q : QueriesToFail)
2064  Q->handleFailed(make_error<FailedToMaterialize>(FailedSymbols));
2065 
2066  return Err;
2067 }
2068 
2069 void ExecutionSession::transferResourceTracker(ResourceTracker &DstRT,
2070  ResourceTracker &SrcRT) {
2071  LLVM_DEBUG({
2072  dbgs() << "In " << SrcRT.getJITDylib().getName()
2073  << " transfering resources from tracker "
2074  << formatv("{0:x}", SrcRT.getKeyUnsafe()) << " to tracker "
2075  << formatv("{0:x}", DstRT.getKeyUnsafe()) << "\n";
2076  });
2077 
2078  // No-op transfers are allowed and do not invalidate the source.
2079  if (&DstRT == &SrcRT)
2080  return;
2081 
2082  assert(&DstRT.getJITDylib() == &SrcRT.getJITDylib() &&
2083  "Can't transfer resources between JITDylibs");
2084  runSessionLocked([&]() {
2085  SrcRT.makeDefunct();
2086  auto &JD = DstRT.getJITDylib();
2087  JD.transferTracker(DstRT, SrcRT);
2088  for (auto *L : reverse(ResourceManagers))
2089  L->handleTransferResources(DstRT.getKeyUnsafe(), SrcRT.getKeyUnsafe());
2090  });
2091 }
2092 
2093 void ExecutionSession::destroyResourceTracker(ResourceTracker &RT) {
2094  runSessionLocked([&]() {
2095  LLVM_DEBUG({
2096  dbgs() << "In " << RT.getJITDylib().getName() << " destroying tracker "
2097  << formatv("{0:x}", RT.getKeyUnsafe()) << "\n";
2098  });
2099  if (!RT.isDefunct())
2100  transferResourceTracker(*RT.getJITDylib().getDefaultResourceTracker(),
2101  RT);
2102  });
2103 }
2104 
2105 Error ExecutionSession::IL_updateCandidatesFor(
2106  JITDylib &JD, JITDylibLookupFlags JDLookupFlags,
2107  SymbolLookupSet &Candidates, SymbolLookupSet *NonCandidates) {
2108  return Candidates.forEachWithRemoval(
2109  [&](const SymbolStringPtr &Name,
2110  SymbolLookupFlags SymLookupFlags) -> Expected<bool> {
2111  /// Search for the symbol. If not found then continue without
2112  /// removal.
2113  auto SymI = JD.Symbols.find(Name);
2114  if (SymI == JD.Symbols.end())
2115  return false;
2116 
2117  // If this is a non-exported symbol and we're matching exported
2118  // symbols only then remove this symbol from the candidates list.
2119  //
2120  // If we're tracking non-candidates then add this to the non-candidate
2121  // list.
2122  if (!SymI->second.getFlags().isExported() &&
2124  if (NonCandidates)
2125  NonCandidates->add(Name, SymLookupFlags);
2126  return true;
2127  }
2128 
2129  // If we match against a materialization-side-effects only symbol
2130  // then make sure it is weakly-referenced. Otherwise bail out with
2131  // an error.
2132  // FIXME: Use a "materialization-side-effects-only symbols must be
2133  // weakly referenced" specific error here to reduce confusion.
2134  if (SymI->second.getFlags().hasMaterializationSideEffectsOnly() &&
2136  return make_error<SymbolsNotFound>(SymbolNameVector({Name}));
2137 
2138  // If we matched against this symbol but it is in the error state
2139  // then bail out and treat it as a failure to materialize.
2140  if (SymI->second.getFlags().hasError()) {
2141  auto FailedSymbolsMap = std::make_shared<SymbolDependenceMap>();
2142  (*FailedSymbolsMap)[&JD] = {Name};
2143  return make_error<FailedToMaterialize>(std::move(FailedSymbolsMap));
2144  }
2145 
2146  // Otherwise this is a match. Remove it from the candidate set.
2147  return true;
2148  });
2149 }
2150 
2151 void ExecutionSession::OL_applyQueryPhase1(
2152  std::unique_ptr<InProgressLookupState> IPLS, Error Err) {
2153 
2154  LLVM_DEBUG({
2155  dbgs() << "Entering OL_applyQueryPhase1:\n"
2156  << " Lookup kind: " << IPLS->K << "\n"
2157  << " Search order: " << IPLS->SearchOrder
2158  << ", Current index = " << IPLS->CurSearchOrderIndex
2159  << (IPLS->NewJITDylib ? " (entering new JITDylib)" : "") << "\n"
2160  << " Lookup set: " << IPLS->LookupSet << "\n"
2161  << " Definition generator candidates: "
2162  << IPLS->DefGeneratorCandidates << "\n"
2163  << " Definition generator non-candidates: "
2164  << IPLS->DefGeneratorNonCandidates << "\n";
2165  });
2166 
2167  // FIXME: We should attach the query as we go: This provides a result in a
2168  // single pass in the common case where all symbols have already reached the
2169  // required state. The query could be detached again in the 'fail' method on
2170  // IPLS. Phase 2 would be reduced to collecting and dispatching the MUs.
2171 
2172  while (IPLS->CurSearchOrderIndex != IPLS->SearchOrder.size()) {
2173 
2174  // If we've been handed an error or received one back from a generator then
2175  // fail the query. We don't need to unlink: At this stage the query hasn't
2176  // actually been lodged.
2177  if (Err)
2178  return IPLS->fail(std::move(Err));
2179 
2180  // Get the next JITDylib and lookup flags.
2181  auto &KV = IPLS->SearchOrder[IPLS->CurSearchOrderIndex];
2182  auto &JD = *KV.first;
2183  auto JDLookupFlags = KV.second;
2184 
2185  LLVM_DEBUG({
2186  dbgs() << "Visiting \"" << JD.getName() << "\" (" << JDLookupFlags
2187  << ") with lookup set " << IPLS->LookupSet << ":\n";
2188  });
2189 
2190  // If we've just reached a new JITDylib then perform some setup.
2191  if (IPLS->NewJITDylib) {
2192 
2193  // Acquire the generator lock for this JITDylib.
2194  IPLS->GeneratorLock = std::unique_lock<std::mutex>(JD.GeneratorsMutex);
2195 
2196  // Add any non-candidates from the last JITDylib (if any) back on to the
2197  // list of definition candidates for this JITDylib, reset definition
2198  // non-candiates to the empty set.
2199  SymbolLookupSet Tmp;
2200  std::swap(IPLS->DefGeneratorNonCandidates, Tmp);
2201  IPLS->DefGeneratorCandidates.append(std::move(Tmp));
2202 
2203  LLVM_DEBUG({
2204  dbgs() << " First time visiting " << JD.getName()
2205  << ", resetting candidate sets and building generator stack\n";
2206  });
2207 
2208  // Build the definition generator stack for this JITDylib.
2209  for (auto &DG : reverse(JD.DefGenerators))
2210  IPLS->CurDefGeneratorStack.push_back(DG);
2211 
2212  // Flag that we've done our initialization.
2213  IPLS->NewJITDylib = false;
2214  }
2215 
2216  // Remove any generation candidates that are already defined (and match) in
2217  // this JITDylib.
2218  runSessionLocked([&] {
2219  // Update the list of candidates (and non-candidates) for definition
2220  // generation.
2221  LLVM_DEBUG(dbgs() << " Updating candidate set...\n");
2222  Err = IL_updateCandidatesFor(
2223  JD, JDLookupFlags, IPLS->DefGeneratorCandidates,
2224  JD.DefGenerators.empty() ? nullptr
2225  : &IPLS->DefGeneratorNonCandidates);
2226  LLVM_DEBUG({
2227  dbgs() << " Remaining candidates = " << IPLS->DefGeneratorCandidates
2228  << "\n";
2229  });
2230  });
2231 
2232  // If we encountered an error while filtering generation candidates then
2233  // bail out.
2234  if (Err)
2235  return IPLS->fail(std::move(Err));
2236 
2237  /// Apply any definition generators on the stack.
2238  LLVM_DEBUG({
2239  if (IPLS->CurDefGeneratorStack.empty())
2240  LLVM_DEBUG(dbgs() << " No generators to run for this JITDylib.\n");
2241  else if (IPLS->DefGeneratorCandidates.empty())
2242  LLVM_DEBUG(dbgs() << " No candidates to generate.\n");
2243  else
2244  dbgs() << " Running " << IPLS->CurDefGeneratorStack.size()
2245  << " remaining generators for "
2246  << IPLS->DefGeneratorCandidates.size() << " candidates\n";
2247  });
2248  while (!IPLS->CurDefGeneratorStack.empty() &&
2249  !IPLS->DefGeneratorCandidates.empty()) {
2250  auto DG = IPLS->CurDefGeneratorStack.back().lock();
2251  IPLS->CurDefGeneratorStack.pop_back();
2252 
2253  if (!DG)
2254  return IPLS->fail(make_error<StringError>(
2255  "DefinitionGenerator removed while lookup in progress",
2257 
2258  auto K = IPLS->K;
2259  auto &LookupSet = IPLS->DefGeneratorCandidates;
2260 
2261  // Run the generator. If the generator takes ownership of QA then this
2262  // will break the loop.
2263  {
2264  LLVM_DEBUG(dbgs() << " Attempting to generate " << LookupSet << "\n");
2265  LookupState LS(std::move(IPLS));
2266  Err = DG->tryToGenerate(LS, K, JD, JDLookupFlags, LookupSet);
2267  IPLS = std::move(LS.IPLS);
2268  }
2269 
2270  // If there was an error then fail the query.
2271  if (Err) {
2272  LLVM_DEBUG({
2273  dbgs() << " Error attempting to generate " << LookupSet << "\n";
2274  });
2275  assert(IPLS && "LS cannot be retained if error is returned");
2276  return IPLS->fail(std::move(Err));
2277  }
2278 
2279  // Otherwise if QA was captured then break the loop.
2280  if (!IPLS) {
2281  LLVM_DEBUG(
2282  { dbgs() << " LookupState captured. Exiting phase1 for now.\n"; });
2283  return;
2284  }
2285 
2286  // Otherwise if we're continuing around the loop then update candidates
2287  // for the next round.
2288  runSessionLocked([&] {
2289  LLVM_DEBUG(dbgs() << " Updating candidate set post-generation\n");
2290  Err = IL_updateCandidatesFor(
2291  JD, JDLookupFlags, IPLS->DefGeneratorCandidates,
2292  JD.DefGenerators.empty() ? nullptr
2293  : &IPLS->DefGeneratorNonCandidates);
2294  });
2295 
2296  // If updating candidates failed then fail the query.
2297  if (Err) {
2298  LLVM_DEBUG(dbgs() << " Error encountered while updating candidates\n");
2299  return IPLS->fail(std::move(Err));
2300  }
2301  }
2302 
2303  // If we get here then we've moved on to the next JITDylib.
2304  LLVM_DEBUG(dbgs() << "Phase 1 moving to next JITDylib.\n");
2305  ++IPLS->CurSearchOrderIndex;
2306  IPLS->NewJITDylib = true;
2307  }
2308 
2309  // Remove any weakly referenced candidates that could not be found/generated.
2310  IPLS->DefGeneratorCandidates.remove_if(
2311  [](const SymbolStringPtr &Name, SymbolLookupFlags SymLookupFlags) {
2312  return SymLookupFlags == SymbolLookupFlags::WeaklyReferencedSymbol;
2313  });
2314 
2315  // If we get here then we've finished searching all JITDylibs.
2316  // If we matched all symbols then move to phase 2, otherwise fail the query
2317  // with a SymbolsNotFound error.
2318  if (IPLS->DefGeneratorCandidates.empty()) {
2319  LLVM_DEBUG(dbgs() << "Phase 1 succeeded.\n");
2320  IPLS->complete(std::move(IPLS));
2321  } else {
2322  LLVM_DEBUG(dbgs() << "Phase 1 failed with unresolved symbols.\n");
2323  IPLS->fail(make_error<SymbolsNotFound>(
2324  IPLS->DefGeneratorCandidates.getSymbolNames()));
2325  }
2326 }
2327 
2328 void ExecutionSession::OL_completeLookup(
2329  std::unique_ptr<InProgressLookupState> IPLS,
2330  std::shared_ptr<AsynchronousSymbolQuery> Q,
2331  RegisterDependenciesFunction RegisterDependencies) {
2332 
2333  LLVM_DEBUG({
2334  dbgs() << "Entering OL_completeLookup:\n"
2335  << " Lookup kind: " << IPLS->K << "\n"
2336  << " Search order: " << IPLS->SearchOrder
2337  << ", Current index = " << IPLS->CurSearchOrderIndex
2338  << (IPLS->NewJITDylib ? " (entering new JITDylib)" : "") << "\n"
2339  << " Lookup set: " << IPLS->LookupSet << "\n"
2340  << " Definition generator candidates: "
2341  << IPLS->DefGeneratorCandidates << "\n"
2342  << " Definition generator non-candidates: "
2343  << IPLS->DefGeneratorNonCandidates << "\n";
2344  });
2345 
2346  bool QueryComplete = false;
2347  DenseMap<JITDylib *, JITDylib::UnmaterializedInfosList> CollectedUMIs;
2348 
2349  auto LodgingErr = runSessionLocked([&]() -> Error {
2350  for (auto &KV : IPLS->SearchOrder) {
2351  auto &JD = *KV.first;
2352  auto JDLookupFlags = KV.second;
2353  LLVM_DEBUG({
2354  dbgs() << "Visiting \"" << JD.getName() << "\" (" << JDLookupFlags
2355  << ") with lookup set " << IPLS->LookupSet << ":\n";
2356  });
2357 
2358  auto Err = IPLS->LookupSet.forEachWithRemoval(
2359  [&](const SymbolStringPtr &Name,
2360  SymbolLookupFlags SymLookupFlags) -> Expected<bool> {
2361  LLVM_DEBUG({
2362  dbgs() << " Attempting to match \"" << Name << "\" ("
2363  << SymLookupFlags << ")... ";
2364  });
2365 
2366  /// Search for the symbol. If not found then continue without
2367  /// removal.
2368  auto SymI = JD.Symbols.find(Name);
2369  if (SymI == JD.Symbols.end()) {
2370  LLVM_DEBUG(dbgs() << "skipping: not present\n");
2371  return false;
2372  }
2373 
2374  // If this is a non-exported symbol and we're matching exported
2375  // symbols only then skip this symbol without removal.
2376  if (!SymI->second.getFlags().isExported() &&
2377  JDLookupFlags ==
2379  LLVM_DEBUG(dbgs() << "skipping: not exported\n");
2380  return false;
2381  }
2382 
2383  // If we match against a materialization-side-effects only symbol
2384  // then make sure it is weakly-referenced. Otherwise bail out with
2385  // an error.
2386  // FIXME: Use a "materialization-side-effects-only symbols must be
2387  // weakly referenced" specific error here to reduce confusion.
2388  if (SymI->second.getFlags().hasMaterializationSideEffectsOnly() &&
2389  SymLookupFlags != SymbolLookupFlags::WeaklyReferencedSymbol) {
2390  LLVM_DEBUG({
2391  dbgs() << "error: "
2392  "required, but symbol is has-side-effects-only\n";
2393  });
2394  return make_error<SymbolsNotFound>(SymbolNameVector({Name}));
2395  }
2396 
2397  // If we matched against this symbol but it is in the error state
2398  // then bail out and treat it as a failure to materialize.
2399  if (SymI->second.getFlags().hasError()) {
2400  LLVM_DEBUG(dbgs() << "error: symbol is in error state\n");
2401  auto FailedSymbolsMap = std::make_shared<SymbolDependenceMap>();
2402  (*FailedSymbolsMap)[&JD] = {Name};
2403  return make_error<FailedToMaterialize>(
2404  std::move(FailedSymbolsMap));
2405  }
2406 
2407  // Otherwise this is a match.
2408 
2409  // If this symbol is already in the requried state then notify the
2410  // query, remove the symbol and continue.
2411  if (SymI->second.getState() >= Q->getRequiredState()) {
2412  LLVM_DEBUG(dbgs()
2413  << "matched, symbol already in required state\n");
2414  Q->notifySymbolMetRequiredState(Name, SymI->second.getSymbol());
2415  return true;
2416  }
2417 
2418  // Otherwise this symbol does not yet meet the required state. Check
2419  // whether it has a materializer attached, and if so prepare to run
2420  // it.
2421  if (SymI->second.hasMaterializerAttached()) {
2422  assert(SymI->second.getAddress() == 0 &&
2423  "Symbol not resolved but already has address?");
2424  auto UMII = JD.UnmaterializedInfos.find(Name);
2425  assert(UMII != JD.UnmaterializedInfos.end() &&
2426  "Lazy symbol should have UnmaterializedInfo");
2427 
2428  auto UMI = UMII->second;
2429  assert(UMI->MU && "Materializer should not be null");
2430  assert(UMI->RT && "Tracker should not be null");
2431  LLVM_DEBUG({
2432  dbgs() << "matched, preparing to dispatch MU@" << UMI->MU.get()
2433  << " (" << UMI->MU->getName() << ")\n";
2434  });
2435 
2436  // Move all symbols associated with this MaterializationUnit into
2437  // materializing state.
2438  for (auto &KV : UMI->MU->getSymbols()) {
2439  auto SymK = JD.Symbols.find(KV.first);
2440  assert(SymK != JD.Symbols.end() &&
2441  "No entry for symbol covered by MaterializationUnit");
2442  SymK->second.setMaterializerAttached(false);
2443  SymK->second.setState(SymbolState::Materializing);
2444  JD.UnmaterializedInfos.erase(KV.first);
2445  }
2446 
2447  // Add MU to the list of MaterializationUnits to be materialized.
2448  CollectedUMIs[&JD].push_back(std::move(UMI));
2449  } else
2450  LLVM_DEBUG(dbgs() << "matched, registering query");
2451 
2452  // Add the query to the PendingQueries list and continue, deleting
2453  // the element from the lookup set.
2454  assert(SymI->second.getState() != SymbolState::NeverSearched &&
2455  SymI->second.getState() != SymbolState::Ready &&
2456  "By this line the symbol should be materializing");
2457  auto &MI = JD.MaterializingInfos[Name];
2458  MI.addQuery(Q);
2459  Q->addQueryDependence(JD, Name);
2460 
2461  return true;
2462  });
2463 
2464  // Handle failure.
2465  if (Err) {
2466 
2467  LLVM_DEBUG({
2468  dbgs() << "Lookup failed. Detaching query and replacing MUs.\n";
2469  });
2470 
2471  // Detach the query.
2472  Q->detach();
2473 
2474  // Replace the MUs.
2475  for (auto &KV : CollectedUMIs) {
2476  auto &JD = *KV.first;
2477  for (auto &UMI : KV.second)
2478  for (auto &KV2 : UMI->MU->getSymbols()) {
2479  assert(!JD.UnmaterializedInfos.count(KV2.first) &&
2480  "Unexpected materializer in map");
2481  auto SymI = JD.Symbols.find(KV2.first);
2482  assert(SymI != JD.Symbols.end() && "Missing symbol entry");
2483  assert(SymI->second.getState() == SymbolState::Materializing &&
2484  "Can not replace symbol that is not materializing");
2485  assert(!SymI->second.hasMaterializerAttached() &&
2486  "MaterializerAttached flag should not be set");
2487  SymI->second.setMaterializerAttached(true);
2488  JD.UnmaterializedInfos[KV2.first] = UMI;
2489  }
2490  }
2491 
2492  return Err;
2493  }
2494  }
2495 
2496  LLVM_DEBUG(dbgs() << "Stripping unmatched weakly-refererced symbols\n");
2497  IPLS->LookupSet.forEachWithRemoval(
2498  [&](const SymbolStringPtr &Name, SymbolLookupFlags SymLookupFlags) {
2499  if (SymLookupFlags == SymbolLookupFlags::WeaklyReferencedSymbol) {
2500  Q->dropSymbol(Name);
2501  return true;
2502  } else
2503  return false;
2504  });
2505 
2506  if (!IPLS->LookupSet.empty()) {
2507  LLVM_DEBUG(dbgs() << "Failing due to unresolved symbols\n");
2508  return make_error<SymbolsNotFound>(IPLS->LookupSet.getSymbolNames());
2509  }
2510 
2511  // Record whether the query completed.
2512  QueryComplete = Q->isComplete();
2513 
2514  LLVM_DEBUG({
2515  dbgs() << "Query successfully "
2516  << (QueryComplete ? "completed" : "lodged") << "\n";
2517  });
2518 
2519  // Move the collected MUs to the OutstandingMUs list.
2520  if (!CollectedUMIs.empty()) {
2521  std::lock_guard<std::recursive_mutex> Lock(OutstandingMUsMutex);
2522 
2523  LLVM_DEBUG(dbgs() << "Adding MUs to dispatch:\n");
2524  for (auto &KV : CollectedUMIs) {
2525  auto &JD = *KV.first;
2526  LLVM_DEBUG({
2527  dbgs() << " For " << JD.getName() << ": Adding " << KV.second.size()
2528  << " MUs.\n";
2529  });
2530  for (auto &UMI : KV.second) {
2531  std::unique_ptr<MaterializationResponsibility> MR(
2533  &JD, std::move(UMI->MU->SymbolFlags),
2534  std::move(UMI->MU->InitSymbol)));
2535  JD.MRTrackers[MR.get()] = UMI->RT;
2536  OutstandingMUs.push_back(
2537  std::make_pair(std::move(UMI->MU), std::move(MR)));
2538  }
2539  }
2540  } else
2541  LLVM_DEBUG(dbgs() << "No MUs to dispatch.\n");
2542 
2543  if (RegisterDependencies && !Q->QueryRegistrations.empty()) {
2544  LLVM_DEBUG(dbgs() << "Registering dependencies\n");
2545  RegisterDependencies(Q->QueryRegistrations);
2546  } else
2547  LLVM_DEBUG(dbgs() << "No dependencies to register\n");
2548 
2549  return Error::success();
2550  });
2551 
2552  if (LodgingErr) {
2553  LLVM_DEBUG(dbgs() << "Failing query\n");
2554  Q->detach();
2555  Q->handleFailed(std::move(LodgingErr));
2556  return;
2557  }
2558 
2559  if (QueryComplete) {
2560  LLVM_DEBUG(dbgs() << "Completing query\n");
2561  Q->handleComplete(*this);
2562  }
2563 
2564  dispatchOutstandingMUs();
2565 }
2566 
2567 void ExecutionSession::OL_completeLookupFlags(
2568  std::unique_ptr<InProgressLookupState> IPLS,
2569  unique_function<void(Expected<SymbolFlagsMap>)> OnComplete) {
2570 
2571  auto Result = runSessionLocked([&]() -> Expected<SymbolFlagsMap> {
2572  LLVM_DEBUG({
2573  dbgs() << "Entering OL_completeLookupFlags:\n"
2574  << " Lookup kind: " << IPLS->K << "\n"
2575  << " Search order: " << IPLS->SearchOrder
2576  << ", Current index = " << IPLS->CurSearchOrderIndex
2577  << (IPLS->NewJITDylib ? " (entering new JITDylib)" : "") << "\n"
2578  << " Lookup set: " << IPLS->LookupSet << "\n"
2579  << " Definition generator candidates: "
2580  << IPLS->DefGeneratorCandidates << "\n"
2581  << " Definition generator non-candidates: "
2582  << IPLS->DefGeneratorNonCandidates << "\n";
2583  });
2584 
2586 
2587  // Attempt to find flags for each symbol.
2588  for (auto &KV : IPLS->SearchOrder) {
2589  auto &JD = *KV.first;
2590  auto JDLookupFlags = KV.second;
2591  LLVM_DEBUG({
2592  dbgs() << "Visiting \"" << JD.getName() << "\" (" << JDLookupFlags
2593  << ") with lookup set " << IPLS->LookupSet << ":\n";
2594  });
2595 
2596  IPLS->LookupSet.forEachWithRemoval([&](const SymbolStringPtr &Name,
2597  SymbolLookupFlags SymLookupFlags) {
2598  LLVM_DEBUG({
2599  dbgs() << " Attempting to match \"" << Name << "\" ("
2600  << SymLookupFlags << ")... ";
2601  });
2602 
2603  // Search for the symbol. If not found then continue without removing
2604  // from the lookup set.
2605  auto SymI = JD.Symbols.find(Name);
2606  if (SymI == JD.Symbols.end()) {
2607  LLVM_DEBUG(dbgs() << "skipping: not present\n");
2608  return false;
2609  }
2610 
2611  // If this is a non-exported symbol then it doesn't match. Skip it.
2612  if (!SymI->second.getFlags().isExported() &&
2614  LLVM_DEBUG(dbgs() << "skipping: not exported\n");
2615  return false;
2616  }
2617 
2618  LLVM_DEBUG({
2619  dbgs() << "matched, \"" << Name << "\" -> " << SymI->second.getFlags()
2620  << "\n";
2621  });
2622  Result[Name] = SymI->second.getFlags();
2623  return true;
2624  });
2625  }
2626 
2627  // Remove any weakly referenced symbols that haven't been resolved.
2628  IPLS->LookupSet.remove_if(
2629  [](const SymbolStringPtr &Name, SymbolLookupFlags SymLookupFlags) {
2630  return SymLookupFlags == SymbolLookupFlags::WeaklyReferencedSymbol;
2631  });
2632 
2633  if (!IPLS->LookupSet.empty()) {
2634  LLVM_DEBUG(dbgs() << "Failing due to unresolved symbols\n");
2635  return make_error<SymbolsNotFound>(IPLS->LookupSet.getSymbolNames());
2636  }
2637 
2638  LLVM_DEBUG(dbgs() << "Succeded, result = " << Result << "\n");
2639  return Result;
2640  });
2641 
2642  // Run the callback on the result.
2643  LLVM_DEBUG(dbgs() << "Sending result to handler.\n");
2644  OnComplete(std::move(Result));
2645 }
2646 
2647 void ExecutionSession::OL_destroyMaterializationResponsibility(
2648  MaterializationResponsibility &MR) {
2649 
2650  assert(MR.SymbolFlags.empty() &&
2651  "All symbols should have been explicitly materialized or failed");
2652  MR.JD->unlinkMaterializationResponsibility(MR);
2653 }
2654 
2655 SymbolNameSet ExecutionSession::OL_getRequestedSymbols(
2656  const MaterializationResponsibility &MR) {
2657  return MR.JD->getRequestedSymbols(MR.SymbolFlags);
2658 }
2659 
2660 Error ExecutionSession::OL_notifyResolved(MaterializationResponsibility &MR,
2661  const SymbolMap &Symbols) {
2662  LLVM_DEBUG({
2663  dbgs() << "In " << MR.JD->getName() << " resolving " << Symbols << "\n";
2664  });
2665 #ifndef NDEBUG
2666  for (auto &KV : Symbols) {
2667  auto WeakFlags = JITSymbolFlags::Weak | JITSymbolFlags::Common;
2668  auto I = MR.SymbolFlags.find(KV.first);
2669  assert(I != MR.SymbolFlags.end() &&
2670  "Resolving symbol outside this responsibility set");
2671  assert(!I->second.hasMaterializationSideEffectsOnly() &&
2672  "Can't resolve materialization-side-effects-only symbol");
2673  assert((KV.second.getFlags() & ~WeakFlags) == (I->second & ~WeakFlags) &&
2674  "Resolving symbol with incorrect flags");
2675  }
2676 #endif
2677 
2678  return MR.JD->resolve(MR, Symbols);
2679 }
2680 
2681 Error ExecutionSession::OL_notifyEmitted(MaterializationResponsibility &MR) {
2682  LLVM_DEBUG({
2683  dbgs() << "In " << MR.JD->getName() << " emitting " << MR.SymbolFlags << "\n";
2684  });
2685 
2686  if (auto Err = MR.JD->emit(MR, MR.SymbolFlags))
2687  return Err;
2688 
2689  MR.SymbolFlags.clear();
2690  return Error::success();
2691 }
2692 
2693 Error ExecutionSession::OL_defineMaterializing(
2694  MaterializationResponsibility &MR, SymbolFlagsMap NewSymbolFlags) {
2695 
2696  LLVM_DEBUG({
2697  dbgs() << "In " << MR.JD->getName() << " defining materializing symbols "
2698  << NewSymbolFlags << "\n";
2699  });
2700  if (auto AcceptedDefs = MR.JD->defineMaterializing(std::move(NewSymbolFlags))) {
2701  // Add all newly accepted symbols to this responsibility object.
2702  for (auto &KV : *AcceptedDefs)
2703  MR.SymbolFlags.insert(KV);
2704  return Error::success();
2705  } else
2706  return AcceptedDefs.takeError();
2707 }
2708 
2709 void ExecutionSession::OL_notifyFailed(MaterializationResponsibility &MR) {
2710 
2711  LLVM_DEBUG({
2712  dbgs() << "In " << MR.JD->getName() << " failing materialization for "
2713  << MR.SymbolFlags << "\n";
2714  });
2715 
2716  JITDylib::FailedSymbolsWorklist Worklist;
2717 
2718  for (auto &KV : MR.SymbolFlags)
2719  Worklist.push_back(std::make_pair(MR.JD.get(), KV.first));
2720  MR.SymbolFlags.clear();
2721 
2722  if (Worklist.empty())
2723  return;
2724 
2726  std::shared_ptr<SymbolDependenceMap> FailedSymbols;
2727 
2728  runSessionLocked([&]() {
2729  auto RTI = MR.JD->MRTrackers.find(&MR);
2730  assert(RTI != MR.JD->MRTrackers.end() && "No tracker for this");
2731  if (RTI->second->isDefunct())
2732  return;
2733 
2734  std::tie(FailedQueries, FailedSymbols) =
2735  JITDylib::failSymbols(std::move(Worklist));
2736  });
2737 
2738  for (auto &Q : FailedQueries)
2739  Q->handleFailed(make_error<FailedToMaterialize>(FailedSymbols));
2740 }
2741 
2742 Error ExecutionSession::OL_replace(MaterializationResponsibility &MR,
2743  std::unique_ptr<MaterializationUnit> MU) {
2744  for (auto &KV : MU->getSymbols()) {
2745  assert(MR.SymbolFlags.count(KV.first) &&
2746  "Replacing definition outside this responsibility set");
2747  MR.SymbolFlags.erase(KV.first);
2748  }
2749 
2750  if (MU->getInitializerSymbol() == MR.InitSymbol)
2751  MR.InitSymbol = nullptr;
2752 
2753  LLVM_DEBUG(MR.JD->getExecutionSession().runSessionLocked([&]() {
2754  dbgs() << "In " << MR.JD->getName() << " replacing symbols with " << *MU
2755  << "\n";
2756  }););
2757 
2758  return MR.JD->replace(MR, std::move(MU));
2759 }
2760 
2761 Expected<std::unique_ptr<MaterializationResponsibility>>
2762 ExecutionSession::OL_delegate(MaterializationResponsibility &MR,
2763  const SymbolNameSet &Symbols) {
2764 
2765  SymbolStringPtr DelegatedInitSymbol;
2766  SymbolFlagsMap DelegatedFlags;
2767 
2768  for (auto &Name : Symbols) {
2769  auto I = MR.SymbolFlags.find(Name);
2770  assert(I != MR.SymbolFlags.end() &&
2771  "Symbol is not tracked by this MaterializationResponsibility "
2772  "instance");
2773 
2774  DelegatedFlags[Name] = std::move(I->second);
2775  if (Name == MR.InitSymbol)
2776  std::swap(MR.InitSymbol, DelegatedInitSymbol);
2777 
2778  MR.SymbolFlags.erase(I);
2779  }
2780 
2781  return MR.JD->delegate(MR, std::move(DelegatedFlags),
2782  std::move(DelegatedInitSymbol));
2783 }
2784 
2785 void ExecutionSession::OL_addDependencies(
2786  MaterializationResponsibility &MR, const SymbolStringPtr &Name,
2787  const SymbolDependenceMap &Dependencies) {
2788  LLVM_DEBUG({
2789  dbgs() << "Adding dependencies for " << Name << ": " << Dependencies
2790  << "\n";
2791  });
2792  assert(MR.SymbolFlags.count(Name) &&
2793  "Symbol not covered by this MaterializationResponsibility instance");
2794  MR.JD->addDependencies(Name, Dependencies);
2795 }
2796 
2797 void ExecutionSession::OL_addDependenciesForAll(
2798  MaterializationResponsibility &MR,
2799  const SymbolDependenceMap &Dependencies) {
2800  LLVM_DEBUG({
2801  dbgs() << "Adding dependencies for all symbols in " << MR.SymbolFlags << ": "
2802  << Dependencies << "\n";
2803  });
2804  for (auto &KV : MR.SymbolFlags)
2805  MR.JD->addDependencies(KV.first, Dependencies);
2806 }
2807 
2808 #ifndef NDEBUG
2809 void ExecutionSession::dumpDispatchInfo(Task &T) {
2810  runSessionLocked([&]() {
2811  dbgs() << "Dispatching: ";
2812  T.printDescription(dbgs());
2813  });
2814 }
2815 #endif // NDEBUG
2816 
2817 } // End namespace orc.
2818 } // End namespace llvm.
llvm::JITSymbolFlags::HasError
@ HasError
Definition: JITSymbol.h:81
getName
static StringRef getName(Value *V)
Definition: ProvenanceAnalysisEvaluator.cpp:42
llvm::orc::Task::ID
static char ID
Definition: Core.h:1223
MI
IRTranslator LLVM IR MI
Definition: IRTranslator.cpp:102
llvm
Definition: AllocatorList.h:23
llvm::orc::SymbolsNotFound::log
void log(raw_ostream &OS) const override
Print an error message to an output stream.
Definition: Core.cpp:108
llvm::orc::JITDylib
A symbol table that supports asynchoronous symbol queries.
Definition: Core.h:894
llvm::orc::ReexportsGenerator::tryToGenerate
Error tryToGenerate(LookupState &LS, LookupKind K, JITDylib &JD, JITDylibLookupFlags JDLookupFlags, const SymbolLookupSet &LookupSet) override
DefinitionGenerators should override this method to insert new definitions into the parent JITDylib.
Definition: Core.cpp:569
llvm::detail::DenseSetImpl::reserve
void reserve(size_t Size)
Grow the DenseSet so that it can contain at least NumEntries items before resizing again.
Definition: DenseSet.h:90
llvm::lltok::Error
@ Error
Definition: LLToken.h:21
llvm::orc::AsynchronousSymbolQuery::notifySymbolMetRequiredState
void notifySymbolMetRequiredState(const SymbolStringPtr &Name, JITEvaluatedSymbol Sym)
Notify the query that a requested symbol has reached the required state.
Definition: Core.cpp:157
llvm::orc::SymbolState::Materializing
@ Materializing
Added to the symbol table, never queried.
llvm::orc::DefinitionGenerator::~DefinitionGenerator
virtual ~DefinitionGenerator()
Definition: Core.cpp:610
llvm::orc::ExecutionSession::reportError
void reportError(Error Err)
Report a error for this execution session.
Definition: Core.h:1336
llvm::orc::InProgressLookupState
Definition: Core.cpp:484
llvm::unique_function< void(Expected< SymbolMap >)>
while
while(!ItemsToConvert.empty())
Definition: NVPTXLowerArgs.cpp:200
llvm::orc::SymbolsCouldNotBeRemoved::convertToErrorCode
std::error_code convertToErrorCode() const override
Convert this error to a std::error_code.
Definition: Core.cpp:117
llvm::orc::ExecutionSession::getJITDylibByName
JITDylib * getJITDylibByName(StringRef Name)
Return a pointer to the "name" JITDylib.
Definition: Core.cpp:1798
llvm::lower_bound
auto lower_bound(R &&Range, T &&Value)
Provide wrappers to std::lower_bound which take ranges instead of having to pass begin/end explicitly...
Definition: STLExtras.h:1592
llvm::orc::LookupState::operator=
LookupState & operator=(LookupState &&)
llvm::orc::ResourceTrackerDefunct::ID
static char ID
Definition: Core.h:393
llvm::orc::JITDylib::getDefaultResourceTracker
ResourceTrackerSP getDefaultResourceTracker()
Get the default resource tracker for this JITDylib.
Definition: Core.cpp:626
llvm::orc::ResourceTrackerDefunct::log
void log(raw_ostream &OS) const override
Print an error message to an output stream.
Definition: Core.cpp:75
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1167
llvm::orc::SymbolLookupSet
A set of symbols to look up, each associated with a SymbolLookupFlags value.
Definition: Core.h:173
llvm::orc::Platform::~Platform
virtual ~Platform()
Definition: Core.cpp:1702
llvm::orc::LookupKind::Static
@ Static
llvm::orc::SymbolStringPtr
Pointer to a pooled string representing a symbol name.
Definition: SymbolStringPool.h:50
llvm::orc::ReExportsMaterializationUnit::getName
StringRef getName() const override
Return the name of this materialization unit.
Definition: Core.cpp:277
llvm::orc::InProgressLookupFlagsState::InProgressLookupFlagsState
InProgressLookupFlagsState(LookupKind K, JITDylibSearchOrder SearchOrder, SymbolLookupSet LookupSet, unique_function< void(Expected< SymbolFlagsMap >)> OnComplete)
Definition: Core.cpp:511
llvm::orc::OrcErrorCode::UnknownORCError
@ UnknownORCError
llvm::orc::ResourceManager::~ResourceManager
virtual ~ResourceManager()
Definition: Core.cpp:66
llvm::Error::success
static ErrorSuccess success()
Create a success value.
Definition: Error.h:332
llvm::orc::InProgressFullLookupState::fail
void fail(Error Err) override
Definition: Core.cpp:552
llvm::orc::JITDylib::clear
Error clear()
Calls remove on all trackers currently associated with this JITDylib.
Definition: Core.cpp:612
llvm::DenseMapBase::erase
bool erase(const KeyT &Val)
Definition: DenseMap.h:302
llvm::orc::ResourceTracker::ResourceTracker
ResourceTracker(const ResourceTracker &)=delete
llvm::orc::FailedToMaterialize::convertToErrorCode
std::error_code convertToErrorCode() const override
Convert this error to a std::error_code.
Definition: Core.cpp:85
llvm::reverse
auto reverse(ContainerTy &&C, std::enable_if_t< has_rbegin< ContainerTy >::value > *=nullptr)
Definition: STLExtras.h:329
llvm::orc::LookupState::~LookupState
~LookupState()
llvm::orc::ResourceTracker
API to remove / transfer ownership of JIT resources.
Definition: Core.h:51
MSVCErrorWorkarounds.h
llvm::orc::ExecutionSession::registerResourceManager
void registerResourceManager(ResourceManager &RM)
Register the given ResourceManager with this ExecutionSession.
Definition: Core.cpp:1781
llvm::orc::MaterializationTask::run
void run() override
Definition: Core.cpp:1760
llvm::orc::buildSimpleReexportsAliasMap
Expected< SymbolAliasMap > buildSimpleReexportsAliasMap(JITDylib &SourceJD, SymbolNameSet Symbols)
Definition: Core.cpp:465
llvm::Optional
Definition: APInt.h:33
llvm::DenseMapBase::count
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:145
T
#define T
Definition: Mips16ISelLowering.cpp:341
llvm::dump
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
Definition: SparseBitVector.h:876
llvm::Expected
Tagged union holding either a T or a Error.
Definition: APFloat.h:42
llvm::orc::LookupState::continueLookup
void continueLookup(Error Err)
Continue the lookup.
Definition: Core.cpp:604
STLExtras.h
llvm::JITSymbolFlags::Common
@ Common
Definition: JITSymbol.h:83
llvm::orc::SymbolsNotFound::convertToErrorCode
std::error_code convertToErrorCode() const override
Convert this error to a std::error_code.
Definition: Core.cpp:104
llvm::orc::orcError
std::error_code orcError(OrcErrorCode ErrCode)
Definition: OrcError.cpp:82
replace
static void replace(Module &M, GlobalVariable *Old, GlobalVariable *New)
Definition: ConstantMerge.cpp:116
llvm::orc::LookupKind
LookupKind
Describes the kind of lookup being performed.
Definition: Core.h:147
llvm::detail::DenseSetImpl::insert
std::pair< iterator, bool > insert(const ValueT &V)
Definition: DenseSet.h:206
llvm::detail::DenseSetImpl< ValueT, DenseMap< ValueT, detail::DenseSetEmpty, DenseMapInfo< ValueT >, detail::DenseSetPair< ValueT > >, DenseMapInfo< ValueT > >::count
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:97
llvm::MachO::SymbolFlags
SymbolFlags
Symbol flags.
Definition: Symbol.h:25
llvm::orc::MaterializationUnit
A MaterializationUnit represents a set of symbol definitions that can be materialized as a group,...
Definition: Core.h:636
llvm::orc::InProgressLookupState::RequiredState
SymbolState RequiredState
Definition: Core.cpp:499
llvm::ArrayRef::empty
bool empty() const
empty - Check if the array is empty.
Definition: ArrayRef.h:160
LLVM_DEBUG
#define LLVM_DEBUG(X)
Definition: Debug.h:122
llvm::orc::ExecutionSession::dispatchTask
void dispatchTask(std::unique_ptr< Task > T)
Materialize the given unit.
Definition: Core.h:1415
llvm::orc::ExecutionSession::JITDylib
friend class JITDylib
Definition: Core.h:1255
llvm::JITEvaluatedSymbol
Represents a symbol that has been evaluated to an address already.
Definition: JITSymbol.h:229
llvm::RISCVFenceField::R
@ R
Definition: RISCVBaseInfo.h:180
llvm::orc::InProgressLookupState::NewJITDylib
bool NewJITDylib
Definition: Core.cpp:503
llvm::orc::JITDylib::createResourceTracker
ResourceTrackerSP createResourceTracker()
Create a resource tracker for this JITDylib.
Definition: Core.cpp:634
DebugUtils.h
llvm::orc::FailedToMaterialize::ID
static char ID
Definition: Core.h:407
llvm::dbgs
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:132
llvm::Lock
static sys::Mutex Lock
Definition: NVPTXUtilities.cpp:39
llvm::orc::RegisterDependenciesFunction
std::function< void(const SymbolDependenceMap &)> RegisterDependenciesFunction
Callback to register the dependencies for a given query.
Definition: Core.h:385
llvm::orc::InProgressLookupState::complete
virtual void complete(std::unique_ptr< InProgressLookupState > IPLS)=0
llvm::orc::ResourceTracker::getJITDylib
JITDylib & getJITDylib() const
Return the JITDylib targeted by this tracker.
Definition: Core.h:66
llvm::orc::ExecutionSession::dump
void dump(raw_ostream &OS)
Dump the state of all the JITDylibs in this session.
Definition: Core.cpp:2008
llvm::Expected
class LLVM_NODISCARD Expected
Definition: raw_ostream.h:35
llvm::formatv
auto formatv(const char *Fmt, Ts &&... Vals) -> formatv_object< decltype(std::make_tuple(detail::build_format_adapter(std::forward< Ts >(Vals))...))>
Definition: FormatVariadic.h:250
llvm::orc::SymbolState
SymbolState
Represents the state that a symbol has reached during materialization.
Definition: Core.h:786
llvm::orc::InProgressLookupState::DefGeneratorNonCandidates
SymbolLookupSet DefGeneratorNonCandidates
Definition: Core.cpp:505
llvm::orc::MissingSymbolDefinitions::log
void log(raw_ostream &OS) const override
Print an error message to an output stream.
Definition: Core.cpp:129
llvm::orc::SymbolLookupFlags
SymbolLookupFlags
Lookup flags that apply to each symbol in a lookup.
Definition: Core.h:135
llvm::orc::UnexpectedSymbolDefinitions::log
void log(raw_ostream &OS) const override
Print an error message to an output stream.
Definition: Core.cpp:138
llvm::orc::Platform::lookupInitSymbols
static Expected< DenseMap< JITDylib *, SymbolMap > > lookupInitSymbols(ExecutionSession &ES, const DenseMap< JITDylib *, SymbolLookupSet > &InitSyms)
A utility function for looking up initializer symbols.
Definition: Core.cpp:1704
llvm::orc::SymbolStringPool
String pool for symbol names used by the JIT.
Definition: SymbolStringPool.h:27
llvm::orc::UnexpectedSymbolDefinitions::ID
static char ID
Definition: Core.h:472
llvm::orc::NoDependenciesToRegister
RegisterDependenciesFunction NoDependenciesToRegister
This can be used as the value for a RegisterDependenciesFunction if there are no dependants to regist...
Definition: Core.cpp:35
llvm::ms_demangle::QualifierMangleMode::Result
@ Result
llvm::orc::OrcErrorCode::UnexpectedSymbolDefinitions
@ UnexpectedSymbolDefinitions
llvm::orc::SymbolMap
DenseMap< SymbolStringPtr, JITEvaluatedSymbol > SymbolMap
A map from symbol names (as SymbolStringPtrs) to JITSymbols (address/flags pairs).
Definition: Core.h:111
llvm::JITEvaluatedSymbol::getFlags
JITSymbolFlags getFlags() const
Return the flags for this symbol.
Definition: JITSymbol.h:254
llvm::orc::InProgressLookupFlagsState::fail
void fail(Error Err) override
Definition: Core.cpp:524
llvm::orc::ExecutionSession::intern
SymbolStringPtr intern(StringRef SymName)
Add a symbol name to the SymbolStringPool and return a pointer to it.
Definition: Core.h:1276
llvm::orc::InProgressLookupState::SearchOrder
JITDylibSearchOrder SearchOrder
Definition: Core.cpp:497
llvm::orc::SymbolAliasMap
DenseMap< SymbolStringPtr, SymbolAliasMapEntry > SymbolAliasMap
A map of Symbols to (Symbol, Flags) pairs.
Definition: Core.h:378
llvm::orc::ExecutionSession::runSessionLocked
decltype(auto) runSessionLocked(Func &&F)
Run the given lambda with the session mutex locked.
Definition: Core.h:1289
llvm::raw_ostream
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:50
llvm::ErrorAsOutParameter
Helper for Errors used as out-parameters.
Definition: Error.h:1060
llvm::orc::AbsoluteSymbolsMaterializationUnit::getName
StringRef getName() const override
Return the name of this materialization unit.
Definition: Core.cpp:246
llvm::orc::FailedToMaterialize::FailedToMaterialize
FailedToMaterialize(std::shared_ptr< SymbolDependenceMap > Symbols)
Definition: Core.cpp:79
llvm::orc::SymbolsNotFound::ID
static char ID
Definition: Core.h:421
FormatVariadic.h
llvm::orc::InProgressLookupState::~InProgressLookupState
virtual ~InProgressLookupState()
Definition: Core.cpp:492
llvm::orc::InProgressLookupState::CurSearchOrderIndex
size_t CurSearchOrderIndex
Definition: Core.cpp:502
llvm::orc::SymbolLookupFlags::WeaklyReferencedSymbol
@ WeaklyReferencedSymbol
llvm::orc::ExecutionSession::createBareJITDylib
JITDylib & createBareJITDylib(std::string Name)
Add a new bare JITDylib to this ExecutionSession.
Definition: Core.cpp:1807
llvm::orc::ExecutionSession::endSession
Error endSession()
End the session. Closes all JITDylibs.
Definition: Core.cpp:1765
llvm::orc::ExecutionSession::ExecutionSession
ExecutionSession(std::shared_ptr< SymbolStringPool > SSP=nullptr)
Construct an ExecutionSession.
Definition: Core.cpp:1762
llvm::orc::MaterializationTask::printDescription
void printDescription(raw_ostream &OS) override
Definition: Core.cpp:1755
G
const DataFlowGraph & G
Definition: RDFGraph.cpp:202
llvm::DenseSet< SymbolStringPtr >
llvm::orc::InProgressLookupFlagsState
Definition: Core.cpp:509
llvm::JITSymbolFlags::hasMaterializationSideEffectsOnly
bool hasMaterializationSideEffectsOnly() const
Returns true if this symbol is a materialization-side-effects-only symbol.
Definition: JITSymbol.h:161
llvm::DenseMapBase::clear
void clear()
Definition: DenseMap.h:111
llvm::find
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1502
Addr
uint64_t Addr
Definition: ELFObjHandler.cpp:80
llvm::Optional::emplace
void emplace(ArgTypes &&... Args)
Create a new object by constructing it in place with the given arguments.
Definition: Optional.h:264
llvm::orc::ExecutionSession::lookupFlags
void lookupFlags(LookupKind K, JITDylibSearchOrder SearchOrder, SymbolLookupSet Symbols, unique_function< void(Expected< SymbolFlagsMap >)> OnComplete)
Search the given JITDylibs to find the flags associated with each of the given symbols.
Definition: Core.cpp:1873
move
compiles ldr LCPI1_0 ldr ldr mov lsr tst moveq r1 ldr LCPI1_1 and r0 bx lr It would be better to do something like to fold the shift into the conditional move
Definition: README.txt:546
llvm::DenseMap< SymbolStringPtr, JITEvaluatedSymbol >
llvm::orc::InProgressLookupState::DefGeneratorCandidates
SymbolLookupSet DefGeneratorCandidates
Definition: Core.cpp:504
I
#define I(x, y, z)
Definition: MD5.cpp:59
llvm::detail::DenseSetImpl::empty
bool empty() const
Definition: DenseSet.h:80
llvm::orc::JITDylib::AsynchronousSymbolQuerySet
std::set< std::shared_ptr< AsynchronousSymbolQuery > > AsynchronousSymbolQuerySet
Definition: Core.h:903
llvm::joinErrors
Error joinErrors(Error E1, Error E2)
Concatenate errors.
Definition: Error.h:429
llvm::orc::SymbolState::NeverSearched
@ NeverSearched
No symbol should be in this state.
llvm::orc::ResourceTrackerSP
uint8_t IntrusiveRefCntPtr< ResourceTracker > ResourceTrackerSP
Definition: Core.h:45
llvm::DenseMapBase::find
iterator find(const_arg_type_t< KeyT > Val)
Definition: DenseMap.h:150
llvm::orc::ReexportsGenerator::ReexportsGenerator
ReexportsGenerator(JITDylib &SourceJD, JITDylibLookupFlags SourceJDLookupFlags, SymbolPredicate Allow=SymbolPredicate())
Create a reexports generator.
Definition: Core.cpp:563
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::orc::AbsoluteSymbolsMaterializationUnit::AbsoluteSymbolsMaterializationUnit
AbsoluteSymbolsMaterializationUnit(SymbolMap Symbols)
Definition: Core.cpp:241
llvm::move
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1540
std::swap
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition: BitVector.h:840
SI
StandardInstrumentations SI(Debug, VerifyEach)
llvm::orc::JITDylibSP
IntrusiveRefCntPtr< JITDylib > JITDylibSP
Definition: Core.h:46
llvm::orc::InProgressLookupFlagsState::complete
void complete(std::unique_ptr< InProgressLookupState > IPLS) override
Definition: Core.cpp:518
llvm::orc::InProgressLookupState::K
LookupKind K
Definition: Core.cpp:496
llvm::orc::JITDylibSearchOrder
std::vector< std::pair< JITDylib *, JITDylibLookupFlags > > JITDylibSearchOrder
A list of (JITDylib*, JITDylibLookupFlags) pairs to be used as a search order during symbol lookup.
Definition: Core.h:152
llvm::orc::JITDylib::getReverseDFSLinkOrder
std::vector< JITDylibSP > getReverseDFSLinkOrder()
Rteurn this JITDylib and its transitive dependencies in reverse DFS order based on linkage relationsh...
Definition: Core.cpp:1869
llvm::orc::DefinitionGenerator
Definition generators can be attached to JITDylibs to generate new definitions for otherwise unresolv...
Definition: Core.h:873
llvm::orc::InProgressLookupState::fail
virtual void fail(Error Err)=0
_
#define _
Definition: HexagonMCCodeEmitter.cpp:47
llvm::orc::reexports
std::unique_ptr< ReExportsMaterializationUnit > reexports(JITDylib &SourceJD, SymbolAliasMap Aliases, JITDylibLookupFlags SourceJDLookupFlags=JITDylibLookupFlags::MatchExportedSymbolsOnly)
Create a materialization unit for re-exporting symbols from another JITDylib with alternative names/f...
Definition: Core.h:773
llvm::orc::ExecutionSession::deregisterResourceManager
void deregisterResourceManager(ResourceManager &RM)
Deregister the given ResourceManager with this ExecutionSession.
Definition: Core.cpp:1785
llvm::orc::InProgressLookupState::CurDefGeneratorStack
std::vector< std::weak_ptr< DefinitionGenerator > > CurDefGeneratorStack
Definition: Core.cpp:506
llvm::sys::fs::remove
std::error_code remove(const Twine &path, bool IgnoreNonExisting=true)
Remove path.
llvm::AArch64::RM
@ RM
Definition: AArch64ISelLowering.h:469
llvm::ArrayRef
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: APInt.h:32
llvm::orc::ExecutionSession::MaterializationResponsibility
friend class MaterializationResponsibility
Definition: Core.h:1257
llvm::JITSymbolFlags::Weak
@ Weak
Definition: JITSymbol.h:82
llvm::orc::ReexportsGenerator::SymbolPredicate
std::function< bool(SymbolStringPtr)> SymbolPredicate
Definition: Core.h:1637
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:58
llvm::orc::SymbolState::Ready
@ Ready
Emitted to memory, but waiting on transitive dependencies.
if
if(llvm_vc STREQUAL "") set(fake_version_inc "$
Definition: CMakeLists.txt:14
llvm::cantFail
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
Definition: Error.h:708
llvm::append_range
void append_range(Container &C, Range &&R)
Wrapper function to append a range to a container.
Definition: STLExtras.h:1672
S
add sub stmia L5 ldr r0 bl L_printf $stub Instead of a and a wouldn t it be better to do three moves *Return an aggregate type is even return S
Definition: README.txt:210
llvm::orc::LookupState
Wraps state for a lookup-in-progress.
Definition: Core.h:848
llvm::orc::JITDylib::getDFSLinkOrder
std::vector< JITDylibSP > getDFSLinkOrder()
Return this JITDylib and its transitive dependencies in DFS order based on linkage relationships.
Definition: Core.cpp:1865
llvm::format
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition: Format.h:124
llvm::orc::SymbolAliasMapEntry
Definition: Core.h:368
llvm::orc::InProgressFullLookupState
Definition: Core.cpp:533
for
this could be done in SelectionDAGISel along with other special for
Definition: README.txt:104
llvm::DenseMapBase::insert
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Definition: DenseMap.h:207
llvm::ArrayRef::front
const T & front() const
front - Get the first element.
Definition: ArrayRef.h:168
llvm::orc::ExecutionSession::createJITDylib
Expected< JITDylib & > createJITDylib(std::string Name)
Add a new JITDylib to this ExecutionSession.
Definition: Core.cpp:1815
llvm::orc::InProgressFullLookupState::InProgressFullLookupState
InProgressFullLookupState(LookupKind K, JITDylibSearchOrder SearchOrder, SymbolLookupSet LookupSet, SymbolState RequiredState, std::shared_ptr< AsynchronousSymbolQuery > Q, RegisterDependenciesFunction RegisterDependencies)
Definition: Core.cpp:535
llvm::orc::SymbolDependenceMap
DenseMap< JITDylib *, SymbolNameSet > SymbolDependenceMap
A map from JITDylibs to sets of symbols.
Definition: Core.h:117
llvm::orc::ResourceTrackerDefunct::convertToErrorCode
std::error_code convertToErrorCode() const override
Convert this error to a std::error_code.
Definition: Core.cpp:71
llvm::find_if
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1509
llvm::orc::SymbolFlagsMap
DenseMap< SymbolStringPtr, JITSymbolFlags > SymbolFlagsMap
A map from symbol names (as SymbolStringPtrs) to JITSymbolFlags.
Definition: Core.h:114
llvm::DenseMapBase::empty
LLVM_NODISCARD bool empty() const
Definition: DenseMap.h:97
llvm::orc::AsynchronousSymbolQuery::AsynchronousSymbolQuery
AsynchronousSymbolQuery(const SymbolLookupSet &Symbols, SymbolState RequiredState, SymbolsResolvedCallback NotifyComplete)
Create a query for the given symbols.
Definition: Core.cpp:143
llvm::orc::ResourceManager
Listens for ResourceTracker operations.
Definition: Core.h:95
llvm::orc::ResourceTracker::transferTo
void transferTo(ResourceTracker &DstRT)
Transfer all resources associated with this key to the given tracker, which must target the same JITD...
Definition: Core.cpp:56
llvm::SymbolTableEntry
Symbol info for RuntimeDyld.
Definition: RuntimeDyldImpl.h:217
llvm::orc::InProgressLookupState::LookupSet
SymbolLookupSet LookupSet
Definition: Core.cpp:498
llvm::GraphProgram::Name
Name
Definition: GraphWriter.h:52
std
Definition: BitVector.h:838
H
#define H(x, y, z)
Definition: MD5.cpp:58
llvm::inconvertibleErrorCode
std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
Definition: Error.cpp:77
llvm::orc::SymbolsNotFound::SymbolsNotFound
SymbolsNotFound(SymbolNameSet Symbols)
Definition: Core.cpp:93
getFlags
static uint32_t getFlags(const Symbol *Sym)
Definition: TapiFile.cpp:28
llvm::DenseMapBase::end
iterator end()
Definition: DenseMap.h:83
llvm::Error
Lightweight error class with error context and mandatory checking.
Definition: Error.h:157
llvm::orc::Task
Represents an abstract task for ORC to run.
Definition: Core.h:1221
llvm::orc::ExecutionSession
An ExecutionSession represents a running JIT program.
Definition: Core.h:1252
llvm::orc::JITDylibLookupFlags::MatchExportedSymbolsOnly
@ MatchExportedSymbolsOnly
llvm::orc::InProgressLookupState::GeneratorLock
std::unique_lock< std::mutex > GeneratorLock
Definition: Core.cpp:501
llvm::AArch64CC::LS
@ LS
Definition: AArch64BaseInfo.h:245
llvm::orc::MissingSymbolDefinitions::convertToErrorCode
std::error_code convertToErrorCode() const override
Convert this error to a std::error_code.
Definition: Core.cpp:125
llvm::DenseMapBase< DenseMap< KeyT, ValueT, DenseMapInfo< KeyT >, llvm::detail::DenseMapPair< KeyT, ValueT > >, KeyT, ValueT, DenseMapInfo< KeyT >, llvm::detail::DenseMapPair< KeyT, ValueT > >::size
unsigned size() const
Definition: DenseMap.h:100
llvm::orc::symbolAliases
std::unique_ptr< ReExportsMaterializationUnit > symbolAliases(SymbolAliasMap Aliases)
Create a ReExportsMaterializationUnit with the given aliases.
Definition: Core.h:764
llvm::orc::ExecutionSession::LookupState
friend class LookupState
Definition: Core.h:1256
llvm::orc::FailedToMaterialize::log
void log(raw_ostream &OS) const override
Print an error message to an output stream.
Definition: Core.cpp:89
Core.h
llvm::orc::ResourceTrackerDefunct::ResourceTrackerDefunct
ResourceTrackerDefunct(ResourceTrackerSP RT)
Definition: Core.cpp:68
llvm::orc::JITDylib::getName
const std::string & getName() const
Get the name for this JITDylib.
Definition: Core.h:911
llvm::orc::JITDylib::define
Error define(std::unique_ptr< MaterializationUnitType > &&MU, ResourceTrackerSP RT=nullptr)
Define all symbols provided by the materialization unit to be part of this JITDylib.
Definition: Core.h:1552
llvm::orc::InProgressLookupState::InProgressLookupState
InProgressLookupState(LookupKind K, JITDylibSearchOrder SearchOrder, SymbolLookupSet LookupSet, SymbolState RequiredState)
Definition: Core.cpp:486
llvm::TPLoop::Allow
@ Allow
Definition: ARMTargetTransformInfo.h:53
llvm::orc::ExecutionSession::lookup
void lookup(LookupKind K, const JITDylibSearchOrder &SearchOrder, SymbolLookupSet Symbols, SymbolState RequiredState, SymbolsResolvedCallback NotifyComplete, RegisterDependenciesFunction RegisterDependencies)
Search the given JITDylibs for the given symbols.
Definition: Core.cpp:1899
llvm::orc::JITDylib::getExecutionSession
ExecutionSession & getExecutionSession() const
Get a reference to the ExecutionSession for this JITDylib.
Definition: Core.h:914
llvm::orc::MissingSymbolDefinitions::ID
static char ID
Definition: Core.h:453
llvm::orc::SymbolNameSet
DenseSet< SymbolStringPtr > SymbolNameSet
A set of symbol names (represented by SymbolStringPtrs for.
Definition: Core.h:104
llvm::orc::JITDylibLookupFlags
JITDylibLookupFlags
Lookup flags that apply to each dylib in the search order for a lookup.
Definition: Core.h:125
llvm::orc::SymbolState::Resolved
@ Resolved
Queried, materialization begun.
llvm::orc::MaterializationTask::ID
static char ID
Definition: Core.h:1238
llvm::orc::ReExportsMaterializationUnit::ReExportsMaterializationUnit
ReExportsMaterializationUnit(JITDylib *SourceJD, JITDylibLookupFlags SourceJDLookupFlags, SymbolAliasMap Aliases)
SourceJD is allowed to be nullptr, in which case the source JITDylib is taken to be whatever JITDylib...
Definition: Core.cpp:271
llvm::orc::MaterializationUnit::SymbolFlags
SymbolFlagsMap SymbolFlags
Definition: Core.h:677
llvm::ThreadSafeRefCountedBase::Release
void Release() const
Definition: IntrusiveRefCntPtr.h:124
llvm::orc::UnexpectedSymbolDefinitions::convertToErrorCode
std::error_code convertToErrorCode() const override
Convert this error to a std::error_code.
Definition: Core.cpp:134
llvm::orc::LookupState::LookupState
LookupState()
llvm::orc::OrcErrorCode::MissingSymbolDefinitions
@ MissingSymbolDefinitions
llvm::orc::JITDylibLookupFlags::MatchAllSymbols
@ MatchAllSymbols
llvm::orc::SymbolLookupFlags::RequiredSymbol
@ RequiredSymbol
llvm::orc::SymbolsResolvedCallback
unique_function< void(Expected< SymbolMap >)> SymbolsResolvedCallback
Callback to notify client that symbols have been resolved.
Definition: Core.h:381
llvm::orc::SymbolsCouldNotBeRemoved::SymbolsCouldNotBeRemoved
SymbolsCouldNotBeRemoved(SymbolNameSet Symbols)
Definition: Core.cpp:112
OrcError.h
llvm::orc::InProgressFullLookupState::complete
void complete(std::unique_ptr< InProgressLookupState > IPLS) override
Definition: Core.cpp:545
llvm::orc::SymbolNameVector
std::vector< SymbolStringPtr > SymbolNameVector
A vector of symbol names.
Definition: Core.h:107
llvm::orc::makeJITDylibSearchOrder
JITDylibSearchOrder makeJITDylibSearchOrder(ArrayRef< JITDylib * > JDs, JITDylibLookupFlags Flags=JITDylibLookupFlags::MatchExportedSymbolsOnly)
Convenience function for creating a search order from an ArrayRef of JITDylib*, all with the same fla...
Definition: Core.h:156
llvm::orc::SymbolsCouldNotBeRemoved::ID
static char ID
Definition: Core.h:436
llvm::orc::ResourceTracker::remove
Error remove()
Remove all resources associated with this key.
Definition: Core.cpp:52
llvm::orc::SymbolsCouldNotBeRemoved::log
void log(raw_ostream &OS) const override
Print an error message to an output stream.
Definition: Core.cpp:121
llvm::orc::ResourceTracker::~ResourceTracker
~ResourceTracker()
Definition: Core.cpp:47
llvm::orc::JITDylib::removeGenerator
void removeGenerator(DefinitionGenerator &G)
Remove a definition generator from this JITDylib.
Definition: Core.cpp:641