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