//===--- Core.cpp - Core ORC APIs (MaterializationUnit, JITDylib, etc.) ---===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "llvm/ExecutionEngine/Orc/Core.h"

#include "llvm/ADT/STLExtras.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/ExecutionEngine/Orc/AbsoluteSymbols.h"
#include "llvm/ExecutionEngine/Orc/DebugUtils.h"
#include "llvm/ExecutionEngine/Orc/InstanceSymbolGeneratorSPS.h"
#include "llvm/ExecutionEngine/Orc/Shared/Mangler.h"
#include "llvm/ExecutionEngine/Orc/Shared/OrcError.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/MSVCErrorWorkarounds.h"
#include "llvm/Support/raw_ostream.h"

#include <condition_variable>
#include <future>
#include <optional>

#define DEBUG_TYPE "orc"

namespace llvm {
namespace orc {

char ResourceTrackerDefunct::ID = 0;
char JITDylibDefunct::ID = 0;
char FailedToMaterialize::ID = 0;
char SymbolsNotFound::ID = 0;
char SymbolsCouldNotBeRemoved::ID = 0;
char MissingSymbolDefinitions::ID = 0;
char UnexpectedSymbolDefinitions::ID = 0;
char UnsatisfiedSymbolDependencies::ID = 0;
char MaterializationTask::ID = 0;
char LookupTask::ID = 0;

RegisterDependenciesFunction NoDependenciesToRegister =
    RegisterDependenciesFunction();

void MaterializationUnit::anchor() {}

ResourceTracker::ResourceTracker(JITDylibSP JD) {
  assert((reinterpret_cast<uintptr_t>(JD.get()) & 0x1) == 0 &&
         "JITDylib must be two byte aligned");
  JD->Retain();
  JDAndFlag.store(reinterpret_cast<uintptr_t>(JD.get()));
}

ResourceTracker::~ResourceTracker() {
  getJITDylib().getExecutionSession().destroyResourceTracker(*this);
  getJITDylib().Release();
}

Error ResourceTracker::remove() {
  return getJITDylib().getExecutionSession().removeResourceTracker(*this);
}

void ResourceTracker::transferTo(ResourceTracker &DstRT) {
  getJITDylib().getExecutionSession().transferResourceTracker(DstRT, *this);
}

void ResourceTracker::makeDefunct() {
  uintptr_t Val = JDAndFlag.load();
  Val |= 0x1U;
  JDAndFlag.store(Val);
}

ResourceManager::~ResourceManager() = default;

ResourceTrackerDefunct::ResourceTrackerDefunct(ResourceTrackerSP RT)
    : RT(std::move(RT)) {}

std::error_code ResourceTrackerDefunct::convertToErrorCode() const {
  return orcError(OrcErrorCode::UnknownORCError);
}

void ResourceTrackerDefunct::log(raw_ostream &OS) const {
  OS << "Resource tracker " << (void *)RT.get() << " became defunct";
}

std::error_code JITDylibDefunct::convertToErrorCode() const {
  return orcError(OrcErrorCode::UnknownORCError);
}

void JITDylibDefunct::log(raw_ostream &OS) const {
  OS << "JITDylib " << JD->getName() << " (" << (void *)JD.get()
     << ") is defunct";
}

FailedToMaterialize::FailedToMaterialize(
    std::shared_ptr<SymbolStringPool> SSP,
    std::shared_ptr<SymbolDependenceMap> Symbols)
    : SSP(std::move(SSP)), Symbols(std::move(Symbols)) {
  assert(this->SSP && "String pool cannot be null");
  assert(!this->Symbols->empty() && "Can not fail to resolve an empty set");

  // FIXME: Use a new dep-map type for FailedToMaterialize errors so that we
  // don't have to manually retain/release.
  for (auto &[JD, Syms] : *this->Symbols)
    JD->Retain();
}

FailedToMaterialize::~FailedToMaterialize() {
  for (auto &[JD, Syms] : *Symbols)
    JD->Release();
}

std::error_code FailedToMaterialize::convertToErrorCode() const {
  return orcError(OrcErrorCode::UnknownORCError);
}

void FailedToMaterialize::log(raw_ostream &OS) const {
  OS << "Failed to materialize symbols: " << *Symbols;
}

UnsatisfiedSymbolDependencies::UnsatisfiedSymbolDependencies(
    std::shared_ptr<SymbolStringPool> SSP, JITDylibSP JD,
    SymbolNameSet FailedSymbols, SymbolDependenceMap BadDeps,
    std::string Explanation)
    : SSP(std::move(SSP)), JD(std::move(JD)),
      FailedSymbols(std::move(FailedSymbols)), BadDeps(std::move(BadDeps)),
      Explanation(std::move(Explanation)) {}

std::error_code UnsatisfiedSymbolDependencies::convertToErrorCode() const {
  return orcError(OrcErrorCode::UnknownORCError);
}

void UnsatisfiedSymbolDependencies::log(raw_ostream &OS) const {
  OS << "In " << JD->getName() << ", failed to materialize " << FailedSymbols
     << ", due to unsatisfied dependencies " << BadDeps;
  if (!Explanation.empty())
    OS << " (" << Explanation << ")";
}

SymbolsNotFound::SymbolsNotFound(std::shared_ptr<SymbolStringPool> SSP,
                                 SymbolNameSet Symbols)
    : SSP(std::move(SSP)) {
  llvm::append_range(this->Symbols, Symbols);
  assert(!this->Symbols.empty() && "Can not fail to resolve an empty set");
}

SymbolsNotFound::SymbolsNotFound(std::shared_ptr<SymbolStringPool> SSP,
                                 SymbolNameVector Symbols)
    : SSP(std::move(SSP)), Symbols(std::move(Symbols)) {
  assert(!this->Symbols.empty() && "Can not fail to resolve an empty set");
}

std::error_code SymbolsNotFound::convertToErrorCode() const {
  return orcError(OrcErrorCode::UnknownORCError);
}

void SymbolsNotFound::log(raw_ostream &OS) const {
  OS << "Symbols not found: " << Symbols;
}

SymbolsCouldNotBeRemoved::SymbolsCouldNotBeRemoved(
    std::shared_ptr<SymbolStringPool> SSP, SymbolNameSet Symbols)
    : SSP(std::move(SSP)), Symbols(std::move(Symbols)) {
  assert(!this->Symbols.empty() && "Can not fail to resolve an empty set");
}

std::error_code SymbolsCouldNotBeRemoved::convertToErrorCode() const {
  return orcError(OrcErrorCode::UnknownORCError);
}

void SymbolsCouldNotBeRemoved::log(raw_ostream &OS) const {
  OS << "Symbols could not be removed: " << Symbols;
}

std::error_code MissingSymbolDefinitions::convertToErrorCode() const {
  return orcError(OrcErrorCode::MissingSymbolDefinitions);
}

void MissingSymbolDefinitions::log(raw_ostream &OS) const {
  OS << "Missing definitions in module " << ModuleName
     << ": " << Symbols;
}

std::error_code UnexpectedSymbolDefinitions::convertToErrorCode() const {
  return orcError(OrcErrorCode::UnexpectedSymbolDefinitions);
}

void UnexpectedSymbolDefinitions::log(raw_ostream &OS) const {
  OS << "Unexpected definitions in module " << ModuleName
     << ": " << Symbols;
}

AsynchronousSymbolQuery::AsynchronousSymbolQuery(
    const SymbolLookupSet &Symbols, SymbolState RequiredState,
    SymbolsResolvedCallback NotifyComplete)
    : NotifyComplete(std::move(NotifyComplete)), RequiredState(RequiredState) {
  assert(RequiredState >= SymbolState::Resolved &&
         "Cannot query for a symbols that have not reached the resolve state "
         "yet");

  OutstandingSymbolsCount = Symbols.size();

  for (auto &[Name, Flags] : Symbols)
    ResolvedSymbols[Name] = ExecutorSymbolDef();
}

void AsynchronousSymbolQuery::notifySymbolMetRequiredState(
    const SymbolStringPtr &Name, ExecutorSymbolDef Sym) {
  auto I = ResolvedSymbols.find(Name);
  assert(I != ResolvedSymbols.end() &&
         "Resolving symbol outside the requested set");
  assert(I->second == ExecutorSymbolDef() &&
         "Redundantly resolving symbol Name");

  // If this is a materialization-side-effects-only symbol then drop it,
  // otherwise update its map entry with its resolved address.
  if (Sym.getFlags().hasMaterializationSideEffectsOnly())
    ResolvedSymbols.erase(I);
  else
    I->second = std::move(Sym);
  --OutstandingSymbolsCount;
}

void AsynchronousSymbolQuery::handleComplete(ExecutionSession &ES) {
  assert(OutstandingSymbolsCount == 0 &&
         "Symbols remain, handleComplete called prematurely");

  class RunQueryCompleteTask : public Task {
  public:
    RunQueryCompleteTask(SymbolMap ResolvedSymbols,
                         SymbolsResolvedCallback NotifyComplete)
        : ResolvedSymbols(std::move(ResolvedSymbols)),
          NotifyComplete(std::move(NotifyComplete)) {}
    void printDescription(raw_ostream &OS) override {
      OS << "Execute query complete callback for " << ResolvedSymbols;
    }
    void run() override { NotifyComplete(std::move(ResolvedSymbols)); }

  private:
    SymbolMap ResolvedSymbols;
    SymbolsResolvedCallback NotifyComplete;
  };

  auto T = std::make_unique<RunQueryCompleteTask>(std::move(ResolvedSymbols),
                                                  std::move(NotifyComplete));
  NotifyComplete = SymbolsResolvedCallback();
  ES.dispatchTask(std::move(T));
}

void AsynchronousSymbolQuery::handleFailed(Error Err) {
  assert(QueryRegistrations.empty() && ResolvedSymbols.empty() &&
         OutstandingSymbolsCount == 0 &&
         "Query should already have been abandoned");
  NotifyComplete(std::move(Err));
  NotifyComplete = SymbolsResolvedCallback();
}

void AsynchronousSymbolQuery::addQueryDependence(JITDylib &JD,
                                                 SymbolStringPtr Name) {
  bool Added = QueryRegistrations[&JD].insert(std::move(Name)).second;
  (void)Added;
  assert(Added && "Duplicate dependence notification?");
}

void AsynchronousSymbolQuery::removeQueryDependence(
    JITDylib &JD, const SymbolStringPtr &Name) {
  auto QRI = QueryRegistrations.find(&JD);
  assert(QRI != QueryRegistrations.end() &&
         "No dependencies registered for JD");
  assert(QRI->second.count(Name) && "No dependency on Name in JD");
  QRI->second.erase(Name);
  if (QRI->second.empty())
    QueryRegistrations.erase(QRI);
}

void AsynchronousSymbolQuery::dropSymbol(const SymbolStringPtr &Name) {
  auto I = ResolvedSymbols.find(Name);
  assert(I != ResolvedSymbols.end() &&
         "Redundant removal of weakly-referenced symbol");
  ResolvedSymbols.erase(I);
  --OutstandingSymbolsCount;
}

void AsynchronousSymbolQuery::detach() {
  ResolvedSymbols.clear();
  OutstandingSymbolsCount = 0;
  for (auto &[JD, Syms] : QueryRegistrations)
    JD->detachQueryHelper(*this, Syms);
  QueryRegistrations.clear();
}

ReExportsMaterializationUnit::ReExportsMaterializationUnit(
    JITDylib *SourceJD, JITDylibLookupFlags SourceJDLookupFlags,
    SymbolAliasMap Aliases)
    : MaterializationUnit(extractFlags(Aliases)), SourceJD(SourceJD),
      SourceJDLookupFlags(SourceJDLookupFlags), Aliases(std::move(Aliases)) {}

StringRef ReExportsMaterializationUnit::getName() const {
  return "<Reexports>";
}

void ReExportsMaterializationUnit::materialize(
    std::unique_ptr<MaterializationResponsibility> R) {

  auto &ES = R->getTargetJITDylib().getExecutionSession();
  JITDylib &TgtJD = R->getTargetJITDylib();
  JITDylib &SrcJD = SourceJD ? *SourceJD : TgtJD;

  // Find the set of requested aliases and aliasees. Return any unrequested
  // aliases back to the JITDylib so as to not prematurely materialize any
  // aliasees.
  auto RequestedSymbols = R->getRequestedSymbols();
  SymbolAliasMap RequestedAliases;

  for (auto &Name : RequestedSymbols) {
    auto I = Aliases.find(Name);
    assert(I != Aliases.end() && "Symbol not found in aliases map?");
    RequestedAliases[Name] = std::move(I->second);
    Aliases.erase(I);
  }

  LLVM_DEBUG({
    ES.runSessionLocked([&]() {
      dbgs() << "materializing reexports: target = " << TgtJD.getName()
             << ", source = " << SrcJD.getName() << " " << RequestedAliases
             << "\n";
    });
  });

  if (!Aliases.empty()) {
    auto Err = SourceJD ? R->replace(reexports(*SourceJD, std::move(Aliases),
                                               SourceJDLookupFlags))
                        : R->replace(symbolAliases(std::move(Aliases)));

    if (Err) {
      // FIXME: Should this be reported / treated as failure to materialize?
      // Or should this be treated as a sanctioned bailing-out?
      ES.reportError(std::move(Err));
      R->failMaterialization();
      return;
    }
  }

  // The OnResolveInfo struct will hold the aliases and responsibility for each
  // query in the list.
  struct OnResolveInfo {
    OnResolveInfo(std::unique_ptr<MaterializationResponsibility> R,
                  SymbolAliasMap Aliases)
        : R(std::move(R)), Aliases(std::move(Aliases)) {}

    std::unique_ptr<MaterializationResponsibility> R;
    SymbolAliasMap Aliases;
    std::vector<SymbolDependenceGroup> SDGs;
  };

  // Build a list of queries to issue. In each round we build a query for the
  // largest set of aliases that we can resolve without encountering a chain of
  // aliases (e.g. Foo -> Bar, Bar -> Baz). Such a chain would deadlock as the
  // query would be waiting on a symbol that it itself had to resolve. Creating
  // a new query for each link in such a chain eliminates the possibility of
  // deadlock. In practice chains are likely to be rare, and this algorithm will
  // usually result in a single query to issue.

  std::vector<std::pair<SymbolLookupSet, std::shared_ptr<OnResolveInfo>>>
      QueryInfos;
  while (!RequestedAliases.empty()) {
    SymbolNameSet ResponsibilitySymbols;
    SymbolLookupSet QuerySymbols;
    SymbolAliasMap QueryAliases;

    // Collect as many aliases as we can without including a chain.
    for (auto &[Alias, AliasInfo] : RequestedAliases) {
      // Chain detected. Skip this symbol for this round.
      if (&SrcJD == &TgtJD && (QueryAliases.count(AliasInfo.Aliasee) ||
                               RequestedAliases.count(AliasInfo.Aliasee)))
        continue;

      ResponsibilitySymbols.insert(Alias);
      QuerySymbols.add(AliasInfo.Aliasee,
                       AliasInfo.AliasFlags.hasMaterializationSideEffectsOnly()
                           ? SymbolLookupFlags::WeaklyReferencedSymbol
                           : SymbolLookupFlags::RequiredSymbol);
      QueryAliases[Alias] = std::move(AliasInfo);
    }

    // Remove the aliases collected this round from the RequestedAliases map.
    for (auto &KV : QueryAliases)
      RequestedAliases.erase(KV.first);

    assert(!QuerySymbols.empty() && "Alias cycle detected!");

    auto NewR = R->delegate(ResponsibilitySymbols);
    if (!NewR) {
      ES.reportError(NewR.takeError());
      R->failMaterialization();
      return;
    }

    auto QueryInfo = std::make_shared<OnResolveInfo>(std::move(*NewR),
                                                     std::move(QueryAliases));
    QueryInfos.push_back(
        make_pair(std::move(QuerySymbols), std::move(QueryInfo)));
  }

  // Issue the queries.
  while (!QueryInfos.empty()) {
    auto QuerySymbols = std::move(QueryInfos.back().first);
    auto QueryInfo = std::move(QueryInfos.back().second);

    QueryInfos.pop_back();

    auto RegisterDependencies = [QueryInfo,
                                 &SrcJD](const SymbolDependenceMap &Deps) {
      // If there were no materializing symbols, just bail out.
      if (Deps.empty())
        return;

      // Otherwise the only deps should be on SrcJD.
      assert(Deps.size() == 1 && Deps.count(&SrcJD) &&
             "Unexpected dependencies for reexports");

      auto &SrcJDDeps = Deps.find(&SrcJD)->second;

      for (auto &[Alias, AliasInfo] : QueryInfo->Aliases)
        if (SrcJDDeps.count(AliasInfo.Aliasee))
          QueryInfo->SDGs.push_back({{Alias}, {{&SrcJD, {AliasInfo.Aliasee}}}});
    };

    auto OnComplete = [QueryInfo](Expected<SymbolMap> Result) {
      auto &ES = QueryInfo->R->getTargetJITDylib().getExecutionSession();
      if (Result) {
        SymbolMap ResolutionMap;
        for (auto &KV : QueryInfo->Aliases) {
          assert((KV.second.AliasFlags.hasMaterializationSideEffectsOnly() ||
                  Result->count(KV.second.Aliasee)) &&
                 "Result map missing entry?");
          // Don't try to resolve materialization-side-effects-only symbols.
          if (KV.second.AliasFlags.hasMaterializationSideEffectsOnly())
            continue;

          ResolutionMap[KV.first] = {(*Result)[KV.second.Aliasee].getAddress(),
                                     KV.second.AliasFlags};
        }
        if (auto Err = QueryInfo->R->notifyResolved(ResolutionMap)) {
          ES.reportError(std::move(Err));
          QueryInfo->R->failMaterialization();
          return;
        }
        if (auto Err = QueryInfo->R->notifyEmitted(QueryInfo->SDGs)) {
          ES.reportError(std::move(Err));
          QueryInfo->R->failMaterialization();
          return;
        }
      } else {
        ES.reportError(Result.takeError());
        QueryInfo->R->failMaterialization();
      }
    };

    ES.lookup(LookupKind::Static,
              JITDylibSearchOrder({{&SrcJD, SourceJDLookupFlags}}),
              QuerySymbols, SymbolState::Resolved, std::move(OnComplete),
              std::move(RegisterDependencies));
  }
}

void ReExportsMaterializationUnit::discard(const JITDylib &JD,
                                           const SymbolStringPtr &Name) {
  assert(Aliases.count(Name) &&
         "Symbol not covered by this MaterializationUnit");
  Aliases.erase(Name);
}

MaterializationUnit::Interface
ReExportsMaterializationUnit::extractFlags(const SymbolAliasMap &Aliases) {
  SymbolFlagsMap SymbolFlags;
  for (auto &KV : Aliases)
    SymbolFlags[KV.first] = KV.second.AliasFlags;

  return MaterializationUnit::Interface(std::move(SymbolFlags), nullptr);
}

Expected<SymbolAliasMap>
buildSimpleReexportsAliasMap(JITDylib &SourceJD, const SymbolNameSet &Symbols) {
  SymbolLookupSet LookupSet(Symbols);
  auto Flags = SourceJD.getExecutionSession().lookupFlags(
      LookupKind::Static, {{&SourceJD, JITDylibLookupFlags::MatchAllSymbols}},
      SymbolLookupSet(std::move(Symbols)));

  if (!Flags)
    return Flags.takeError();

  SymbolAliasMap Result;
  for (auto &Name : Symbols) {
    assert(Flags->count(Name) && "Missing entry in flags map");
    Result[Name] = SymbolAliasMapEntry(Name, (*Flags)[Name]);
  }

  return Result;
}

class InProgressLookupState {
public:
  // FIXME: Reduce the number of SymbolStringPtrs here. See
  //        https://github.com/llvm/llvm-project/issues/55576.

