brintos

brintos / llvm-project-archived public Read only

0
0
Text · 111.6 KiB · 9233c8e Raw
3238 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/ExecutionEngine/Orc/Core.h"10 11#include "llvm/ADT/STLExtras.h"12#include "llvm/Config/llvm-config.h"13#include "llvm/ExecutionEngine/Orc/DebugUtils.h"14#include "llvm/ExecutionEngine/Orc/Shared/OrcError.h"15#include "llvm/Support/FormatVariadic.h"16#include "llvm/Support/MSVCErrorWorkarounds.h"17#include "llvm/Support/raw_ostream.h"18 19#include <condition_variable>20#include <future>21#include <optional>22 23#define DEBUG_TYPE "orc"24 25namespace llvm {26namespace orc {27 28char ResourceTrackerDefunct::ID = 0;29char FailedToMaterialize::ID = 0;30char SymbolsNotFound::ID = 0;31char SymbolsCouldNotBeRemoved::ID = 0;32char MissingSymbolDefinitions::ID = 0;33char UnexpectedSymbolDefinitions::ID = 0;34char UnsatisfiedSymbolDependencies::ID = 0;35char MaterializationTask::ID = 0;36char LookupTask::ID = 0;37 38RegisterDependenciesFunction NoDependenciesToRegister =39    RegisterDependenciesFunction();40 41void MaterializationUnit::anchor() {}42 43ResourceTracker::ResourceTracker(JITDylibSP JD) {44  assert((reinterpret_cast<uintptr_t>(JD.get()) & 0x1) == 0 &&45         "JITDylib must be two byte aligned");46  JD->Retain();47  JDAndFlag.store(reinterpret_cast<uintptr_t>(JD.get()));48}49 50ResourceTracker::~ResourceTracker() {51  getJITDylib().getExecutionSession().destroyResourceTracker(*this);52  getJITDylib().Release();53}54 55Error ResourceTracker::remove() {56  return getJITDylib().getExecutionSession().removeResourceTracker(*this);57}58 59void ResourceTracker::transferTo(ResourceTracker &DstRT) {60  getJITDylib().getExecutionSession().transferResourceTracker(DstRT, *this);61}62 63void ResourceTracker::makeDefunct() {64  uintptr_t Val = JDAndFlag.load();65  Val |= 0x1U;66  JDAndFlag.store(Val);67}68 69ResourceManager::~ResourceManager() = default;70 71ResourceTrackerDefunct::ResourceTrackerDefunct(ResourceTrackerSP RT)72    : RT(std::move(RT)) {}73 74std::error_code ResourceTrackerDefunct::convertToErrorCode() const {75  return orcError(OrcErrorCode::UnknownORCError);76}77 78void ResourceTrackerDefunct::log(raw_ostream &OS) const {79  OS << "Resource tracker " << (void *)RT.get() << " became defunct";80}81 82FailedToMaterialize::FailedToMaterialize(83    std::shared_ptr<SymbolStringPool> SSP,84    std::shared_ptr<SymbolDependenceMap> Symbols)85    : SSP(std::move(SSP)), Symbols(std::move(Symbols)) {86  assert(this->SSP && "String pool cannot be null");87  assert(!this->Symbols->empty() && "Can not fail to resolve an empty set");88 89  // FIXME: Use a new dep-map type for FailedToMaterialize errors so that we90  // don't have to manually retain/release.91  for (auto &[JD, Syms] : *this->Symbols)92    JD->Retain();93}94 95FailedToMaterialize::~FailedToMaterialize() {96  for (auto &[JD, Syms] : *Symbols)97    JD->Release();98}99 100std::error_code FailedToMaterialize::convertToErrorCode() const {101  return orcError(OrcErrorCode::UnknownORCError);102}103 104void FailedToMaterialize::log(raw_ostream &OS) const {105  OS << "Failed to materialize symbols: " << *Symbols;106}107 108UnsatisfiedSymbolDependencies::UnsatisfiedSymbolDependencies(109    std::shared_ptr<SymbolStringPool> SSP, JITDylibSP JD,110    SymbolNameSet FailedSymbols, SymbolDependenceMap BadDeps,111    std::string Explanation)112    : SSP(std::move(SSP)), JD(std::move(JD)),113      FailedSymbols(std::move(FailedSymbols)), BadDeps(std::move(BadDeps)),114      Explanation(std::move(Explanation)) {}115 116std::error_code UnsatisfiedSymbolDependencies::convertToErrorCode() const {117  return orcError(OrcErrorCode::UnknownORCError);118}119 120void UnsatisfiedSymbolDependencies::log(raw_ostream &OS) const {121  OS << "In " << JD->getName() << ", failed to materialize " << FailedSymbols122     << ", due to unsatisfied dependencies " << BadDeps;123  if (!Explanation.empty())124    OS << " (" << Explanation << ")";125}126 127SymbolsNotFound::SymbolsNotFound(std::shared_ptr<SymbolStringPool> SSP,128                                 SymbolNameSet Symbols)129    : SSP(std::move(SSP)) {130  llvm::append_range(this->Symbols, Symbols);131  assert(!this->Symbols.empty() && "Can not fail to resolve an empty set");132}133 134SymbolsNotFound::SymbolsNotFound(std::shared_ptr<SymbolStringPool> SSP,135                                 SymbolNameVector Symbols)136    : SSP(std::move(SSP)), Symbols(std::move(Symbols)) {137  assert(!this->Symbols.empty() && "Can not fail to resolve an empty set");138}139 140std::error_code SymbolsNotFound::convertToErrorCode() const {141  return orcError(OrcErrorCode::UnknownORCError);142}143 144void SymbolsNotFound::log(raw_ostream &OS) const {145  OS << "Symbols not found: " << Symbols;146}147 148SymbolsCouldNotBeRemoved::SymbolsCouldNotBeRemoved(149    std::shared_ptr<SymbolStringPool> SSP, SymbolNameSet Symbols)150    : SSP(std::move(SSP)), Symbols(std::move(Symbols)) {151  assert(!this->Symbols.empty() && "Can not fail to resolve an empty set");152}153 154std::error_code SymbolsCouldNotBeRemoved::convertToErrorCode() const {155  return orcError(OrcErrorCode::UnknownORCError);156}157 158void SymbolsCouldNotBeRemoved::log(raw_ostream &OS) const {159  OS << "Symbols could not be removed: " << Symbols;160}161 162std::error_code MissingSymbolDefinitions::convertToErrorCode() const {163  return orcError(OrcErrorCode::MissingSymbolDefinitions);164}165 166void MissingSymbolDefinitions::log(raw_ostream &OS) const {167  OS << "Missing definitions in module " << ModuleName168     << ": " << Symbols;169}170 171std::error_code UnexpectedSymbolDefinitions::convertToErrorCode() const {172  return orcError(OrcErrorCode::UnexpectedSymbolDefinitions);173}174 175void UnexpectedSymbolDefinitions::log(raw_ostream &OS) const {176  OS << "Unexpected definitions in module " << ModuleName177     << ": " << Symbols;178}179 180void SymbolInstance::lookupAsync(LookupAsyncOnCompleteFn OnComplete) const {181  JD->getExecutionSession().lookup(182      LookupKind::Static, {{JD.get(), JITDylibLookupFlags::MatchAllSymbols}},183      SymbolLookupSet(Name), SymbolState::Ready,184      [OnComplete = std::move(OnComplete)185#ifndef NDEBUG186           ,187       Name = this->Name // Captured for the assert below only.188#endif                   // NDEBUG189  ](Expected<SymbolMap> Result) mutable {190        if (Result) {191          assert(Result->size() == 1 && "Unexpected number of results");192          assert(Result->count(Name) &&193                 "Result does not contain expected symbol");194          OnComplete(Result->begin()->second);195        } else196          OnComplete(Result.takeError());197      },198      NoDependenciesToRegister);199}200 201AsynchronousSymbolQuery::AsynchronousSymbolQuery(202    const SymbolLookupSet &Symbols, SymbolState RequiredState,203    SymbolsResolvedCallback NotifyComplete)204    : NotifyComplete(std::move(NotifyComplete)), RequiredState(RequiredState) {205  assert(RequiredState >= SymbolState::Resolved &&206         "Cannot query for a symbols that have not reached the resolve state "207         "yet");208 209  OutstandingSymbolsCount = Symbols.size();210 211  for (auto &[Name, Flags] : Symbols)212    ResolvedSymbols[Name] = ExecutorSymbolDef();213}214 215void AsynchronousSymbolQuery::notifySymbolMetRequiredState(216    const SymbolStringPtr &Name, ExecutorSymbolDef Sym) {217  auto I = ResolvedSymbols.find(Name);218  assert(I != ResolvedSymbols.end() &&219         "Resolving symbol outside the requested set");220  assert(I->second == ExecutorSymbolDef() &&221         "Redundantly resolving symbol Name");222 223  // If this is a materialization-side-effects-only symbol then drop it,224  // otherwise update its map entry with its resolved address.225  if (Sym.getFlags().hasMaterializationSideEffectsOnly())226    ResolvedSymbols.erase(I);227  else228    I->second = std::move(Sym);229  --OutstandingSymbolsCount;230}231 232void AsynchronousSymbolQuery::handleComplete(ExecutionSession &ES) {233  assert(OutstandingSymbolsCount == 0 &&234         "Symbols remain, handleComplete called prematurely");235 236  class RunQueryCompleteTask : public Task {237  public:238    RunQueryCompleteTask(SymbolMap ResolvedSymbols,239                         SymbolsResolvedCallback NotifyComplete)240        : ResolvedSymbols(std::move(ResolvedSymbols)),241          NotifyComplete(std::move(NotifyComplete)) {}242    void printDescription(raw_ostream &OS) override {243      OS << "Execute query complete callback for " << ResolvedSymbols;244    }245    void run() override { NotifyComplete(std::move(ResolvedSymbols)); }246 247  private:248    SymbolMap ResolvedSymbols;249    SymbolsResolvedCallback NotifyComplete;250  };251 252  auto T = std::make_unique<RunQueryCompleteTask>(std::move(ResolvedSymbols),253                                                  std::move(NotifyComplete));254  NotifyComplete = SymbolsResolvedCallback();255  ES.dispatchTask(std::move(T));256}257 258void AsynchronousSymbolQuery::handleFailed(Error Err) {259  assert(QueryRegistrations.empty() && ResolvedSymbols.empty() &&260         OutstandingSymbolsCount == 0 &&261         "Query should already have been abandoned");262  NotifyComplete(std::move(Err));263  NotifyComplete = SymbolsResolvedCallback();264}265 266void AsynchronousSymbolQuery::addQueryDependence(JITDylib &JD,267                                                 SymbolStringPtr Name) {268  bool Added = QueryRegistrations[&JD].insert(std::move(Name)).second;269  (void)Added;270  assert(Added && "Duplicate dependence notification?");271}272 273void AsynchronousSymbolQuery::removeQueryDependence(274    JITDylib &JD, const SymbolStringPtr &Name) {275  auto QRI = QueryRegistrations.find(&JD);276  assert(QRI != QueryRegistrations.end() &&277         "No dependencies registered for JD");278  assert(QRI->second.count(Name) && "No dependency on Name in JD");279  QRI->second.erase(Name);280  if (QRI->second.empty())281    QueryRegistrations.erase(QRI);282}283 284void AsynchronousSymbolQuery::dropSymbol(const SymbolStringPtr &Name) {285  auto I = ResolvedSymbols.find(Name);286  assert(I != ResolvedSymbols.end() &&287         "Redundant removal of weakly-referenced symbol");288  ResolvedSymbols.erase(I);289  --OutstandingSymbolsCount;290}291 292void AsynchronousSymbolQuery::detach() {293  ResolvedSymbols.clear();294  OutstandingSymbolsCount = 0;295  for (auto &[JD, Syms] : QueryRegistrations)296    JD->detachQueryHelper(*this, Syms);297  QueryRegistrations.clear();298}299 300ReExportsMaterializationUnit::ReExportsMaterializationUnit(301    JITDylib *SourceJD, JITDylibLookupFlags SourceJDLookupFlags,302    SymbolAliasMap Aliases)303    : MaterializationUnit(extractFlags(Aliases)), SourceJD(SourceJD),304      SourceJDLookupFlags(SourceJDLookupFlags), Aliases(std::move(Aliases)) {}305 306StringRef ReExportsMaterializationUnit::getName() const {307  return "<Reexports>";308}309 310void ReExportsMaterializationUnit::materialize(311    std::unique_ptr<MaterializationResponsibility> R) {312 313  auto &ES = R->getTargetJITDylib().getExecutionSession();314  JITDylib &TgtJD = R->getTargetJITDylib();315  JITDylib &SrcJD = SourceJD ? *SourceJD : TgtJD;316 317  // Find the set of requested aliases and aliasees. Return any unrequested318  // aliases back to the JITDylib so as to not prematurely materialize any319  // aliasees.320  auto RequestedSymbols = R->getRequestedSymbols();321  SymbolAliasMap RequestedAliases;322 323  for (auto &Name : RequestedSymbols) {324    auto I = Aliases.find(Name);325    assert(I != Aliases.end() && "Symbol not found in aliases map?");326    RequestedAliases[Name] = std::move(I->second);327    Aliases.erase(I);328  }329 330  LLVM_DEBUG({331    ES.runSessionLocked([&]() {332      dbgs() << "materializing reexports: target = " << TgtJD.getName()333             << ", source = " << SrcJD.getName() << " " << RequestedAliases334             << "\n";335    });336  });337 338  if (!Aliases.empty()) {339    auto Err = SourceJD ? R->replace(reexports(*SourceJD, std::move(Aliases),340                                               SourceJDLookupFlags))341                        : R->replace(symbolAliases(std::move(Aliases)));342 343    if (Err) {344      // FIXME: Should this be reported / treated as failure to materialize?345      // Or should this be treated as a sanctioned bailing-out?346      ES.reportError(std::move(Err));347      R->failMaterialization();348      return;349    }350  }351 352  // The OnResolveInfo struct will hold the aliases and responsibility for each353  // query in the list.354  struct OnResolveInfo {355    OnResolveInfo(std::unique_ptr<MaterializationResponsibility> R,356                  SymbolAliasMap Aliases)357        : R(std::move(R)), Aliases(std::move(Aliases)) {}358 359    std::unique_ptr<MaterializationResponsibility> R;360    SymbolAliasMap Aliases;361    std::vector<SymbolDependenceGroup> SDGs;362  };363 364  // Build a list of queries to issue. In each round we build a query for the365  // largest set of aliases that we can resolve without encountering a chain of366  // aliases (e.g. Foo -> Bar, Bar -> Baz). Such a chain would deadlock as the367  // query would be waiting on a symbol that it itself had to resolve. Creating368  // a new query for each link in such a chain eliminates the possibility of369  // deadlock. In practice chains are likely to be rare, and this algorithm will370  // usually result in a single query to issue.371 372  std::vector<std::pair<SymbolLookupSet, std::shared_ptr<OnResolveInfo>>>373      QueryInfos;374  while (!RequestedAliases.empty()) {375    SymbolNameSet ResponsibilitySymbols;376    SymbolLookupSet QuerySymbols;377    SymbolAliasMap QueryAliases;378 379    // Collect as many aliases as we can without including a chain.380    for (auto &KV : RequestedAliases) {381      // Chain detected. Skip this symbol for this round.382      if (&SrcJD == &TgtJD && (QueryAliases.count(KV.second.Aliasee) ||383                               RequestedAliases.count(KV.second.Aliasee)))384        continue;385 386      ResponsibilitySymbols.insert(KV.first);387      QuerySymbols.add(KV.second.Aliasee,388                       KV.second.AliasFlags.hasMaterializationSideEffectsOnly()389                           ? SymbolLookupFlags::WeaklyReferencedSymbol390                           : SymbolLookupFlags::RequiredSymbol);391      QueryAliases[KV.first] = std::move(KV.second);392    }393 394    // Remove the aliases collected this round from the RequestedAliases map.395    for (auto &KV : QueryAliases)396      RequestedAliases.erase(KV.first);397 398    assert(!QuerySymbols.empty() && "Alias cycle detected!");399 400    auto NewR = R->delegate(ResponsibilitySymbols);401    if (!NewR) {402      ES.reportError(NewR.takeError());403      R->failMaterialization();404      return;405    }406 407    auto QueryInfo = std::make_shared<OnResolveInfo>(std::move(*NewR),408                                                     std::move(QueryAliases));409    QueryInfos.push_back(410        make_pair(std::move(QuerySymbols), std::move(QueryInfo)));411  }412 413  // Issue the queries.414  while (!QueryInfos.empty()) {415    auto QuerySymbols = std::move(QueryInfos.back().first);416    auto QueryInfo = std::move(QueryInfos.back().second);417 418    QueryInfos.pop_back();419 420    auto RegisterDependencies = [QueryInfo,421                                 &SrcJD](const SymbolDependenceMap &Deps) {422      // If there were no materializing symbols, just bail out.423      if (Deps.empty())424        return;425 426      // Otherwise the only deps should be on SrcJD.427      assert(Deps.size() == 1 && Deps.count(&SrcJD) &&428             "Unexpected dependencies for reexports");429 430      auto &SrcJDDeps = Deps.find(&SrcJD)->second;431 432      for (auto &[Alias, AliasInfo] : QueryInfo->Aliases)433        if (SrcJDDeps.count(AliasInfo.Aliasee))434          QueryInfo->SDGs.push_back({{Alias}, {{&SrcJD, {AliasInfo.Aliasee}}}});435    };436 437    auto OnComplete = [QueryInfo](Expected<SymbolMap> Result) {438      auto &ES = QueryInfo->R->getTargetJITDylib().getExecutionSession();439      if (Result) {440        SymbolMap ResolutionMap;441        for (auto &KV : QueryInfo->Aliases) {442          assert((KV.second.AliasFlags.hasMaterializationSideEffectsOnly() ||443                  Result->count(KV.second.Aliasee)) &&444                 "Result map missing entry?");445          // Don't try to resolve materialization-side-effects-only symbols.446          if (KV.second.AliasFlags.hasMaterializationSideEffectsOnly())447            continue;448 449          ResolutionMap[KV.first] = {(*Result)[KV.second.Aliasee].getAddress(),450                                     KV.second.AliasFlags};451        }452        if (auto Err = QueryInfo->R->notifyResolved(ResolutionMap)) {453          ES.reportError(std::move(Err));454          QueryInfo->R->failMaterialization();455          return;456        }457        if (auto Err = QueryInfo->R->notifyEmitted(QueryInfo->SDGs)) {458          ES.reportError(std::move(Err));459          QueryInfo->R->failMaterialization();460          return;461        }462      } else {463        ES.reportError(Result.takeError());464        QueryInfo->R->failMaterialization();465      }466    };467 468    ES.lookup(LookupKind::Static,469              JITDylibSearchOrder({{&SrcJD, SourceJDLookupFlags}}),470              QuerySymbols, SymbolState::Resolved, std::move(OnComplete),471              std::move(RegisterDependencies));472  }473}474 475void ReExportsMaterializationUnit::discard(const JITDylib &JD,476                                           const SymbolStringPtr &Name) {477  assert(Aliases.count(Name) &&478         "Symbol not covered by this MaterializationUnit");479  Aliases.erase(Name);480}481 482MaterializationUnit::Interface483ReExportsMaterializationUnit::extractFlags(const SymbolAliasMap &Aliases) {484  SymbolFlagsMap SymbolFlags;485  for (auto &KV : Aliases)486    SymbolFlags[KV.first] = KV.second.AliasFlags;487 488  return MaterializationUnit::Interface(std::move(SymbolFlags), nullptr);489}490 491Expected<SymbolAliasMap> buildSimpleReexportsAliasMap(JITDylib &SourceJD,492                                                      SymbolNameSet Symbols) {493  SymbolLookupSet LookupSet(Symbols);494  auto Flags = SourceJD.getExecutionSession().lookupFlags(495      LookupKind::Static, {{&SourceJD, JITDylibLookupFlags::MatchAllSymbols}},496      SymbolLookupSet(std::move(Symbols)));497 498  if (!Flags)499    return Flags.takeError();500 501  SymbolAliasMap Result;502  for (auto &Name : Symbols) {503    assert(Flags->count(Name) && "Missing entry in flags map");504    Result[Name] = SymbolAliasMapEntry(Name, (*Flags)[Name]);505  }506 507  return Result;508}509 510class InProgressLookupState {511public:512  // FIXME: Reduce the number of SymbolStringPtrs here. See513  //        https://github.com/llvm/llvm-project/issues/55576.514 515  InProgressLookupState(LookupKind K, JITDylibSearchOrder SearchOrder,516                        SymbolLookupSet LookupSet, SymbolState RequiredState)517      : K(K), SearchOrder(std::move(SearchOrder)),518        LookupSet(std::move(LookupSet)), RequiredState(RequiredState) {519    DefGeneratorCandidates = this->LookupSet;520  }521  virtual ~InProgressLookupState() = default;522  virtual void complete(std::unique_ptr<InProgressLookupState> IPLS) = 0;523  virtual void fail(Error Err) = 0;524 525  LookupKind K;526  JITDylibSearchOrder SearchOrder;527  SymbolLookupSet LookupSet;528  SymbolState RequiredState;529 530  size_t CurSearchOrderIndex = 0;531  bool NewJITDylib = true;532  SymbolLookupSet DefGeneratorCandidates;533  SymbolLookupSet DefGeneratorNonCandidates;534 535  enum {536    NotInGenerator,      // Not currently using a generator.537    ResumedForGenerator, // Resumed after being auto-suspended before generator.538    InGenerator          // Currently using generator.539  } GenState = NotInGenerator;540  std::vector<std::weak_ptr<DefinitionGenerator>> CurDefGeneratorStack;541};542 543class InProgressLookupFlagsState : public InProgressLookupState {544public:545  InProgressLookupFlagsState(546      LookupKind K, JITDylibSearchOrder SearchOrder, SymbolLookupSet LookupSet,547      unique_function<void(Expected<SymbolFlagsMap>)> OnComplete)548      : InProgressLookupState(K, std::move(SearchOrder), std::move(LookupSet),549                              SymbolState::NeverSearched),550        OnComplete(std::move(OnComplete)) {}551 552  void complete(std::unique_ptr<InProgressLookupState> IPLS) override {553    auto &ES = SearchOrder.front().first->getExecutionSession();554    ES.OL_completeLookupFlags(std::move(IPLS), std::move(OnComplete));555  }556 557  void fail(Error Err) override { OnComplete(std::move(Err)); }558 559private:560  unique_function<void(Expected<SymbolFlagsMap>)> OnComplete;561};562 563class InProgressFullLookupState : public InProgressLookupState {564public:565  InProgressFullLookupState(LookupKind K, JITDylibSearchOrder SearchOrder,566                            SymbolLookupSet LookupSet,567                            SymbolState RequiredState,568                            std::shared_ptr<AsynchronousSymbolQuery> Q,569                            RegisterDependenciesFunction RegisterDependencies)570      : InProgressLookupState(K, std::move(SearchOrder), std::move(LookupSet),571                              RequiredState),572        Q(std::move(Q)), RegisterDependencies(std::move(RegisterDependencies)) {573  }574 575  void complete(std::unique_ptr<InProgressLookupState> IPLS) override {576    auto &ES = SearchOrder.front().first->getExecutionSession();577    ES.OL_completeLookup(std::move(IPLS), std::move(Q),578                         std::move(RegisterDependencies));579  }580 581  void fail(Error Err) override {582    Q->detach();583    Q->handleFailed(std::move(Err));584  }585 586private:587  std::shared_ptr<AsynchronousSymbolQuery> Q;588  RegisterDependenciesFunction RegisterDependencies;589};590 591ReexportsGenerator::ReexportsGenerator(JITDylib &SourceJD,592                                       JITDylibLookupFlags SourceJDLookupFlags,593                                       SymbolPredicate Allow)594    : SourceJD(SourceJD), SourceJDLookupFlags(SourceJDLookupFlags),595      Allow(std::move(Allow)) {}596 597Error ReexportsGenerator::tryToGenerate(LookupState &LS, LookupKind K,598                                        JITDylib &JD,599                                        JITDylibLookupFlags JDLookupFlags,600                                        const SymbolLookupSet &LookupSet) {601  assert(&JD != &SourceJD && "Cannot re-export from the same dylib");602 603  // Use lookupFlags to find the subset of symbols that match our lookup.604  auto Flags = JD.getExecutionSession().lookupFlags(605      K, {{&SourceJD, JDLookupFlags}}, LookupSet);606  if (!Flags)607    return Flags.takeError();608 609  // Create an alias map.610  orc::SymbolAliasMap AliasMap;611  for (auto &KV : *Flags)612    if (!Allow || Allow(KV.first))613      AliasMap[KV.first] = SymbolAliasMapEntry(KV.first, KV.second);614 615  if (AliasMap.empty())616    return Error::success();617 618  // Define the re-exports.619  return JD.define(reexports(SourceJD, AliasMap, SourceJDLookupFlags));620}621 622LookupState::LookupState(std::unique_ptr<InProgressLookupState> IPLS)623    : IPLS(std::move(IPLS)) {}624 625void LookupState::reset(InProgressLookupState *IPLS) { this->IPLS.reset(IPLS); }626 627LookupState::LookupState() = default;628LookupState::LookupState(LookupState &&) = default;629LookupState &LookupState::operator=(LookupState &&) = default;630LookupState::~LookupState() = default;631 632void LookupState::continueLookup(Error Err) {633  assert(IPLS && "Cannot call continueLookup on empty LookupState");634  auto &ES = IPLS->SearchOrder.begin()->first->getExecutionSession();635  ES.OL_applyQueryPhase1(std::move(IPLS), std::move(Err));636}637 638DefinitionGenerator::~DefinitionGenerator() {639  std::deque<LookupState> LookupsToFail;640  {641    std::lock_guard<std::mutex> Lock(M);642    std::swap(PendingLookups, LookupsToFail);643    InUse = false;644  }645 646  for (auto &LS : LookupsToFail)647    LS.continueLookup(make_error<StringError>(648        "Query waiting on DefinitionGenerator that was destroyed",649        inconvertibleErrorCode()));650}651 652JITDylib::~JITDylib() {653  LLVM_DEBUG(dbgs() << "Destroying JITDylib " << getName() << "\n");654}655 656Error JITDylib::clear() {657  std::vector<ResourceTrackerSP> TrackersToRemove;658  ES.runSessionLocked([&]() {659    assert(State != Closed && "JD is defunct");660    for (auto &KV : TrackerSymbols)661      TrackersToRemove.push_back(KV.first);662    TrackersToRemove.push_back(getDefaultResourceTracker());663  });664 665  Error Err = Error::success();666  for (auto &RT : TrackersToRemove)667    Err = joinErrors(std::move(Err), RT->remove());668  return Err;669}670 671ResourceTrackerSP JITDylib::getDefaultResourceTracker() {672  return ES.runSessionLocked([this] {673    assert(State != Closed && "JD is defunct");674    if (!DefaultTracker)675      DefaultTracker = new ResourceTracker(this);676    return DefaultTracker;677  });678}679 680ResourceTrackerSP JITDylib::createResourceTracker() {681  return ES.runSessionLocked([this] {682    assert(State == Open && "JD is defunct");683    ResourceTrackerSP RT = new ResourceTracker(this);684    return RT;685  });686}687 688void JITDylib::removeGenerator(DefinitionGenerator &G) {689  // DefGenerator moved into TmpDG to ensure that it's destroyed outside the690  // session lock (since it may have to send errors to pending queries).691  std::shared_ptr<DefinitionGenerator> TmpDG;692 693  ES.runSessionLocked([&] {694    assert(State == Open && "JD is defunct");695    auto I = llvm::find_if(DefGenerators,696                           [&](const std::shared_ptr<DefinitionGenerator> &H) {697                             return H.get() == &G;698                           });699    assert(I != DefGenerators.end() && "Generator not found");700    TmpDG = std::move(*I);701    DefGenerators.erase(I);702  });703}704 705Expected<SymbolFlagsMap>706JITDylib::defineMaterializing(MaterializationResponsibility &FromMR,707                              SymbolFlagsMap SymbolFlags) {708 709  return ES.runSessionLocked([&]() -> Expected<SymbolFlagsMap> {710    if (FromMR.RT->isDefunct())711      return make_error<ResourceTrackerDefunct>(FromMR.RT);712 713    std::vector<NonOwningSymbolStringPtr> AddedSyms;714    std::vector<NonOwningSymbolStringPtr> RejectedWeakDefs;715 716    for (auto &[Name, Flags] : SymbolFlags) {717      auto EntryItr = Symbols.find(Name);718 719      // If the entry already exists...720      if (EntryItr != Symbols.end()) {721 722        // If this is a strong definition then error out.723        if (!Flags.isWeak()) {724          // Remove any symbols already added.725          for (auto &S : AddedSyms)726            Symbols.erase(Symbols.find_as(S));727 728          // FIXME: Return all duplicates.729          return make_error<DuplicateDefinition>(730              std::string(*Name), "defineMaterializing operation");731        }732 733        // Otherwise just make a note to discard this symbol after the loop.734        RejectedWeakDefs.push_back(NonOwningSymbolStringPtr(Name));735        continue;736      } else737        EntryItr =738          Symbols.insert(std::make_pair(Name, SymbolTableEntry(Flags))).first;739 740      AddedSyms.push_back(NonOwningSymbolStringPtr(Name));741      EntryItr->second.setState(SymbolState::Materializing);742    }743 744    // Remove any rejected weak definitions from the SymbolFlags map.745    while (!RejectedWeakDefs.empty()) {746      SymbolFlags.erase(SymbolFlags.find_as(RejectedWeakDefs.back()));747      RejectedWeakDefs.pop_back();748    }749 750    return SymbolFlags;751  });752}753 754Error JITDylib::replace(MaterializationResponsibility &FromMR,755                        std::unique_ptr<MaterializationUnit> MU) {756  assert(MU != nullptr && "Can not replace with a null MaterializationUnit");757  std::unique_ptr<MaterializationUnit> MustRunMU;758  std::unique_ptr<MaterializationResponsibility> MustRunMR;759 760  auto Err =761      ES.runSessionLocked([&, this]() -> Error {762        if (FromMR.RT->isDefunct())763          return make_error<ResourceTrackerDefunct>(std::move(FromMR.RT));764 765#ifndef NDEBUG766        for (auto &KV : MU->getSymbols()) {767          auto SymI = Symbols.find(KV.first);768          assert(SymI != Symbols.end() && "Replacing unknown symbol");769          assert(SymI->second.getState() == SymbolState::Materializing &&770                 "Can not replace a symbol that ha is not materializing");771          assert(!SymI->second.hasMaterializerAttached() &&772                 "Symbol should not have materializer attached already");773          assert(UnmaterializedInfos.count(KV.first) == 0 &&774                 "Symbol being replaced should have no UnmaterializedInfo");775        }776#endif // NDEBUG777 778        // If the tracker is defunct we need to bail out immediately.779 780        // If any symbol has pending queries against it then we need to781        // materialize MU immediately.782        for (auto &KV : MU->getSymbols()) {783          auto MII = MaterializingInfos.find(KV.first);784          if (MII != MaterializingInfos.end()) {785            if (MII->second.hasQueriesPending()) {786              MustRunMR = ES.createMaterializationResponsibility(787                  *FromMR.RT, std::move(MU->SymbolFlags),788                  std::move(MU->InitSymbol));789              MustRunMU = std::move(MU);790              return Error::success();791            }792          }793        }794 795        // Otherwise, make MU responsible for all the symbols.796        auto UMI = std::make_shared<UnmaterializedInfo>(std::move(MU),797                                                        FromMR.RT.get());798        for (auto &KV : UMI->MU->getSymbols()) {799          auto SymI = Symbols.find(KV.first);800          assert(SymI->second.getState() == SymbolState::Materializing &&801                 "Can not replace a symbol that is not materializing");802          assert(!SymI->second.hasMaterializerAttached() &&803                 "Can not replace a symbol that has a materializer attached");804          assert(UnmaterializedInfos.count(KV.first) == 0 &&805                 "Unexpected materializer entry in map");806          SymI->second.setAddress(SymI->second.getAddress());807          SymI->second.setMaterializerAttached(true);808 809          auto &UMIEntry = UnmaterializedInfos[KV.first];810          assert((!UMIEntry || !UMIEntry->MU) &&811                 "Replacing symbol with materializer still attached");812          UMIEntry = UMI;813        }814 815        return Error::success();816      });817 818  if (Err)819    return Err;820 821  if (MustRunMU) {822    assert(MustRunMR && "MustRunMU set implies MustRunMR set");823    ES.dispatchTask(std::make_unique<MaterializationTask>(824        std::move(MustRunMU), std::move(MustRunMR)));825  } else {826    assert(!MustRunMR && "MustRunMU unset implies MustRunMR unset");827  }828 829  return Error::success();830}831 832Expected<std::unique_ptr<MaterializationResponsibility>>833JITDylib::delegate(MaterializationResponsibility &FromMR,834                   SymbolFlagsMap SymbolFlags, SymbolStringPtr InitSymbol) {835 836  return ES.runSessionLocked(837      [&]() -> Expected<std::unique_ptr<MaterializationResponsibility>> {838        if (FromMR.RT->isDefunct())839          return make_error<ResourceTrackerDefunct>(std::move(FromMR.RT));840 841        return ES.createMaterializationResponsibility(842            *FromMR.RT, std::move(SymbolFlags), std::move(InitSymbol));843      });844}845 846SymbolNameSet847JITDylib::getRequestedSymbols(const SymbolFlagsMap &SymbolFlags) const {848  return ES.runSessionLocked([&]() {849    SymbolNameSet RequestedSymbols;850 851    for (auto &KV : SymbolFlags) {852      assert(Symbols.count(KV.first) && "JITDylib does not cover this symbol?");853      assert(Symbols.find(KV.first)->second.getState() !=854                 SymbolState::NeverSearched &&855             Symbols.find(KV.first)->second.getState() != SymbolState::Ready &&856             "getRequestedSymbols can only be called for symbols that have "857             "started materializing");858      auto I = MaterializingInfos.find(KV.first);859      if (I == MaterializingInfos.end())860        continue;861 862      if (I->second.hasQueriesPending())863        RequestedSymbols.insert(KV.first);864    }865 866    return RequestedSymbols;867  });868}869 870Error JITDylib::resolve(MaterializationResponsibility &MR,871                        const SymbolMap &Resolved) {872  AsynchronousSymbolQuerySet CompletedQueries;873 874  if (auto Err = ES.runSessionLocked([&, this]() -> Error {875        if (MR.RT->isDefunct())876          return make_error<ResourceTrackerDefunct>(MR.RT);877 878        if (State != Open)879          return make_error<StringError>("JITDylib " + getName() +880                                             " is defunct",881                                         inconvertibleErrorCode());882 883        struct WorklistEntry {884          SymbolTable::iterator SymI;885          ExecutorSymbolDef ResolvedSym;886        };887 888        SymbolNameSet SymbolsInErrorState;889        std::vector<WorklistEntry> Worklist;890        Worklist.reserve(Resolved.size());891 892        // Build worklist and check for any symbols in the error state.893        for (const auto &KV : Resolved) {894 895          assert(!KV.second.getFlags().hasError() &&896                 "Resolution result can not have error flag set");897 898          auto SymI = Symbols.find(KV.first);899 900          assert(SymI != Symbols.end() && "Symbol not found");901          assert(!SymI->second.hasMaterializerAttached() &&902                 "Resolving symbol with materializer attached?");903          assert(SymI->second.getState() == SymbolState::Materializing &&904                 "Symbol should be materializing");905          assert(SymI->second.getAddress() == ExecutorAddr() &&906                 "Symbol has already been resolved");907 908          if (SymI->second.getFlags().hasError())909            SymbolsInErrorState.insert(KV.first);910          else {911            if (SymI->second.getFlags() & JITSymbolFlags::Common) {912              [[maybe_unused]] auto WeakOrCommon =913                  JITSymbolFlags::Weak | JITSymbolFlags::Common;914              assert((KV.second.getFlags() & WeakOrCommon) &&915                     "Common symbols must be resolved as common or weak");916              assert((KV.second.getFlags() & ~WeakOrCommon) ==917                         (SymI->second.getFlags() & ~JITSymbolFlags::Common) &&918                     "Resolving symbol with incorrect flags");919 920            } else921              assert(KV.second.getFlags() == SymI->second.getFlags() &&922                     "Resolved flags should match the declared flags");923 924            Worklist.push_back(925                {SymI, {KV.second.getAddress(), SymI->second.getFlags()}});926          }927        }928 929        // If any symbols were in the error state then bail out.930        if (!SymbolsInErrorState.empty()) {931          auto FailedSymbolsDepMap = std::make_shared<SymbolDependenceMap>();932          (*FailedSymbolsDepMap)[this] = std::move(SymbolsInErrorState);933          return make_error<FailedToMaterialize>(934              getExecutionSession().getSymbolStringPool(),935              std::move(FailedSymbolsDepMap));936        }937 938        while (!Worklist.empty()) {939          auto SymI = Worklist.back().SymI;940          auto ResolvedSym = Worklist.back().ResolvedSym;941          Worklist.pop_back();942 943          auto &Name = SymI->first;944 945          // Resolved symbols can not be weak: discard the weak flag.946          JITSymbolFlags ResolvedFlags = ResolvedSym.getFlags();947          SymI->second.setAddress(ResolvedSym.getAddress());948          SymI->second.setFlags(ResolvedFlags);949          SymI->second.setState(SymbolState::Resolved);950 951          auto MII = MaterializingInfos.find(Name);952          if (MII == MaterializingInfos.end())953            continue;954 955          auto &MI = MII->second;956          for (auto &Q : MI.takeQueriesMeeting(SymbolState::Resolved)) {957            Q->notifySymbolMetRequiredState(Name, ResolvedSym);958            if (Q->isComplete())959              CompletedQueries.insert(std::move(Q));960          }961        }962 963        return Error::success();964      }))965    return Err;966 967  // Otherwise notify all the completed queries.968  for (auto &Q : CompletedQueries) {969    assert(Q->isComplete() && "Q not completed");970    Q->handleComplete(ES);971  }972 973  return Error::success();974}975 976void JITDylib::unlinkMaterializationResponsibility(977    MaterializationResponsibility &MR) {978  ES.runSessionLocked([&]() {979    auto I = TrackerMRs.find(MR.RT.get());980    assert(I != TrackerMRs.end() && "No MRs in TrackerMRs list for RT");981    assert(I->second.count(&MR) && "MR not in TrackerMRs list for RT");982    I->second.erase(&MR);983    if (I->second.empty())984      TrackerMRs.erase(MR.RT.get());985  });986}987 988void JITDylib::shrinkMaterializationInfoMemory() {989  // DenseMap::erase never shrinks its storage; use clear to heuristically free990  // memory since we may have long-lived JDs after linking is done.991 992  if (UnmaterializedInfos.empty())993    UnmaterializedInfos.clear();994 995  if (MaterializingInfos.empty())996    MaterializingInfos.clear();997}998 999void JITDylib::setLinkOrder(JITDylibSearchOrder NewLinkOrder,1000                            bool LinkAgainstThisJITDylibFirst) {1001  ES.runSessionLocked([&]() {1002    assert(State == Open && "JD is defunct");1003    if (LinkAgainstThisJITDylibFirst) {1004      LinkOrder.clear();1005      if (NewLinkOrder.empty() || NewLinkOrder.front().first != this)1006        LinkOrder.push_back(1007            std::make_pair(this, JITDylibLookupFlags::MatchAllSymbols));1008      llvm::append_range(LinkOrder, NewLinkOrder);1009    } else1010      LinkOrder = std::move(NewLinkOrder);1011  });1012}1013 1014void JITDylib::addToLinkOrder(const JITDylibSearchOrder &NewLinks) {1015  ES.runSessionLocked([&]() {1016    for (auto &KV : NewLinks) {1017      // Skip elements of NewLinks that are already in the link order.1018      if (llvm::is_contained(LinkOrder, KV))1019        continue;1020 1021      LinkOrder.push_back(std::move(KV));1022    }1023  });1024}1025 1026void JITDylib::addToLinkOrder(JITDylib &JD, JITDylibLookupFlags JDLookupFlags) {1027  ES.runSessionLocked([&]() { LinkOrder.push_back({&JD, JDLookupFlags}); });1028}1029 1030void JITDylib::replaceInLinkOrder(JITDylib &OldJD, JITDylib &NewJD,1031                                  JITDylibLookupFlags JDLookupFlags) {1032  ES.runSessionLocked([&]() {1033    assert(State == Open && "JD is defunct");1034    for (auto &KV : LinkOrder)1035      if (KV.first == &OldJD) {1036        KV = {&NewJD, JDLookupFlags};1037        break;1038      }1039  });1040}1041 1042void JITDylib::removeFromLinkOrder(JITDylib &JD) {1043  ES.runSessionLocked([&]() {1044    assert(State == Open && "JD is defunct");1045    auto I = llvm::find_if(LinkOrder,1046                           [&](const JITDylibSearchOrder::value_type &KV) {1047                             return KV.first == &JD;1048                           });1049    if (I != LinkOrder.end())1050      LinkOrder.erase(I);1051  });1052}1053 1054Error JITDylib::remove(const SymbolNameSet &Names) {1055  return ES.runSessionLocked([&]() -> Error {1056    assert(State == Open && "JD is defunct");1057    using SymbolMaterializerItrPair =1058        std::pair<SymbolTable::iterator, UnmaterializedInfosMap::iterator>;1059    std::vector<SymbolMaterializerItrPair> SymbolsToRemove;1060    SymbolNameSet Missing;1061    SymbolNameSet Materializing;1062 1063    for (auto &Name : Names) {1064      auto I = Symbols.find(Name);1065 1066      // Note symbol missing.1067      if (I == Symbols.end()) {1068        Missing.insert(Name);1069        continue;1070      }1071 1072      // Note symbol materializing.1073      if (I->second.getState() != SymbolState::NeverSearched &&1074          I->second.getState() != SymbolState::Ready) {1075        Materializing.insert(Name);1076        continue;1077      }1078 1079      auto UMII = I->second.hasMaterializerAttached()1080                      ? UnmaterializedInfos.find(Name)1081                      : UnmaterializedInfos.end();1082      SymbolsToRemove.push_back(std::make_pair(I, UMII));1083    }1084 1085    // If any of the symbols are not defined, return an error.1086    if (!Missing.empty())1087      return make_error<SymbolsNotFound>(ES.getSymbolStringPool(),1088                                         std::move(Missing));1089 1090    // If any of the symbols are currently materializing, return an error.1091    if (!Materializing.empty())1092      return make_error<SymbolsCouldNotBeRemoved>(ES.getSymbolStringPool(),1093                                                  std::move(Materializing));1094 1095    // Remove the symbols.1096    for (auto &SymbolMaterializerItrPair : SymbolsToRemove) {1097      auto UMII = SymbolMaterializerItrPair.second;1098 1099      // If there is a materializer attached, call discard.1100      if (UMII != UnmaterializedInfos.end()) {1101        UMII->second->MU->doDiscard(*this, UMII->first);1102        UnmaterializedInfos.erase(UMII);1103      }1104 1105      auto SymI = SymbolMaterializerItrPair.first;1106      Symbols.erase(SymI);1107    }1108 1109    shrinkMaterializationInfoMemory();1110 1111    return Error::success();1112  });1113}1114 1115void JITDylib::dump(raw_ostream &OS) {1116  ES.runSessionLocked([&, this]() {1117    OS << "JITDylib \"" << getName() << "\" (ES: "1118       << format("0x%016" PRIx64, reinterpret_cast<uintptr_t>(&ES))1119       << ", State = ";1120    switch (State) {1121    case Open:1122      OS << "Open";1123      break;1124    case Closing:1125      OS << "Closing";1126      break;1127    case Closed:1128      OS << "Closed";1129      break;1130    }1131    OS << ")\n";1132    if (State == Closed)1133      return;1134    OS << "Link order: " << LinkOrder << "\n"1135       << "Symbol table:\n";1136 1137    // Sort symbols so we get a deterministic order and can check them in tests.1138    std::vector<std::pair<SymbolStringPtr, SymbolTableEntry *>> SymbolsSorted;1139    for (auto &KV : Symbols)1140      SymbolsSorted.emplace_back(KV.first, &KV.second);1141    std::sort(SymbolsSorted.begin(), SymbolsSorted.end(),1142              [](const auto &L, const auto &R) { return *L.first < *R.first; });1143 1144    for (auto &KV : SymbolsSorted) {1145      OS << "    \"" << *KV.first << "\": ";1146      if (auto Addr = KV.second->getAddress())1147        OS << Addr;1148      else1149        OS << "<not resolved> ";1150 1151      OS << " " << KV.second->getFlags() << " " << KV.second->getState();1152 1153      if (KV.second->hasMaterializerAttached()) {1154        OS << " (Materializer ";1155        auto I = UnmaterializedInfos.find(KV.first);1156        assert(I != UnmaterializedInfos.end() &&1157               "Lazy symbol should have UnmaterializedInfo");1158        OS << I->second->MU.get() << ", " << I->second->MU->getName() << ")\n";1159      } else1160        OS << "\n";1161    }1162 1163    if (!MaterializingInfos.empty())1164      OS << "  MaterializingInfos entries:\n";1165    for (auto &KV : MaterializingInfos) {1166      OS << "    \"" << *KV.first << "\":\n"1167         << "      " << KV.second.pendingQueries().size()1168         << " pending queries: { ";1169      for (const auto &Q : KV.second.pendingQueries())1170        OS << Q.get() << " (" << Q->getRequiredState() << ") ";1171      OS << "}\n";1172    }1173  });1174}1175 1176void JITDylib::MaterializingInfo::addQuery(1177    std::shared_ptr<AsynchronousSymbolQuery> Q) {1178 1179  auto I = llvm::lower_bound(1180      llvm::reverse(PendingQueries), Q->getRequiredState(),1181      [](const std::shared_ptr<AsynchronousSymbolQuery> &V, SymbolState S) {1182        return V->getRequiredState() <= S;1183      });1184  PendingQueries.insert(I.base(), std::move(Q));1185}1186 1187void JITDylib::MaterializingInfo::removeQuery(1188    const AsynchronousSymbolQuery &Q) {1189  // FIXME: Implement 'find_as' for shared_ptr<T>/T*.1190  auto I = llvm::find_if(1191      PendingQueries, [&Q](const std::shared_ptr<AsynchronousSymbolQuery> &V) {1192        return V.get() == &Q;1193      });1194  if (I != PendingQueries.end())1195    PendingQueries.erase(I);1196}1197 1198JITDylib::AsynchronousSymbolQueryList1199JITDylib::MaterializingInfo::takeQueriesMeeting(SymbolState RequiredState) {1200  AsynchronousSymbolQueryList Result;1201  while (!PendingQueries.empty()) {1202    if (PendingQueries.back()->getRequiredState() > RequiredState)1203      break;1204 1205    Result.push_back(std::move(PendingQueries.back()));1206    PendingQueries.pop_back();1207  }1208 1209  return Result;1210}1211 1212JITDylib::JITDylib(ExecutionSession &ES, std::string Name)1213    : JITLinkDylib(std::move(Name)), ES(ES) {1214  LinkOrder.push_back({this, JITDylibLookupFlags::MatchAllSymbols});1215}1216 1217JITDylib::RemoveTrackerResult JITDylib::IL_removeTracker(ResourceTracker &RT) {1218  // Note: Should be called under the session lock.1219  assert(State != Closed && "JD is defunct");1220 1221  SymbolNameVector SymbolsToRemove;1222  SymbolNameVector SymbolsToFail;1223 1224  if (&RT == DefaultTracker.get()) {1225    SymbolNameSet TrackedSymbols;1226    for (auto &KV : TrackerSymbols)1227      TrackedSymbols.insert_range(KV.second);1228 1229    for (auto &KV : Symbols) {1230      auto &Sym = KV.first;1231      if (!TrackedSymbols.count(Sym))1232        SymbolsToRemove.push_back(Sym);1233    }1234 1235    DefaultTracker.reset();1236  } else {1237    /// Check for a non-default tracker.1238    auto I = TrackerSymbols.find(&RT);1239    if (I != TrackerSymbols.end()) {1240      SymbolsToRemove = std::move(I->second);1241      TrackerSymbols.erase(I);1242    }1243    // ... if not found this tracker was already defunct. Nothing to do.1244  }1245 1246  for (auto &Sym : SymbolsToRemove) {1247    assert(Symbols.count(Sym) && "Symbol not in symbol table");1248 1249    // If there is a MaterializingInfo then collect any queries to fail.1250    auto MII = MaterializingInfos.find(Sym);1251    if (MII != MaterializingInfos.end())1252      SymbolsToFail.push_back(Sym);1253  }1254 1255  auto [QueriesToFail, FailedSymbols] =1256      ES.IL_failSymbols(*this, std::move(SymbolsToFail));1257 1258  std::vector<std::unique_ptr<MaterializationUnit>> DefunctMUs;1259 1260  // Removed symbols should be taken out of the table altogether.1261  for (auto &Sym : SymbolsToRemove) {1262    auto I = Symbols.find(Sym);1263    assert(I != Symbols.end() && "Symbol not present in table");1264 1265    // Remove Materializer if present.1266    if (I->second.hasMaterializerAttached()) {1267      // FIXME: Should this discard the symbols?1268      auto J = UnmaterializedInfos.find(Sym);1269      assert(J != UnmaterializedInfos.end() &&1270             "Symbol table indicates MU present, but no UMI record");1271      if (J->second->MU)1272        DefunctMUs.push_back(std::move(J->second->MU));1273      UnmaterializedInfos.erase(J);1274    } else {1275      assert(!UnmaterializedInfos.count(Sym) &&1276             "Symbol has materializer attached");1277    }1278 1279    Symbols.erase(I);1280  }1281 1282  shrinkMaterializationInfoMemory();1283 1284  return {std::move(QueriesToFail), std::move(FailedSymbols),1285          std::move(DefunctMUs)};1286}1287 1288void JITDylib::transferTracker(ResourceTracker &DstRT, ResourceTracker &SrcRT) {1289  assert(State != Closed && "JD is defunct");1290  assert(&DstRT != &SrcRT && "No-op transfers shouldn't call transferTracker");1291  assert(&DstRT.getJITDylib() == this && "DstRT is not for this JITDylib");1292  assert(&SrcRT.getJITDylib() == this && "SrcRT is not for this JITDylib");1293 1294  // Update trackers for any not-yet materialized units.1295  for (auto &KV : UnmaterializedInfos) {1296    if (KV.second->RT == &SrcRT)1297      KV.second->RT = &DstRT;1298  }1299 1300  // Update trackers for any active materialization responsibilities.1301  {1302    auto I = TrackerMRs.find(&SrcRT);1303    if (I != TrackerMRs.end()) {1304      auto &SrcMRs = I->second;1305      auto &DstMRs = TrackerMRs[&DstRT];1306      for (auto *MR : SrcMRs)1307        MR->RT = &DstRT;1308      if (DstMRs.empty())1309        DstMRs = std::move(SrcMRs);1310      else1311        DstMRs.insert_range(SrcMRs);1312      // Erase SrcRT entry in TrackerMRs. Use &SrcRT key rather than iterator I1313      // for this, since I may have been invalidated by 'TrackerMRs[&DstRT]'.1314      TrackerMRs.erase(&SrcRT);1315    }1316  }1317 1318  // If we're transfering to the default tracker we just need to delete the1319  // tracked symbols for the source tracker.1320  if (&DstRT == DefaultTracker.get()) {1321    TrackerSymbols.erase(&SrcRT);1322    return;1323  }1324 1325  // If we're transferring from the default tracker we need to find all1326  // currently untracked symbols.1327  if (&SrcRT == DefaultTracker.get()) {1328    assert(!TrackerSymbols.count(&SrcRT) &&1329           "Default tracker should not appear in TrackerSymbols");1330 1331    SymbolNameVector SymbolsToTrack;1332 1333    SymbolNameSet CurrentlyTrackedSymbols;1334    for (auto &KV : TrackerSymbols)1335      CurrentlyTrackedSymbols.insert_range(KV.second);1336 1337    for (auto &KV : Symbols) {1338      auto &Sym = KV.first;1339      if (!CurrentlyTrackedSymbols.count(Sym))1340        SymbolsToTrack.push_back(Sym);1341    }1342 1343    TrackerSymbols[&DstRT] = std::move(SymbolsToTrack);1344    return;1345  }1346 1347  auto &DstTrackedSymbols = TrackerSymbols[&DstRT];1348 1349  // Finally if neither SrtRT or DstRT are the default tracker then1350  // just append DstRT's tracked symbols to SrtRT's.1351  auto SI = TrackerSymbols.find(&SrcRT);1352  if (SI == TrackerSymbols.end())1353    return;1354 1355  DstTrackedSymbols.reserve(DstTrackedSymbols.size() + SI->second.size());1356  for (auto &Sym : SI->second)1357    DstTrackedSymbols.push_back(std::move(Sym));1358  TrackerSymbols.erase(SI);1359}1360 1361Error JITDylib::defineImpl(MaterializationUnit &MU) {1362  LLVM_DEBUG({ dbgs() << "  " << MU.getSymbols() << "\n"; });1363 1364  SymbolNameSet Duplicates;1365  std::vector<SymbolStringPtr> ExistingDefsOverridden;1366  std::vector<SymbolStringPtr> MUDefsOverridden;1367 1368  for (const auto &KV : MU.getSymbols()) {1369    auto I = Symbols.find(KV.first);1370 1371    if (I != Symbols.end()) {1372      if (KV.second.isStrong()) {1373        if (I->second.getFlags().isStrong() ||1374            I->second.getState() > SymbolState::NeverSearched)1375          Duplicates.insert(KV.first);1376        else {1377          assert(I->second.getState() == SymbolState::NeverSearched &&1378                 "Overridden existing def should be in the never-searched "1379                 "state");1380          ExistingDefsOverridden.push_back(KV.first);1381        }1382      } else1383        MUDefsOverridden.push_back(KV.first);1384    }1385  }1386 1387  // If there were any duplicate definitions then bail out.1388  if (!Duplicates.empty()) {1389    LLVM_DEBUG(1390        { dbgs() << "  Error: Duplicate symbols " << Duplicates << "\n"; });1391    return make_error<DuplicateDefinition>(std::string(**Duplicates.begin()),1392                                           MU.getName().str());1393  }1394 1395  // Discard any overridden defs in this MU.1396  LLVM_DEBUG({1397    if (!MUDefsOverridden.empty())1398      dbgs() << "  Defs in this MU overridden: " << MUDefsOverridden << "\n";1399  });1400  for (auto &S : MUDefsOverridden)1401    MU.doDiscard(*this, S);1402 1403  // Discard existing overridden defs.1404  LLVM_DEBUG({1405    if (!ExistingDefsOverridden.empty())1406      dbgs() << "  Existing defs overridden by this MU: " << MUDefsOverridden1407             << "\n";1408  });1409  for (auto &S : ExistingDefsOverridden) {1410 1411    auto UMII = UnmaterializedInfos.find(S);1412    assert(UMII != UnmaterializedInfos.end() &&1413           "Overridden existing def should have an UnmaterializedInfo");1414    UMII->second->MU->doDiscard(*this, S);1415  }1416 1417  // Finally, add the defs from this MU.1418  for (auto &KV : MU.getSymbols()) {1419    auto &SymEntry = Symbols[KV.first];1420    SymEntry.setFlags(KV.second);1421    SymEntry.setState(SymbolState::NeverSearched);1422    SymEntry.setMaterializerAttached(true);1423  }1424 1425  return Error::success();1426}1427 1428void JITDylib::installMaterializationUnit(1429    std::unique_ptr<MaterializationUnit> MU, ResourceTracker &RT) {1430 1431  /// defineImpl succeeded.1432  if (&RT != DefaultTracker.get()) {1433    auto &TS = TrackerSymbols[&RT];1434    TS.reserve(TS.size() + MU->getSymbols().size());1435    for (auto &KV : MU->getSymbols())1436      TS.push_back(KV.first);1437  }1438 1439  auto UMI = std::make_shared<UnmaterializedInfo>(std::move(MU), &RT);1440  for (auto &KV : UMI->MU->getSymbols())1441    UnmaterializedInfos[KV.first] = UMI;1442}1443 1444void JITDylib::detachQueryHelper(AsynchronousSymbolQuery &Q,1445                                 const SymbolNameSet &QuerySymbols) {1446  for (auto &QuerySymbol : QuerySymbols) {1447    auto MII = MaterializingInfos.find(QuerySymbol);1448    if (MII != MaterializingInfos.end())1449      MII->second.removeQuery(Q);1450  }1451}1452 1453Platform::~Platform() = default;1454 1455Expected<DenseMap<JITDylib *, SymbolMap>> Platform::lookupInitSymbols(1456    ExecutionSession &ES,1457    const DenseMap<JITDylib *, SymbolLookupSet> &InitSyms) {1458 1459  DenseMap<JITDylib *, SymbolMap> CompoundResult;1460  Error CompoundErr = Error::success();1461  std::mutex LookupMutex;1462  std::condition_variable CV;1463  uint64_t Count = InitSyms.size();1464 1465  LLVM_DEBUG({1466    dbgs() << "Issuing init-symbol lookup:\n";1467    for (auto &KV : InitSyms)1468      dbgs() << "  " << KV.first->getName() << ": " << KV.second << "\n";1469  });1470 1471  for (auto &KV : InitSyms) {1472    auto *JD = KV.first;1473    auto Names = std::move(KV.second);1474    ES.lookup(1475        LookupKind::Static,1476        JITDylibSearchOrder({{JD, JITDylibLookupFlags::MatchAllSymbols}}),1477        std::move(Names), SymbolState::Ready,1478        [&, JD](Expected<SymbolMap> Result) {1479          {1480            std::lock_guard<std::mutex> Lock(LookupMutex);1481            --Count;1482            if (Result) {1483              assert(!CompoundResult.count(JD) &&1484                     "Duplicate JITDylib in lookup?");1485              CompoundResult[JD] = std::move(*Result);1486            } else1487              CompoundErr =1488                  joinErrors(std::move(CompoundErr), Result.takeError());1489          }1490          CV.notify_one();1491        },1492        NoDependenciesToRegister);1493  }1494 1495  std::unique_lock<std::mutex> Lock(LookupMutex);1496  CV.wait(Lock, [&] { return Count == 0; });1497 1498  if (CompoundErr)1499    return std::move(CompoundErr);1500 1501  return std::move(CompoundResult);1502}1503 1504void Platform::lookupInitSymbolsAsync(1505    unique_function<void(Error)> OnComplete, ExecutionSession &ES,1506    const DenseMap<JITDylib *, SymbolLookupSet> &InitSyms) {1507 1508  class TriggerOnComplete {1509  public:1510    using OnCompleteFn = unique_function<void(Error)>;1511    TriggerOnComplete(OnCompleteFn OnComplete)1512        : OnComplete(std::move(OnComplete)) {}1513    ~TriggerOnComplete() { OnComplete(std::move(LookupResult)); }1514    void reportResult(Error Err) {1515      std::lock_guard<std::mutex> Lock(ResultMutex);1516      LookupResult = joinErrors(std::move(LookupResult), std::move(Err));1517    }1518 1519  private:1520    std::mutex ResultMutex;1521    Error LookupResult{Error::success()};1522    OnCompleteFn OnComplete;1523  };1524 1525  LLVM_DEBUG({1526    dbgs() << "Issuing init-symbol lookup:\n";1527    for (auto &KV : InitSyms)1528      dbgs() << "  " << KV.first->getName() << ": " << KV.second << "\n";1529  });1530 1531  auto TOC = std::make_shared<TriggerOnComplete>(std::move(OnComplete));1532 1533  for (auto &KV : InitSyms) {1534    auto *JD = KV.first;1535    auto Names = std::move(KV.second);1536    ES.lookup(1537        LookupKind::Static,1538        JITDylibSearchOrder({{JD, JITDylibLookupFlags::MatchAllSymbols}}),1539        std::move(Names), SymbolState::Ready,1540        [TOC](Expected<SymbolMap> Result) {1541          TOC->reportResult(Result.takeError());1542        },1543        NoDependenciesToRegister);1544  }1545}1546 1547MaterializationTask::~MaterializationTask() {1548  // If this task wasn't run then fail materialization.1549  if (MR)1550    MR->failMaterialization();1551}1552 1553void MaterializationTask::printDescription(raw_ostream &OS) {1554  OS << "Materialization task: " << MU->getName() << " in "1555     << MR->getTargetJITDylib().getName();1556}1557 1558void MaterializationTask::run() {1559  assert(MU && "MU should not be null");1560  assert(MR && "MR should not be null");1561  MU->materialize(std::move(MR));1562}1563 1564void LookupTask::printDescription(raw_ostream &OS) { OS << "Lookup task"; }1565 1566void LookupTask::run() { LS.continueLookup(Error::success()); }1567 1568ExecutionSession::ExecutionSession(std::unique_ptr<ExecutorProcessControl> EPC)1569    : EPC(std::move(EPC)) {1570  // Associated EPC and this.1571  this->EPC->ES = this;1572}1573 1574ExecutionSession::~ExecutionSession() {1575  // You must call endSession prior to destroying the session.1576  assert(!SessionOpen &&1577         "Session still open. Did you forget to call endSession?");1578}1579 1580Error ExecutionSession::endSession() {1581  LLVM_DEBUG(dbgs() << "Ending ExecutionSession " << this << "\n");1582 1583  auto JDsToRemove = runSessionLocked([&] {1584 1585#ifdef EXPENSIVE_CHECKS1586    verifySessionState("Entering ExecutionSession::endSession");1587#endif1588 1589    SessionOpen = false;1590    return JDs;1591  });1592 1593  std::reverse(JDsToRemove.begin(), JDsToRemove.end());1594 1595  auto Err = removeJITDylibs(std::move(JDsToRemove));1596 1597  Err = joinErrors(std::move(Err), EPC->disconnect());1598 1599  return Err;1600}1601 1602void ExecutionSession::registerResourceManager(ResourceManager &RM) {1603  runSessionLocked([&] { ResourceManagers.push_back(&RM); });1604}1605 1606void ExecutionSession::deregisterResourceManager(ResourceManager &RM) {1607  runSessionLocked([&] {1608    assert(!ResourceManagers.empty() && "No managers registered");1609    if (ResourceManagers.back() == &RM)1610      ResourceManagers.pop_back();1611    else {1612      auto I = llvm::find(ResourceManagers, &RM);1613      assert(I != ResourceManagers.end() && "RM not registered");1614      ResourceManagers.erase(I);1615    }1616  });1617}1618 1619JITDylib *ExecutionSession::getJITDylibByName(StringRef Name) {1620  return runSessionLocked([&, this]() -> JITDylib * {1621    for (auto &JD : JDs)1622      if (JD->getName() == Name)1623        return JD.get();1624    return nullptr;1625  });1626}1627 1628JITDylib &ExecutionSession::createBareJITDylib(std::string Name) {1629  assert(!getJITDylibByName(Name) && "JITDylib with that name already exists");1630  return runSessionLocked([&, this]() -> JITDylib & {1631    assert(SessionOpen && "Cannot create JITDylib after session is closed");1632    JDs.push_back(new JITDylib(*this, std::move(Name)));1633    return *JDs.back();1634  });1635}1636 1637Expected<JITDylib &> ExecutionSession::createJITDylib(std::string Name) {1638  auto &JD = createBareJITDylib(Name);1639  if (P)1640    if (auto Err = P->setupJITDylib(JD))1641      return std::move(Err);1642  return JD;1643}1644 1645Error ExecutionSession::removeJITDylibs(std::vector<JITDylibSP> JDsToRemove) {1646  // Set JD to 'Closing' state and remove JD from the ExecutionSession.1647  runSessionLocked([&] {1648    for (auto &JD : JDsToRemove) {1649      assert(JD->State == JITDylib::Open && "JD already closed");1650      JD->State = JITDylib::Closing;1651      auto I = llvm::find(JDs, JD);1652      assert(I != JDs.end() && "JD does not appear in session JDs");1653      JDs.erase(I);1654    }1655  });1656 1657  // Clear JITDylibs and notify the platform.1658  Error Err = Error::success();1659  for (auto JD : JDsToRemove) {1660    Err = joinErrors(std::move(Err), JD->clear());1661    if (P)1662      Err = joinErrors(std::move(Err), P->teardownJITDylib(*JD));1663  }1664 1665  // Set JD to closed state. Clear remaining data structures.1666  runSessionLocked([&] {1667    for (auto &JD : JDsToRemove) {1668      assert(JD->State == JITDylib::Closing && "JD should be closing");1669      JD->State = JITDylib::Closed;1670      assert(JD->Symbols.empty() && "JD.Symbols is not empty after clear");1671      assert(JD->UnmaterializedInfos.empty() &&1672             "JD.UnmaterializedInfos is not empty after clear");1673      assert(JD->MaterializingInfos.empty() &&1674             "JD.MaterializingInfos is not empty after clear");1675      assert(JD->TrackerSymbols.empty() &&1676             "TrackerSymbols is not empty after clear");1677      JD->DefGenerators.clear();1678      JD->LinkOrder.clear();1679    }1680  });1681 1682  return Err;1683}1684 1685Expected<std::vector<JITDylibSP>>1686JITDylib::getDFSLinkOrder(ArrayRef<JITDylibSP> JDs) {1687  if (JDs.empty())1688    return std::vector<JITDylibSP>();1689 1690  auto &ES = JDs.front()->getExecutionSession();1691  return ES.runSessionLocked([&]() -> Expected<std::vector<JITDylibSP>> {1692    DenseSet<JITDylib *> Visited;1693    std::vector<JITDylibSP> Result;1694 1695    for (auto &JD : JDs) {1696 1697      if (JD->State != Open)1698        return make_error<StringError>(1699            "Error building link order: " + JD->getName() + " is defunct",1700            inconvertibleErrorCode());1701      if (Visited.count(JD.get()))1702        continue;1703 1704      SmallVector<JITDylibSP, 64> WorkStack;1705      WorkStack.push_back(JD);1706      Visited.insert(JD.get());1707 1708      while (!WorkStack.empty()) {1709        Result.push_back(std::move(WorkStack.back()));1710        WorkStack.pop_back();1711 1712        for (auto &KV : llvm::reverse(Result.back()->LinkOrder)) {1713          auto &JD = *KV.first;1714          if (!Visited.insert(&JD).second)1715            continue;1716          WorkStack.push_back(&JD);1717        }1718      }1719    }1720    return Result;1721  });1722}1723 1724Expected<std::vector<JITDylibSP>>1725JITDylib::getReverseDFSLinkOrder(ArrayRef<JITDylibSP> JDs) {1726  auto Result = getDFSLinkOrder(JDs);1727  if (Result)1728    std::reverse(Result->begin(), Result->end());1729  return Result;1730}1731 1732Expected<std::vector<JITDylibSP>> JITDylib::getDFSLinkOrder() {1733  return getDFSLinkOrder({this});1734}1735 1736Expected<std::vector<JITDylibSP>> JITDylib::getReverseDFSLinkOrder() {1737  return getReverseDFSLinkOrder({this});1738}1739 1740void ExecutionSession::lookupFlags(1741    LookupKind K, JITDylibSearchOrder SearchOrder, SymbolLookupSet LookupSet,1742    unique_function<void(Expected<SymbolFlagsMap>)> OnComplete) {1743 1744  OL_applyQueryPhase1(std::make_unique<InProgressLookupFlagsState>(1745                          K, std::move(SearchOrder), std::move(LookupSet),1746                          std::move(OnComplete)),1747                      Error::success());1748}1749 1750Expected<SymbolFlagsMap>1751ExecutionSession::lookupFlags(LookupKind K, JITDylibSearchOrder SearchOrder,1752                              SymbolLookupSet LookupSet) {1753 1754  std::promise<MSVCPExpected<SymbolFlagsMap>> ResultP;1755  OL_applyQueryPhase1(std::make_unique<InProgressLookupFlagsState>(1756                          K, std::move(SearchOrder), std::move(LookupSet),1757                          [&ResultP](Expected<SymbolFlagsMap> Result) {1758                            ResultP.set_value(std::move(Result));1759                          }),1760                      Error::success());1761 1762  auto ResultF = ResultP.get_future();1763  return ResultF.get();1764}1765 1766void ExecutionSession::lookup(1767    LookupKind K, const JITDylibSearchOrder &SearchOrder,1768    SymbolLookupSet Symbols, SymbolState RequiredState,1769    SymbolsResolvedCallback NotifyComplete,1770    RegisterDependenciesFunction RegisterDependencies) {1771 1772  LLVM_DEBUG({1773    runSessionLocked([&]() {1774      dbgs() << "Looking up " << Symbols << " in " << SearchOrder1775             << " (required state: " << RequiredState << ")\n";1776    });1777  });1778 1779  // lookup can be re-entered recursively if running on a single thread. Run any1780  // outstanding MUs in case this query depends on them, otherwise this lookup1781  // will starve waiting for a result from an MU that is stuck in the queue.1782  dispatchOutstandingMUs();1783 1784  auto Unresolved = std::move(Symbols);1785  auto Q = std::make_shared<AsynchronousSymbolQuery>(Unresolved, RequiredState,1786                                                     std::move(NotifyComplete));1787 1788  auto IPLS = std::make_unique<InProgressFullLookupState>(1789      K, SearchOrder, std::move(Unresolved), RequiredState, std::move(Q),1790      std::move(RegisterDependencies));1791 1792  OL_applyQueryPhase1(std::move(IPLS), Error::success());1793}1794 1795Expected<SymbolMap>1796ExecutionSession::lookup(const JITDylibSearchOrder &SearchOrder,1797                         SymbolLookupSet Symbols, LookupKind K,1798                         SymbolState RequiredState,1799                         RegisterDependenciesFunction RegisterDependencies) {1800#if LLVM_ENABLE_THREADS1801  // In the threaded case we use promises to return the results.1802  std::promise<MSVCPExpected<SymbolMap>> PromisedResult;1803 1804  auto NotifyComplete = [&](Expected<SymbolMap> R) {1805    PromisedResult.set_value(std::move(R));1806  };1807 1808#else1809  SymbolMap Result;1810  Error ResolutionError = Error::success();1811 1812  auto NotifyComplete = [&](Expected<SymbolMap> R) {1813    ErrorAsOutParameter _(ResolutionError);1814    if (R)1815      Result = std::move(*R);1816    else1817      ResolutionError = R.takeError();1818  };1819#endif1820 1821  // Perform the asynchronous lookup.1822  lookup(K, SearchOrder, std::move(Symbols), RequiredState,1823         std::move(NotifyComplete), RegisterDependencies);1824 1825#if LLVM_ENABLE_THREADS1826  return PromisedResult.get_future().get();1827#else1828  if (ResolutionError)1829    return std::move(ResolutionError);1830 1831  return Result;1832#endif1833}1834 1835Expected<ExecutorSymbolDef>1836ExecutionSession::lookup(const JITDylibSearchOrder &SearchOrder,1837                         SymbolStringPtr Name, SymbolState RequiredState) {1838  SymbolLookupSet Names({Name});1839 1840  if (auto ResultMap = lookup(SearchOrder, std::move(Names), LookupKind::Static,1841                              RequiredState, NoDependenciesToRegister)) {1842    assert(ResultMap->size() == 1 && "Unexpected number of results");1843    assert(ResultMap->count(Name) && "Missing result for symbol");1844    return std::move(ResultMap->begin()->second);1845  } else1846    return ResultMap.takeError();1847}1848 1849Expected<ExecutorSymbolDef>1850ExecutionSession::lookup(ArrayRef<JITDylib *> SearchOrder, SymbolStringPtr Name,1851                         SymbolState RequiredState) {1852  return lookup(makeJITDylibSearchOrder(SearchOrder), Name, RequiredState);1853}1854 1855Expected<ExecutorSymbolDef>1856ExecutionSession::lookup(ArrayRef<JITDylib *> SearchOrder, StringRef Name,1857                         SymbolState RequiredState) {1858  return lookup(SearchOrder, intern(Name), RequiredState);1859}1860 1861Error ExecutionSession::registerJITDispatchHandlers(1862    JITDylib &JD, JITDispatchHandlerAssociationMap WFs) {1863 1864  auto TagSyms = lookup({{&JD, JITDylibLookupFlags::MatchAllSymbols}},1865                        SymbolLookupSet::fromMapKeys(1866                            WFs, SymbolLookupFlags::WeaklyReferencedSymbol));1867  if (!TagSyms)1868    return TagSyms.takeError();1869 1870  // Associate tag addresses with implementations.1871  std::lock_guard<std::mutex> Lock(JITDispatchHandlersMutex);1872 1873  // Check that no tags are being overwritten.1874  for (auto &[TagName, TagSym] : *TagSyms) {1875    auto TagAddr = TagSym.getAddress();1876    if (JITDispatchHandlers.count(TagAddr))1877      return make_error<StringError>("Tag " + formatv("{0:x}", TagAddr) +1878                                         " (for " + *TagName +1879                                         ") already registered",1880                                     inconvertibleErrorCode());1881  }1882 1883  // At this point we're guaranteed to succeed. Install the handlers.1884  for (auto &[TagName, TagSym] : *TagSyms) {1885    auto TagAddr = TagSym.getAddress();1886    auto I = WFs.find(TagName);1887    assert(I != WFs.end() && I->second &&1888           "JITDispatchHandler implementation missing");1889    JITDispatchHandlers[TagAddr] =1890        std::make_shared<JITDispatchHandlerFunction>(std::move(I->second));1891    LLVM_DEBUG({1892      dbgs() << "Associated function tag \"" << *TagName << "\" ("1893             << formatv("{0:x}", TagAddr) << ") with handler\n";1894    });1895  }1896 1897  return Error::success();1898}1899 1900void ExecutionSession::runJITDispatchHandler(SendResultFunction SendResult,1901                                             ExecutorAddr HandlerFnTagAddr,1902                                             ArrayRef<char> ArgBuffer) {1903 1904  std::shared_ptr<JITDispatchHandlerFunction> F;1905  {1906    std::lock_guard<std::mutex> Lock(JITDispatchHandlersMutex);1907    auto I = JITDispatchHandlers.find(HandlerFnTagAddr);1908    if (I != JITDispatchHandlers.end())1909      F = I->second;1910  }1911 1912  if (F)1913    (*F)(std::move(SendResult), ArgBuffer.data(), ArgBuffer.size());1914  else1915    SendResult(shared::WrapperFunctionResult::createOutOfBandError(1916        ("No function registered for tag " +1917         formatv("{0:x16}", HandlerFnTagAddr))1918            .str()));1919}1920 1921void ExecutionSession::dump(raw_ostream &OS) {1922  runSessionLocked([this, &OS]() {1923    for (auto &JD : JDs)1924      JD->dump(OS);1925  });1926}1927 1928#ifdef EXPENSIVE_CHECKS1929bool ExecutionSession::verifySessionState(Twine Phase) {1930  return runSessionLocked([&]() {1931    bool AllOk = true;1932 1933    for (auto &JD : JDs) {1934 1935      auto LogFailure = [&]() -> raw_fd_ostream & {1936        auto &Stream = errs();1937        if (AllOk)1938          Stream << "ERROR: Bad ExecutionSession state detected " << Phase1939                 << "\n";1940        Stream << "  In JITDylib " << JD->getName() << ", ";1941        AllOk = false;1942        return Stream;1943      };1944 1945      if (JD->State != JITDylib::Open) {1946        LogFailure()1947            << "state is not Open, but JD is in ExecutionSession list.";1948      }1949 1950      // Check symbol table.1951      // 1. If the entry state isn't resolved then check that no address has1952      //    been set.1953      // 2. Check that if the hasMaterializerAttached flag is set then there is1954      //    an UnmaterializedInfo entry, and vice-versa.1955      for (auto &[Sym, Entry] : JD->Symbols) {1956        // Check that unresolved symbols have null addresses.1957        if (Entry.getState() < SymbolState::Resolved) {1958          if (Entry.getAddress()) {1959            LogFailure() << "symbol " << Sym << " has state "1960                         << Entry.getState()1961                         << " (not-yet-resolved) but non-null address "1962                         << Entry.getAddress() << ".\n";1963          }1964        }1965 1966        // Check that the hasMaterializerAttached flag is correct.1967        auto UMIItr = JD->UnmaterializedInfos.find(Sym);1968        if (Entry.hasMaterializerAttached()) {1969          if (UMIItr == JD->UnmaterializedInfos.end()) {1970            LogFailure() << "symbol " << Sym1971                         << " entry claims materializer attached, but "1972                            "UnmaterializedInfos has no corresponding entry.\n";1973          }1974        } else if (UMIItr != JD->UnmaterializedInfos.end()) {1975          LogFailure()1976              << "symbol " << Sym1977              << " entry claims no materializer attached, but "1978                 "UnmaterializedInfos has an unexpected entry for it.\n";1979        }1980      }1981 1982      // Check that every UnmaterializedInfo entry has a corresponding entry1983      // in the Symbols table.1984      for (auto &[Sym, UMI] : JD->UnmaterializedInfos) {1985        auto SymItr = JD->Symbols.find(Sym);1986        if (SymItr == JD->Symbols.end()) {1987          LogFailure()1988              << "symbol " << Sym1989              << " has UnmaterializedInfos entry, but no Symbols entry.\n";1990        }1991      }1992 1993      // Check consistency of the MaterializingInfos table.1994      for (auto &[Sym, MII] : JD->MaterializingInfos) {1995 1996        auto SymItr = JD->Symbols.find(Sym);1997        if (SymItr == JD->Symbols.end()) {1998          // If there's no Symbols entry for this MaterializingInfos entry then1999          // report that.2000          LogFailure()2001              << "symbol " << Sym2002              << " has MaterializingInfos entry, but no Symbols entry.\n";2003        } else {2004          // Otherwise check consistency between Symbols and MaterializingInfos.2005 2006          // Ready symbols should not have MaterializingInfos.2007          if (SymItr->second.getState() == SymbolState::Ready) {2008            LogFailure()2009                << "symbol " << Sym2010                << " is in Ready state, should not have MaterializingInfo.\n";2011          }2012 2013          // Pending queries should be for subsequent states.2014          auto CurState = static_cast<SymbolState>(2015              static_cast<std::underlying_type_t<SymbolState>>(2016                  SymItr->second.getState()) + 1);2017          for (auto &Q : MII.PendingQueries) {2018            if (Q->getRequiredState() != CurState) {2019              if (Q->getRequiredState() > CurState)2020                CurState = Q->getRequiredState();2021              else2022                LogFailure() << "symbol " << Sym2023                             << " has stale or misordered queries.\n";2024            }2025          }2026        }2027      }2028    }2029 2030    return AllOk;2031  });2032}2033#endif // EXPENSIVE_CHECKS2034 2035void ExecutionSession::dispatchOutstandingMUs() {2036  LLVM_DEBUG(dbgs() << "Dispatching MaterializationUnits...\n");2037  while (true) {2038    std::optional<std::pair<std::unique_ptr<MaterializationUnit>,2039                            std::unique_ptr<MaterializationResponsibility>>>2040        JMU;2041 2042    {2043      std::lock_guard<std::recursive_mutex> Lock(OutstandingMUsMutex);2044      if (!OutstandingMUs.empty()) {2045        JMU.emplace(std::move(OutstandingMUs.back()));2046        OutstandingMUs.pop_back();2047      }2048    }2049 2050    if (!JMU)2051      break;2052 2053    assert(JMU->first && "No MU?");2054    LLVM_DEBUG(dbgs() << "  Dispatching \"" << JMU->first->getName() << "\"\n");2055    dispatchTask(std::make_unique<MaterializationTask>(std::move(JMU->first),2056                                                       std::move(JMU->second)));2057  }2058  LLVM_DEBUG(dbgs() << "Done dispatching MaterializationUnits.\n");2059}2060 2061Error ExecutionSession::removeResourceTracker(ResourceTracker &RT) {2062  LLVM_DEBUG({2063    dbgs() << "In " << RT.getJITDylib().getName() << " removing tracker "2064           << formatv("{0:x}", RT.getKeyUnsafe()) << "\n";2065  });2066  std::vector<ResourceManager *> CurrentResourceManagers;2067 2068  JITDylib::RemoveTrackerResult R;2069 2070  runSessionLocked([&] {2071    CurrentResourceManagers = ResourceManagers;2072    RT.makeDefunct();2073    R = RT.getJITDylib().IL_removeTracker(RT);2074  });2075 2076  // Release any defunct MaterializationUnits.2077  R.DefunctMUs.clear();2078 2079  Error Err = Error::success();2080 2081  auto &JD = RT.getJITDylib();2082  for (auto *L : reverse(CurrentResourceManagers))2083    Err = joinErrors(std::move(Err),2084                     L->handleRemoveResources(JD, RT.getKeyUnsafe()));2085 2086  for (auto &Q : R.QueriesToFail)2087    Q->handleFailed(make_error<FailedToMaterialize>(getSymbolStringPool(),2088                                                    R.FailedSymbols));2089 2090  return Err;2091}2092 2093void ExecutionSession::transferResourceTracker(ResourceTracker &DstRT,2094                                               ResourceTracker &SrcRT) {2095  LLVM_DEBUG({2096    dbgs() << "In " << SrcRT.getJITDylib().getName()2097           << " transfering resources from tracker "2098           << formatv("{0:x}", SrcRT.getKeyUnsafe()) << " to tracker "2099           << formatv("{0:x}", DstRT.getKeyUnsafe()) << "\n";2100  });2101 2102  // No-op transfers are allowed and do not invalidate the source.2103  if (&DstRT == &SrcRT)2104    return;2105 2106  assert(&DstRT.getJITDylib() == &SrcRT.getJITDylib() &&2107         "Can't transfer resources between JITDylibs");2108  runSessionLocked([&]() {2109    SrcRT.makeDefunct();2110    auto &JD = DstRT.getJITDylib();2111    JD.transferTracker(DstRT, SrcRT);2112    for (auto *L : reverse(ResourceManagers))2113      L->handleTransferResources(JD, DstRT.getKeyUnsafe(),2114                                 SrcRT.getKeyUnsafe());2115  });2116}2117 2118void ExecutionSession::destroyResourceTracker(ResourceTracker &RT) {2119  runSessionLocked([&]() {2120    LLVM_DEBUG({2121      dbgs() << "In " << RT.getJITDylib().getName() << " destroying tracker "2122             << formatv("{0:x}", RT.getKeyUnsafe()) << "\n";2123    });2124    if (!RT.isDefunct())2125      transferResourceTracker(*RT.getJITDylib().getDefaultResourceTracker(),2126                              RT);2127  });2128}2129 2130Error ExecutionSession::IL_updateCandidatesFor(2131    JITDylib &JD, JITDylibLookupFlags JDLookupFlags,2132    SymbolLookupSet &Candidates, SymbolLookupSet *NonCandidates) {2133  return Candidates.forEachWithRemoval(2134      [&](const SymbolStringPtr &Name,2135          SymbolLookupFlags SymLookupFlags) -> Expected<bool> {2136        /// Search for the symbol. If not found then continue without2137        /// removal.2138        auto SymI = JD.Symbols.find(Name);2139        if (SymI == JD.Symbols.end())2140          return false;2141 2142        // If this is a non-exported symbol and we're matching exported2143        // symbols only then remove this symbol from the candidates list.2144        //2145        // If we're tracking non-candidates then add this to the non-candidate2146        // list.2147        if (!SymI->second.getFlags().isExported() &&2148            JDLookupFlags == JITDylibLookupFlags::MatchExportedSymbolsOnly) {2149          if (NonCandidates)2150            NonCandidates->add(Name, SymLookupFlags);2151          return true;2152        }2153 2154        // If we match against a materialization-side-effects only symbol2155        // then make sure it is weakly-referenced. Otherwise bail out with2156        // an error.2157        // FIXME: Use a "materialization-side-effects-only symbols must be2158        // weakly referenced" specific error here to reduce confusion.2159        if (SymI->second.getFlags().hasMaterializationSideEffectsOnly() &&2160            SymLookupFlags != SymbolLookupFlags::WeaklyReferencedSymbol)2161          return make_error<SymbolsNotFound>(getSymbolStringPool(),2162                                             SymbolNameVector({Name}));2163 2164        // If we matched against this symbol but it is in the error state2165        // then bail out and treat it as a failure to materialize.2166        if (SymI->second.getFlags().hasError()) {2167          auto FailedSymbolsMap = std::make_shared<SymbolDependenceMap>();2168          (*FailedSymbolsMap)[&JD] = {Name};2169          return make_error<FailedToMaterialize>(getSymbolStringPool(),2170                                                 std::move(FailedSymbolsMap));2171        }2172 2173        // Otherwise this is a match. Remove it from the candidate set.2174        return true;2175      });2176}2177 2178void ExecutionSession::OL_resumeLookupAfterGeneration(2179    InProgressLookupState &IPLS) {2180 2181  assert(IPLS.GenState != InProgressLookupState::NotInGenerator &&2182         "Should not be called for not-in-generator lookups");2183  IPLS.GenState = InProgressLookupState::NotInGenerator;2184 2185  LookupState LS;2186 2187  if (auto DG = IPLS.CurDefGeneratorStack.back().lock()) {2188    IPLS.CurDefGeneratorStack.pop_back();2189    std::lock_guard<std::mutex> Lock(DG->M);2190 2191    // If there are no pending lookups then mark the generator as free and2192    // return.2193    if (DG->PendingLookups.empty()) {2194      DG->InUse = false;2195      return;2196    }2197 2198    // Otherwise resume the next lookup.2199    LS = std::move(DG->PendingLookups.front());2200    DG->PendingLookups.pop_front();2201  }2202 2203  if (LS.IPLS) {2204    LS.IPLS->GenState = InProgressLookupState::ResumedForGenerator;2205    dispatchTask(std::make_unique<LookupTask>(std::move(LS)));2206  }2207}2208 2209void ExecutionSession::OL_applyQueryPhase1(2210    std::unique_ptr<InProgressLookupState> IPLS, Error Err) {2211 2212  LLVM_DEBUG({2213    dbgs() << "Entering OL_applyQueryPhase1:\n"2214           << "  Lookup kind: " << IPLS->K << "\n"2215           << "  Search order: " << IPLS->SearchOrder2216           << ", Current index = " << IPLS->CurSearchOrderIndex2217           << (IPLS->NewJITDylib ? " (entering new JITDylib)" : "") << "\n"2218           << "  Lookup set: " << IPLS->LookupSet << "\n"2219           << "  Definition generator candidates: "2220           << IPLS->DefGeneratorCandidates << "\n"2221           << "  Definition generator non-candidates: "2222           << IPLS->DefGeneratorNonCandidates << "\n";2223  });2224 2225  if (IPLS->GenState == InProgressLookupState::InGenerator)2226    OL_resumeLookupAfterGeneration(*IPLS);2227 2228  assert(IPLS->GenState != InProgressLookupState::InGenerator &&2229         "Lookup should not be in InGenerator state here");2230 2231  // FIXME: We should attach the query as we go: This provides a result in a2232  // single pass in the common case where all symbols have already reached the2233  // required state. The query could be detached again in the 'fail' method on2234  // IPLS. Phase 2 would be reduced to collecting and dispatching the MUs.2235 2236  while (IPLS->CurSearchOrderIndex != IPLS->SearchOrder.size()) {2237 2238    // If we've been handed an error or received one back from a generator then2239    // fail the query. We don't need to unlink: At this stage the query hasn't2240    // actually been lodged.2241    if (Err)2242      return IPLS->fail(std::move(Err));2243 2244    // Get the next JITDylib and lookup flags.2245    auto &KV = IPLS->SearchOrder[IPLS->CurSearchOrderIndex];2246    auto &JD = *KV.first;2247    auto JDLookupFlags = KV.second;2248 2249    LLVM_DEBUG({2250      dbgs() << "Visiting \"" << JD.getName() << "\" (" << JDLookupFlags2251             << ") with lookup set " << IPLS->LookupSet << ":\n";2252    });2253 2254    // If we've just reached a new JITDylib then perform some setup.2255    if (IPLS->NewJITDylib) {2256      // Add any non-candidates from the last JITDylib (if any) back on to the2257      // list of definition candidates for this JITDylib, reset definition2258      // non-candidates to the empty set.2259      SymbolLookupSet Tmp;2260      std::swap(IPLS->DefGeneratorNonCandidates, Tmp);2261      IPLS->DefGeneratorCandidates.append(std::move(Tmp));2262 2263      LLVM_DEBUG({2264        dbgs() << "  First time visiting " << JD.getName()2265               << ", resetting candidate sets and building generator stack\n";2266      });2267 2268      // Build the definition generator stack for this JITDylib.2269      runSessionLocked([&] {2270        IPLS->CurDefGeneratorStack.reserve(JD.DefGenerators.size());2271        llvm::append_range(IPLS->CurDefGeneratorStack,2272                           reverse(JD.DefGenerators));2273      });2274 2275      // Flag that we've done our initialization.2276      IPLS->NewJITDylib = false;2277    }2278 2279    // Remove any generation candidates that are already defined (and match) in2280    // this JITDylib.2281    runSessionLocked([&] {2282      // Update the list of candidates (and non-candidates) for definition2283      // generation.2284      LLVM_DEBUG(dbgs() << "  Updating candidate set...\n");2285      Err = IL_updateCandidatesFor(2286          JD, JDLookupFlags, IPLS->DefGeneratorCandidates,2287          JD.DefGenerators.empty() ? nullptr2288                                   : &IPLS->DefGeneratorNonCandidates);2289      LLVM_DEBUG({2290        dbgs() << "    Remaining candidates = " << IPLS->DefGeneratorCandidates2291               << "\n";2292      });2293 2294      // If this lookup was resumed after auto-suspension but all candidates2295      // have already been generated (by some previous call to the generator)2296      // treat the lookup as if it had completed generation.2297      if (IPLS->GenState == InProgressLookupState::ResumedForGenerator &&2298          IPLS->DefGeneratorCandidates.empty())2299        OL_resumeLookupAfterGeneration(*IPLS);2300    });2301 2302    // If we encountered an error while filtering generation candidates then2303    // bail out.2304    if (Err)2305      return IPLS->fail(std::move(Err));2306 2307    /// Apply any definition generators on the stack.2308    LLVM_DEBUG({2309      if (IPLS->CurDefGeneratorStack.empty())2310        LLVM_DEBUG(dbgs() << "  No generators to run for this JITDylib.\n");2311      else if (IPLS->DefGeneratorCandidates.empty())2312        LLVM_DEBUG(dbgs() << "  No candidates to generate.\n");2313      else2314        dbgs() << "  Running " << IPLS->CurDefGeneratorStack.size()2315               << " remaining generators for "2316               << IPLS->DefGeneratorCandidates.size() << " candidates\n";2317    });2318    while (!IPLS->CurDefGeneratorStack.empty() &&2319           !IPLS->DefGeneratorCandidates.empty()) {2320      auto DG = IPLS->CurDefGeneratorStack.back().lock();2321 2322      if (!DG)2323        return IPLS->fail(make_error<StringError>(2324            "DefinitionGenerator removed while lookup in progress",2325            inconvertibleErrorCode()));2326 2327      // At this point the lookup is in either the NotInGenerator state, or in2328      // the ResumedForGenerator state.2329      // If this lookup is in the NotInGenerator state then check whether the2330      // generator is in use. If the generator is not in use then move the2331      // lookup to the InGenerator state and continue. If the generator is2332      // already in use then just add this lookup to the pending lookups list2333      // and bail out.2334      // If this lookup is in the ResumedForGenerator state then just move it2335      // to InGenerator and continue.2336      if (IPLS->GenState == InProgressLookupState::NotInGenerator) {2337        std::lock_guard<std::mutex> Lock(DG->M);2338        if (DG->InUse) {2339          DG->PendingLookups.push_back(std::move(IPLS));2340          return;2341        }2342        DG->InUse = true;2343      }2344 2345      IPLS->GenState = InProgressLookupState::InGenerator;2346 2347      auto K = IPLS->K;2348      auto &LookupSet = IPLS->DefGeneratorCandidates;2349 2350      // Run the generator. If the generator takes ownership of QA then this2351      // will break the loop.2352      {2353        LLVM_DEBUG(dbgs() << "  Attempting to generate " << LookupSet << "\n");2354        LookupState LS(std::move(IPLS));2355        Err = DG->tryToGenerate(LS, K, JD, JDLookupFlags, LookupSet);2356        IPLS = std::move(LS.IPLS);2357      }2358 2359      // If the lookup returned then pop the generator stack and unblock the2360      // next lookup on this generator (if any).2361      if (IPLS)2362        OL_resumeLookupAfterGeneration(*IPLS);2363 2364      // If there was an error then fail the query.2365      if (Err) {2366        LLVM_DEBUG({2367          dbgs() << "  Error attempting to generate " << LookupSet << "\n";2368        });2369        assert(IPLS && "LS cannot be retained if error is returned");2370        return IPLS->fail(std::move(Err));2371      }2372 2373      // Otherwise if QA was captured then break the loop.2374      if (!IPLS) {2375        LLVM_DEBUG(2376            { dbgs() << "  LookupState captured. Exiting phase1 for now.\n"; });2377        return;2378      }2379 2380      // Otherwise if we're continuing around the loop then update candidates2381      // for the next round.2382      runSessionLocked([&] {2383        LLVM_DEBUG(dbgs() << "  Updating candidate set post-generation\n");2384        Err = IL_updateCandidatesFor(2385            JD, JDLookupFlags, IPLS->DefGeneratorCandidates,2386            JD.DefGenerators.empty() ? nullptr2387                                     : &IPLS->DefGeneratorNonCandidates);2388      });2389 2390      // If updating candidates failed then fail the query.2391      if (Err) {2392        LLVM_DEBUG(dbgs() << "  Error encountered while updating candidates\n");2393        return IPLS->fail(std::move(Err));2394      }2395    }2396 2397    if (IPLS->DefGeneratorCandidates.empty() &&2398        IPLS->DefGeneratorNonCandidates.empty()) {2399      // Early out if there are no remaining symbols.2400      LLVM_DEBUG(dbgs() << "All symbols matched.\n");2401      IPLS->CurSearchOrderIndex = IPLS->SearchOrder.size();2402      break;2403    } else {2404      // If we get here then we've moved on to the next JITDylib with candidates2405      // remaining.2406      LLVM_DEBUG(dbgs() << "Phase 1 moving to next JITDylib.\n");2407      ++IPLS->CurSearchOrderIndex;2408      IPLS->NewJITDylib = true;2409    }2410  }2411 2412  // Remove any weakly referenced candidates that could not be found/generated.2413  IPLS->DefGeneratorCandidates.remove_if(2414      [](const SymbolStringPtr &Name, SymbolLookupFlags SymLookupFlags) {2415        return SymLookupFlags == SymbolLookupFlags::WeaklyReferencedSymbol;2416      });2417 2418  // If we get here then we've finished searching all JITDylibs.2419  // If we matched all symbols then move to phase 2, otherwise fail the query2420  // with a SymbolsNotFound error.2421  if (IPLS->DefGeneratorCandidates.empty()) {2422    LLVM_DEBUG(dbgs() << "Phase 1 succeeded.\n");2423    IPLS->complete(std::move(IPLS));2424  } else {2425    LLVM_DEBUG(dbgs() << "Phase 1 failed with unresolved symbols.\n");2426    IPLS->fail(make_error<SymbolsNotFound>(2427        getSymbolStringPool(), IPLS->DefGeneratorCandidates.getSymbolNames()));2428  }2429}2430 2431void ExecutionSession::OL_completeLookup(2432    std::unique_ptr<InProgressLookupState> IPLS,2433    std::shared_ptr<AsynchronousSymbolQuery> Q,2434    RegisterDependenciesFunction RegisterDependencies) {2435 2436  LLVM_DEBUG({2437    dbgs() << "Entering OL_completeLookup:\n"2438           << "  Lookup kind: " << IPLS->K << "\n"2439           << "  Search order: " << IPLS->SearchOrder2440           << ", Current index = " << IPLS->CurSearchOrderIndex2441           << (IPLS->NewJITDylib ? " (entering new JITDylib)" : "") << "\n"2442           << "  Lookup set: " << IPLS->LookupSet << "\n"2443           << "  Definition generator candidates: "2444           << IPLS->DefGeneratorCandidates << "\n"2445           << "  Definition generator non-candidates: "2446           << IPLS->DefGeneratorNonCandidates << "\n";2447  });2448 2449  bool QueryComplete = false;2450  DenseMap<JITDylib *, JITDylib::UnmaterializedInfosList> CollectedUMIs;2451 2452  auto LodgingErr = runSessionLocked([&]() -> Error {2453    for (auto &KV : IPLS->SearchOrder) {2454      auto &JD = *KV.first;2455      auto JDLookupFlags = KV.second;2456      LLVM_DEBUG({2457        dbgs() << "Visiting \"" << JD.getName() << "\" (" << JDLookupFlags2458               << ") with lookup set " << IPLS->LookupSet << ":\n";2459      });2460 2461      auto Err = IPLS->LookupSet.forEachWithRemoval(2462          [&](const SymbolStringPtr &Name,2463              SymbolLookupFlags SymLookupFlags) -> Expected<bool> {2464            LLVM_DEBUG({2465              dbgs() << "  Attempting to match \"" << Name << "\" ("2466                     << SymLookupFlags << ")... ";2467            });2468 2469            /// Search for the symbol. If not found then continue without2470            /// removal.2471            auto SymI = JD.Symbols.find(Name);2472            if (SymI == JD.Symbols.end()) {2473              LLVM_DEBUG(dbgs() << "skipping: not present\n");2474              return false;2475            }2476 2477            // If this is a non-exported symbol and we're matching exported2478            // symbols only then skip this symbol without removal.2479            if (!SymI->second.getFlags().isExported() &&2480                JDLookupFlags ==2481                    JITDylibLookupFlags::MatchExportedSymbolsOnly) {2482              LLVM_DEBUG(dbgs() << "skipping: not exported\n");2483              return false;2484            }2485 2486            // If we match against a materialization-side-effects only symbol2487            // then make sure it is weakly-referenced. Otherwise bail out with2488            // an error.2489            // FIXME: Use a "materialization-side-effects-only symbols must be2490            // weakly referenced" specific error here to reduce confusion.2491            if (SymI->second.getFlags().hasMaterializationSideEffectsOnly() &&2492                SymLookupFlags != SymbolLookupFlags::WeaklyReferencedSymbol) {2493              LLVM_DEBUG({2494                dbgs() << "error: "2495                          "required, but symbol is has-side-effects-only\n";2496              });2497              return make_error<SymbolsNotFound>(getSymbolStringPool(),2498                                                 SymbolNameVector({Name}));2499            }2500 2501            // If we matched against this symbol but it is in the error state2502            // then bail out and treat it as a failure to materialize.2503            if (SymI->second.getFlags().hasError()) {2504              LLVM_DEBUG(dbgs() << "error: symbol is in error state\n");2505              auto FailedSymbolsMap = std::make_shared<SymbolDependenceMap>();2506              (*FailedSymbolsMap)[&JD] = {Name};2507              return make_error<FailedToMaterialize>(2508                  getSymbolStringPool(), std::move(FailedSymbolsMap));2509            }2510 2511            // Otherwise this is a match.2512 2513            // If this symbol is already in the required state then notify the2514            // query, remove the symbol and continue.2515            if (SymI->second.getState() >= Q->getRequiredState()) {2516              LLVM_DEBUG(dbgs()2517                         << "matched, symbol already in required state\n");2518              Q->notifySymbolMetRequiredState(Name, SymI->second.getSymbol());2519 2520              // If this symbol is in anything other than the Ready state then2521              // we need to track the dependence.2522              if (SymI->second.getState() != SymbolState::Ready)2523                Q->addQueryDependence(JD, Name);2524 2525              return true;2526            }2527 2528            // Otherwise this symbol does not yet meet the required state. Check2529            // whether it has a materializer attached, and if so prepare to run2530            // it.2531            if (SymI->second.hasMaterializerAttached()) {2532              assert(SymI->second.getAddress() == ExecutorAddr() &&2533                     "Symbol not resolved but already has address?");2534              auto UMII = JD.UnmaterializedInfos.find(Name);2535              assert(UMII != JD.UnmaterializedInfos.end() &&2536                     "Lazy symbol should have UnmaterializedInfo");2537 2538              auto UMI = UMII->second;2539              assert(UMI->MU && "Materializer should not be null");2540              assert(UMI->RT && "Tracker should not be null");2541              LLVM_DEBUG({2542                dbgs() << "matched, preparing to dispatch MU@" << UMI->MU.get()2543                       << " (" << UMI->MU->getName() << ")\n";2544              });2545 2546              // Move all symbols associated with this MaterializationUnit into2547              // materializing state.2548              for (auto &KV : UMI->MU->getSymbols()) {2549                auto SymK = JD.Symbols.find(KV.first);2550                assert(SymK != JD.Symbols.end() &&2551                       "No entry for symbol covered by MaterializationUnit");2552                SymK->second.setMaterializerAttached(false);2553                SymK->second.setState(SymbolState::Materializing);2554                JD.UnmaterializedInfos.erase(KV.first);2555              }2556 2557              // Add MU to the list of MaterializationUnits to be materialized.2558              CollectedUMIs[&JD].push_back(std::move(UMI));2559            } else2560              LLVM_DEBUG(dbgs() << "matched, registering query");2561 2562            // Add the query to the PendingQueries list and continue, deleting2563            // the element from the lookup set.2564            assert(SymI->second.getState() != SymbolState::NeverSearched &&2565                   SymI->second.getState() != SymbolState::Ready &&2566                   "By this line the symbol should be materializing");2567            auto &MI = JD.MaterializingInfos[Name];2568            MI.addQuery(Q);2569            Q->addQueryDependence(JD, Name);2570 2571            return true;2572          });2573 2574      JD.shrinkMaterializationInfoMemory();2575 2576      // Handle failure.2577      if (Err) {2578 2579        LLVM_DEBUG({2580          dbgs() << "Lookup failed. Detaching query and replacing MUs.\n";2581        });2582 2583        // Detach the query.2584        Q->detach();2585 2586        // Replace the MUs.2587        for (auto &KV : CollectedUMIs) {2588          auto &JD = *KV.first;2589          for (auto &UMI : KV.second)2590            for (auto &KV2 : UMI->MU->getSymbols()) {2591              assert(!JD.UnmaterializedInfos.count(KV2.first) &&2592                     "Unexpected materializer in map");2593              auto SymI = JD.Symbols.find(KV2.first);2594              assert(SymI != JD.Symbols.end() && "Missing symbol entry");2595              assert(SymI->second.getState() == SymbolState::Materializing &&2596                     "Can not replace symbol that is not materializing");2597              assert(!SymI->second.hasMaterializerAttached() &&2598                     "MaterializerAttached flag should not be set");2599              SymI->second.setMaterializerAttached(true);2600              JD.UnmaterializedInfos[KV2.first] = UMI;2601            }2602        }2603 2604        return Err;2605      }2606    }2607 2608    LLVM_DEBUG(dbgs() << "Stripping unmatched weakly-referenced symbols\n");2609    IPLS->LookupSet.forEachWithRemoval(2610        [&](const SymbolStringPtr &Name, SymbolLookupFlags SymLookupFlags) {2611          if (SymLookupFlags == SymbolLookupFlags::WeaklyReferencedSymbol) {2612            Q->dropSymbol(Name);2613            return true;2614          } else2615            return false;2616        });2617 2618    if (!IPLS->LookupSet.empty()) {2619      LLVM_DEBUG(dbgs() << "Failing due to unresolved symbols\n");2620      return make_error<SymbolsNotFound>(getSymbolStringPool(),2621                                         IPLS->LookupSet.getSymbolNames());2622    }2623 2624    // Record whether the query completed.2625    QueryComplete = Q->isComplete();2626 2627    LLVM_DEBUG({2628      dbgs() << "Query successfully "2629             << (QueryComplete ? "completed" : "lodged") << "\n";2630    });2631 2632    // Move the collected MUs to the OutstandingMUs list.2633    if (!CollectedUMIs.empty()) {2634      std::lock_guard<std::recursive_mutex> Lock(OutstandingMUsMutex);2635 2636      LLVM_DEBUG(dbgs() << "Adding MUs to dispatch:\n");2637      for (auto &KV : CollectedUMIs) {2638        LLVM_DEBUG({2639          auto &JD = *KV.first;2640          dbgs() << "  For " << JD.getName() << ": Adding " << KV.second.size()2641                 << " MUs.\n";2642        });2643        for (auto &UMI : KV.second) {2644          auto MR = createMaterializationResponsibility(2645              *UMI->RT, std::move(UMI->MU->SymbolFlags),2646              std::move(UMI->MU->InitSymbol));2647          OutstandingMUs.push_back(2648              std::make_pair(std::move(UMI->MU), std::move(MR)));2649        }2650      }2651    } else2652      LLVM_DEBUG(dbgs() << "No MUs to dispatch.\n");2653 2654    if (RegisterDependencies && !Q->QueryRegistrations.empty()) {2655      LLVM_DEBUG(dbgs() << "Registering dependencies\n");2656      RegisterDependencies(Q->QueryRegistrations);2657    } else2658      LLVM_DEBUG(dbgs() << "No dependencies to register\n");2659 2660    return Error::success();2661  });2662 2663  if (LodgingErr) {2664    LLVM_DEBUG(dbgs() << "Failing query\n");2665    Q->detach();2666    Q->handleFailed(std::move(LodgingErr));2667    return;2668  }2669 2670  if (QueryComplete) {2671    LLVM_DEBUG(dbgs() << "Completing query\n");2672    Q->handleComplete(*this);2673  }2674 2675  dispatchOutstandingMUs();2676}2677 2678void ExecutionSession::OL_completeLookupFlags(2679    std::unique_ptr<InProgressLookupState> IPLS,2680    unique_function<void(Expected<SymbolFlagsMap>)> OnComplete) {2681 2682  auto Result = runSessionLocked([&]() -> Expected<SymbolFlagsMap> {2683    LLVM_DEBUG({2684      dbgs() << "Entering OL_completeLookupFlags:\n"2685             << "  Lookup kind: " << IPLS->K << "\n"2686             << "  Search order: " << IPLS->SearchOrder2687             << ", Current index = " << IPLS->CurSearchOrderIndex2688             << (IPLS->NewJITDylib ? " (entering new JITDylib)" : "") << "\n"2689             << "  Lookup set: " << IPLS->LookupSet << "\n"2690             << "  Definition generator candidates: "2691             << IPLS->DefGeneratorCandidates << "\n"2692             << "  Definition generator non-candidates: "2693             << IPLS->DefGeneratorNonCandidates << "\n";2694    });2695 2696    SymbolFlagsMap Result;2697 2698    // Attempt to find flags for each symbol.2699    for (auto &KV : IPLS->SearchOrder) {2700      auto &JD = *KV.first;2701      auto JDLookupFlags = KV.second;2702      LLVM_DEBUG({2703        dbgs() << "Visiting \"" << JD.getName() << "\" (" << JDLookupFlags2704               << ") with lookup set " << IPLS->LookupSet << ":\n";2705      });2706 2707      IPLS->LookupSet.forEachWithRemoval([&](const SymbolStringPtr &Name,2708                                             SymbolLookupFlags SymLookupFlags) {2709        LLVM_DEBUG({2710          dbgs() << "  Attempting to match \"" << Name << "\" ("2711                 << SymLookupFlags << ")... ";2712        });2713 2714        // Search for the symbol. If not found then continue without removing2715        // from the lookup set.2716        auto SymI = JD.Symbols.find(Name);2717        if (SymI == JD.Symbols.end()) {2718          LLVM_DEBUG(dbgs() << "skipping: not present\n");2719          return false;2720        }2721 2722        // If this is a non-exported symbol then it doesn't match. Skip it.2723        if (!SymI->second.getFlags().isExported() &&2724            JDLookupFlags == JITDylibLookupFlags::MatchExportedSymbolsOnly) {2725          LLVM_DEBUG(dbgs() << "skipping: not exported\n");2726          return false;2727        }2728 2729        LLVM_DEBUG({2730          dbgs() << "matched, \"" << Name << "\" -> " << SymI->second.getFlags()2731                 << "\n";2732        });2733        Result[Name] = SymI->second.getFlags();2734        return true;2735      });2736    }2737 2738    // Remove any weakly referenced symbols that haven't been resolved.2739    IPLS->LookupSet.remove_if(2740        [](const SymbolStringPtr &Name, SymbolLookupFlags SymLookupFlags) {2741          return SymLookupFlags == SymbolLookupFlags::WeaklyReferencedSymbol;2742        });2743 2744    if (!IPLS->LookupSet.empty()) {2745      LLVM_DEBUG(dbgs() << "Failing due to unresolved symbols\n");2746      return make_error<SymbolsNotFound>(getSymbolStringPool(),2747                                         IPLS->LookupSet.getSymbolNames());2748    }2749 2750    LLVM_DEBUG(dbgs() << "Succeded, result = " << Result << "\n");2751    return Result;2752  });2753 2754  // Run the callback on the result.2755  LLVM_DEBUG(dbgs() << "Sending result to handler.\n");2756  OnComplete(std::move(Result));2757}2758 2759void ExecutionSession::OL_destroyMaterializationResponsibility(2760    MaterializationResponsibility &MR) {2761 2762  assert(MR.SymbolFlags.empty() &&2763         "All symbols should have been explicitly materialized or failed");2764  MR.JD.unlinkMaterializationResponsibility(MR);2765}2766 2767SymbolNameSet ExecutionSession::OL_getRequestedSymbols(2768    const MaterializationResponsibility &MR) {2769  return MR.JD.getRequestedSymbols(MR.SymbolFlags);2770}2771 2772Error ExecutionSession::OL_notifyResolved(MaterializationResponsibility &MR,2773                                          const SymbolMap &Symbols) {2774  LLVM_DEBUG({2775    dbgs() << "In " << MR.JD.getName() << " resolving " << Symbols << "\n";2776  });2777#ifndef NDEBUG2778  for (auto &KV : Symbols) {2779    auto I = MR.SymbolFlags.find(KV.first);2780    assert(I != MR.SymbolFlags.end() &&2781           "Resolving symbol outside this responsibility set");2782    assert(!I->second.hasMaterializationSideEffectsOnly() &&2783           "Can't resolve materialization-side-effects-only symbol");2784    if (I->second & JITSymbolFlags::Common) {2785      auto WeakOrCommon = JITSymbolFlags::Weak | JITSymbolFlags::Common;2786      assert((KV.second.getFlags() & WeakOrCommon) &&2787             "Common symbols must be resolved as common or weak");2788      assert((KV.second.getFlags() & ~WeakOrCommon) ==2789                 (I->second & ~JITSymbolFlags::Common) &&2790             "Resolving symbol with incorrect flags");2791    } else2792      assert(KV.second.getFlags() == I->second &&2793             "Resolving symbol with incorrect flags");2794  }2795#endif2796 2797  return MR.JD.resolve(MR, Symbols);2798}2799 2800WaitingOnGraph::ExternalState2801ExecutionSession::IL_getSymbolState(JITDylib *JD,2802                                    NonOwningSymbolStringPtr Name) {2803  if (JD->State != JITDylib::Open)2804    return WaitingOnGraph::ExternalState::Failed;2805 2806  auto I = JD->Symbols.find_as(Name);2807 2808  // FIXME: Can we eliminate this possibility if we support query binding?2809  if (I == JD->Symbols.end())2810    return WaitingOnGraph::ExternalState::Failed;2811 2812  if (I->second.getFlags().hasError())2813    return WaitingOnGraph::ExternalState::Failed;2814 2815  if (I->second.getState() == SymbolState::Ready)2816    return WaitingOnGraph::ExternalState::Ready;2817 2818  return WaitingOnGraph::ExternalState::None;2819}2820 2821template <typename UpdateSymbolFn, typename UpdateQueryFn>2822void ExecutionSession::IL_collectQueries(2823    JITDylib::AsynchronousSymbolQuerySet &Qs,2824    WaitingOnGraph::ContainerElementsMap &QualifiedSymbols,2825    UpdateSymbolFn &&UpdateSymbol, UpdateQueryFn &&UpdateQuery) {2826 2827  for (auto &[JD, Symbols] : QualifiedSymbols) {2828    // IL_emit and JITDylib removal are synchronized by the session lock.2829    // Since JITDylib removal removes any contained nodes from the2830    // WaitingOnGraph, we should be able to assert that all nodes in the2831    // WaitingOnGraph have not been removed.2832    assert(JD->State == JITDylib::Open &&2833           "WaitingOnGraph includes definition in defunct JITDylib");2834    for (auto &Symbol : Symbols) {2835      // Update symbol table.2836      auto I = JD->Symbols.find_as(Symbol);2837      assert(I != JD->Symbols.end() &&2838             "Failed Symbol missing from JD symbol table");2839      auto &Entry = I->second;2840      UpdateSymbol(Entry);2841 2842      // Collect queries.2843      auto J = JD->MaterializingInfos.find_as(Symbol);2844      if (J != JD->MaterializingInfos.end()) {2845        for (auto &Q : J->second.takeAllPendingQueries()) {2846          UpdateQuery(*Q, *JD, Symbol, Entry);2847          Qs.insert(std::move(Q));2848        }2849        JD->MaterializingInfos.erase(J);2850      }2851    }2852  }2853}2854 2855Expected<ExecutionSession::EmitQueries>2856ExecutionSession::IL_emit(MaterializationResponsibility &MR,2857                          WaitingOnGraph::SimplifyResult SR) {2858 2859  if (MR.RT->isDefunct())2860    return make_error<ResourceTrackerDefunct>(MR.RT);2861 2862  auto &TargetJD = MR.getTargetJITDylib();2863  if (TargetJD.State != JITDylib::Open)2864    return make_error<StringError>("JITDylib " + TargetJD.getName() +2865                                       " is defunct",2866                                   inconvertibleErrorCode());2867 2868#ifdef EXPENSIVE_CHECKS2869  verifySessionState("entering ExecutionSession::IL_emit");2870#endif2871 2872  auto ER = G.emit(std::move(SR),2873                   [this](JITDylib *JD, NonOwningSymbolStringPtr Name) {2874                     return IL_getSymbolState(JD, Name);2875                   });2876 2877  EmitQueries EQ;2878 2879  // Handle failed queries.2880  for (auto &SN : ER.Failed)2881    IL_collectQueries(2882        EQ.Failed, SN->defs(),2883        [](JITDylib::SymbolTableEntry &E) {2884          E.setFlags(E.getFlags() = JITSymbolFlags::HasError);2885        },2886        [&](AsynchronousSymbolQuery &Q, JITDylib &JD,2887            NonOwningSymbolStringPtr Name, JITDylib::SymbolTableEntry &E) {2888          auto &FS = EQ.FailedSymsForQuery[&Q];2889          if (!FS)2890            FS = std::make_shared<SymbolDependenceMap>();2891          (*FS)[&JD].insert(SymbolStringPtr(Name));2892        });2893 2894  for (auto &FQ : EQ.Failed)2895    FQ->detach();2896 2897  for (auto &SN : ER.Ready)2898    IL_collectQueries(2899        EQ.Completed, SN->defs(),2900        [](JITDylib::SymbolTableEntry &E) { E.setState(SymbolState::Ready); },2901        [](AsynchronousSymbolQuery &Q, JITDylib &JD,2902           NonOwningSymbolStringPtr Name, JITDylib::SymbolTableEntry &E) {2903          Q.notifySymbolMetRequiredState(SymbolStringPtr(Name), E.getSymbol());2904        });2905 2906  // std::erase_if is not available in C++17, and llvm::erase_if does not work2907  // here.2908  for (auto it = EQ.Completed.begin(), end = EQ.Completed.end(); it != end;) {2909    if ((*it)->isComplete()) {2910      ++it;2911    } else {2912      it = EQ.Completed.erase(it);2913    }2914  }2915 2916#ifdef EXPENSIVE_CHECKS2917  verifySessionState("exiting ExecutionSession::IL_emit");2918#endif2919 2920  return std::move(EQ);2921}2922 2923Error ExecutionSession::OL_notifyEmitted(2924    MaterializationResponsibility &MR,2925    ArrayRef<SymbolDependenceGroup> DepGroups) {2926  LLVM_DEBUG({2927    dbgs() << "In " << MR.JD.getName() << " emitting " << MR.SymbolFlags2928           << "\n";2929    if (!DepGroups.empty()) {2930      dbgs() << "  Initial dependencies:\n";2931      for (auto &SDG : DepGroups) {2932        dbgs() << "    Symbols: " << SDG.Symbols2933               << ", Dependencies: " << SDG.Dependencies << "\n";2934      }2935    }2936  });2937 2938#ifndef NDEBUG2939  SymbolNameSet Visited;2940  for (auto &DG : DepGroups) {2941    for (auto &Sym : DG.Symbols) {2942      assert(MR.SymbolFlags.count(Sym) &&2943             "DG contains dependence for symbol outside this MR");2944      assert(Visited.insert(Sym).second &&2945             "DG contains duplicate entries for Name");2946    }2947  }2948#endif // NDEBUG2949 2950  std::vector<std::unique_ptr<WaitingOnGraph::SuperNode>> SNs;2951  WaitingOnGraph::ContainerElementsMap Residual;2952  {2953    auto &JDResidual = Residual[&MR.getTargetJITDylib()];2954    for (auto &[Name, Flags] : MR.getSymbols())2955      JDResidual.insert(NonOwningSymbolStringPtr(Name));2956 2957    for (auto &SDG : DepGroups) {2958      WaitingOnGraph::ContainerElementsMap Defs;2959      assert(!SDG.Symbols.empty());2960      auto &JDDefs = Defs[&MR.getTargetJITDylib()];2961      for (auto &Def : SDG.Symbols) {2962        JDDefs.insert(NonOwningSymbolStringPtr(Def));2963        JDResidual.erase(NonOwningSymbolStringPtr(Def));2964      }2965      WaitingOnGraph::ContainerElementsMap Deps;2966      if (!SDG.Dependencies.empty()) {2967        for (auto &[JD, Syms] : SDG.Dependencies) {2968          auto &JDDeps = Deps[JD];2969          for (auto &Dep : Syms)2970            JDDeps.insert(NonOwningSymbolStringPtr(Dep));2971        }2972      }2973      SNs.push_back(std::make_unique<WaitingOnGraph::SuperNode>(2974          std::move(Defs), std::move(Deps)));2975    }2976    if (!JDResidual.empty())2977      SNs.push_back(std::make_unique<WaitingOnGraph::SuperNode>(2978          std::move(Residual), WaitingOnGraph::ContainerElementsMap()));2979  }2980 2981  auto SR = WaitingOnGraph::simplify(std::move(SNs));2982 2983  LLVM_DEBUG({2984    dbgs() << "  Simplified dependencies:\n";2985    for (auto &SN : SR.superNodes()) {2986 2987      auto SortedLibs = [](WaitingOnGraph::ContainerElementsMap &C) {2988        std::vector<JITDylib *> JDs;2989        for (auto &[JD, _] : C)2990          JDs.push_back(JD);2991        llvm::sort(JDs, [](const JITDylib *LHS, const JITDylib *RHS) {2992          return LHS->getName() < RHS->getName();2993        });2994        return JDs;2995      };2996 2997      auto SortedNames = [](WaitingOnGraph::ElementSet &Elems) {2998        std::vector<NonOwningSymbolStringPtr> Names(Elems.begin(), Elems.end());2999        llvm::sort(Names, [](const NonOwningSymbolStringPtr &LHS,3000                             const NonOwningSymbolStringPtr &RHS) {3001          return *LHS < *RHS;3002        });3003        return Names;3004      };3005 3006      dbgs() << "    Defs: {";3007      for (auto *JD : SortedLibs(SN->defs())) {3008        dbgs() << " (" << JD->getName() << ", [";3009        for (auto &Sym : SortedNames(SN->defs()[JD]))3010          dbgs() << " " << Sym;3011        dbgs() << " ])";3012      }3013      dbgs() << " }, Deps: {";3014      for (auto *JD : SortedLibs(SN->deps())) {3015        dbgs() << " (" << JD->getName() << ", [";3016        for (auto &Sym : SortedNames(SN->deps()[JD]))3017          dbgs() << " " << Sym;3018        dbgs() << " ])";3019      }3020      dbgs() << " }\n";3021    }3022  });3023  auto EmitQueries =3024      runSessionLocked([&]() { return IL_emit(MR, std::move(SR)); });3025 3026  // On error bail out.3027  if (!EmitQueries)3028    return EmitQueries.takeError();3029 3030  // Otherwise notify failed queries, and any updated queries that have been3031  // completed.3032 3033  // FIXME: Get rid of error return from notifyEmitted.3034  SymbolDependenceMap BadDeps;3035  {3036    for (auto &FQ : EmitQueries->Failed) {3037      FQ->detach();3038      assert(EmitQueries->FailedSymsForQuery.count(FQ.get()) &&3039             "Missing failed symbols for query");3040      auto FailedSyms = std::move(EmitQueries->FailedSymsForQuery[FQ.get()]);3041      for (auto &[JD, Syms] : *FailedSyms) {3042        auto &BadDepsForJD = BadDeps[JD];3043        for (auto &Sym : Syms)3044          BadDepsForJD.insert(Sym);3045      }3046      FQ->handleFailed(make_error<FailedToMaterialize>(getSymbolStringPool(),3047                                                       std::move(FailedSyms)));3048    }3049  }3050 3051  for (auto &UQ : EmitQueries->Completed)3052    UQ->handleComplete(*this);3053 3054  // If there are any bad dependencies then return an error.3055  if (!BadDeps.empty()) {3056    SymbolNameSet BadNames;3057    // Note: The name set calculated here is bogus: it includes all symbols in3058    //       the MR, not just the ones that failed. We want to remove the error3059    //       return path from notifyEmitted anyway, so this is just a brief3060    //       placeholder to maintain (roughly) the current error behavior.3061    for (auto &[Name, Flags] : MR.getSymbols())3062      BadNames.insert(Name);3063    MR.SymbolFlags.clear();3064    return make_error<UnsatisfiedSymbolDependencies>(3065        getSymbolStringPool(), &MR.getTargetJITDylib(), std::move(BadNames),3066        std::move(BadDeps), "dependencies removed or in error state");3067  }3068 3069  MR.SymbolFlags.clear();3070  return Error::success();3071}3072 3073Error ExecutionSession::OL_defineMaterializing(3074    MaterializationResponsibility &MR, SymbolFlagsMap NewSymbolFlags) {3075 3076  LLVM_DEBUG({3077    dbgs() << "In " << MR.JD.getName() << " defining materializing symbols "3078           << NewSymbolFlags << "\n";3079  });3080  if (auto AcceptedDefs =3081          MR.JD.defineMaterializing(MR, std::move(NewSymbolFlags))) {3082    // Add all newly accepted symbols to this responsibility object.3083    for (auto &KV : *AcceptedDefs)3084      MR.SymbolFlags.insert(KV);3085    return Error::success();3086  } else3087    return AcceptedDefs.takeError();3088}3089 3090std::pair<JITDylib::AsynchronousSymbolQuerySet,3091          std::shared_ptr<SymbolDependenceMap>>3092ExecutionSession::IL_failSymbols(JITDylib &JD,3093                                 const SymbolNameVector &SymbolsToFail) {3094 3095#ifdef EXPENSIVE_CHECKS3096  verifySessionState("entering ExecutionSession::IL_failSymbols");3097#endif3098 3099  JITDylib::AsynchronousSymbolQuerySet FailedQueries;3100  auto Fail = [&](JITDylib *FailJD, NonOwningSymbolStringPtr FailSym) {3101    auto I = FailJD->Symbols.find_as(FailSym);3102    assert(I != FailJD->Symbols.end());3103    I->second.setFlags(I->second.getFlags() | JITSymbolFlags::HasError);3104    auto J = FailJD->MaterializingInfos.find_as(FailSym);3105    if (J != FailJD->MaterializingInfos.end()) {3106      for (auto &Q : J->second.takeAllPendingQueries())3107        FailedQueries.insert(std::move(Q));3108      FailJD->MaterializingInfos.erase(J);3109    }3110  };3111 3112  auto FailedSymbolsMap = std::make_shared<SymbolDependenceMap>();3113 3114  {3115    auto &FailedSymsForJD = (*FailedSymbolsMap)[&JD];3116    for (auto &Sym : SymbolsToFail) {3117      FailedSymsForJD.insert(Sym);3118      Fail(&JD, NonOwningSymbolStringPtr(Sym));3119    }3120  }3121 3122  WaitingOnGraph::ContainerElementsMap ToFail;3123  auto &JDToFail = ToFail[&JD];3124  for (auto &Sym : SymbolsToFail)3125    JDToFail.insert(NonOwningSymbolStringPtr(Sym));3126 3127  auto FailedSNs = G.fail(ToFail);3128 3129  for (auto &SN : FailedSNs) {3130    for (auto &[FailJD, Defs] : SN->defs()) {3131      auto &FailedSymsForFailJD = (*FailedSymbolsMap)[FailJD];3132      for (auto &Def : Defs) {3133        FailedSymsForFailJD.insert(SymbolStringPtr(Def));3134        Fail(FailJD, Def);3135      }3136    }3137  }3138 3139  // Detach all failed queries.3140  for (auto &Q : FailedQueries)3141    Q->detach();3142 3143#ifdef EXPENSIVE_CHECKS3144  verifySessionState("exiting ExecutionSession::IL_failSymbols");3145#endif3146 3147  return std::make_pair(std::move(FailedQueries), std::move(FailedSymbolsMap));3148}3149 3150void ExecutionSession::OL_notifyFailed(MaterializationResponsibility &MR) {3151 3152  LLVM_DEBUG({3153    dbgs() << "In " << MR.JD.getName() << " failing materialization for "3154           << MR.SymbolFlags << "\n";3155  });3156 3157  if (MR.SymbolFlags.empty())3158    return;3159 3160  SymbolNameVector SymbolsToFail;3161  for (auto &[Name, Flags] : MR.SymbolFlags)3162    SymbolsToFail.push_back(Name);3163  MR.SymbolFlags.clear();3164 3165  JITDylib::AsynchronousSymbolQuerySet FailedQueries;3166  std::shared_ptr<SymbolDependenceMap> FailedSymbols;3167 3168  std::tie(FailedQueries, FailedSymbols) = runSessionLocked([&]() {3169    // If the tracker is defunct then there's nothing to do here.3170    if (MR.RT->isDefunct())3171      return std::pair<JITDylib::AsynchronousSymbolQuerySet,3172                       std::shared_ptr<SymbolDependenceMap>>();3173    return IL_failSymbols(MR.getTargetJITDylib(), SymbolsToFail);3174  });3175 3176  for (auto &Q : FailedQueries) {3177    Q->detach();3178    Q->handleFailed(3179        make_error<FailedToMaterialize>(getSymbolStringPool(), FailedSymbols));3180  }3181}3182 3183Error ExecutionSession::OL_replace(MaterializationResponsibility &MR,3184                                   std::unique_ptr<MaterializationUnit> MU) {3185  for (auto &KV : MU->getSymbols()) {3186    assert(MR.SymbolFlags.count(KV.first) &&3187           "Replacing definition outside this responsibility set");3188    MR.SymbolFlags.erase(KV.first);3189  }3190 3191  if (MU->getInitializerSymbol() == MR.InitSymbol)3192    MR.InitSymbol = nullptr;3193 3194  LLVM_DEBUG(MR.JD.getExecutionSession().runSessionLocked([&]() {3195    dbgs() << "In " << MR.JD.getName() << " replacing symbols with " << *MU3196           << "\n";3197  }););3198 3199  return MR.JD.replace(MR, std::move(MU));3200}3201 3202Expected<std::unique_ptr<MaterializationResponsibility>>3203ExecutionSession::OL_delegate(MaterializationResponsibility &MR,3204                              const SymbolNameSet &Symbols) {3205 3206  SymbolStringPtr DelegatedInitSymbol;3207  SymbolFlagsMap DelegatedFlags;3208 3209  for (auto &Name : Symbols) {3210    auto I = MR.SymbolFlags.find(Name);3211    assert(I != MR.SymbolFlags.end() &&3212           "Symbol is not tracked by this MaterializationResponsibility "3213           "instance");3214 3215    DelegatedFlags[Name] = std::move(I->second);3216    if (Name == MR.InitSymbol)3217      std::swap(MR.InitSymbol, DelegatedInitSymbol);3218 3219    MR.SymbolFlags.erase(I);3220  }3221 3222  return MR.JD.delegate(MR, std::move(DelegatedFlags),3223                        std::move(DelegatedInitSymbol));3224}3225 3226#ifndef NDEBUG3227void ExecutionSession::dumpDispatchInfo(Task &T) {3228  runSessionLocked([&]() {3229    dbgs() << "Dispatching: ";3230    T.printDescription(dbgs());3231    dbgs() << "\n";3232  });3233}3234#endif // NDEBUG3235 3236} // End namespace orc.3237} // End namespace llvm.3238