  InProgressLookupState(LookupKind K, JITDylibSearchOrder SearchOrder,
                        SymbolLookupSet LookupSet, SymbolState RequiredState)
      : K(K), SearchOrder(std::move(SearchOrder)),
        LookupSet(std::move(LookupSet)), RequiredState(RequiredState) {
    DefGeneratorCandidates = this->LookupSet;
  }
  virtual ~InProgressLookupState() = default;
  virtual void complete(std::unique_ptr<InProgressLookupState> IPLS) = 0;
  virtual void fail(Error Err) = 0;

  LookupKind K;
  JITDylibSearchOrder SearchOrder;
  SymbolLookupSet LookupSet;
  SymbolState RequiredState;

  size_t CurSearchOrderIndex = 0;
  bool NewJITDylib = true;
  SymbolLookupSet DefGeneratorCandidates;
  SymbolLookupSet DefGeneratorNonCandidates;

  enum {
    NotInGenerator,      // Not currently using a generator.
    ResumedForGenerator, // Resumed after being auto-suspended before generator.
    InGenerator          // Currently using generator.
  } GenState = NotInGenerator;
  std::vector<std::weak_ptr<DefinitionGenerator>> CurDefGeneratorStack;
};

class InProgressLookupFlagsState : public InProgressLookupState {
public:
  InProgressLookupFlagsState(
      LookupKind K, JITDylibSearchOrder SearchOrder, SymbolLookupSet LookupSet,
      unique_function<void(Expected<SymbolFlagsMap>)> OnComplete)
      : InProgressLookupState(K, std::move(SearchOrder), std::move(LookupSet),
                              SymbolState::NeverSearched),
        OnComplete(std::move(OnComplete)) {}

  void complete(std::unique_ptr<InProgressLookupState> IPLS) override {
    auto &ES = SearchOrder.front().first->getExecutionSession();
    ES.OL_completeLookupFlags(std::move(IPLS), std::move(OnComplete));
  }

  void fail(Error Err) override { OnComplete(std::move(Err)); }

private:
  unique_function<void(Expected<SymbolFlagsMap>)> OnComplete;
};

class InProgressFullLookupState : public InProgressLookupState {
public:
  InProgressFullLookupState(LookupKind K, JITDylibSearchOrder SearchOrder,
                            SymbolLookupSet LookupSet,
                            SymbolState RequiredState,
                            std::shared_ptr<AsynchronousSymbolQuery> Q,
                            RegisterDependenciesFunction RegisterDependencies)
      : InProgressLookupState(K, std::move(SearchOrder), std::move(LookupSet),
                              RequiredState),
        Q(std::move(Q)), RegisterDependencies(std::move(RegisterDependencies)) {
  }

  void complete(std::unique_ptr<InProgressLookupState> IPLS) override {
    auto &ES = SearchOrder.front().first->getExecutionSession();
    ES.OL_completeLookup(std::move(IPLS), std::move(Q),
                         std::move(RegisterDependencies));
  }

  void fail(Error Err) override {
    Q->detach();
    Q->handleFailed(std::move(Err));
  }

private:
  std::shared_ptr<AsynchronousSymbolQuery> Q;
  RegisterDependenciesFunction RegisterDependencies;
};

ReexportsGenerator::ReexportsGenerator(JITDylib &SourceJD,
                                       JITDylibLookupFlags SourceJDLookupFlags,
                                       SymbolPredicate Allow)
    : SourceJD(SourceJD), SourceJDLookupFlags(SourceJDLookupFlags),
      Allow(std::move(Allow)) {}

Error ReexportsGenerator::tryToGenerate(LookupState &LS, LookupKind K,
                                        JITDylib &JD,
                                        JITDylibLookupFlags JDLookupFlags,
                                        const SymbolLookupSet &LookupSet) {
  assert(&JD != &SourceJD && "Cannot re-export from the same dylib");

  // Use lookupFlags to find the subset of symbols that match our lookup.
  auto Flags = JD.getExecutionSession().lookupFlags(
      K, {{&SourceJD, JDLookupFlags}}, LookupSet);
  if (!Flags)
    return Flags.takeError();

  // Create an alias map.
  orc::SymbolAliasMap AliasMap;
  for (auto &KV : *Flags)
    if (!Allow || Allow(KV.first))
      AliasMap[KV.first] = SymbolAliasMapEntry(KV.first, KV.second);

  if (AliasMap.empty())
    return Error::success();

  // Define the re-exports.
  return JD.define(reexports(SourceJD, AliasMap, SourceJDLookupFlags));
}

LookupState::LookupState(std::unique_ptr<InProgressLookupState> IPLS)
    : IPLS(std::move(IPLS)) {}

void LookupState::reset(InProgressLookupState *IPLS) { this->IPLS.reset(IPLS); }

LookupState::LookupState() = default;
LookupState::LookupState(LookupState &&) = default;
LookupState &LookupState::operator=(LookupState &&) = default;
LookupState::~LookupState() = default;

void LookupState::continueLookup(Error Err) {
  assert(IPLS && "Cannot call continueLookup on empty LookupState");
  auto &ES = IPLS->SearchOrder.begin()->first->getExecutionSession();
  ES.OL_applyQueryPhase1(std::move(IPLS), std::move(Err));
}

DefinitionGenerator::~DefinitionGenerator() {
  std::deque<LookupState> LookupsToFail;
  {
    std::lock_guard<std::mutex> Lock(M);
    std::swap(PendingLookups, LookupsToFail);
    InUse = false;
  }

  for (auto &LS : LookupsToFail)
    LS.continueLookup(make_error<StringError>(
        "Query waiting on DefinitionGenerator that was destroyed",
        inconvertibleErrorCode()));
}

JITDylib::~JITDylib() {
  LLVM_DEBUG(dbgs() << "Destroying JITDylib " << getName() << "\n");
}

Error JITDylib::clear() {
  std::vector<ResourceTrackerSP> TrackersToRemove;
  ES.runSessionLocked([&]() {
    assert(State != Closed && "JD is defunct");
    for (auto &KV : TrackerSymbols)
      TrackersToRemove.push_back(KV.first);
    TrackersToRemove.push_back(getDefaultResourceTracker());
  });

  Error Err = Error::success();
  for (auto &RT : TrackersToRemove)
    Err = joinErrors(std::move(Err), RT->remove());
  return Err;
}

ResourceTrackerSP JITDylib::getDefaultResourceTracker() {
  return ES.runSessionLocked([this] {
    assert(State != Closed && "JD is defunct");
    if (!DefaultTracker)
      DefaultTracker = new ResourceTracker(this);
    return DefaultTracker;
  });
}

ResourceTrackerSP JITDylib::createResourceTracker() {
  return ES.runSessionLocked([this] {
    assert(State == Open && "JD is defunct");
    ResourceTrackerSP RT = new ResourceTracker(this);
    return RT;
  });
}

void JITDylib::removeGenerator(DefinitionGenerator &G) {
  // DefGenerator moved into TmpDG to ensure that it's destroyed outside the
  // session lock (since it may have to send errors to pending queries).
  std::shared_ptr<DefinitionGenerator> TmpDG;

  ES.runSessionLocked([&] {
    assert(State == Open && "JD is defunct");
    auto I = llvm::find_if(DefGenerators,
                           [&](const std::shared_ptr<DefinitionGenerator> &H) {
                             return H.get() == &G;
                           });
    assert(I != DefGenerators.end() && "Generator not found");
    TmpDG = std::move(*I);
    DefGenerators.erase(I);
  });
}

Expected<SymbolFlagsMap>
JITDylib::defineMaterializing(MaterializationResponsibility &FromMR,
                              SymbolFlagsMap SymbolFlags) {

  return ES.runSessionLocked([&]() -> Expected<SymbolFlagsMap> {
    if (FromMR.RT->isDefunct())
      return make_error<ResourceTrackerDefunct>(FromMR.RT);

    std::vector<NonOwningSymbolStringPtr> AddedSyms;
    std::vector<NonOwningSymbolStringPtr> RejectedWeakDefs;

    for (auto &[Name, Flags] : SymbolFlags) {
      auto EntryItr = Symbols.find(Name);

      // If the entry already exists...
      if (EntryItr != Symbols.end()) {

        // If this is a strong definition then error out.
        if (!Flags.isWeak()) {
          // Remove any symbols already added.
          for (auto &S : AddedSyms)
            Symbols.erase(Symbols.find_as(S));

          // FIXME: Return all duplicates.
          return make_error<DuplicateDefinition>(
              std::string(*Name), "defineMaterializing operation");
        }

        // Otherwise just make a note to discard this symbol after the loop.
        RejectedWeakDefs.push_back(NonOwningSymbolStringPtr(Name));
        continue;
      } else
        EntryItr =
          Symbols.insert(std::make_pair(Name, SymbolTableEntry(Flags))).first;

      AddedSyms.push_back(NonOwningSymbolStringPtr(Name));
      EntryItr->second.setState(SymbolState::Materializing);
    }

    // Remove any rejected weak definitions from the SymbolFlags map.
    while (!RejectedWeakDefs.empty()) {
      SymbolFlags.erase(SymbolFlags.find_as(RejectedWeakDefs.back()));
      RejectedWeakDefs.pop_back();
    }

    return SymbolFlags;
  });
}

Error JITDylib::replace(MaterializationResponsibility &FromMR,
                        std::unique_ptr<MaterializationUnit> MU) {
  assert(MU != nullptr && "Can not replace with a null MaterializationUnit");
  std::unique_ptr<MaterializationUnit> MustRunMU;
  std::unique_ptr<MaterializationResponsibility> MustRunMR;

  auto Err =
      ES.runSessionLocked([&, this]() -> Error {
        if (FromMR.RT->isDefunct())
          return make_error<ResourceTrackerDefunct>(std::move(FromMR.RT));

#ifndef NDEBUG
        for (auto &KV : MU->getSymbols()) {
          auto SymI = Symbols.find(KV.first);
          assert(SymI != Symbols.end() && "Replacing unknown symbol");
          assert(SymI->second.getState() == SymbolState::Materializing &&
                 "Can not replace a symbol that ha is not materializing");
          assert(!SymI->second.hasMaterializerAttached() &&
                 "Symbol should not have materializer attached already");
          assert(UnmaterializedInfos.count(KV.first) == 0 &&
                 "Symbol being replaced should have no UnmaterializedInfo");
        }
#endif // NDEBUG

        // If the tracker is defunct we need to bail out immediately.

        // If any symbol has pending queries against it then we need to
        // materialize MU immediately.
        for (auto &KV : MU->getSymbols()) {
          auto MII = MaterializingInfos.find(KV.first);
          if (MII != MaterializingInfos.end()) {
            if (MII->second.hasQueriesPending()) {
              MustRunMR = ES.createMaterializationResponsibility(
                  *FromMR.RT, std::move(MU->SymbolFlags),
                  std::move(MU->InitSymbol));
              MustRunMU = std::move(MU);
              return Error::success();
            }
          }
        }

        // Otherwise, make MU responsible for all the symbols.
        auto UMI = std::make_shared<UnmaterializedInfo>(std::move(MU),
                                                        FromMR.RT.get());
        for (auto &KV : UMI->MU->getSymbols()) {
          auto SymI = Symbols.find(KV.first);
          assert(SymI->second.getState() == SymbolState::Materializing &&
                 "Can not replace a symbol that is not materializing");
          assert(!SymI->second.hasMaterializerAttached() &&
                 "Can not replace a symbol that has a materializer attached");
          assert(UnmaterializedInfos.count(KV.first) == 0 &&
                 "Unexpected materializer entry in map");
          SymI->second.setAddress(SymI->second.getAddress());
          SymI->second.setMaterializerAttached(true);

          auto &UMIEntry = UnmaterializedInfos[KV.first];
          assert((!UMIEntry || !UMIEntry->MU) &&
                 "Replacing symbol with materializer still attached");
          UMIEntry = UMI;
        }

        return Error::success();
      });

  if (Err)
    return Err;

  if (MustRunMU) {
    assert(MustRunMR && "MustRunMU set implies MustRunMR set");
    ES.dispatchTask(std::make_unique<MaterializationTask>(
        std::move(MustRunMU), std::move(MustRunMR)));
  } else {
    assert(!MustRunMR && "MustRunMU unset implies MustRunMR unset");
  }

  return Error::success();
}

Expected<std::unique_ptr<MaterializationResponsibility>>
JITDylib::delegate(MaterializationResponsibility &FromMR,
                   SymbolFlagsMap SymbolFlags, SymbolStringPtr InitSymbol) {

  return ES.runSessionLocked(
      [&]() -> Expected<std::unique_ptr<MaterializationResponsibility>> {
        if (FromMR.RT->isDefunct())
          return make_error<ResourceTrackerDefunct>(std::move(FromMR.RT));

        return ES.createMaterializationResponsibility(
            *FromMR.RT, std::move(SymbolFlags), std::move(InitSymbol));
      });
}

SymbolNameSet
JITDylib::getRequestedSymbols(const SymbolFlagsMap &SymbolFlags) const {
  return ES.runSessionLocked([&]() {
    SymbolNameSet RequestedSymbols;

    for (auto &KV : SymbolFlags) {
      assert(Symbols.count(KV.first) && "JITDylib does not cover this symbol?");
      assert(Symbols.find(KV.first)->second.getState() !=
                 SymbolState::NeverSearched &&
             Symbols.find(KV.first)->second.getState() != SymbolState::Ready &&
             "getRequestedSymbols can only be called for symbols that have "
             "started materializing");
      auto I = MaterializingInfos.find(KV.first);
      if (I == MaterializingInfos.end())
        continue;

      if (I->second.hasQueriesPending())
        RequestedSymbols.insert(KV.first);
    }

    return RequestedSymbols;
  });
}

Error JITDylib::resolve(MaterializationResponsibility &MR,
                        const SymbolMap &Resolved) {
  AsynchronousSymbolQuerySet CompletedQueries;

  if (auto Err = ES.runSessionLocked([&, this]() -> Error {
        if (MR.RT->isDefunct())
          return make_error<ResourceTrackerDefunct>(MR.RT);

        if (State != Open)
          return make_error<StringError>("JITDylib " + getName() +
                                             " is defunct",
                                         inconvertibleErrorCode());

        struct WorklistEntry {
          SymbolTable::iterator SymI;
          ExecutorSymbolDef ResolvedSym;
        };

        SymbolNameSet SymbolsInErrorState;
        std::vector<WorklistEntry> Worklist;
        Worklist.reserve(Resolved.size());

        // Build worklist and check for any symbols in the error state.
        for (const auto &KV : Resolved) {

          assert(!KV.second.getFlags().hasError() &&
                 "Resolution result can not have error flag set");

          auto SymI = Symbols.find(KV.first);

          assert(SymI != Symbols.end() && "Symbol not found");
          assert(!SymI->second.hasMaterializerAttached() &&
                 "Resolving symbol with materializer attached?");
          assert(SymI->second.getState() == SymbolState::Materializing &&
                 "Symbol should be materializing");
          assert(SymI->second.getAddress() == ExecutorAddr() &&
                 "Symbol has already been resolved");

          if (SymI->second.getFlags().hasError())
            SymbolsInErrorState.insert(KV.first);
          else {
            if (SymI->second.getFlags() & JITSymbolFlags::Common) {
              [[maybe_unused]] auto WeakOrCommon =
                  JITSymbolFlags::Weak | JITSymbolFlags::Common;
              assert((KV.second.getFlags() & WeakOrCommon) &&
                     "Common symbols must be resolved as common or weak");
              assert((KV.second.getFlags() & ~WeakOrCommon) ==
                         (SymI->second.getFlags() & ~JITSymbolFlags::Common) &&
                     "Resolving symbol with incorrect flags");

            } else
              assert(KV.second.getFlags() == SymI->second.getFlags() &&
                     "Resolved flags should match the declared flags");

            Worklist.push_back(
                {SymI, {KV.second.getAddress(), SymI->second.getFlags()}});
          }
        }

        // If any symbols were in the error state then bail out.
        if (!SymbolsInErrorState.empty()) {
          auto FailedSymbolsDepMap = std::make_shared<SymbolDependenceMap>();
          (*FailedSymbolsDepMap)[this] = std::move(SymbolsInErrorState);
          return make_error<FailedToMaterialize>(
              getExecutionSession().getSymbolStringPool(),
              std::move(FailedSymbolsDepMap));
        }

        while (!Worklist.empty()) {
          auto SymI = Worklist.back().SymI;
          auto ResolvedSym = Worklist.back().ResolvedSym;
          Worklist.pop_back();

          auto &Name = SymI->first;

          // Resolved symbols can not be weak: discard the weak flag.
          JITSymbolFlags ResolvedFlags = ResolvedSym.getFlags();
          SymI->second.setAddress(ResolvedSym.getAddress());
          SymI->second.setFlags(ResolvedFlags);
          SymI->second.setState(SymbolState::Resolved);

          auto MII = MaterializingInfos.find(Name);
          if (MII == MaterializingInfos.end())
            continue;

          auto &MI = MII->second;
          for (auto &Q : MI.takeQueriesMeeting(SymbolState::Resolved)) {
            Q->notifySymbolMetRequiredState(Name, ResolvedSym);
            if (Q->isComplete())
              CompletedQueries.insert(std::move(Q));
          }
        }

        return Error::success();
      }))
    return Err;

  // Otherwise notify all the completed queries.
  for (auto &Q : CompletedQueries) {
    assert(Q->isComplete() && "Q not completed");
    Q->handleComplete(ES);
  }

  return Error::success();
}

void JITDylib::unlinkMaterializationResponsibility(
    MaterializationResponsibility &MR) {
  ES.runSessionLocked([&]() {
    auto I = TrackerMRs.find(MR.RT.get());
    assert(I != TrackerMRs.end() && "No MRs in TrackerMRs list for RT");
    assert(I->second.count(&MR) && "MR not in TrackerMRs list for RT");
    I->second.erase(&MR);
    if (I->second.empty())
      TrackerMRs.erase(MR.RT.get());
  });
}

void JITDylib::shrinkMaterializationInfoMemory() {
  // DenseMap::erase never shrinks its storage; use clear to heuristically free
  // memory since we may have long-lived JDs after linking is done.

  if (UnmaterializedInfos.empty())
    UnmaterializedInfos.clear();

  if (MaterializingInfos.empty())
    MaterializingInfos.clear();
}

void JITDylib::setLinkOrder(JITDylibSearchOrder NewLinkOrder,
                            bool LinkAgainstThisJITDylibFirst) {
  ES.runSessionLocked([&]() {
    assert(State == Open && "JD is defunct");
    if (LinkAgainstThisJITDylibFirst) {
      LinkOrder.clear();
      if (NewLinkOrder.empty() || NewLinkOrder.front().first != this)
        LinkOrder.push_back(
            std::make_pair(this, JITDylibLookupFlags::MatchAllSymbols));
      llvm::append_range(LinkOrder, NewLinkOrder);
    } else
      LinkOrder = std::move(NewLinkOrder);
  });
}

void JITDylib::addToLinkOrder(const JITDylibSearchOrder &NewLinks) {
  ES.runSessionLocked([&]() {
    for (auto &KV : NewLinks) {
      // Skip elements of NewLinks that are already in the link order.
      if (llvm::is_contained(LinkOrder, KV))
        continue;

      LinkOrder.push_back(std::move(KV));
    }
  });
}

void JITDylib::addToLinkOrder(JITDylib &JD, JITDylibLookupFlags JDLookupFlags) {
  ES.runSessionLocked([&]() { LinkOrder.push_back({&JD, JDLookupFlags}); });
}

void JITDylib::replaceInLinkOrder(JITDylib &OldJD, JITDylib &NewJD,
                                  JITDylibLookupFlags JDLookupFlags) {
  ES.runSessionLocked([&]() {
    assert(State == Open && "JD is defunct");
    for (auto &KV : LinkOrder)
      if (KV.first == &OldJD) {
        KV = {&NewJD, JDLookupFlags};
        break;
      }
  });
}

void JITDylib::removeFromLinkOrder(JITDylib &JD) {
  ES.runSessionLocked([&]() {
    assert(State == Open && "JD is defunct");
    auto I = llvm::find_if(LinkOrder,
                           [&](const JITDylibSearchOrder::value_type &KV) {
                             return KV.first == &JD;
                           });
    if (I != LinkOrder.end())
      LinkOrder.erase(I);
  });
}

Error JITDylib::remove(const SymbolNameSet &Names) {
  return ES.runSessionLocked([&]() -> Error {
    assert(State == Open && "JD is defunct");
    SmallVector<SymbolStringPtr, 0> SymbolsToRemove;
    SymbolNameSet Missing;
    SymbolNameSet Materializing;

    for (auto &Name : Names) {
      auto I = Symbols.find(Name);

      // Note symbol missing.
      if (I == Symbols.end()) {
        Missing.insert(Name);
        continue;
      }

      // Note symbol materializing.
      if (I->second.getState() != SymbolState::NeverSearched &&
          I->second.getState() != SymbolState::Ready) {
        Materializing.insert(Name);
        continue;
      }

      SymbolsToRemove.push_back(Name);
    }

    // If any of the symbols are not defined, return an error.
    if (!Missing.empty())
      return make_error<SymbolsNotFound>(ES.getSymbolStringPool(),
                                         std::move(Missing));

    // If any of the symbols are currently materializing, return an error.
    if (!Materializing.empty())
      return make_error<SymbolsCouldNotBeRemoved>(ES.getSymbolStringPool(),
                                                  std::move(Materializing));

    // Remove the symbols. Erase by key rather than holding iterators across the
    // loop: a prior erase invalidates other stored iterators under
    // backward-shift deletion.
    for (const SymbolStringPtr &Name : SymbolsToRemove) {
      // If there is a materializer attached, call discard.
      auto UMII = UnmaterializedInfos.find(Name);
      if (UMII != UnmaterializedInfos.end()) {
        UMII->second->MU->doDiscard(*this, UMII->first);
        UnmaterializedInfos.erase(UMII);
      }

      Symbols.erase(Name);
    }

    shrinkMaterializationInfoMemory();

    return Error::success();
  });
}

void JITDylib::dump(raw_ostream &OS) {
  ES.runSessionLocked([&, this]() {
    OS << "JITDylib \"" << getName() << "\" (ES: "
       << format("0x%016" PRIx64, reinterpret_cast<uintptr_t>(&ES))
       << ", State = ";
    switch (State) {
    case Open:
      OS << "Open";
      break;
    case Closing:
      OS << "Closing";
      break;
    case Closed:
      OS << "Closed";
      break;
    }
    OS << ")\n";
    if (State == Closed)
      return;
    OS << "Link order: " << LinkOrder << "\n"
       << "Symbol table:\n";

    // Sort symbols so we get a deterministic order and can check them in tests.
    std::vector<std::pair<SymbolStringPtr, SymbolTableEntry *>> SymbolsSorted;
    for (auto &KV : Symbols)
      SymbolsSorted.emplace_back(KV.first, &KV.second);
    std::sort(SymbolsSorted.begin(), SymbolsSorted.end(),
              [](const auto &L, const auto &R) { return *L.first < *R.first; });

    for (auto &KV : SymbolsSorted) {
      OS << "    \"" << *KV.first << "\": ";
      if (auto Addr = KV.second->getAddress())
        OS << Addr;
      else
        OS << "<not resolved> ";

      OS << " " << KV.second->getFlags() << " " << KV.second->getState();

      if (KV.second->hasMaterializerAttached()) {
        OS << " (Materializer ";
        auto I = UnmaterializedInfos.find(KV.first);
        assert(I != UnmaterializedInfos.end() &&
               "Lazy symbol should have UnmaterializedInfo");
        OS << I->second->MU.get() << ", " << I->second->MU->getName() << ")\n";
      } else
        OS << "\n";
    }

    if (!MaterializingInfos.empty())
      OS << "  MaterializingInfos entries:\n";
    for (auto &KV : MaterializingInfos) {
      OS << "    \"" << *KV.first << "\":\n"
         << "      " << KV.second.pendingQueries().size()
         << " pending queries: { ";
      for (const auto &Q : KV.second.pendingQueries())
        OS << Q.get() << " (" << Q->getRequiredState() << ") ";
      OS << "}\n";
    }
  });
}

void JITDylib::MaterializingInfo::addQuery(
    std::shared_ptr<AsynchronousSymbolQuery> Q) {

  auto I = llvm::lower_bound(
      llvm::reverse(PendingQueries), Q->getRequiredState(),
      [](const std::shared_ptr<AsynchronousSymbolQuery> &V, SymbolState S) {
        return V->getRequiredState() <= S;
      });
  PendingQueries.insert(I.base(), std::move(Q));
}

void JITDylib::MaterializingInfo::removeQuery(
    const AsynchronousSymbolQuery &Q) {
  // FIXME: Implement 'find_as' for shared_ptr<T>/T*.
  auto I = llvm::find_if(
      PendingQueries, [&Q](const std::shared_ptr<AsynchronousSymbolQuery> &V) {
        return V.get() == &Q;
      });
  if (I != PendingQueries.end())
    PendingQueries.erase(I);
}

JITDylib::AsynchronousSymbolQueryList
JITDylib::MaterializingInfo::takeQueriesMeeting(SymbolState RequiredState) {
  AsynchronousSymbolQueryList Result;
  while (!PendingQueries.empty()) {
    if (PendingQueries.back()->getRequiredState() > RequiredState)
      break;

    Result.push_back(std::move(PendingQueries.back()));
    PendingQueries.pop_back();
  }

  return Result;
}

JITDylib::JITDylib(ExecutionSession &ES, std::string Name)
    : JITLinkDylib(std::move(Name)), ES(ES) {
  LinkOrder.push_back({this, JITDylibLookupFlags::MatchAllSymbols});
}

JITDylib::RemoveTrackerResult JITDylib::IL_removeTracker(ResourceTracker &RT) {
  // Note: Should be called under the session lock.
  assert(State != Closed && "JD is defunct");

  SymbolNameVector SymbolsToRemove;
  SymbolNameVector SymbolsToFail;

  if (&RT == DefaultTracker.get()) {
    SymbolNameSet TrackedSymbols;
    for (auto &KV : TrackerSymbols)
      TrackedSymbols.insert_range(KV.second);

    for (auto &KV : Symbols) {
      auto &Sym = KV.first;
      if (!TrackedSymbols.count(Sym))
        SymbolsToRemove.push_back(Sym);
    }

    DefaultTracker.reset();
  } else {
    /// Check for a non-default tracker.
    auto I = TrackerSymbols.find(&RT);
    if (I != TrackerSymbols.end()) {
      SymbolsToRemove = std::move(I->second);
      TrackerSymbols.erase(I);
    }
    // ... if not found this tracker was already defunct. Nothing to do.
  }

  for (auto &Sym : SymbolsToRemove) {
    assert(Symbols.count(Sym) && "Symbol not in symbol table");

    // If there is a MaterializingInfo then collect any queries to fail.
    auto MII = MaterializingInfos.find(Sym);
    if (MII != MaterializingInfos.end())
      SymbolsToFail.push_back(Sym);
  }

  auto [QueriesToFail, FailedSymbols] =
      ES.IL_failSymbols(*this, std::move(SymbolsToFail));

  std::vector<std::unique_ptr<MaterializationUnit>> DefunctMUs;

  // Removed symbols should be taken out of the table altogether.
  for (auto &Sym : SymbolsToRemove) {
    auto I = Symbols.find(Sym);
    assert(I != Symbols.end() && "Symbol not present in table");

    // Remove Materializer if present.
    if (I->second.hasMaterializerAttached()) {
      // FIXME: Should this discard the symbols?
      auto J = UnmaterializedInfos.find(Sym);
      assert(J != UnmaterializedInfos.end() &&
             "Symbol table indicates MU present, but no UMI record");
      if (J->second->MU)
        DefunctMUs.push_back(std::move(J->second->MU));
      UnmaterializedInfos.erase(J);
    } else {
      assert(!UnmaterializedInfos.count(Sym) &&
             "Symbol has materializer attached");
    }

    Symbols.erase(I);
  }

  shrinkMaterializationInfoMemory();

  return {std::move(QueriesToFail), std::move(FailedSymbols),
          std::move(DefunctMUs)};
}

void JITDylib::transferTracker(ResourceTracker &DstRT, ResourceTracker &SrcRT) {
  assert(State != Closed && "JD is defunct");
  assert(&DstRT != &SrcRT && "No-op transfers shouldn't call transferTracker");
  assert(&DstRT.getJITDylib() == this && "DstRT is not for this JITDylib");
  assert(&SrcRT.getJITDylib() == this && "SrcRT is not for this JITDylib");

  // Update trackers for any not-yet materialized units.
  for (auto &KV : UnmaterializedInfos) {
    if (KV.second->RT == &SrcRT)
      KV.second->RT = &DstRT;
  }

  // Update trackers for any active materialization responsibilities.
  {
    auto I = TrackerMRs.find(&SrcRT);
    if (I != TrackerMRs.end()) {
      auto &SrcMRs = I->second;
      auto &DstMRs = TrackerMRs[&DstRT];
      for (auto *MR : SrcMRs)
        MR->RT = &DstRT;
      if (DstMRs.empty())
        DstMRs = std::move(SrcMRs);
      else
        DstMRs.insert_range(SrcMRs);
      // Erase SrcRT entry in TrackerMRs. Use &SrcRT key rather than iterator I
      // for this, since I may have been invalidated by 'TrackerMRs[&DstRT]'.
      TrackerMRs.erase(&SrcRT);
    }
  }

  // If we're transfering to the default tracker we just need to delete the
  // tracked symbols for the source tracker.
  if (&DstRT == DefaultTracker.get()) {
    TrackerSymbols.erase(&SrcRT);
    return;
  }

  // If we're transferring from the default tracker we need to find all
  // currently untracked symbols.
  if (&SrcRT == DefaultTracker.get()) {
    assert(!TrackerSymbols.count(&SrcRT) &&
           "Default tracker should not appear in TrackerSymbols");

    SymbolNameVector SymbolsToTrack;

    SymbolNameSet CurrentlyTrackedSymbols;
    for (auto &KV : TrackerSymbols)
      CurrentlyTrackedSymbols.insert_range(KV.second);

    for (auto &KV : Symbols) {
      auto &Sym = KV.first;
      if (!CurrentlyTrackedSymbols.count(Sym))
        SymbolsToTrack.push_back(Sym);
    }

    TrackerSymbols[&DstRT] = std::move(SymbolsToTrack);
    return;
  }

  auto &DstTrackedSymbols = TrackerSymbols[&DstRT];

  // Finally if neither SrtRT or DstRT are the default tracker then
  // just append DstRT's tracked symbols to SrtRT's.
  auto SI = TrackerSymbols.find(&SrcRT);
  if (SI == TrackerSymbols.end())
    return;

  DstTrackedSymbols.reserve(DstTrackedSymbols.size() + SI->second.size());
  for (auto &Sym : SI->second)
    DstTrackedSymbols.push_back(std::move(Sym));
  TrackerSymbols.erase(SI);
}

Error JITDylib::defineImpl(MaterializationUnit &MU) {
  LLVM_DEBUG({ dbgs() << "  " << MU.getSymbols() << "\n"; });

  SymbolNameSet Duplicates;
  std::vector<SymbolStringPtr> ExistingDefsOverridden;
  std::vector<SymbolStringPtr> MUDefsOverridden;

  for (const auto &KV : MU.getSymbols()) {
    auto I = Symbols.find(KV.first);

    if (I != Symbols.end()) {
      if (KV.second.isStrong()) {
        if (I->second.getFlags().isStrong() ||
            I->second.getState() > SymbolState::NeverSearched)
          Duplicates.insert(KV.first);
        else {
          assert(I->second.getState() == SymbolState::NeverSearched &&
                 "Overridden existing def should be in the never-searched "
                 "state");
          ExistingDefsOverridden.push_back(KV.first);
        }
      } else
        MUDefsOverridden.push_back(KV.first);
    }
  }

  // If there were any duplicate definitions then bail out.
  if (!Duplicates.empty()) {
    LLVM_DEBUG(
        { dbgs() << "  Error: Duplicate symbols " << Duplicates << "\n"; });
    return make_error<DuplicateDefinition>(std::string(**Duplicates.begin()),
                                           MU.getName().str());
  }

  // Discard any overridden defs in this MU.
  LLVM_DEBUG({
    if (!MUDefsOverridden.empty())
      dbgs() << "  Defs in this MU overridden: " << MUDefsOverridden << "\n";
  });
  for (auto &S : MUDefsOverridden)
    MU.doDiscard(*this, S);

  // Discard existing overridden defs.
  LLVM_DEBUG({
    if (!ExistingDefsOverridden.empty())
      dbgs() << "  Existing defs overridden by this MU: " << MUDefsOverridden
             << "\n";
  });
  for (auto &S : ExistingDefsOverridden) {

    auto UMII = UnmaterializedInfos.find(S);
    assert(UMII != UnmaterializedInfos.end() &&
           "Overridden existing def should have an UnmaterializedInfo");
    UMII->second->MU->doDiscard(*this, S);
  }

  // Finally, add the defs from this MU.
  for (auto &KV : MU.getSymbols()) {
    auto &SymEntry = Symbols[KV.first];
    SymEntry.setFlags(KV.second);
    SymEntry.setState(SymbolState::NeverSearched);
    SymEntry.setMaterializerAttached(true);
  }

  return Error::success();
}

void JITDylib::installMaterializationUnit(
    std::unique_ptr<MaterializationUnit> MU, ResourceTracker &RT) {

  /// defineImpl succeeded.
  if (&RT != DefaultTracker.get()) {
    auto &TS = TrackerSymbols[&RT];
    TS.reserve(TS.size() + MU->getSymbols().size());
    for (auto &KV : MU->getSymbols())
      TS.push_back(KV.first);
  }

  auto UMI = std::make_shared<UnmaterializedInfo>(std::move(MU), &RT);
  for (auto &KV : UMI->MU->getSymbols())
    UnmaterializedInfos[KV.first] = UMI;
}

void JITDylib::detachQueryHelper(AsynchronousSymbolQuery &Q,
                                 const SymbolNameSet &QuerySymbols) {
  for (auto &QuerySymbol : QuerySymbols) {
    auto MII = MaterializingInfos.find(QuerySymbol);
    if (MII != MaterializingInfos.end())
      MII->second.removeQuery(Q);
  }
}

Platform::~Platform() = default;

Expected<DenseMap<JITDylib *, SymbolMap>> Platform::lookupInitSymbols(
    ExecutionSession &ES,
    const DenseMap<JITDylib *, SymbolLookupSet> &InitSyms) {

  DenseMap<JITDylib *, SymbolMap> CompoundResult;
  Error CompoundErr = Error::success();
  std::mutex LookupMutex;
  std::condition_variable CV;
  uint64_t Count = InitSyms.size();

  LLVM_DEBUG({
    dbgs() << "Issuing init-symbol lookup:\n";
    for (auto &KV : InitSyms)
      dbgs() << "  " << KV.first->getName() << ": " << KV.second << "\n";
  });

  for (auto &KV : InitSyms) {
    auto *JD = KV.first;
    auto Names = std::move(KV.second);
    ES.lookup(
        LookupKind::Static,
        JITDylibSearchOrder({{JD, JITDylibLookupFlags::MatchAllSymbols}}),
        std::move(Names), SymbolState::Ready,
        [&, JD](Expected<SymbolMap> Result) {
          std::lock_guard<std::mutex> Lock(LookupMutex);
          --Count;
          if (Result) {
            assert(!CompoundResult.count(JD) &&
                   "Duplicate JITDylib in lookup?");
            CompoundResult[JD] = std::move(*Result);
          } else {
            CompoundErr =
                joinErrors(std::move(CompoundErr), Result.takeError());
          }
          CV.notify_one();
        },
        NoDependenciesToRegister);
  }

  std::unique_lock<std::mutex> Lock(LookupMutex);
  CV.wait(Lock, [&] { return Count == 0; });

  if (CompoundErr)
    return std::move(CompoundErr);

  return std::move(CompoundResult);
}

void Platform::lookupInitSymbolsAsync(
    unique_function<void(Error)> OnComplete, ExecutionSession &ES,
    const DenseMap<JITDylib *, SymbolLookupSet> &InitSyms) {

  class TriggerOnComplete {
  public:
    using OnCompleteFn = unique_function<void(Error)>;
    TriggerOnComplete(OnCompleteFn OnComplete)
        : OnComplete(std::move(OnComplete)) {}
    ~TriggerOnComplete() { OnComplete(std::move(LookupResult)); }
    void reportResult(Error Err) {
      std::lock_guard<std::mutex> Lock(ResultMutex);
      LookupResult = joinErrors(std::move(LookupResult), std::move(Err));
    }

  private:
    std::mutex ResultMutex;
    Error LookupResult{Error::success()};
    OnCompleteFn OnComplete;
  };

  LLVM_DEBUG({
    dbgs() << "Issuing init-symbol lookup:\n";
    for (auto &KV : InitSyms)
      dbgs() << "  " << KV.first->getName() << ": " << KV.second << "\n";
  });

  auto TOC = std::make_shared<TriggerOnComplete>(std::move(OnComplete));

  for (auto &KV : InitSyms) {
    auto *JD = KV.first;
    auto Names = std::move(KV.second);
    ES.lookup(
        LookupKind::Static,
        JITDylibSearchOrder({{JD, JITDylibLookupFlags::MatchAllSymbols}}),
        std::move(Names), SymbolState::Ready,
        [TOC](Expected<SymbolMap> Result) {
          TOC->reportResult(Result.takeError());
        },
        NoDependenciesToRegister);
  }
}

MaterializationTask::~MaterializationTask() {
  // If this task wasn't run then fail materialization.
  if (MR)
    MR->failMaterialization();
}

void MaterializationTask::printDescription(raw_ostream &OS) {
  OS << "Materialization task: " << MU->getName() << " in "
     << MR->getTargetJITDylib().getName();
}

void MaterializationTask::run() {
  assert(MU && "MU should not be null");
  assert(MR && "MR should not be null");
  MU->materialize(std::move(MR));
}

void LookupTask::printDescription(raw_ostream &OS) { OS << "Lookup task"; }

void LookupTask::run() { LS.continueLookup(Error::success()); }

ExecutionSession::ExecutionSession(std::unique_ptr<ExecutorProcessControl> EPC)
    : EPC(std::move(EPC)), BootstrapJD(createBareJITDylib("<bootstrap>")) {
  // Associated EPC and this.
  this->EPC->ES = this;
  SymbolMap BootstrapSymbols;
  for (auto &[Name, Ptr] : this->EPC->getBootstrapSymbolsMap())
    BootstrapSymbols[intern(Name)] =
        ExecutorSymbolDef(Ptr, JITSymbolFlags::Exported);
  // Can't fail: BootstrapJD is a new, empty JD and the BootstrapSymbols
  // variable is a map, so can't contain duplicates.
  cantFail(BootstrapJD.define(absoluteSymbols(std::move(BootstrapSymbols))));

  // If the executor provides the ORC runtime's instance-symbol lookup then
  // make instance symbols available via the bootstrap JITDylib.
  //
  // TODO: Bind the lookup proxy with a weak lookupAndApply in BootstrapJD,
  //       rather than searching the bootstrap symbols map. That isn't safe
  //       yet: the blocking lookup materializes BootstrapJD's absolute
  //       symbols via a task, so it would hang with a dispatcher that defers
  //       tasks. To fix this we should add a version of absoluteSymbols that
  //       is guaranteed to inject definitions directly into the symbol table
  //       without spawning a task, and guarantee that blocking lookups return
  //       without dispatching if all symbols are already fully materialized.
  Mangler Mangle(getTargetTriple());
  auto &BootstrapSymbolsMap = this->EPC->getBootstrapSymbolsMap();
  auto LookupFnI = BootstrapSymbolsMap.find(
      Mangle.mangledCopy(rt::sps_ci::SessionLookupInstanceSymbols::Name));
  if (LookupFnI != BootstrapSymbolsMap.end())
    BootstrapJD.addGenerator(
        sps::createInstanceSymbolGenerator(LookupFnI->second));
}

ExecutionSession::~ExecutionSession() {
  // You must call endSession prior to destroying the session.
  assert(!SessionOpen &&
         "Session still open. Did you forget to call endSession?");
}

Error ExecutionSession::endSession() {
  LLVM_DEBUG(dbgs() << "Ending ExecutionSession " << this << "\n");

  WaitingOnGraph::OpRecorder *GOpRecorderToEnd = nullptr;
  auto JDsToRemove = runSessionLocked([&] {

#ifdef EXPENSIVE_CHECKS
    verifySessionState("Entering ExecutionSession::endSession");
#endif

    if (SessionOpen)
      GOpRecorderToEnd = GOpRecorder;
    SessionOpen = false;
    return JDs;
  });

  std::reverse(JDsToRemove.begin(), JDsToRemove.end());

  auto Err = removeJITDylibs(std::move(JDsToRemove));

  Err = joinErrors(std::move(Err), EPC->disconnect());

  if (GOpRecorderToEnd)
    GOpRecorderToEnd->recordEnd();

  return Err;
}

void ExecutionSession::registerResourceManager(ResourceManager &RM) {
  runSessionLocked([&] { ResourceManagers.push_back(&RM); });
}

void ExecutionSession::deregisterResourceManager(ResourceManager &RM) {
  runSessionLocked([&] {
    assert(!ResourceManagers.empty() && "No managers registered");
    if (ResourceManagers.back() == &RM)
      ResourceManagers.pop_back();
    else {
      auto I = llvm::find(ResourceManagers, &RM);
      assert(I != ResourceManagers.end() && "RM not registered");
      ResourceManagers.erase(I);
    }
  });
}

JITDylib *ExecutionSession::getJITDylibByName(StringRef Name) {
  return runSessionLocked([&, this]() -> JITDylib * {
    for (auto &JD : JDs)
      if (JD->getName() == Name)
        return JD.get();
    return nullptr;
  });
}

JITDylib &ExecutionSession::createBareJITDylib(std::string Name) {
  assert(!getJITDylibByName(Name) && "JITDylib with that name already exists");
  return runSessionLocked([&, this]() -> JITDylib & {
    assert(SessionOpen && "Cannot create JITDylib after session is closed");
    JDs.push_back(new JITDylib(*this, std::move(Name)));
    return *JDs.back();
  });
}

Expected<JITDylib &> ExecutionSession::createJITDylib(std::string Name) {
  auto &JD = createBareJITDylib(Name);
  if (P)
    if (auto Err = P->setupJITDylib(JD))
      return std::move(Err);
  return JD;
}

Error ExecutionSession::removeJITDylibs(std::vector<JITDylibSP> JDsToRemove) {
  // Set JD to 'Closing' state and remove JD from the ExecutionSession.
  runSessionLocked([&] {
    for (auto &JD : JDsToRemove) {
      assert(JD->State == JITDylib::Open && "JD already closed");
      JD->State = JITDylib::Closing;
      auto I = llvm::find(JDs, JD);
      assert(I != JDs.end() && "JD does not appear in session JDs");
      JDs.erase(I);
    }
  });

  // Clear JITDylibs and notify the platform.
  Error Err = Error::success();
  for (auto JD : JDsToRemove) {
    Err = joinErrors(std::move(Err), JD->clear());
    if (P)
      Err = joinErrors(std::move(Err), P->teardownJITDylib(*JD));
  }

  // Set JD to closed state. Clear remaining data structures.
  runSessionLocked([&] {
    for (auto &JD : JDsToRemove) {
      assert(JD->State == JITDylib::Closing && "JD should be closing");
      JD->State = JITDylib::Closed;
      assert(JD->Symbols.empty() && "JD.Symbols is not empty after clear");
      assert(JD->UnmaterializedInfos.empty() &&
             "JD.UnmaterializedInfos is not empty after clear");
      assert(JD->MaterializingInfos.empty() &&
             "JD.MaterializingInfos is not empty after clear");
      assert(JD->TrackerSymbols.empty() &&
             "TrackerSymbols is not empty after clear");
      JD->DefGenerators.clear();
      JD->LinkOrder.clear();
    }
  });

  return Err;
}

Expected<std::vector<JITDylibSP>>
JITDylib::getDFSLinkOrder(ArrayRef<JITDylibSP> JDs) {
  if (JDs.empty())
    return std::vector<JITDylibSP>();

  auto &ES = JDs.front()->getExecutionSession();
  return ES.runSessionLocked([&]() -> Expected<std::vector<JITDylibSP>> {
    DenseSet<JITDylib *> Visited;
    std::vector<JITDylibSP> Result;

    for (auto &JD : JDs) {

      if (JD->State != Open)
        return make_error<StringError>(
            "Error building link order: " + JD->getName() + " is defunct",
            inconvertibleErrorCode());
      if (Visited.count(JD.get()))
        continue;

      SmallVector<JITDylibSP, 64> WorkStack;
      WorkStack.push_back(JD);
      Visited.insert(JD.get());

      while (!WorkStack.empty()) {
        Result.push_back(std::move(WorkStack.back()));
        WorkStack.pop_back();

        for (auto &KV : llvm::reverse(Result.back()->LinkOrder)) {
          auto &JD = *KV.first;
          if (!Visited.insert(&JD).second)
            continue;
          WorkStack.push_back(&JD);
        }
      }
    }
    return Result;
  });
}

Expected<std::vector<JITDylibSP>>
JITDylib::getReverseDFSLinkOrder(ArrayRef<JITDylibSP> JDs) {
  auto Result = getDFSLinkOrder(JDs);
  if (Result)
    std::reverse(Result->begin(), Result->end());
  return Result;
}

Expected<std::vector<JITDylibSP>> JITDylib::getDFSLinkOrder() {
  return getDFSLinkOrder({this});
}

Expected<std::vector<JITDylibSP>> JITDylib::getReverseDFSLinkOrder() {
  return getReverseDFSLinkOrder({this});
}

void ExecutionSession::lookupFlags(
    LookupKind K, JITDylibSearchOrder SearchOrder, SymbolLookupSet LookupSet,
    unique_function<void(Expected<SymbolFlagsMap>)> OnComplete) {

  OL_applyQueryPhase1(std::make_unique<InProgressLookupFlagsState>(
                          K, std::move(SearchOrder), std::move(LookupSet),
                          std::move(OnComplete)),
                      Error::success());
}

Expected<SymbolFlagsMap>
ExecutionSession::lookupFlags(LookupKind K, JITDylibSearchOrder SearchOrder,
                              SymbolLookupSet LookupSet) {

  std::promise<MSVCPExpected<SymbolFlagsMap>> ResultP;
  OL_applyQueryPhase1(std::make_unique<InProgressLookupFlagsState>(
                          K, std::move(SearchOrder), std::move(LookupSet),
                          [&ResultP](Expected<SymbolFlagsMap> Result) {
                            ResultP.set_value(std::move(Result));
                          }),
                      Error::success());

  auto ResultF = ResultP.get_future();
  return ResultF.get();
}

void ExecutionSession::lookup(
    LookupKind K, const JITDylibSearchOrder &SearchOrder,
    SymbolLookupSet Symbols, SymbolState RequiredState,
    SymbolsResolvedCallback NotifyComplete,
    RegisterDependenciesFunction RegisterDependencies) {

  LLVM_DEBUG({
    runSessionLocked([&]() {
      dbgs() << "Looking up " << Symbols << " in " << SearchOrder
             << " (required state: " << RequiredState << ")\n";
    });
  });

  // lookup can be re-entered recursively if running on a single thread. Run any
  // outstanding MUs in case this query depends on them, otherwise this lookup
  // will starve waiting for a result from an MU that is stuck in the queue.
  dispatchOutstandingMUs();

  auto Unresolved = std::move(Symbols);
  auto Q = std::make_shared<AsynchronousSymbolQuery>(Unresolved, RequiredState,
                                                     std::move(NotifyComplete));

  auto IPLS = std::make_unique<InProgressFullLookupState>(
      K, SearchOrder, std::move(Unresolved), RequiredState, std::move(Q),
      std::move(RegisterDependencies));

  OL_applyQueryPhase1(std::move(IPLS), Error::success());
}

Expected<SymbolMap>
ExecutionSession::lookup(const JITDylibSearchOrder &SearchOrder,
                         SymbolLookupSet Symbols, LookupKind K,
                         SymbolState RequiredState,
                         RegisterDependenciesFunction RegisterDependencies) {
#if LLVM_ENABLE_THREADS
  // In the threaded case we use promises to return the results.
  std::promise<MSVCPExpected<SymbolMap>> PromisedResult;

  auto NotifyComplete = [&](Expected<SymbolMap> R) {
    PromisedResult.set_value(std::move(R));
  };

#else
  SymbolMap Result;
  Error ResolutionError = Error::success();

  auto NotifyComplete = [&](Expected<SymbolMap> R) {
    ErrorAsOutParameter _(ResolutionError);
    if (R)
      Result = std::move(*R);
    else
      ResolutionError = R.takeError();
  };
#endif

  // Perform the asynchronous lookup.
  lookup(K, SearchOrder, std::move(Symbols), RequiredState,
         std::move(NotifyComplete), RegisterDependencies);

#if LLVM_ENABLE_THREADS
  return PromisedResult.get_future().get();
#else
  if (ResolutionError)
    return std::move(ResolutionError);

  return Result;
#endif
}

Expected<ExecutorSymbolDef>
ExecutionSession::lookup(const JITDylibSearchOrder &SearchOrder,
                         SymbolStringPtr Name, SymbolState RequiredState) {
  SymbolLookupSet Names({Name});

  if (auto ResultMap = lookup(SearchOrder, std::move(Names), LookupKind::Static,
                              RequiredState, NoDependenciesToRegister)) {
    assert(ResultMap->size() == 1 && "Unexpected number of results");
    assert(ResultMap->count(Name) && "Missing result for symbol");
    return std::move(ResultMap->begin()->second);
  } else
    return ResultMap.takeError();
}

Expected<ExecutorSymbolDef>
ExecutionSession::lookup(ArrayRef<JITDylib *> SearchOrder, SymbolStringPtr Name,
                         SymbolState RequiredState) {
  return lookup(makeJITDylibSearchOrder(SearchOrder), Name, RequiredState);
}

Expected<ExecutorSymbolDef>
ExecutionSession::lookup(ArrayRef<JITDylib *> SearchOrder, StringRef Name,
                         SymbolState RequiredState) {
  return lookup(SearchOrder, intern(Name), RequiredState);
}

Error ExecutionSession::registerCallControllerHandlers(
    JITDylib &JD, std::vector<CallControllerHandlerBinding> Hs) {

  // Mangle and intern the tag names, and take the handlers.
  Mangler Mangle(getTargetTriple());
  DenseMap<SymbolStringPtr, CallControllerHandlerFn> Handlers;
  SymbolLookupSet LookupSet;
  for (auto &H : Hs) {
    auto TagName = Mangle.withMangledNameDo(
        [&](StringRef N) { return intern(N); }, H.getName());
    auto Handler = H.takeHandler();
    assert(Handler && "CallControllerHandler implementation missing");
    if (!Handlers.try_emplace(TagName, std::move(Handler)).second)
      return make_error<StringError>(
          "Duplicate call-controller handler binding for tag " + *TagName,
          inconvertibleErrorCode());
    LookupSet.add(std::move(TagName), H.getLookupFlags());
  }

  auto TagSyms = lookup({{&JD, JITDylibLookupFlags::MatchAllSymbols}},
                        std::move(LookupSet));
  if (!TagSyms)
    return TagSyms.takeError();

  // Associate tag addresses with implementations.
  std::lock_guard<std::mutex> Lock(CallControllerHandlersMutex);

  // Check that no tags are being overwritten.
  for (auto &[TagName, TagSym] : *TagSyms) {
    auto TagAddr = TagSym.getAddress();
    if (CallControllerHandlers.count(TagAddr))
      return make_error<StringError>("Tag " + formatv("{0:x}", TagAddr) +
                                         " (for " + *TagName +
                                         ") already registered",
                                     inconvertibleErrorCode());
  }

  // At this point we're guaranteed to succeed. Install the handlers. Handlers
  // for weakly referenced tags that weren't found are dropped.
  for (auto &[TagName, TagSym] : *TagSyms) {
    auto TagAddr = TagSym.getAddress();
    auto I = Handlers.find(TagName);
    assert(I != Handlers.end() && "No handler for tag in lookup result");
    CallControllerHandlers[TagAddr] =
        std::make_unique<CallControllerHandlerFn>(std::move(I->second));
    LLVM_DEBUG({
      dbgs() << "Registered call-controller handler for tag \"" << *TagName
             << "\" (" << formatv("{0:x}", TagAddr) << ")\n";
    });
  }

  return Error::success();
}

void ExecutionSession::runCallControllerHandler(
    CallControllerReturnFn Return, ExecutorAddr HandlerFnTagAddr,
    shared::WrapperFunctionBuffer ArgBytes) {

  // Handlers are never removed, so H remains valid after the lock is
  // released.
  CallControllerHandlerFn *H = nullptr;
  {
    std::lock_guard<std::mutex> Lock(CallControllerHandlersMutex);
    auto I = CallControllerHandlers.find(HandlerFnTagAddr);
    if (I != CallControllerHandlers.end())
      H = I->second.get();
  }

  if (!H)
    return Return(shared::WrapperFunctionBuffer::createOutOfBandError(
        ("No call-controller handler registered for tag " +
         formatv("{0:x16}", HandlerFnTagAddr))
            .str()));

  (*H)(std::move(Return), std::move(ArgBytes));
}

void ExecutionSession::dump(raw_ostream &OS) {
  runSessionLocked([this, &OS]() {
    for (auto &JD : JDs)
      JD->dump(OS);
  });
}

#ifdef EXPENSIVE_CHECKS
bool ExecutionSession::verifySessionState(Twine Phase) {
  return runSessionLocked([&]() {
    bool AllOk = true;

    for (auto &JD : JDs) {

      auto LogFailure = [&]() -> raw_fd_ostream & {
        auto &Stream = errs();
        if (AllOk)
          Stream << "ERROR: Bad ExecutionSession state detected " << Phase
                 << "\n";
        Stream << "  In JITDylib " << JD->getName() << ", ";
        AllOk = false;
        return Stream;
      };

      if (JD->State != JITDylib::Open) {
        LogFailure()
            << "state is not Open, but JD is in ExecutionSession list.";
      }

      // Check symbol table.
      // 1. If the entry state isn't resolved then check that no address has
      //    been set.
      // 2. Check that if the hasMaterializerAttached flag is set then there is
      //    an UnmaterializedInfo entry, and vice-versa.
      for (auto &[Sym, Entry] : JD->Symbols) {
        // Check that unresolved symbols have null addresses.
        if (Entry.getState() < SymbolState::Resolved) {
          if (Entry.getAddress()) {
            LogFailure() << "symbol " << Sym << " has state "
                         << Entry.getState()
                         << " (not-yet-resolved) but non-null address "
                         << Entry.getAddress() << ".\n";
          }
        }

        // Check that the hasMaterializerAttached flag is correct.
        auto UMIItr = JD->UnmaterializedInfos.find(Sym);
        if (Entry.hasMaterializerAttached()) {
          if (UMIItr == JD->UnmaterializedInfos.end()) {
            LogFailure() << "symbol " << Sym
                         << " entry claims materializer attached, but "
                            "UnmaterializedInfos has no corresponding entry.\n";
          }
        } else if (UMIItr != JD->UnmaterializedInfos.end()) {
          LogFailure()
              << "symbol " << Sym
              << " entry claims no materializer attached, but "
                 "UnmaterializedInfos has an unexpected entry for it.\n";
        }
      }

      // Check that every UnmaterializedInfo entry has a corresponding entry
      // in the Symbols table.
      for (auto &[Sym, UMI] : JD->UnmaterializedInfos) {
        auto SymItr = JD->Symbols.find(Sym);
        if (SymItr == JD->Symbols.end()) {
          LogFailure()
              << "symbol " << Sym
              << " has UnmaterializedInfos entry, but no Symbols entry.\n";
        }
      }

      // Check consistency of the MaterializingInfos table.
      for (auto &[Sym, MII] : JD->MaterializingInfos) {

        auto SymItr = JD->Symbols.find(Sym);
        if (SymItr == JD->Symbols.end()) {
          // If there's no Symbols entry for this MaterializingInfos entry then
          // report that.
          LogFailure()
              << "symbol " << Sym
              << " has MaterializingInfos entry, but no Symbols entry.\n";
        } else {
          // Otherwise check consistency between Symbols and MaterializingInfos.

          // Ready symbols should not have MaterializingInfos.
          if (SymItr->second.getState() == SymbolState::Ready) {
            LogFailure()
                << "symbol " << Sym
                << " is in Ready state, should not have MaterializingInfo.\n";
          }

          // Pending queries should be for subsequent states.
          auto CurState = static_cast<SymbolState>(
              static_cast<std::underlying_type_t<SymbolState>>(
                  SymItr->second.getState()) + 1);
          for (auto &Q : MII.PendingQueries) {
            if (Q->getRequiredState() != CurState) {
              if (Q->getRequiredState() > CurState)
                CurState = Q->getRequiredState();
              else
                LogFailure() << "symbol " << Sym
                             << " has stale or misordered queries.\n";
            }
          }
        }
      }
    }

    return AllOk;
  });
}
#endif // EXPENSIVE_CHECKS

void ExecutionSession::dispatchOutstandingMUs() {
  LLVM_DEBUG(dbgs() << "Dispatching MaterializationUnits...\n");
  while (true) {
    std::optional<std::pair<std::unique_ptr<MaterializationUnit>,
                            std::unique_ptr<MaterializationResponsibility>>>
        JMU;

    {
      std::lock_guard<std::recursive_mutex> Lock(OutstandingMUsMutex);
      if (!OutstandingMUs.empty()) {
        JMU.emplace(std::move(OutstandingMUs.back()));
        OutstandingMUs.pop_back();
      }
    }

    if (!JMU)
      break;

    assert(JMU->first && "No MU?");
    LLVM_DEBUG(dbgs() << "  Dispatching \"" << JMU->first->getName() << "\"\n");
    dispatchTask(std::make_unique<MaterializationTask>(std::move(JMU->first),
                                                       std::move(JMU->second)));
  }
  LLVM_DEBUG(dbgs() << "Done dispatching MaterializationUnits.\n");
}

Error ExecutionSession::removeResourceTracker(ResourceTracker &RT) {
  LLVM_DEBUG({
    dbgs() << "In " << RT.getJITDylib().getName() << " removing tracker "
           << formatv("{0:x}", RT.getKeyUnsafe()) << "\n";
  });
  std::vector<ResourceManager *> CurrentResourceManagers;

  JITDylib::RemoveTrackerResult R;

  runSessionLocked([&] {
    CurrentResourceManagers = ResourceManagers;
    RT.makeDefunct();
    R = RT.getJITDylib().IL_removeTracker(RT);
  });

  // Release any defunct MaterializationUnits.
  R.DefunctMUs.clear();

  Error Err = Error::success();

  auto &JD = RT.getJITDylib();
  for (auto *L : reverse(CurrentResourceManagers))
    Err = joinErrors(std::move(Err),
                     L->handleRemoveResources(JD, RT.getKeyUnsafe()));

  for (auto &Q : R.QueriesToFail)
    Q->handleFailed(make_error<FailedToMaterialize>(getSymbolStringPool(),
                                                    R.FailedSymbols));

  return Err;
}

void ExecutionSession::transferResourceTracker(ResourceTracker &DstRT,
                                               ResourceTracker &SrcRT) {
  LLVM_DEBUG({
    dbgs() << "In " << SrcRT.getJITDylib().getName()
           << " transfering resources from tracker "
           << formatv("{0:x}", SrcRT.getKeyUnsafe()) << " to tracker "
           << formatv("{0:x}", DstRT.getKeyUnsafe()) << "\n";
  });

  // No-op transfers are allowed and do not invalidate the source.
  if (&DstRT == &SrcRT)
    return;

  assert(&DstRT.getJITDylib() == &SrcRT.getJITDylib() &&
         "Can't transfer resources between JITDylibs");
  runSessionLocked([&]() {
    SrcRT.makeDefunct();
    auto &JD = DstRT.getJITDylib();
    JD.transferTracker(DstRT, SrcRT);
    for (auto *L : reverse(ResourceManagers))
      L->handleTransferResources(JD, DstRT.getKeyUnsafe(),
                                 SrcRT.getKeyUnsafe());
  });
}

void ExecutionSession::destroyResourceTracker(ResourceTracker &RT) {
  runSessionLocked([&]() {
    LLVM_DEBUG({
      dbgs() << "In " << RT.getJITDylib().getName() << " destroying tracker "
             << formatv("{0:x}", RT.getKeyUnsafe()) << "\n";
    });
    if (!RT.isDefunct())
      transferResourceTracker(*RT.getJITDylib().getDefaultResourceTracker(),
                              RT);
  });
}

Error ExecutionSession::IL_updateCandidatesFor(
    JITDylib &JD, JITDylibLookupFlags JDLookupFlags,
    SymbolLookupSet &Candidates, SymbolLookupSet *NonCandidates) {
  return Candidates.forEachWithRemoval(
      [&](const SymbolStringPtr &Name,
          SymbolLookupFlags SymLookupFlags) -> Expected<bool> {
        /// Search for the symbol. If not found then continue without
        /// removal.
        auto SymI = JD.Symbols.find(Name);
        if (SymI == JD.Symbols.end())
          return false;

        // If this is a non-exported symbol and we're matching exported
        // symbols only then remove this symbol from the candidates list.
        //
        // If we're tracking non-candidates then add this to the non-candidate
        // list.
        if (!SymI->second.getFlags().isExported() &&
            JDLookupFlags == JITDylibLookupFlags::MatchExportedSymbolsOnly) {
          if (NonCandidates)
            NonCandidates->add(Name, SymLookupFlags);
          return true;
        }

        // If we match against a materialization-side-effects only symbol
        // then make sure it is weakly-referenced. Otherwise bail out with
        // an error.
        // FIXME: Use a "materialization-side-effects-only symbols must be
        // weakly referenced" specific error here to reduce confusion.
        if (SymI->second.getFlags().hasMaterializationSideEffectsOnly() &&
            SymLookupFlags != SymbolLookupFlags::WeaklyReferencedSymbol)
          return make_error<SymbolsNotFound>(getSymbolStringPool(),
                                             SymbolNameVector({Name}));

        // If we matched against this symbol but it is in the error state
        // then bail out and treat it as a failure to materialize.
        if (SymI->second.getFlags().hasError()) {
          auto FailedSymbolsMap = std::make_shared<SymbolDependenceMap>();
          (*FailedSymbolsMap)[&JD] = {Name};
          return make_error<FailedToMaterialize>(getSymbolStringPool(),
                                                 std::move(FailedSymbolsMap));
        }

        // Otherwise this is a match. Remove it from the candidate set.
        return true;
      });
}

void ExecutionSession::OL_resumeLookupAfterGeneration(
    InProgressLookupState &IPLS) {

  assert(IPLS.GenState != InProgressLookupState::NotInGenerator &&
         "Should not be called for not-in-generator lookups");
  IPLS.GenState = InProgressLookupState::NotInGenerator;

  LookupState LS;

  if (auto DG = IPLS.CurDefGeneratorStack.back().lock()) {
    IPLS.CurDefGeneratorStack.pop_back();
    std::lock_guard<std::mutex> Lock(DG->M);

    // If there are no pending lookups then mark the generator as free and
    // return.
    if (DG->PendingLookups.empty()) {
      DG->InUse = false;
      return;
    }

    // Otherwise resume the next lookup.
    LS = std::move(DG->PendingLookups.front());
    DG->PendingLookups.pop_front();
  }

  if (LS.IPLS) {
    LS.IPLS->GenState = InProgressLookupState::ResumedForGenerator;
    dispatchTask(std::make_unique<LookupTask>(std::move(LS)));
  }
}

void ExecutionSession::OL_applyQueryPhase1(
    std::unique_ptr<InProgressLookupState> IPLS, Error Err) {

  LLVM_DEBUG({
    dbgs() << "Entering OL_applyQueryPhase1:\n"
           << "  Lookup kind: " << IPLS->K << "\n"
           << "  Search order: " << IPLS->SearchOrder
           << ", Current index = " << IPLS->CurSearchOrderIndex
           << (IPLS->NewJITDylib ? " (entering new JITDylib)" : "") << "\n"
           << "  Lookup set: " << IPLS->LookupSet << "\n"
           << "  Definition generator candidates: "
           << IPLS->DefGeneratorCandidates << "\n"
           << "  Definition generator non-candidates: "
           << IPLS->DefGeneratorNonCandidates << "\n";
  });

  if (IPLS->GenState == InProgressLookupState::InGenerator)
    OL_resumeLookupAfterGeneration(*IPLS);

  assert(IPLS->GenState != InProgressLookupState::InGenerator &&
         "Lookup should not be in InGenerator state here");

  // FIXME: We should attach the query as we go: This provides a result in a
  // single pass in the common case where all symbols have already reached the
  // required state. The query could be detached again in the 'fail' method on
  // IPLS. Phase 2 would be reduced to collecting and dispatching the MUs.

  while (IPLS->CurSearchOrderIndex != IPLS->SearchOrder.size()) {

    // If we've been handed an error or received one back from a generator then
    // fail the query. We don't need to unlink: At this stage the query hasn't
    // actually been lodged.
    if (Err)
      return IPLS->fail(std::move(Err));

    // Get the next JITDylib and lookup flags.
    auto &KV = IPLS->SearchOrder[IPLS->CurSearchOrderIndex];
    auto &JD = *KV.first;
    auto JDLookupFlags = KV.second;

    LLVM_DEBUG({
      dbgs() << "Visiting \"" << JD.getName() << "\" (" << JDLookupFlags
             << ") with lookup set " << IPLS->LookupSet << ":\n";
    });

    // If we've just reached a new JITDylib then perform some setup.
    if (IPLS->NewJITDylib) {
      // Add any non-candidates from the last JITDylib (if any) back on to the
      // list of definition candidates for this JITDylib, reset definition
      // non-candidates to the empty set.
      SymbolLookupSet Tmp;
      std::swap(IPLS->DefGeneratorNonCandidates, Tmp);
      IPLS->DefGeneratorCandidates.append(std::move(Tmp));

      LLVM_DEBUG({
        dbgs() << "  First time visiting " << JD.getName()
               << ", resetting candidate sets and building generator stack\n";
      });

      // Build the definition generator stack for this JITDylib.
      runSessionLocked([&] {
        IPLS->CurDefGeneratorStack.reserve(JD.DefGenerators.size());
        llvm::append_range(IPLS->CurDefGeneratorStack,
                           reverse(JD.DefGenerators));
      });

      // Flag that we've done our initialization.
      IPLS->NewJITDylib = false;
    }

    // Remove any generation candidates that are already defined (and match) in
    // this JITDylib.
    runSessionLocked([&] {
      // Update the list of candidates (and non-candidates) for definition
      // generation.
      LLVM_DEBUG(dbgs() << "  Updating candidate set...\n");
      Err = IL_updateCandidatesFor(
          JD, JDLookupFlags, IPLS->DefGeneratorCandidates,
          JD.DefGenerators.empty() ? nullptr
                                   : &IPLS->DefGeneratorNonCandidates);
      LLVM_DEBUG({
        dbgs() << "    Remaining candidates = " << IPLS->DefGeneratorCandidates
               << "\n";
      });

      // If this lookup was resumed after auto-suspension but all candidates
      // have already been generated (by some previous call to the generator)
      // treat the lookup as if it had completed generation.
      if (IPLS->GenState == InProgressLookupState::ResumedForGenerator &&
          IPLS->DefGeneratorCandidates.empty())
        OL_resumeLookupAfterGeneration(*IPLS);
    });

    // If we encountered an error while filtering generation candidates then
    // bail out.
    if (Err)
      return IPLS->fail(std::move(Err));

    /// Apply any definition generators on the stack.
    LLVM_DEBUG({
      if (IPLS->CurDefGeneratorStack.empty())
        LLVM_DEBUG(dbgs() << "  No generators to run for this JITDylib.\n");
      else if (IPLS->DefGeneratorCandidates.empty())
        LLVM_DEBUG(dbgs() << "  No candidates to generate.\n");
      else
        dbgs() << "  Running " << IPLS->CurDefGeneratorStack.size()
               << " remaining generators for "
               << IPLS->DefGeneratorCandidates.size() << " candidates\n";
    });
    while (!IPLS->CurDefGeneratorStack.empty() &&
           !IPLS->DefGeneratorCandidates.empty()) {
      auto DG = IPLS->CurDefGeneratorStack.back().lock();

      if (!DG)
        return IPLS->fail(make_error<StringError>(
            "DefinitionGenerator removed while lookup in progress",
            inconvertibleErrorCode()));

      // At this point the lookup is in either the NotInGenerator state, or in
      // the ResumedForGenerator state.
      // If this lookup is in the NotInGenerator state then check whether the
      // generator is in use. If the generator is not in use then move the
      // lookup to the InGenerator state and continue. If the generator is
      // already in use then just add this lookup to the pending lookups list
      // and bail out.
      // If this lookup is in the ResumedForGenerator state then just move it
      // to InGenerator and continue.
      if (IPLS->GenState == InProgressLookupState::NotInGenerator) {
        std::lock_guard<std::mutex> Lock(DG->M);
        if (DG->InUse) {
          DG->PendingLookups.push_back(std::move(IPLS));
          return;
        }
        DG->InUse = true;
      }

      IPLS->GenState = InProgressLookupState::InGenerator;

      auto K = IPLS->K;
      auto &LookupSet = IPLS->DefGeneratorCandidates;

      // Run the generator. If the generator takes ownership of QA then this
      // will break the loop.
      {
        LLVM_DEBUG(dbgs() << "  Attempting to generate " << LookupSet << "\n");
        LookupState LS(std::move(IPLS));
        Err = DG->tryToGenerate(LS, K, JD, JDLookupFlags, LookupSet);
        IPLS = std::move(LS.IPLS);
      }

      // If the lookup returned then pop the generator stack and unblock the
      // next lookup on this generator (if any).
      if (IPLS)
        OL_resumeLookupAfterGeneration(*IPLS);

      // If there was an error then fail the query.
      if (Err) {
        LLVM_DEBUG({
          dbgs() << "  Error attempting to generate " << LookupSet << "\n";
        });
        assert(IPLS && "LS cannot be retained if error is returned");
        return IPLS->fail(std::move(Err));
      }

      // Otherwise if QA was captured then break the loop.
      if (!IPLS) {
        LLVM_DEBUG(
            { dbgs() << "  LookupState captured. Exiting phase1 for now.\n"; });
        return;
      }

      // Otherwise if we're continuing around the loop then update candidates
      // for the next round.
      runSessionLocked([&] {
        LLVM_DEBUG(dbgs() << "  Updating candidate set post-generation\n");
        Err = IL_updateCandidatesFor(
            JD, JDLookupFlags, IPLS->DefGeneratorCandidates,
            JD.DefGenerators.empty() ? nullptr
                                     : &IPLS->DefGeneratorNonCandidates);
      });

      // If updating candidates failed then fail the query.
      if (Err) {
        LLVM_DEBUG(dbgs() << "  Error encountered while updating candidates\n");
        return IPLS->fail(std::move(Err));
      }
    }

    if (IPLS->DefGeneratorCandidates.empty() &&
        IPLS->DefGeneratorNonCandidates.empty()) {
      // Early out if there are no remaining symbols.
      LLVM_DEBUG(dbgs() << "All symbols matched.\n");
      IPLS->CurSearchOrderIndex = IPLS->SearchOrder.size();
      break;
    } else {
      // If we get here then we've moved on to the next JITDylib with candidates
      // remaining.
      LLVM_DEBUG(dbgs() << "Phase 1 moving to next JITDylib.\n");
      ++IPLS->CurSearchOrderIndex;
      IPLS->NewJITDylib = true;
    }
  }

  // Remove any weakly referenced candidates that could not be found/generated.
  IPLS->DefGeneratorCandidates.remove_if(
      [](const SymbolStringPtr &Name, SymbolLookupFlags SymLookupFlags) {
        return SymLookupFlags == SymbolLookupFlags::WeaklyReferencedSymbol;
      });

  // If we get here then we've finished searching all JITDylibs.
  // If we matched all symbols then move to phase 2, otherwise fail the query
  // with a SymbolsNotFound error.
  if (IPLS->DefGeneratorCandidates.empty()) {
    LLVM_DEBUG(dbgs() << "Phase 1 succeeded.\n");
    IPLS->complete(std::move(IPLS));
  } else {
    LLVM_DEBUG(dbgs() << "Phase 1 failed with unresolved symbols.\n");
    IPLS->fail(make_error<SymbolsNotFound>(
        getSymbolStringPool(), IPLS->DefGeneratorCandidates.getSymbolNames()));
  }
}

void ExecutionSession::OL_completeLookup(
    std::unique_ptr<InProgressLookupState> IPLS,
    std::shared_ptr<AsynchronousSymbolQuery> Q,
    RegisterDependenciesFunction RegisterDependencies) {

  LLVM_DEBUG({
    dbgs() << "Entering OL_completeLookup:\n"
           << "  Lookup kind: " << IPLS->K << "\n"
           << "  Search order: " << IPLS->SearchOrder
           << ", Current index = " << IPLS->CurSearchOrderIndex
           << (IPLS->NewJITDylib ? " (entering new JITDylib)" : "") << "\n"
           << "  Lookup set: " << IPLS->LookupSet << "\n"
           << "  Definition generator candidates: "
           << IPLS->DefGeneratorCandidates << "\n"
           << "  Definition generator non-candidates: "
           << IPLS->DefGeneratorNonCandidates << "\n";
  });

  bool QueryComplete = false;
  DenseMap<JITDylib *, JITDylib::UnmaterializedInfosList> CollectedUMIs;

  auto LodgingErr = runSessionLocked([&]() -> Error {
    for (auto &KV : IPLS->SearchOrder) {
      auto &JD = *KV.first;
      auto JDLookupFlags = KV.second;
      LLVM_DEBUG({
        dbgs() << "Visiting \"" << JD.getName() << "\" (" << JDLookupFlags
               << ") with lookup set " << IPLS->LookupSet << ":\n";
      });

      auto Err = IPLS->LookupSet.forEachWithRemoval(
          [&](const SymbolStringPtr &Name,
              SymbolLookupFlags SymLookupFlags) -> Expected<bool> {
            LLVM_DEBUG({
              dbgs() << "  Attempting to match \"" << Name << "\" ("
                     << SymLookupFlags << ")... ";
            });

            /// Search for the symbol. If not found then continue without
            /// removal.
            auto SymI = JD.Symbols.find(Name);
            if (SymI == JD.Symbols.end()) {
              LLVM_DEBUG(dbgs() << "skipping: not present\n");
              return false;
            }

            // If this is a non-exported symbol and we're matching exported
            // symbols only then skip this symbol without removal.
            if (!SymI->second.getFlags().isExported() &&
                JDLookupFlags ==
                    JITDylibLookupFlags::MatchExportedSymbolsOnly) {
              LLVM_DEBUG(dbgs() << "skipping: not exported\n");
              return false;
            }

            // If we match against a materialization-side-effects only symbol
            // then make sure it is weakly-referenced. Otherwise bail out with
            // an error.
            // FIXME: Use a "materialization-side-effects-only symbols must be
            // weakly referenced" specific error here to reduce confusion.
            if (SymI->second.getFlags().hasMaterializationSideEffectsOnly() &&
                SymLookupFlags != SymbolLookupFlags::WeaklyReferencedSymbol) {
              LLVM_DEBUG({
                dbgs() << "error: "
                          "required, but symbol is has-side-effects-only\n";
              });
              return make_error<SymbolsNotFound>(getSymbolStringPool(),
                                                 SymbolNameVector({Name}));
            }

            // If we matched against this symbol but it is in the error state
            // then bail out and treat it as a failure to materialize.
            if (SymI->second.getFlags().hasError()) {
              LLVM_DEBUG(dbgs() << "error: symbol is in error state\n");
              auto FailedSymbolsMap = std::make_shared<SymbolDependenceMap>();
              (*FailedSymbolsMap)[&JD] = {Name};
              return make_error<FailedToMaterialize>(
                  getSymbolStringPool(), std::move(FailedSymbolsMap));
            }

            // Otherwise this is a match.

            // If this symbol is already in the required state then notify the
            // query, remove the symbol and continue.
            if (SymI->second.getState() >= Q->getRequiredState()) {
              LLVM_DEBUG(dbgs()
                         << "matched, symbol already in required state\n");
              Q->notifySymbolMetRequiredState(Name, SymI->second.getSymbol());

              // If this symbol is in anything other than the Ready state then
              // we need to track the dependence.
              if (SymI->second.getState() != SymbolState::Ready)
                Q->addQueryDependence(JD, Name);

              return true;
            }

            // Otherwise this symbol does not yet meet the required state. Check
            // whether it has a materializer attached, and if so prepare to run
            // it.
            if (SymI->second.hasMaterializerAttached()) {
              assert(SymI->second.getAddress() == ExecutorAddr() &&
                     "Symbol not resolved but already has address?");
              auto UMII = JD.UnmaterializedInfos.find(Name);
              assert(UMII != JD.UnmaterializedInfos.end() &&
                     "Lazy symbol should have UnmaterializedInfo");

              auto UMI = UMII->second;
              assert(UMI->MU && "Materializer should not be null");
              assert(UMI->RT && "Tracker should not be null");
              LLVM_DEBUG({
                dbgs() << "matched, preparing to dispatch MU@" << UMI->MU.get()
                       << " (" << UMI->MU->getName() << ")\n";
              });

              // Move all symbols associated with this MaterializationUnit into
              // materializing state.
              for (auto &KV : UMI->MU->getSymbols()) {
                auto SymK = JD.Symbols.find(KV.first);
                assert(SymK != JD.Symbols.end() &&
                       "No entry for symbol covered by MaterializationUnit");
                SymK->second.setMaterializerAttached(false);
                SymK->second.setState(SymbolState::Materializing);
                JD.UnmaterializedInfos.erase(KV.first);
              }

              // Add MU to the list of MaterializationUnits to be materialized.
              CollectedUMIs[&JD].push_back(std::move(UMI));
            } else
              LLVM_DEBUG(dbgs() << "matched, registering query");

            // Add the query to the PendingQueries list and continue, deleting
            // the element from the lookup set.
            assert(SymI->second.getState() != SymbolState::NeverSearched &&
                   SymI->second.getState() != SymbolState::Ready &&
                   "By this line the symbol should be materializing");
            auto &MI = JD.MaterializingInfos[Name];
            MI.addQuery(Q);
            Q->addQueryDependence(JD, Name);

            return true;
          });

      JD.shrinkMaterializationInfoMemory();

      // Handle failure.
      if (Err) {

        LLVM_DEBUG({
          dbgs() << "Lookup failed. Detaching query and replacing MUs.\n";
        });

        // Detach the query.
        Q->detach();

        // Replace the MUs.
        for (auto &KV : CollectedUMIs) {
          auto &JD = *KV.first;
          for (auto &UMI : KV.second)
            for (auto &KV2 : UMI->MU->getSymbols()) {
              assert(!JD.UnmaterializedInfos.count(KV2.first) &&
                     "Unexpected materializer in map");
              auto SymI = JD.Symbols.find(KV2.first);
              assert(SymI != JD.Symbols.end() && "Missing symbol entry");
              assert(SymI->second.getState() == SymbolState::Materializing &&
                     "Can not replace symbol that is not materializing");
              assert(!SymI->second.hasMaterializerAttached() &&
                     "MaterializerAttached flag should not be set");
              SymI->second.setMaterializerAttached(true);
              JD.UnmaterializedInfos[KV2.first] = UMI;
            }
        }

        return Err;
      }
    }

    LLVM_DEBUG(dbgs() << "Stripping unmatched weakly-referenced symbols\n");
    IPLS->LookupSet.forEachWithRemoval(
        [&](const SymbolStringPtr &Name, SymbolLookupFlags SymLookupFlags) {
          if (SymLookupFlags == SymbolLookupFlags::WeaklyReferencedSymbol) {
            Q->dropSymbol(Name);
            return true;
          } else
            return false;
        });

    if (!IPLS->LookupSet.empty()) {
      LLVM_DEBUG(dbgs() << "Failing due to unresolved symbols\n");
      return make_error<SymbolsNotFound>(getSymbolStringPool(),
                                         IPLS->LookupSet.getSymbolNames());
    }

    // Record whether the query completed.
    QueryComplete = Q->isComplete();

    LLVM_DEBUG({
      dbgs() << "Query successfully "
             << (QueryComplete ? "completed" : "lodged") << "\n";
    });

    // Move the collected MUs to the OutstandingMUs list.
    if (!CollectedUMIs.empty()) {
      std::lock_guard<std::recursive_mutex> Lock(OutstandingMUsMutex);

      LLVM_DEBUG(dbgs() << "Adding MUs to dispatch:\n");
      for (auto &KV : CollectedUMIs) {
        LLVM_DEBUG({
          auto &JD = *KV.first;
          dbgs() << "  For " << JD.getName() << ": Adding " << KV.second.size()
                 << " MUs.\n";
        });
        for (auto &UMI : KV.second) {
          auto MR = createMaterializationResponsibility(
              *UMI->RT, std::move(UMI->MU->SymbolFlags),
              std::move(UMI->MU->InitSymbol));
          OutstandingMUs.push_back(
              std::make_pair(std::move(UMI->MU), std::move(MR)));
        }
      }
    } else
      LLVM_DEBUG(dbgs() << "No MUs to dispatch.\n");

    if (RegisterDependencies && !Q->QueryRegistrations.empty()) {
      LLVM_DEBUG(dbgs() << "Registering dependencies\n");
      RegisterDependencies(Q->QueryRegistrations);
    } else
      LLVM_DEBUG(dbgs() << "No dependencies to register\n");

    return Error::success();
  });

  if (LodgingErr) {
    LLVM_DEBUG(dbgs() << "Failing query\n");
    Q->detach();
    Q->handleFailed(std::move(LodgingErr));
    return;
  }

  if (QueryComplete) {
    LLVM_DEBUG(dbgs() << "Completing query\n");
    Q->handleComplete(*this);
  }

  dispatchOutstandingMUs();
}

void ExecutionSession::OL_completeLookupFlags(
    std::unique_ptr<InProgressLookupState> IPLS,
    unique_function<void(Expected<SymbolFlagsMap>)> OnComplete) {

  auto Result = runSessionLocked([&]() -> Expected<SymbolFlagsMap> {
    LLVM_DEBUG({
      dbgs() << "Entering OL_completeLookupFlags:\n"
             << "  Lookup kind: " << IPLS->K << "\n"
             << "  Search order: " << IPLS->SearchOrder
             << ", Current index = " << IPLS->CurSearchOrderIndex
             << (IPLS->NewJITDylib ? " (entering new JITDylib)" : "") << "\n"
             << "  Lookup set: " << IPLS->LookupSet << "\n"
             << "  Definition generator candidates: "
             << IPLS->DefGeneratorCandidates << "\n"
             << "  Definition generator non-candidates: "
             << IPLS->DefGeneratorNonCandidates << "\n";
    });

    SymbolFlagsMap Result;

    // Attempt to find flags for each symbol.
    for (auto &KV : IPLS->SearchOrder) {
      auto &JD = *KV.first;
      auto JDLookupFlags = KV.second;
      LLVM_DEBUG({
        dbgs() << "Visiting \"" << JD.getName() << "\" (" << JDLookupFlags
               << ") with lookup set " << IPLS->LookupSet << ":\n";
      });

      IPLS->LookupSet.forEachWithRemoval([&](const SymbolStringPtr &Name,
                                             SymbolLookupFlags SymLookupFlags) {
        LLVM_DEBUG({
          dbgs() << "  Attempting to match \"" << Name << "\" ("
                 << SymLookupFlags << ")... ";
        });

        // Search for the symbol. If not found then continue without removing
        // from the lookup set.
        auto SymI = JD.Symbols.find(Name);
        if (SymI == JD.Symbols.end()) {
          LLVM_DEBUG(dbgs() << "skipping: not present\n");
          return false;
        }

        // If this is a non-exported symbol then it doesn't match. Skip it.
        if (!SymI->second.getFlags().isExported() &&
            JDLookupFlags == JITDylibLookupFlags::MatchExportedSymbolsOnly) {
          LLVM_DEBUG(dbgs() << "skipping: not exported\n");
          return false;
        }

        LLVM_DEBUG({
          dbgs() << "matched, \"" << Name << "\" -> " << SymI->second.getFlags()
                 << "\n";
        });
        Result[Name] = SymI->second.getFlags();
        return true;
      });
    }

    // Remove any weakly referenced symbols that haven't been resolved.
    IPLS->LookupSet.remove_if(
        [](const SymbolStringPtr &Name, SymbolLookupFlags SymLookupFlags) {
          return SymLookupFlags == SymbolLookupFlags::WeaklyReferencedSymbol;
        });

    if (!IPLS->LookupSet.empty()) {
      LLVM_DEBUG(dbgs() << "Failing due to unresolved symbols\n");
      return make_error<SymbolsNotFound>(getSymbolStringPool(),
                                         IPLS->LookupSet.getSymbolNames());
    }

    LLVM_DEBUG(dbgs() << "Succeded, result = " << Result << "\n");
    return Result;
  });

  // Run the callback on the result.
  LLVM_DEBUG(dbgs() << "Sending result to handler.\n");
  OnComplete(std::move(Result));
}

void ExecutionSession::OL_destroyMaterializationResponsibility(
    MaterializationResponsibility &MR) {

  assert(MR.SymbolFlags.empty() &&
         "All symbols should have been explicitly materialized or failed");
  MR.JD.unlinkMaterializationResponsibility(MR);
}

SymbolNameSet ExecutionSession::OL_getRequestedSymbols(
    const MaterializationResponsibility &MR) {
  return MR.JD.getRequestedSymbols(MR.SymbolFlags);
}

Error ExecutionSession::OL_notifyResolved(MaterializationResponsibility &MR,
                                          const SymbolMap &Symbols) {
  LLVM_DEBUG({
    dbgs() << "In " << MR.JD.getName() << " resolving " << Symbols << "\n";
  });
#ifndef NDEBUG
  for (auto &KV : Symbols) {
    auto I = MR.SymbolFlags.find(KV.first);
    assert(I != MR.SymbolFlags.end() &&
           "Resolving symbol outside this responsibility set");
    assert(!I->second.hasMaterializationSideEffectsOnly() &&
           "Can't resolve materialization-side-effects-only symbol");
    if (I->second & JITSymbolFlags::Common) {
      auto WeakOrCommon = JITSymbolFlags::Weak | JITSymbolFlags::Common;
      assert((KV.second.getFlags() & WeakOrCommon) &&
             "Common symbols must be resolved as common or weak");
      assert((KV.second.getFlags() & ~WeakOrCommon) ==
                 (I->second & ~JITSymbolFlags::Common) &&
             "Resolving symbol with incorrect flags");
    } else
      assert(KV.second.getFlags() == I->second &&
             "Resolving symbol with incorrect flags");
  }
#endif

  return MR.JD.resolve(MR, Symbols);
}

WaitingOnGraph::ExternalState
ExecutionSession::IL_getSymbolState(JITDylib *JD,
                                    NonOwningSymbolStringPtr Name) {
  if (JD->State != JITDylib::Open)
    return WaitingOnGraph::ExternalState::Failed;

  auto I = JD->Symbols.find_as(Name);

  // FIXME: Can we eliminate this possibility if we support query binding?
  if (I == JD->Symbols.end())
    return WaitingOnGraph::ExternalState::Failed;

  if (I->second.getFlags().hasError())
    return WaitingOnGraph::ExternalState::Failed;

  if (I->second.getState() == SymbolState::Ready)
    return WaitingOnGraph::ExternalState::Ready;

  return WaitingOnGraph::ExternalState::None;
}

template <typename UpdateSymbolFn, typename UpdateQueryFn>
void ExecutionSession::IL_collectQueries(
    JITDylib::AsynchronousSymbolQuerySet &Qs,
    WaitingOnGraph::ContainerElementsMap &QualifiedSymbols,
    UpdateSymbolFn &&UpdateSymbol, UpdateQueryFn &&UpdateQuery) {

  for (auto &[JD, Symbols] : QualifiedSymbols) {
    // IL_emit and JITDylib removal are synchronized by the session lock.
    // Since JITDylib removal removes any contained nodes from the
    // WaitingOnGraph, we should be able to assert that all nodes in the
    // WaitingOnGraph have not been removed.
    assert(JD->State == JITDylib::Open &&
           "WaitingOnGraph includes definition in defunct JITDylib");
    for (auto &Symbol : Symbols) {
      // Update symbol table.
      auto I = JD->Symbols.find_as(Symbol);
      assert(I != JD->Symbols.end() &&
             "Failed Symbol missing from JD symbol table");
      auto &Entry = I->second;
      UpdateSymbol(Entry);

      // Collect queries.
      auto J = JD->MaterializingInfos.find_as(Symbol);
      if (J != JD->MaterializingInfos.end()) {
        for (auto &Q : J->second.takeAllPendingQueries()) {
          UpdateQuery(*Q, *JD, Symbol, Entry);
          Qs.insert(std::move(Q));
        }
        JD->MaterializingInfos.erase(J);
      }
    }
  }
}

Expected<ExecutionSession::EmitQueries>
ExecutionSession::IL_emit(MaterializationResponsibility &MR,
                          WaitingOnGraph::SimplifyResult SR) {

  if (MR.RT->isDefunct())
    return make_error<ResourceTrackerDefunct>(MR.RT);

  auto &TargetJD = MR.getTargetJITDylib();
  if (TargetJD.State != JITDylib::Open)
    return make_error<StringError>("JITDylib " + TargetJD.getName() +
                                       " is defunct",
                                   inconvertibleErrorCode());

#ifdef EXPENSIVE_CHECKS
  verifySessionState("entering ExecutionSession::IL_emit");
#endif

  auto ER = G.emit(std::move(SR),
                   [this](JITDylib *JD, NonOwningSymbolStringPtr Name) {
                     return IL_getSymbolState(JD, Name);
                   });

  EmitQueries EQ;

  // Handle failed queries.
  for (auto &SN : ER.Failed)
    IL_collectQueries(
        EQ.Failed, SN->defs(),
        [](JITDylib::SymbolTableEntry &E) {
          E.setFlags(E.getFlags() = JITSymbolFlags::HasError);
        },
        [&](AsynchronousSymbolQuery &Q, JITDylib &JD,
            NonOwningSymbolStringPtr Name, JITDylib::SymbolTableEntry &E) {
          auto &FS = EQ.FailedSymsForQuery[&Q];
          if (!FS)
            FS = std::make_shared<SymbolDependenceMap>();
          (*FS)[&JD].insert(SymbolStringPtr(Name));
        });

  for (auto &FQ : EQ.Failed)
    FQ->detach();

  for (auto &SN : ER.Ready)
    IL_collectQueries(
        EQ.Completed, SN->defs(),
        [](JITDylib::SymbolTableEntry &E) { E.setState(SymbolState::Ready); },
        [](AsynchronousSymbolQuery &Q, JITDylib &JD,
           NonOwningSymbolStringPtr Name, JITDylib::SymbolTableEntry &E) {
          Q.notifySymbolMetRequiredState(SymbolStringPtr(Name), E.getSymbol());
        });

  // std::erase_if is not available in C++17, and llvm::erase_if does not work
  // here.
  for (auto it = EQ.Completed.begin(), end = EQ.Completed.end(); it != end;) {
    if ((*it)->isComplete()) {
      ++it;
    } else {
      it = EQ.Completed.erase(it);
    }
  }

#ifdef EXPENSIVE_CHECKS
  verifySessionState("exiting ExecutionSession::IL_emit");
#endif

  return std::move(EQ);
}

Error ExecutionSession::OL_notifyEmitted(
    MaterializationResponsibility &MR,
    ArrayRef<SymbolDependenceGroup> DepGroups) {
  LLVM_DEBUG({
    dbgs() << "In " << MR.JD.getName() << " emitting " << MR.SymbolFlags
           << "\n";
    if (!DepGroups.empty()) {
      dbgs() << "  Initial dependencies:\n";
      for (auto &SDG : DepGroups) {
        dbgs() << "    Symbols: " << SDG.Symbols
               << ", Dependencies: " << SDG.Dependencies << "\n";
      }
    }
  });

#ifndef NDEBUG
  SymbolNameSet Visited;
  for (auto &DG : DepGroups) {
    for (auto &Sym : DG.Symbols) {
      assert(MR.SymbolFlags.count(Sym) &&
             "DG contains dependence for symbol outside this MR");
      assert(Visited.insert(Sym).second &&
             "DG contains duplicate entries for Name");
    }
  }
#endif // NDEBUG

  std::vector<std::unique_ptr<WaitingOnGraph::SuperNode>> SNs;
  WaitingOnGraph::ContainerElementsMap Residual;
  {
    auto &JDResidual = Residual[&MR.getTargetJITDylib()];
    for (auto &[Name, Flags] : MR.getSymbols())
      JDResidual.insert(NonOwningSymbolStringPtr(Name));

    for (auto &SDG : DepGroups) {
      WaitingOnGraph::ContainerElementsMap Defs;
      assert(!SDG.Symbols.empty());
      auto &JDDefs = Defs[&MR.getTargetJITDylib()];
      for (auto &Def : SDG.Symbols) {
        JDDefs.insert(NonOwningSymbolStringPtr(Def));
        JDResidual.erase(NonOwningSymbolStringPtr(Def));
      }
      WaitingOnGraph::ContainerElementsMap Deps;
      if (!SDG.Dependencies.empty()) {
        for (auto &[JD, Syms] : SDG.Dependencies) {
          auto &JDDeps = Deps[JD];
          for (auto &Dep : Syms)
            JDDeps.insert(NonOwningSymbolStringPtr(Dep));
        }
      }
      SNs.push_back(std::make_unique<WaitingOnGraph::SuperNode>(
          std::move(Defs), std::move(Deps)));
    }
    if (!JDResidual.empty())
      SNs.push_back(std::make_unique<WaitingOnGraph::SuperNode>(
          std::move(Residual), WaitingOnGraph::ContainerElementsMap()));
  }

  auto SR = WaitingOnGraph::simplify(std::move(SNs), GOpRecorder);

  LLVM_DEBUG({
    dbgs() << "  Simplified dependencies:\n";
    for (auto &SN : SR.superNodes()) {

      auto SortedLibs = [](WaitingOnGraph::ContainerElementsMap &C) {
        std::vector<JITDylib *> JDs;
        for (auto &[JD, _] : C)
          JDs.push_back(JD);
        llvm::sort(JDs, [](const JITDylib *LHS, const JITDylib *RHS) {
          return LHS->getName() < RHS->getName();
        });
        return JDs;
      };

      auto SortedNames = [](WaitingOnGraph::ElementSet &Elems) {
        std::vector<NonOwningSymbolStringPtr> Names(Elems.begin(), Elems.end());
        llvm::sort(Names, [](const NonOwningSymbolStringPtr &LHS,
                             const NonOwningSymbolStringPtr &RHS) {
          return *LHS < *RHS;
        });
        return Names;
      };

      dbgs() << "    Defs: {";
      for (auto *JD : SortedLibs(SN->defs())) {
        dbgs() << " (" << JD->getName() << ", [";
        for (auto &Sym : SortedNames(SN->defs()[JD]))
          dbgs() << " " << Sym;
        dbgs() << " ])";
      }
      dbgs() << " }, Deps: {";
      for (auto *JD : SortedLibs(SN->deps())) {
        dbgs() << " (" << JD->getName() << ", [";
        for (auto &Sym : SortedNames(SN->deps()[JD]))
          dbgs() << " " << Sym;
        dbgs() << " ])";
      }
      dbgs() << " }\n";
    }
  });
  auto EmitQueries =
      runSessionLocked([&]() { return IL_emit(MR, std::move(SR)); });

  // On error bail out.
  if (!EmitQueries)
    return EmitQueries.takeError();

  // Otherwise notify failed queries, and any updated queries that have been
  // completed.

  // FIXME: Get rid of error return from notifyEmitted.
  SymbolDependenceMap BadDeps;
  {
    for (auto &FQ : EmitQueries->Failed) {
      FQ->detach();
      assert(EmitQueries->FailedSymsForQuery.count(FQ.get()) &&
             "Missing failed symbols for query");
      auto FailedSyms = std::move(EmitQueries->FailedSymsForQuery[FQ.get()]);
      for (auto &[JD, Syms] : *FailedSyms) {
        auto &BadDepsForJD = BadDeps[JD];
        for (auto &Sym : Syms)
          BadDepsForJD.insert(Sym);
      }
      FQ->handleFailed(make_error<FailedToMaterialize>(getSymbolStringPool(),
                                                       std::move(FailedSyms)));
    }
  }

  for (auto &UQ : EmitQueries->Completed)
    UQ->handleComplete(*this);

  // If there are any bad dependencies then return an error.
  if (!BadDeps.empty()) {
    SymbolNameSet BadNames;
    // Note: The name set calculated here is bogus: it includes all symbols in
    //       the MR, not just the ones that failed. We want to remove the error
    //       return path from notifyEmitted anyway, so this is just a brief
    //       placeholder to maintain (roughly) the current error behavior.
    for (auto &[Name, Flags] : MR.getSymbols())
      BadNames.insert(Name);
    MR.SymbolFlags.clear();
    return make_error<UnsatisfiedSymbolDependencies>(
        getSymbolStringPool(), &MR.getTargetJITDylib(), std::move(BadNames),
        std::move(BadDeps), "dependencies removed or in error state");
  }

  MR.SymbolFlags.clear();
  return Error::success();
}

Error ExecutionSession::OL_defineMaterializing(
    MaterializationResponsibility &MR, SymbolFlagsMap NewSymbolFlags) {

  LLVM_DEBUG({
    dbgs() << "In " << MR.JD.getName() << " defining materializing symbols "
           << NewSymbolFlags << "\n";
  });
  if (auto AcceptedDefs =
          MR.JD.defineMaterializing(MR, std::move(NewSymbolFlags))) {
    // Add all newly accepted symbols to this responsibility object.
    for (auto &KV : *AcceptedDefs)
      MR.SymbolFlags.insert(KV);
    return Error::success();
  } else
    return AcceptedDefs.takeError();
}

std::pair<JITDylib::AsynchronousSymbolQuerySet,
          std::shared_ptr<SymbolDependenceMap>>
ExecutionSession::IL_failSymbols(JITDylib &JD,
                                 const SymbolNameVector &SymbolsToFail) {

#ifdef EXPENSIVE_CHECKS
  verifySessionState("entering ExecutionSession::IL_failSymbols");
#endif

  // Early out in the easy case.
  if (SymbolsToFail.empty())
    return {};

  JITDylib::AsynchronousSymbolQuerySet FailedQueries;
  auto Fail = [&](JITDylib *FailJD, NonOwningSymbolStringPtr FailSym) {
    auto I = FailJD->Symbols.find_as(FailSym);
    assert(I != FailJD->Symbols.end());
    I->second.setFlags(I->second.getFlags() | JITSymbolFlags::HasError);
    auto J = FailJD->MaterializingInfos.find_as(FailSym);
    if (J != FailJD->MaterializingInfos.end()) {
      for (auto &Q : J->second.takeAllPendingQueries())
        FailedQueries.insert(std::move(Q));
      FailJD->MaterializingInfos.erase(J);
    }
  };

  auto FailedSymbolsMap = std::make_shared<SymbolDependenceMap>();

  {
    auto &FailedSymsForJD = (*FailedSymbolsMap)[&JD];
    for (auto &Sym : SymbolsToFail) {
      FailedSymsForJD.insert(Sym);
      Fail(&JD, NonOwningSymbolStringPtr(Sym));
    }
  }

  WaitingOnGraph::ContainerElementsMap ToFail;
  auto &JDToFail = ToFail[&JD];
  for (auto &Sym : SymbolsToFail)
    JDToFail.insert(NonOwningSymbolStringPtr(Sym));

  auto FailedSNs = G.fail(ToFail, GOpRecorder);

  for (auto &SN : FailedSNs) {
    for (auto &[FailJD, Defs] : SN->defs()) {
      auto &FailedSymsForFailJD = (*FailedSymbolsMap)[FailJD];
      for (auto &Def : Defs) {
        FailedSymsForFailJD.insert(SymbolStringPtr(Def));
        Fail(FailJD, Def);
      }
    }
  }

  // Detach all failed queries.
  for (auto &Q : FailedQueries)
    Q->detach();

#ifdef EXPENSIVE_CHECKS
  verifySessionState("exiting ExecutionSession::IL_failSymbols");
#endif

  return std::make_pair(std::move(FailedQueries), std::move(FailedSymbolsMap));
}

void ExecutionSession::OL_notifyFailed(MaterializationResponsibility &MR) {

  LLVM_DEBUG({
    dbgs() << "In " << MR.JD.getName() << " failing materialization for "
           << MR.SymbolFlags << "\n";
  });

  if (MR.SymbolFlags.empty())
    return;

  SymbolNameVector SymbolsToFail;
  for (auto &[Name, Flags] : MR.SymbolFlags)
    SymbolsToFail.push_back(Name);
  MR.SymbolFlags.clear();

  JITDylib::AsynchronousSymbolQuerySet FailedQueries;
  std::shared_ptr<SymbolDependenceMap> FailedSymbols;

  std::tie(FailedQueries, FailedSymbols) = runSessionLocked([&]() {
    // If the tracker is defunct then there's nothing to do here.
    if (MR.RT->isDefunct())
      return std::pair<JITDylib::AsynchronousSymbolQuerySet,
                       std::shared_ptr<SymbolDependenceMap>>();
    return IL_failSymbols(MR.getTargetJITDylib(), SymbolsToFail);
  });

  for (auto &Q : FailedQueries) {
    Q->detach();
    Q->handleFailed(
        make_error<FailedToMaterialize>(getSymbolStringPool(), FailedSymbols));
  }
}

Error ExecutionSession::OL_replace(MaterializationResponsibility &MR,
                                   std::unique_ptr<MaterializationUnit> MU) {
  for (auto &KV : MU->getSymbols()) {
    assert(MR.SymbolFlags.count(KV.first) &&
           "Replacing definition outside this responsibility set");
    MR.SymbolFlags.erase(KV.first);
  }

  if (MU->getInitializerSymbol() == MR.InitSymbol)
    MR.InitSymbol = nullptr;

  LLVM_DEBUG(MR.JD.getExecutionSession().runSessionLocked([&]() {
    dbgs() << "In " << MR.JD.getName() << " replacing symbols with " << *MU
           << "\n";
  }););

  return MR.JD.replace(MR, std::move(MU));
}

Expected<std::unique_ptr<MaterializationResponsibility>>
ExecutionSession::OL_delegate(MaterializationResponsibility &MR,
                              const SymbolNameSet &Symbols) {

  SymbolStringPtr DelegatedInitSymbol;
  SymbolFlagsMap DelegatedFlags;

  for (auto &Name : Symbols) {
    auto I = MR.SymbolFlags.find(Name);
    assert(I != MR.SymbolFlags.end() &&
           "Symbol is not tracked by this MaterializationResponsibility "
           "instance");

    DelegatedFlags[Name] = std::move(I->second);
    if (Name == MR.InitSymbol)
      std::swap(MR.InitSymbol, DelegatedInitSymbol);

    MR.SymbolFlags.erase(I);
  }

  return MR.JD.delegate(MR, std::move(DelegatedFlags),
                        std::move(DelegatedInitSymbol));
}

#ifndef NDEBUG
void ExecutionSession::dumpDispatchInfo(Task &T) {
  runSessionLocked([&]() {
    dbgs() << "Dispatching: ";
    T.printDescription(dbgs());
    dbgs() << "\n";
  });
}
#endif // NDEBUG

} // End namespace orc.
} // End namespace llvm.
