xref: /freebsd-src/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/Core.cpp (revision 6e516c87b6d779911edde7481d8aef165b837a03)
10b57cec5SDimitry Andric //===--- Core.cpp - Core ORC APIs (MaterializationUnit, JITDylib, etc.) ---===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "llvm/ExecutionEngine/Orc/Core.h"
10480093f4SDimitry Andric 
11480093f4SDimitry Andric #include "llvm/ADT/STLExtras.h"
120b57cec5SDimitry Andric #include "llvm/Config/llvm-config.h"
135ffd83dbSDimitry Andric #include "llvm/ExecutionEngine/Orc/DebugUtils.h"
14e8d8bef9SDimitry Andric #include "llvm/ExecutionEngine/Orc/Shared/OrcError.h"
15e8d8bef9SDimitry Andric #include "llvm/Support/FormatVariadic.h"
16e8d8bef9SDimitry Andric #include "llvm/Support/MSVCErrorWorkarounds.h"
170b57cec5SDimitry Andric 
185ffd83dbSDimitry Andric #include <condition_variable>
190b57cec5SDimitry Andric #include <future>
20bdd1243dSDimitry Andric #include <optional>
210b57cec5SDimitry Andric 
220b57cec5SDimitry Andric #define DEBUG_TYPE "orc"
230b57cec5SDimitry Andric 
240b57cec5SDimitry Andric namespace llvm {
250b57cec5SDimitry Andric namespace orc {
260b57cec5SDimitry Andric 
27e8d8bef9SDimitry Andric char ResourceTrackerDefunct::ID = 0;
280b57cec5SDimitry Andric char FailedToMaterialize::ID = 0;
290b57cec5SDimitry Andric char SymbolsNotFound::ID = 0;
300b57cec5SDimitry Andric char SymbolsCouldNotBeRemoved::ID = 0;
315ffd83dbSDimitry Andric char MissingSymbolDefinitions::ID = 0;
325ffd83dbSDimitry Andric char UnexpectedSymbolDefinitions::ID = 0;
330fca6ea1SDimitry Andric char UnsatisfiedSymbolDependencies::ID = 0;
34fe6060f1SDimitry Andric char MaterializationTask::ID = 0;
355f757f3fSDimitry Andric char LookupTask::ID = 0;
360b57cec5SDimitry Andric 
370b57cec5SDimitry Andric RegisterDependenciesFunction NoDependenciesToRegister =
380b57cec5SDimitry Andric     RegisterDependenciesFunction();
390b57cec5SDimitry Andric 
400b57cec5SDimitry Andric void MaterializationUnit::anchor() {}
410b57cec5SDimitry Andric 
42e8d8bef9SDimitry Andric ResourceTracker::ResourceTracker(JITDylibSP JD) {
43e8d8bef9SDimitry Andric   assert((reinterpret_cast<uintptr_t>(JD.get()) & 0x1) == 0 &&
44e8d8bef9SDimitry Andric          "JITDylib must be two byte aligned");
45e8d8bef9SDimitry Andric   JD->Retain();
46e8d8bef9SDimitry Andric   JDAndFlag.store(reinterpret_cast<uintptr_t>(JD.get()));
47e8d8bef9SDimitry Andric }
48e8d8bef9SDimitry Andric 
49e8d8bef9SDimitry Andric ResourceTracker::~ResourceTracker() {
50e8d8bef9SDimitry Andric   getJITDylib().getExecutionSession().destroyResourceTracker(*this);
51e8d8bef9SDimitry Andric   getJITDylib().Release();
52e8d8bef9SDimitry Andric }
53e8d8bef9SDimitry Andric 
54e8d8bef9SDimitry Andric Error ResourceTracker::remove() {
55e8d8bef9SDimitry Andric   return getJITDylib().getExecutionSession().removeResourceTracker(*this);
56e8d8bef9SDimitry Andric }
57e8d8bef9SDimitry Andric 
58e8d8bef9SDimitry Andric void ResourceTracker::transferTo(ResourceTracker &DstRT) {
59e8d8bef9SDimitry Andric   getJITDylib().getExecutionSession().transferResourceTracker(DstRT, *this);
60e8d8bef9SDimitry Andric }
61e8d8bef9SDimitry Andric 
62e8d8bef9SDimitry Andric void ResourceTracker::makeDefunct() {
63e8d8bef9SDimitry Andric   uintptr_t Val = JDAndFlag.load();
64e8d8bef9SDimitry Andric   Val |= 0x1U;
65e8d8bef9SDimitry Andric   JDAndFlag.store(Val);
66e8d8bef9SDimitry Andric }
67e8d8bef9SDimitry Andric 
6881ad6265SDimitry Andric ResourceManager::~ResourceManager() = default;
69e8d8bef9SDimitry Andric 
70e8d8bef9SDimitry Andric ResourceTrackerDefunct::ResourceTrackerDefunct(ResourceTrackerSP RT)
71e8d8bef9SDimitry Andric     : RT(std::move(RT)) {}
72e8d8bef9SDimitry Andric 
73e8d8bef9SDimitry Andric std::error_code ResourceTrackerDefunct::convertToErrorCode() const {
74e8d8bef9SDimitry Andric   return orcError(OrcErrorCode::UnknownORCError);
75e8d8bef9SDimitry Andric }
76e8d8bef9SDimitry Andric 
77e8d8bef9SDimitry Andric void ResourceTrackerDefunct::log(raw_ostream &OS) const {
78e8d8bef9SDimitry Andric   OS << "Resource tracker " << (void *)RT.get() << " became defunct";
79e8d8bef9SDimitry Andric }
80e8d8bef9SDimitry Andric 
818bcb0991SDimitry Andric FailedToMaterialize::FailedToMaterialize(
8281ad6265SDimitry Andric     std::shared_ptr<SymbolStringPool> SSP,
838bcb0991SDimitry Andric     std::shared_ptr<SymbolDependenceMap> Symbols)
8481ad6265SDimitry Andric     : SSP(std::move(SSP)), Symbols(std::move(Symbols)) {
8581ad6265SDimitry Andric   assert(this->SSP && "String pool cannot be null");
868bcb0991SDimitry Andric   assert(!this->Symbols->empty() && "Can not fail to resolve an empty set");
8781ad6265SDimitry Andric 
8881ad6265SDimitry Andric   // FIXME: Use a new dep-map type for FailedToMaterialize errors so that we
8981ad6265SDimitry Andric   // don't have to manually retain/release.
900fca6ea1SDimitry Andric   for (auto &[JD, Syms] : *this->Symbols)
910fca6ea1SDimitry Andric     JD->Retain();
9281ad6265SDimitry Andric }
9381ad6265SDimitry Andric 
9481ad6265SDimitry Andric FailedToMaterialize::~FailedToMaterialize() {
950fca6ea1SDimitry Andric   for (auto &[JD, Syms] : *Symbols)
960fca6ea1SDimitry Andric     JD->Release();
970b57cec5SDimitry Andric }
980b57cec5SDimitry Andric 
990b57cec5SDimitry Andric std::error_code FailedToMaterialize::convertToErrorCode() const {
1000b57cec5SDimitry Andric   return orcError(OrcErrorCode::UnknownORCError);
1010b57cec5SDimitry Andric }
1020b57cec5SDimitry Andric 
1030b57cec5SDimitry Andric void FailedToMaterialize::log(raw_ostream &OS) const {
1048bcb0991SDimitry Andric   OS << "Failed to materialize symbols: " << *Symbols;
1050b57cec5SDimitry Andric }
1060b57cec5SDimitry Andric 
1070fca6ea1SDimitry Andric UnsatisfiedSymbolDependencies::UnsatisfiedSymbolDependencies(
1080fca6ea1SDimitry Andric     std::shared_ptr<SymbolStringPool> SSP, JITDylibSP JD,
1090fca6ea1SDimitry Andric     SymbolNameSet FailedSymbols, SymbolDependenceMap BadDeps,
1100fca6ea1SDimitry Andric     std::string Explanation)
1110fca6ea1SDimitry Andric     : SSP(std::move(SSP)), JD(std::move(JD)),
1120fca6ea1SDimitry Andric       FailedSymbols(std::move(FailedSymbols)), BadDeps(std::move(BadDeps)),
1130fca6ea1SDimitry Andric       Explanation(std::move(Explanation)) {}
1140fca6ea1SDimitry Andric 
1150fca6ea1SDimitry Andric std::error_code UnsatisfiedSymbolDependencies::convertToErrorCode() const {
1160fca6ea1SDimitry Andric   return orcError(OrcErrorCode::UnknownORCError);
1170fca6ea1SDimitry Andric }
1180fca6ea1SDimitry Andric 
1190fca6ea1SDimitry Andric void UnsatisfiedSymbolDependencies::log(raw_ostream &OS) const {
1200fca6ea1SDimitry Andric   OS << "In " << JD->getName() << ", failed to materialize " << FailedSymbols
1210fca6ea1SDimitry Andric      << ", due to unsatisfied dependencies " << BadDeps;
1220fca6ea1SDimitry Andric   if (!Explanation.empty())
1230fca6ea1SDimitry Andric     OS << " (" << Explanation << ")";
1240fca6ea1SDimitry Andric }
1250fca6ea1SDimitry Andric 
126349cc55cSDimitry Andric SymbolsNotFound::SymbolsNotFound(std::shared_ptr<SymbolStringPool> SSP,
127349cc55cSDimitry Andric                                  SymbolNameSet Symbols)
128349cc55cSDimitry Andric     : SSP(std::move(SSP)) {
129480093f4SDimitry Andric   for (auto &Sym : Symbols)
130480093f4SDimitry Andric     this->Symbols.push_back(Sym);
131480093f4SDimitry Andric   assert(!this->Symbols.empty() && "Can not fail to resolve an empty set");
132480093f4SDimitry Andric }
133480093f4SDimitry Andric 
134349cc55cSDimitry Andric SymbolsNotFound::SymbolsNotFound(std::shared_ptr<SymbolStringPool> SSP,
135349cc55cSDimitry Andric                                  SymbolNameVector Symbols)
136349cc55cSDimitry Andric     : SSP(std::move(SSP)), Symbols(std::move(Symbols)) {
1370b57cec5SDimitry Andric   assert(!this->Symbols.empty() && "Can not fail to resolve an empty set");
1380b57cec5SDimitry Andric }
1390b57cec5SDimitry Andric 
1400b57cec5SDimitry Andric std::error_code SymbolsNotFound::convertToErrorCode() const {
1410b57cec5SDimitry Andric   return orcError(OrcErrorCode::UnknownORCError);
1420b57cec5SDimitry Andric }
1430b57cec5SDimitry Andric 
1440b57cec5SDimitry Andric void SymbolsNotFound::log(raw_ostream &OS) const {
1450b57cec5SDimitry Andric   OS << "Symbols not found: " << Symbols;
1460b57cec5SDimitry Andric }
1470b57cec5SDimitry Andric 
148349cc55cSDimitry Andric SymbolsCouldNotBeRemoved::SymbolsCouldNotBeRemoved(
149349cc55cSDimitry Andric     std::shared_ptr<SymbolStringPool> SSP, SymbolNameSet Symbols)
150349cc55cSDimitry Andric     : SSP(std::move(SSP)), Symbols(std::move(Symbols)) {
1510b57cec5SDimitry Andric   assert(!this->Symbols.empty() && "Can not fail to resolve an empty set");
1520b57cec5SDimitry Andric }
1530b57cec5SDimitry Andric 
1540b57cec5SDimitry Andric std::error_code SymbolsCouldNotBeRemoved::convertToErrorCode() const {
1550b57cec5SDimitry Andric   return orcError(OrcErrorCode::UnknownORCError);
1560b57cec5SDimitry Andric }
1570b57cec5SDimitry Andric 
1580b57cec5SDimitry Andric void SymbolsCouldNotBeRemoved::log(raw_ostream &OS) const {
1590b57cec5SDimitry Andric   OS << "Symbols could not be removed: " << Symbols;
1600b57cec5SDimitry Andric }
1610b57cec5SDimitry Andric 
1625ffd83dbSDimitry Andric std::error_code MissingSymbolDefinitions::convertToErrorCode() const {
1635ffd83dbSDimitry Andric   return orcError(OrcErrorCode::MissingSymbolDefinitions);
1645ffd83dbSDimitry Andric }
1655ffd83dbSDimitry Andric 
1665ffd83dbSDimitry Andric void MissingSymbolDefinitions::log(raw_ostream &OS) const {
1675ffd83dbSDimitry Andric   OS << "Missing definitions in module " << ModuleName
1685ffd83dbSDimitry Andric      << ": " << Symbols;
1695ffd83dbSDimitry Andric }
1705ffd83dbSDimitry Andric 
1715ffd83dbSDimitry Andric std::error_code UnexpectedSymbolDefinitions::convertToErrorCode() const {
1725ffd83dbSDimitry Andric   return orcError(OrcErrorCode::UnexpectedSymbolDefinitions);
1735ffd83dbSDimitry Andric }
1745ffd83dbSDimitry Andric 
1755ffd83dbSDimitry Andric void UnexpectedSymbolDefinitions::log(raw_ostream &OS) const {
1765ffd83dbSDimitry Andric   OS << "Unexpected definitions in module " << ModuleName
1775ffd83dbSDimitry Andric      << ": " << Symbols;
1785ffd83dbSDimitry Andric }
1795ffd83dbSDimitry Andric 
1800b57cec5SDimitry Andric AsynchronousSymbolQuery::AsynchronousSymbolQuery(
181480093f4SDimitry Andric     const SymbolLookupSet &Symbols, SymbolState RequiredState,
1820b57cec5SDimitry Andric     SymbolsResolvedCallback NotifyComplete)
1830b57cec5SDimitry Andric     : NotifyComplete(std::move(NotifyComplete)), RequiredState(RequiredState) {
1840b57cec5SDimitry Andric   assert(RequiredState >= SymbolState::Resolved &&
1850b57cec5SDimitry Andric          "Cannot query for a symbols that have not reached the resolve state "
1860b57cec5SDimitry Andric          "yet");
1870b57cec5SDimitry Andric 
1880b57cec5SDimitry Andric   OutstandingSymbolsCount = Symbols.size();
1890b57cec5SDimitry Andric 
1900fca6ea1SDimitry Andric   for (auto &[Name, Flags] : Symbols)
1910fca6ea1SDimitry Andric     ResolvedSymbols[Name] = ExecutorSymbolDef();
1920b57cec5SDimitry Andric }
1930b57cec5SDimitry Andric 
1940b57cec5SDimitry Andric void AsynchronousSymbolQuery::notifySymbolMetRequiredState(
19506c3fb27SDimitry Andric     const SymbolStringPtr &Name, ExecutorSymbolDef Sym) {
1960b57cec5SDimitry Andric   auto I = ResolvedSymbols.find(Name);
1970b57cec5SDimitry Andric   assert(I != ResolvedSymbols.end() &&
1980b57cec5SDimitry Andric          "Resolving symbol outside the requested set");
19906c3fb27SDimitry Andric   assert(I->second == ExecutorSymbolDef() &&
20006c3fb27SDimitry Andric          "Redundantly resolving symbol Name");
2015ffd83dbSDimitry Andric 
2025ffd83dbSDimitry Andric   // If this is a materialization-side-effects-only symbol then drop it,
2035ffd83dbSDimitry Andric   // otherwise update its map entry with its resolved address.
2045ffd83dbSDimitry Andric   if (Sym.getFlags().hasMaterializationSideEffectsOnly())
2055ffd83dbSDimitry Andric     ResolvedSymbols.erase(I);
2065ffd83dbSDimitry Andric   else
2070b57cec5SDimitry Andric     I->second = std::move(Sym);
2080b57cec5SDimitry Andric   --OutstandingSymbolsCount;
2090b57cec5SDimitry Andric }
2100b57cec5SDimitry Andric 
211fe6060f1SDimitry Andric void AsynchronousSymbolQuery::handleComplete(ExecutionSession &ES) {
2120b57cec5SDimitry Andric   assert(OutstandingSymbolsCount == 0 &&
2130b57cec5SDimitry Andric          "Symbols remain, handleComplete called prematurely");
2140b57cec5SDimitry Andric 
215fe6060f1SDimitry Andric   class RunQueryCompleteTask : public Task {
216fe6060f1SDimitry Andric   public:
217fe6060f1SDimitry Andric     RunQueryCompleteTask(SymbolMap ResolvedSymbols,
218fe6060f1SDimitry Andric                          SymbolsResolvedCallback NotifyComplete)
219fe6060f1SDimitry Andric         : ResolvedSymbols(std::move(ResolvedSymbols)),
220fe6060f1SDimitry Andric           NotifyComplete(std::move(NotifyComplete)) {}
221fe6060f1SDimitry Andric     void printDescription(raw_ostream &OS) override {
222fe6060f1SDimitry Andric       OS << "Execute query complete callback for " << ResolvedSymbols;
223fe6060f1SDimitry Andric     }
224fe6060f1SDimitry Andric     void run() override { NotifyComplete(std::move(ResolvedSymbols)); }
225fe6060f1SDimitry Andric 
226fe6060f1SDimitry Andric   private:
227fe6060f1SDimitry Andric     SymbolMap ResolvedSymbols;
228fe6060f1SDimitry Andric     SymbolsResolvedCallback NotifyComplete;
229fe6060f1SDimitry Andric   };
230fe6060f1SDimitry Andric 
231fe6060f1SDimitry Andric   auto T = std::make_unique<RunQueryCompleteTask>(std::move(ResolvedSymbols),
232fe6060f1SDimitry Andric                                                   std::move(NotifyComplete));
2330b57cec5SDimitry Andric   NotifyComplete = SymbolsResolvedCallback();
234fe6060f1SDimitry Andric   ES.dispatchTask(std::move(T));
2350b57cec5SDimitry Andric }
2360b57cec5SDimitry Andric 
2370b57cec5SDimitry Andric void AsynchronousSymbolQuery::handleFailed(Error Err) {
2380b57cec5SDimitry Andric   assert(QueryRegistrations.empty() && ResolvedSymbols.empty() &&
2390b57cec5SDimitry Andric          OutstandingSymbolsCount == 0 &&
2400b57cec5SDimitry Andric          "Query should already have been abandoned");
2410b57cec5SDimitry Andric   NotifyComplete(std::move(Err));
2420b57cec5SDimitry Andric   NotifyComplete = SymbolsResolvedCallback();
2430b57cec5SDimitry Andric }
2440b57cec5SDimitry Andric 
2450b57cec5SDimitry Andric void AsynchronousSymbolQuery::addQueryDependence(JITDylib &JD,
2460b57cec5SDimitry Andric                                                  SymbolStringPtr Name) {
2470b57cec5SDimitry Andric   bool Added = QueryRegistrations[&JD].insert(std::move(Name)).second;
2480b57cec5SDimitry Andric   (void)Added;
2490b57cec5SDimitry Andric   assert(Added && "Duplicate dependence notification?");
2500b57cec5SDimitry Andric }
2510b57cec5SDimitry Andric 
2520b57cec5SDimitry Andric void AsynchronousSymbolQuery::removeQueryDependence(
2530b57cec5SDimitry Andric     JITDylib &JD, const SymbolStringPtr &Name) {
2540b57cec5SDimitry Andric   auto QRI = QueryRegistrations.find(&JD);
2550b57cec5SDimitry Andric   assert(QRI != QueryRegistrations.end() &&
2560b57cec5SDimitry Andric          "No dependencies registered for JD");
2570b57cec5SDimitry Andric   assert(QRI->second.count(Name) && "No dependency on Name in JD");
2580b57cec5SDimitry Andric   QRI->second.erase(Name);
2590b57cec5SDimitry Andric   if (QRI->second.empty())
2600b57cec5SDimitry Andric     QueryRegistrations.erase(QRI);
2610b57cec5SDimitry Andric }
2620b57cec5SDimitry Andric 
2635ffd83dbSDimitry Andric void AsynchronousSymbolQuery::dropSymbol(const SymbolStringPtr &Name) {
2645ffd83dbSDimitry Andric   auto I = ResolvedSymbols.find(Name);
2655ffd83dbSDimitry Andric   assert(I != ResolvedSymbols.end() &&
2665ffd83dbSDimitry Andric          "Redundant removal of weakly-referenced symbol");
2675ffd83dbSDimitry Andric   ResolvedSymbols.erase(I);
2685ffd83dbSDimitry Andric   --OutstandingSymbolsCount;
2695ffd83dbSDimitry Andric }
2705ffd83dbSDimitry Andric 
2710b57cec5SDimitry Andric void AsynchronousSymbolQuery::detach() {
2720b57cec5SDimitry Andric   ResolvedSymbols.clear();
2730b57cec5SDimitry Andric   OutstandingSymbolsCount = 0;
2740fca6ea1SDimitry Andric   for (auto &[JD, Syms] : QueryRegistrations)
2750fca6ea1SDimitry Andric     JD->detachQueryHelper(*this, Syms);
2760b57cec5SDimitry Andric   QueryRegistrations.clear();
2770b57cec5SDimitry Andric }
2780b57cec5SDimitry Andric 
2790b57cec5SDimitry Andric AbsoluteSymbolsMaterializationUnit::AbsoluteSymbolsMaterializationUnit(
280e8d8bef9SDimitry Andric     SymbolMap Symbols)
2810eae32dcSDimitry Andric     : MaterializationUnit(extractFlags(Symbols)), Symbols(std::move(Symbols)) {}
2820b57cec5SDimitry Andric 
2830b57cec5SDimitry Andric StringRef AbsoluteSymbolsMaterializationUnit::getName() const {
2840b57cec5SDimitry Andric   return "<Absolute Symbols>";
2850b57cec5SDimitry Andric }
2860b57cec5SDimitry Andric 
2870b57cec5SDimitry Andric void AbsoluteSymbolsMaterializationUnit::materialize(
288e8d8bef9SDimitry Andric     std::unique_ptr<MaterializationResponsibility> R) {
28981ad6265SDimitry Andric   // Even though these are just absolute symbols we need to check for failure
29081ad6265SDimitry Andric   // to resolve/emit: the tracker for these symbols may have been removed while
29181ad6265SDimitry Andric   // the materialization was in flight (e.g. due to a failure in some action
29281ad6265SDimitry Andric   // triggered by the queries attached to the resolution/emission of these
29381ad6265SDimitry Andric   // symbols).
29481ad6265SDimitry Andric   if (auto Err = R->notifyResolved(Symbols)) {
29581ad6265SDimitry Andric     R->getExecutionSession().reportError(std::move(Err));
29681ad6265SDimitry Andric     R->failMaterialization();
29781ad6265SDimitry Andric     return;
29881ad6265SDimitry Andric   }
2990fca6ea1SDimitry Andric   if (auto Err = R->notifyEmitted({})) {
30081ad6265SDimitry Andric     R->getExecutionSession().reportError(std::move(Err));
30181ad6265SDimitry Andric     R->failMaterialization();
30281ad6265SDimitry Andric     return;
30381ad6265SDimitry Andric   }
3040b57cec5SDimitry Andric }
3050b57cec5SDimitry Andric 
3060b57cec5SDimitry Andric void AbsoluteSymbolsMaterializationUnit::discard(const JITDylib &JD,
3070b57cec5SDimitry Andric                                                  const SymbolStringPtr &Name) {
3080b57cec5SDimitry Andric   assert(Symbols.count(Name) && "Symbol is not part of this MU");
3090b57cec5SDimitry Andric   Symbols.erase(Name);
3100b57cec5SDimitry Andric }
3110b57cec5SDimitry Andric 
3120eae32dcSDimitry Andric MaterializationUnit::Interface
3130b57cec5SDimitry Andric AbsoluteSymbolsMaterializationUnit::extractFlags(const SymbolMap &Symbols) {
3140b57cec5SDimitry Andric   SymbolFlagsMap Flags;
3150fca6ea1SDimitry Andric   for (const auto &[Name, Def] : Symbols)
3160fca6ea1SDimitry Andric     Flags[Name] = Def.getFlags();
3170eae32dcSDimitry Andric   return MaterializationUnit::Interface(std::move(Flags), nullptr);
3180b57cec5SDimitry Andric }
3190b57cec5SDimitry Andric 
3200b57cec5SDimitry Andric ReExportsMaterializationUnit::ReExportsMaterializationUnit(
321480093f4SDimitry Andric     JITDylib *SourceJD, JITDylibLookupFlags SourceJDLookupFlags,
322e8d8bef9SDimitry Andric     SymbolAliasMap Aliases)
3230eae32dcSDimitry Andric     : MaterializationUnit(extractFlags(Aliases)), SourceJD(SourceJD),
324e8d8bef9SDimitry Andric       SourceJDLookupFlags(SourceJDLookupFlags), Aliases(std::move(Aliases)) {}
3250b57cec5SDimitry Andric 
3260b57cec5SDimitry Andric StringRef ReExportsMaterializationUnit::getName() const {
3270b57cec5SDimitry Andric   return "<Reexports>";
3280b57cec5SDimitry Andric }
3290b57cec5SDimitry Andric 
3300b57cec5SDimitry Andric void ReExportsMaterializationUnit::materialize(
331e8d8bef9SDimitry Andric     std::unique_ptr<MaterializationResponsibility> R) {
3320b57cec5SDimitry Andric 
333e8d8bef9SDimitry Andric   auto &ES = R->getTargetJITDylib().getExecutionSession();
334e8d8bef9SDimitry Andric   JITDylib &TgtJD = R->getTargetJITDylib();
3350b57cec5SDimitry Andric   JITDylib &SrcJD = SourceJD ? *SourceJD : TgtJD;
3360b57cec5SDimitry Andric 
3370b57cec5SDimitry Andric   // Find the set of requested aliases and aliasees. Return any unrequested
3380b57cec5SDimitry Andric   // aliases back to the JITDylib so as to not prematurely materialize any
3390b57cec5SDimitry Andric   // aliasees.
340e8d8bef9SDimitry Andric   auto RequestedSymbols = R->getRequestedSymbols();
3410b57cec5SDimitry Andric   SymbolAliasMap RequestedAliases;
3420b57cec5SDimitry Andric 
3430b57cec5SDimitry Andric   for (auto &Name : RequestedSymbols) {
3440b57cec5SDimitry Andric     auto I = Aliases.find(Name);
3450b57cec5SDimitry Andric     assert(I != Aliases.end() && "Symbol not found in aliases map?");
3460b57cec5SDimitry Andric     RequestedAliases[Name] = std::move(I->second);
3470b57cec5SDimitry Andric     Aliases.erase(I);
3480b57cec5SDimitry Andric   }
3490b57cec5SDimitry Andric 
3500b57cec5SDimitry Andric   LLVM_DEBUG({
3510b57cec5SDimitry Andric     ES.runSessionLocked([&]() {
3520b57cec5SDimitry Andric       dbgs() << "materializing reexports: target = " << TgtJD.getName()
3530b57cec5SDimitry Andric              << ", source = " << SrcJD.getName() << " " << RequestedAliases
3540b57cec5SDimitry Andric              << "\n";
3550b57cec5SDimitry Andric     });
3560b57cec5SDimitry Andric   });
3570b57cec5SDimitry Andric 
3580b57cec5SDimitry Andric   if (!Aliases.empty()) {
359e8d8bef9SDimitry Andric     auto Err = SourceJD ? R->replace(reexports(*SourceJD, std::move(Aliases),
360e8d8bef9SDimitry Andric                                                SourceJDLookupFlags))
361e8d8bef9SDimitry Andric                         : R->replace(symbolAliases(std::move(Aliases)));
362e8d8bef9SDimitry Andric 
363e8d8bef9SDimitry Andric     if (Err) {
364e8d8bef9SDimitry Andric       // FIXME: Should this be reported / treated as failure to materialize?
365e8d8bef9SDimitry Andric       // Or should this be treated as a sanctioned bailing-out?
366e8d8bef9SDimitry Andric       ES.reportError(std::move(Err));
367e8d8bef9SDimitry Andric       R->failMaterialization();
368e8d8bef9SDimitry Andric       return;
369e8d8bef9SDimitry Andric     }
3700b57cec5SDimitry Andric   }
3710b57cec5SDimitry Andric 
3725f757f3fSDimitry Andric   // The OnResolveInfo struct will hold the aliases and responsibility for each
3730b57cec5SDimitry Andric   // query in the list.
3740b57cec5SDimitry Andric   struct OnResolveInfo {
375e8d8bef9SDimitry Andric     OnResolveInfo(std::unique_ptr<MaterializationResponsibility> R,
376e8d8bef9SDimitry Andric                   SymbolAliasMap Aliases)
3770b57cec5SDimitry Andric         : R(std::move(R)), Aliases(std::move(Aliases)) {}
3780b57cec5SDimitry Andric 
379e8d8bef9SDimitry Andric     std::unique_ptr<MaterializationResponsibility> R;
3800b57cec5SDimitry Andric     SymbolAliasMap Aliases;
3810fca6ea1SDimitry Andric     std::vector<SymbolDependenceGroup> SDGs;
3820b57cec5SDimitry Andric   };
3830b57cec5SDimitry Andric 
3845ffd83dbSDimitry Andric   // Build a list of queries to issue. In each round we build a query for the
3855ffd83dbSDimitry Andric   // largest set of aliases that we can resolve without encountering a chain of
3865ffd83dbSDimitry Andric   // aliases (e.g. Foo -> Bar, Bar -> Baz). Such a chain would deadlock as the
3875ffd83dbSDimitry Andric   // query would be waiting on a symbol that it itself had to resolve. Creating
3885ffd83dbSDimitry Andric   // a new query for each link in such a chain eliminates the possibility of
3895ffd83dbSDimitry Andric   // deadlock. In practice chains are likely to be rare, and this algorithm will
3905ffd83dbSDimitry Andric   // usually result in a single query to issue.
3910b57cec5SDimitry Andric 
392480093f4SDimitry Andric   std::vector<std::pair<SymbolLookupSet, std::shared_ptr<OnResolveInfo>>>
3930b57cec5SDimitry Andric       QueryInfos;
3940b57cec5SDimitry Andric   while (!RequestedAliases.empty()) {
3950b57cec5SDimitry Andric     SymbolNameSet ResponsibilitySymbols;
396480093f4SDimitry Andric     SymbolLookupSet QuerySymbols;
3970b57cec5SDimitry Andric     SymbolAliasMap QueryAliases;
3980b57cec5SDimitry Andric 
3990b57cec5SDimitry Andric     // Collect as many aliases as we can without including a chain.
4000b57cec5SDimitry Andric     for (auto &KV : RequestedAliases) {
4010b57cec5SDimitry Andric       // Chain detected. Skip this symbol for this round.
4020b57cec5SDimitry Andric       if (&SrcJD == &TgtJD && (QueryAliases.count(KV.second.Aliasee) ||
4030b57cec5SDimitry Andric                                RequestedAliases.count(KV.second.Aliasee)))
4040b57cec5SDimitry Andric         continue;
4050b57cec5SDimitry Andric 
4060b57cec5SDimitry Andric       ResponsibilitySymbols.insert(KV.first);
4075ffd83dbSDimitry Andric       QuerySymbols.add(KV.second.Aliasee,
4085ffd83dbSDimitry Andric                        KV.second.AliasFlags.hasMaterializationSideEffectsOnly()
4095ffd83dbSDimitry Andric                            ? SymbolLookupFlags::WeaklyReferencedSymbol
4105ffd83dbSDimitry Andric                            : SymbolLookupFlags::RequiredSymbol);
4110b57cec5SDimitry Andric       QueryAliases[KV.first] = std::move(KV.second);
4120b57cec5SDimitry Andric     }
4130b57cec5SDimitry Andric 
4140b57cec5SDimitry Andric     // Remove the aliases collected this round from the RequestedAliases map.
4150b57cec5SDimitry Andric     for (auto &KV : QueryAliases)
4160b57cec5SDimitry Andric       RequestedAliases.erase(KV.first);
4170b57cec5SDimitry Andric 
4180b57cec5SDimitry Andric     assert(!QuerySymbols.empty() && "Alias cycle detected!");
4190b57cec5SDimitry Andric 
420e8d8bef9SDimitry Andric     auto NewR = R->delegate(ResponsibilitySymbols);
421e8d8bef9SDimitry Andric     if (!NewR) {
422e8d8bef9SDimitry Andric       ES.reportError(NewR.takeError());
423e8d8bef9SDimitry Andric       R->failMaterialization();
424e8d8bef9SDimitry Andric       return;
425e8d8bef9SDimitry Andric     }
426e8d8bef9SDimitry Andric 
427e8d8bef9SDimitry Andric     auto QueryInfo = std::make_shared<OnResolveInfo>(std::move(*NewR),
428e8d8bef9SDimitry Andric                                                      std::move(QueryAliases));
4290b57cec5SDimitry Andric     QueryInfos.push_back(
4300b57cec5SDimitry Andric         make_pair(std::move(QuerySymbols), std::move(QueryInfo)));
4310b57cec5SDimitry Andric   }
4320b57cec5SDimitry Andric 
4330b57cec5SDimitry Andric   // Issue the queries.
4340b57cec5SDimitry Andric   while (!QueryInfos.empty()) {
4350b57cec5SDimitry Andric     auto QuerySymbols = std::move(QueryInfos.back().first);
4360b57cec5SDimitry Andric     auto QueryInfo = std::move(QueryInfos.back().second);
4370b57cec5SDimitry Andric 
4380b57cec5SDimitry Andric     QueryInfos.pop_back();
4390b57cec5SDimitry Andric 
4400b57cec5SDimitry Andric     auto RegisterDependencies = [QueryInfo,
4410b57cec5SDimitry Andric                                  &SrcJD](const SymbolDependenceMap &Deps) {
4420b57cec5SDimitry Andric       // If there were no materializing symbols, just bail out.
4430b57cec5SDimitry Andric       if (Deps.empty())
4440b57cec5SDimitry Andric         return;
4450b57cec5SDimitry Andric 
4460b57cec5SDimitry Andric       // Otherwise the only deps should be on SrcJD.
4470b57cec5SDimitry Andric       assert(Deps.size() == 1 && Deps.count(&SrcJD) &&
4480b57cec5SDimitry Andric              "Unexpected dependencies for reexports");
4490b57cec5SDimitry Andric 
4500b57cec5SDimitry Andric       auto &SrcJDDeps = Deps.find(&SrcJD)->second;
4510b57cec5SDimitry Andric 
4520fca6ea1SDimitry Andric       for (auto &[Alias, AliasInfo] : QueryInfo->Aliases)
4530fca6ea1SDimitry Andric         if (SrcJDDeps.count(AliasInfo.Aliasee))
4540fca6ea1SDimitry Andric           QueryInfo->SDGs.push_back({{Alias}, {{&SrcJD, {AliasInfo.Aliasee}}}});
4550b57cec5SDimitry Andric     };
4560b57cec5SDimitry Andric 
4570b57cec5SDimitry Andric     auto OnComplete = [QueryInfo](Expected<SymbolMap> Result) {
458e8d8bef9SDimitry Andric       auto &ES = QueryInfo->R->getTargetJITDylib().getExecutionSession();
4590b57cec5SDimitry Andric       if (Result) {
4600b57cec5SDimitry Andric         SymbolMap ResolutionMap;
4610b57cec5SDimitry Andric         for (auto &KV : QueryInfo->Aliases) {
4625ffd83dbSDimitry Andric           assert((KV.second.AliasFlags.hasMaterializationSideEffectsOnly() ||
4635ffd83dbSDimitry Andric                   Result->count(KV.second.Aliasee)) &&
4640b57cec5SDimitry Andric                  "Result map missing entry?");
4655ffd83dbSDimitry Andric           // Don't try to resolve materialization-side-effects-only symbols.
4665ffd83dbSDimitry Andric           if (KV.second.AliasFlags.hasMaterializationSideEffectsOnly())
4675ffd83dbSDimitry Andric             continue;
4685ffd83dbSDimitry Andric 
46906c3fb27SDimitry Andric           ResolutionMap[KV.first] = {(*Result)[KV.second.Aliasee].getAddress(),
47006c3fb27SDimitry Andric                                      KV.second.AliasFlags};
4710b57cec5SDimitry Andric         }
472e8d8bef9SDimitry Andric         if (auto Err = QueryInfo->R->notifyResolved(ResolutionMap)) {
4738bcb0991SDimitry Andric           ES.reportError(std::move(Err));
474e8d8bef9SDimitry Andric           QueryInfo->R->failMaterialization();
4758bcb0991SDimitry Andric           return;
4768bcb0991SDimitry Andric         }
4770fca6ea1SDimitry Andric         if (auto Err = QueryInfo->R->notifyEmitted(QueryInfo->SDGs)) {
4788bcb0991SDimitry Andric           ES.reportError(std::move(Err));
479e8d8bef9SDimitry Andric           QueryInfo->R->failMaterialization();
4808bcb0991SDimitry Andric           return;
4818bcb0991SDimitry Andric         }
4820b57cec5SDimitry Andric       } else {
4830b57cec5SDimitry Andric         ES.reportError(Result.takeError());
484e8d8bef9SDimitry Andric         QueryInfo->R->failMaterialization();
4850b57cec5SDimitry Andric       }
4860b57cec5SDimitry Andric     };
4870b57cec5SDimitry Andric 
488480093f4SDimitry Andric     ES.lookup(LookupKind::Static,
489480093f4SDimitry Andric               JITDylibSearchOrder({{&SrcJD, SourceJDLookupFlags}}),
490480093f4SDimitry Andric               QuerySymbols, SymbolState::Resolved, std::move(OnComplete),
4910b57cec5SDimitry Andric               std::move(RegisterDependencies));
4920b57cec5SDimitry Andric   }
4930b57cec5SDimitry Andric }
4940b57cec5SDimitry Andric 
4950b57cec5SDimitry Andric void ReExportsMaterializationUnit::discard(const JITDylib &JD,
4960b57cec5SDimitry Andric                                            const SymbolStringPtr &Name) {
4970b57cec5SDimitry Andric   assert(Aliases.count(Name) &&
4980b57cec5SDimitry Andric          "Symbol not covered by this MaterializationUnit");
4990b57cec5SDimitry Andric   Aliases.erase(Name);
5000b57cec5SDimitry Andric }
5010b57cec5SDimitry Andric 
5020eae32dcSDimitry Andric MaterializationUnit::Interface
5030b57cec5SDimitry Andric ReExportsMaterializationUnit::extractFlags(const SymbolAliasMap &Aliases) {
5040b57cec5SDimitry Andric   SymbolFlagsMap SymbolFlags;
5050b57cec5SDimitry Andric   for (auto &KV : Aliases)
5060b57cec5SDimitry Andric     SymbolFlags[KV.first] = KV.second.AliasFlags;
5070b57cec5SDimitry Andric 
5080eae32dcSDimitry Andric   return MaterializationUnit::Interface(std::move(SymbolFlags), nullptr);
5090b57cec5SDimitry Andric }
5100b57cec5SDimitry Andric 
511e8d8bef9SDimitry Andric Expected<SymbolAliasMap> buildSimpleReexportsAliasMap(JITDylib &SourceJD,
512e8d8bef9SDimitry Andric                                                       SymbolNameSet Symbols) {
513480093f4SDimitry Andric   SymbolLookupSet LookupSet(Symbols);
514e8d8bef9SDimitry Andric   auto Flags = SourceJD.getExecutionSession().lookupFlags(
515e8d8bef9SDimitry Andric       LookupKind::Static, {{&SourceJD, JITDylibLookupFlags::MatchAllSymbols}},
516e8d8bef9SDimitry Andric       SymbolLookupSet(std::move(Symbols)));
5170b57cec5SDimitry Andric 
5180b57cec5SDimitry Andric   if (!Flags)
5190b57cec5SDimitry Andric     return Flags.takeError();
5200b57cec5SDimitry Andric 
5210b57cec5SDimitry Andric   SymbolAliasMap Result;
5220b57cec5SDimitry Andric   for (auto &Name : Symbols) {
5230b57cec5SDimitry Andric     assert(Flags->count(Name) && "Missing entry in flags map");
5240b57cec5SDimitry Andric     Result[Name] = SymbolAliasMapEntry(Name, (*Flags)[Name]);
5250b57cec5SDimitry Andric   }
5260b57cec5SDimitry Andric 
5270b57cec5SDimitry Andric   return Result;
5280b57cec5SDimitry Andric }
5290b57cec5SDimitry Andric 
530e8d8bef9SDimitry Andric class InProgressLookupState {
531e8d8bef9SDimitry Andric public:
53281ad6265SDimitry Andric   // FIXME: Reduce the number of SymbolStringPtrs here. See
53381ad6265SDimitry Andric   //        https://github.com/llvm/llvm-project/issues/55576.
53481ad6265SDimitry Andric 
535e8d8bef9SDimitry Andric   InProgressLookupState(LookupKind K, JITDylibSearchOrder SearchOrder,
536e8d8bef9SDimitry Andric                         SymbolLookupSet LookupSet, SymbolState RequiredState)
537e8d8bef9SDimitry Andric       : K(K), SearchOrder(std::move(SearchOrder)),
538e8d8bef9SDimitry Andric         LookupSet(std::move(LookupSet)), RequiredState(RequiredState) {
539e8d8bef9SDimitry Andric     DefGeneratorCandidates = this->LookupSet;
540e8d8bef9SDimitry Andric   }
54181ad6265SDimitry Andric   virtual ~InProgressLookupState() = default;
542e8d8bef9SDimitry Andric   virtual void complete(std::unique_ptr<InProgressLookupState> IPLS) = 0;
543e8d8bef9SDimitry Andric   virtual void fail(Error Err) = 0;
544e8d8bef9SDimitry Andric 
545e8d8bef9SDimitry Andric   LookupKind K;
546e8d8bef9SDimitry Andric   JITDylibSearchOrder SearchOrder;
547e8d8bef9SDimitry Andric   SymbolLookupSet LookupSet;
548e8d8bef9SDimitry Andric   SymbolState RequiredState;
549e8d8bef9SDimitry Andric 
550e8d8bef9SDimitry Andric   size_t CurSearchOrderIndex = 0;
551e8d8bef9SDimitry Andric   bool NewJITDylib = true;
552e8d8bef9SDimitry Andric   SymbolLookupSet DefGeneratorCandidates;
553e8d8bef9SDimitry Andric   SymbolLookupSet DefGeneratorNonCandidates;
5545f757f3fSDimitry Andric 
5555f757f3fSDimitry Andric   enum {
5565f757f3fSDimitry Andric     NotInGenerator,      // Not currently using a generator.
5575f757f3fSDimitry Andric     ResumedForGenerator, // Resumed after being auto-suspended before generator.
5585f757f3fSDimitry Andric     InGenerator          // Currently using generator.
5595f757f3fSDimitry Andric   } GenState = NotInGenerator;
560e8d8bef9SDimitry Andric   std::vector<std::weak_ptr<DefinitionGenerator>> CurDefGeneratorStack;
561e8d8bef9SDimitry Andric };
562e8d8bef9SDimitry Andric 
563e8d8bef9SDimitry Andric class InProgressLookupFlagsState : public InProgressLookupState {
564e8d8bef9SDimitry Andric public:
565e8d8bef9SDimitry Andric   InProgressLookupFlagsState(
566e8d8bef9SDimitry Andric       LookupKind K, JITDylibSearchOrder SearchOrder, SymbolLookupSet LookupSet,
567e8d8bef9SDimitry Andric       unique_function<void(Expected<SymbolFlagsMap>)> OnComplete)
568e8d8bef9SDimitry Andric       : InProgressLookupState(K, std::move(SearchOrder), std::move(LookupSet),
569e8d8bef9SDimitry Andric                               SymbolState::NeverSearched),
570e8d8bef9SDimitry Andric         OnComplete(std::move(OnComplete)) {}
571e8d8bef9SDimitry Andric 
572e8d8bef9SDimitry Andric   void complete(std::unique_ptr<InProgressLookupState> IPLS) override {
573e8d8bef9SDimitry Andric     auto &ES = SearchOrder.front().first->getExecutionSession();
574e8d8bef9SDimitry Andric     ES.OL_completeLookupFlags(std::move(IPLS), std::move(OnComplete));
575e8d8bef9SDimitry Andric   }
576e8d8bef9SDimitry Andric 
5775f757f3fSDimitry Andric   void fail(Error Err) override { OnComplete(std::move(Err)); }
578e8d8bef9SDimitry Andric 
579e8d8bef9SDimitry Andric private:
580e8d8bef9SDimitry Andric   unique_function<void(Expected<SymbolFlagsMap>)> OnComplete;
581e8d8bef9SDimitry Andric };
582e8d8bef9SDimitry Andric 
583e8d8bef9SDimitry Andric class InProgressFullLookupState : public InProgressLookupState {
584e8d8bef9SDimitry Andric public:
585e8d8bef9SDimitry Andric   InProgressFullLookupState(LookupKind K, JITDylibSearchOrder SearchOrder,
586e8d8bef9SDimitry Andric                             SymbolLookupSet LookupSet,
587e8d8bef9SDimitry Andric                             SymbolState RequiredState,
588e8d8bef9SDimitry Andric                             std::shared_ptr<AsynchronousSymbolQuery> Q,
589e8d8bef9SDimitry Andric                             RegisterDependenciesFunction RegisterDependencies)
590e8d8bef9SDimitry Andric       : InProgressLookupState(K, std::move(SearchOrder), std::move(LookupSet),
591e8d8bef9SDimitry Andric                               RequiredState),
592e8d8bef9SDimitry Andric         Q(std::move(Q)), RegisterDependencies(std::move(RegisterDependencies)) {
593e8d8bef9SDimitry Andric   }
594e8d8bef9SDimitry Andric 
595e8d8bef9SDimitry Andric   void complete(std::unique_ptr<InProgressLookupState> IPLS) override {
596e8d8bef9SDimitry Andric     auto &ES = SearchOrder.front().first->getExecutionSession();
597e8d8bef9SDimitry Andric     ES.OL_completeLookup(std::move(IPLS), std::move(Q),
598e8d8bef9SDimitry Andric                          std::move(RegisterDependencies));
599e8d8bef9SDimitry Andric   }
600e8d8bef9SDimitry Andric 
601e8d8bef9SDimitry Andric   void fail(Error Err) override {
602e8d8bef9SDimitry Andric     Q->detach();
603e8d8bef9SDimitry Andric     Q->handleFailed(std::move(Err));
604e8d8bef9SDimitry Andric   }
605e8d8bef9SDimitry Andric 
606e8d8bef9SDimitry Andric private:
607e8d8bef9SDimitry Andric   std::shared_ptr<AsynchronousSymbolQuery> Q;
608e8d8bef9SDimitry Andric   RegisterDependenciesFunction RegisterDependencies;
609e8d8bef9SDimitry Andric };
610e8d8bef9SDimitry Andric 
6110b57cec5SDimitry Andric ReexportsGenerator::ReexportsGenerator(JITDylib &SourceJD,
612480093f4SDimitry Andric                                        JITDylibLookupFlags SourceJDLookupFlags,
6130b57cec5SDimitry Andric                                        SymbolPredicate Allow)
614480093f4SDimitry Andric     : SourceJD(SourceJD), SourceJDLookupFlags(SourceJDLookupFlags),
6150b57cec5SDimitry Andric       Allow(std::move(Allow)) {}
6160b57cec5SDimitry Andric 
617e8d8bef9SDimitry Andric Error ReexportsGenerator::tryToGenerate(LookupState &LS, LookupKind K,
618e8d8bef9SDimitry Andric                                         JITDylib &JD,
619480093f4SDimitry Andric                                         JITDylibLookupFlags JDLookupFlags,
620480093f4SDimitry Andric                                         const SymbolLookupSet &LookupSet) {
621480093f4SDimitry Andric   assert(&JD != &SourceJD && "Cannot re-export from the same dylib");
6220b57cec5SDimitry Andric 
623480093f4SDimitry Andric   // Use lookupFlags to find the subset of symbols that match our lookup.
624e8d8bef9SDimitry Andric   auto Flags = JD.getExecutionSession().lookupFlags(
625e8d8bef9SDimitry Andric       K, {{&SourceJD, JDLookupFlags}}, LookupSet);
6260b57cec5SDimitry Andric   if (!Flags)
6270b57cec5SDimitry Andric     return Flags.takeError();
6280b57cec5SDimitry Andric 
629480093f4SDimitry Andric   // Create an alias map.
630480093f4SDimitry Andric   orc::SymbolAliasMap AliasMap;
631480093f4SDimitry Andric   for (auto &KV : *Flags)
632480093f4SDimitry Andric     if (!Allow || Allow(KV.first))
6330b57cec5SDimitry Andric       AliasMap[KV.first] = SymbolAliasMapEntry(KV.first, KV.second);
6340b57cec5SDimitry Andric 
635480093f4SDimitry Andric   if (AliasMap.empty())
636480093f4SDimitry Andric     return Error::success();
6370b57cec5SDimitry Andric 
638480093f4SDimitry Andric   // Define the re-exports.
639480093f4SDimitry Andric   return JD.define(reexports(SourceJD, AliasMap, SourceJDLookupFlags));
6400b57cec5SDimitry Andric }
6410b57cec5SDimitry Andric 
642e8d8bef9SDimitry Andric LookupState::LookupState(std::unique_ptr<InProgressLookupState> IPLS)
643e8d8bef9SDimitry Andric     : IPLS(std::move(IPLS)) {}
644e8d8bef9SDimitry Andric 
645e8d8bef9SDimitry Andric void LookupState::reset(InProgressLookupState *IPLS) { this->IPLS.reset(IPLS); }
646e8d8bef9SDimitry Andric 
647e8d8bef9SDimitry Andric LookupState::LookupState() = default;
648e8d8bef9SDimitry Andric LookupState::LookupState(LookupState &&) = default;
649e8d8bef9SDimitry Andric LookupState &LookupState::operator=(LookupState &&) = default;
650e8d8bef9SDimitry Andric LookupState::~LookupState() = default;
651e8d8bef9SDimitry Andric 
652e8d8bef9SDimitry Andric void LookupState::continueLookup(Error Err) {
653e8d8bef9SDimitry Andric   assert(IPLS && "Cannot call continueLookup on empty LookupState");
654e8d8bef9SDimitry Andric   auto &ES = IPLS->SearchOrder.begin()->first->getExecutionSession();
655e8d8bef9SDimitry Andric   ES.OL_applyQueryPhase1(std::move(IPLS), std::move(Err));
656e8d8bef9SDimitry Andric }
657e8d8bef9SDimitry Andric 
6585f757f3fSDimitry Andric DefinitionGenerator::~DefinitionGenerator() {
6595f757f3fSDimitry Andric   std::deque<LookupState> LookupsToFail;
6605f757f3fSDimitry Andric   {
6615f757f3fSDimitry Andric     std::lock_guard<std::mutex> Lock(M);
6625f757f3fSDimitry Andric     std::swap(PendingLookups, LookupsToFail);
6635f757f3fSDimitry Andric     InUse = false;
6645f757f3fSDimitry Andric   }
6655f757f3fSDimitry Andric 
6665f757f3fSDimitry Andric   for (auto &LS : LookupsToFail)
6675f757f3fSDimitry Andric     LS.continueLookup(make_error<StringError>(
6685f757f3fSDimitry Andric         "Query waiting on DefinitionGenerator that was destroyed",
6695f757f3fSDimitry Andric         inconvertibleErrorCode()));
6705f757f3fSDimitry Andric }
671e8d8bef9SDimitry Andric 
6724824e7fdSDimitry Andric JITDylib::~JITDylib() {
6734824e7fdSDimitry Andric   LLVM_DEBUG(dbgs() << "Destroying JITDylib " << getName() << "\n");
6744824e7fdSDimitry Andric }
6754824e7fdSDimitry Andric 
676e8d8bef9SDimitry Andric Error JITDylib::clear() {
677e8d8bef9SDimitry Andric   std::vector<ResourceTrackerSP> TrackersToRemove;
678e8d8bef9SDimitry Andric   ES.runSessionLocked([&]() {
6794824e7fdSDimitry Andric     assert(State != Closed && "JD is defunct");
680e8d8bef9SDimitry Andric     for (auto &KV : TrackerSymbols)
681e8d8bef9SDimitry Andric       TrackersToRemove.push_back(KV.first);
682e8d8bef9SDimitry Andric     TrackersToRemove.push_back(getDefaultResourceTracker());
683e8d8bef9SDimitry Andric   });
684e8d8bef9SDimitry Andric 
685e8d8bef9SDimitry Andric   Error Err = Error::success();
686e8d8bef9SDimitry Andric   for (auto &RT : TrackersToRemove)
687e8d8bef9SDimitry Andric     Err = joinErrors(std::move(Err), RT->remove());
688e8d8bef9SDimitry Andric   return Err;
689e8d8bef9SDimitry Andric }
690e8d8bef9SDimitry Andric 
691e8d8bef9SDimitry Andric ResourceTrackerSP JITDylib::getDefaultResourceTracker() {
692e8d8bef9SDimitry Andric   return ES.runSessionLocked([this] {
6934824e7fdSDimitry Andric     assert(State != Closed && "JD is defunct");
694e8d8bef9SDimitry Andric     if (!DefaultTracker)
695e8d8bef9SDimitry Andric       DefaultTracker = new ResourceTracker(this);
696e8d8bef9SDimitry Andric     return DefaultTracker;
697e8d8bef9SDimitry Andric   });
698e8d8bef9SDimitry Andric }
699e8d8bef9SDimitry Andric 
700e8d8bef9SDimitry Andric ResourceTrackerSP JITDylib::createResourceTracker() {
701e8d8bef9SDimitry Andric   return ES.runSessionLocked([this] {
7024824e7fdSDimitry Andric     assert(State == Open && "JD is defunct");
703e8d8bef9SDimitry Andric     ResourceTrackerSP RT = new ResourceTracker(this);
704e8d8bef9SDimitry Andric     return RT;
705e8d8bef9SDimitry Andric   });
706e8d8bef9SDimitry Andric }
7078bcb0991SDimitry Andric 
7088bcb0991SDimitry Andric void JITDylib::removeGenerator(DefinitionGenerator &G) {
7095f757f3fSDimitry Andric   // DefGenerator moved into TmpDG to ensure that it's destroyed outside the
7105f757f3fSDimitry Andric   // session lock (since it may have to send errors to pending queries).
7115f757f3fSDimitry Andric   std::shared_ptr<DefinitionGenerator> TmpDG;
7125f757f3fSDimitry Andric 
7134824e7fdSDimitry Andric   ES.runSessionLocked([&] {
7144824e7fdSDimitry Andric     assert(State == Open && "JD is defunct");
715e8d8bef9SDimitry Andric     auto I = llvm::find_if(DefGenerators,
716e8d8bef9SDimitry Andric                            [&](const std::shared_ptr<DefinitionGenerator> &H) {
7178bcb0991SDimitry Andric                              return H.get() == &G;
7188bcb0991SDimitry Andric                            });
7198bcb0991SDimitry Andric     assert(I != DefGenerators.end() && "Generator not found");
7205f757f3fSDimitry Andric     TmpDG = std::move(*I);
7218bcb0991SDimitry Andric     DefGenerators.erase(I);
7224824e7fdSDimitry Andric   });
7238bcb0991SDimitry Andric }
7248bcb0991SDimitry Andric 
72513138422SDimitry Andric Expected<SymbolFlagsMap>
72606c3fb27SDimitry Andric JITDylib::defineMaterializing(MaterializationResponsibility &FromMR,
72706c3fb27SDimitry Andric                               SymbolFlagsMap SymbolFlags) {
72813138422SDimitry Andric 
72913138422SDimitry Andric   return ES.runSessionLocked([&]() -> Expected<SymbolFlagsMap> {
73006c3fb27SDimitry Andric     if (FromMR.RT->isDefunct())
73106c3fb27SDimitry Andric       return make_error<ResourceTrackerDefunct>(FromMR.RT);
73206c3fb27SDimitry Andric 
73306c3fb27SDimitry Andric     std::vector<NonOwningSymbolStringPtr> AddedSyms;
73406c3fb27SDimitry Andric     std::vector<NonOwningSymbolStringPtr> RejectedWeakDefs;
7350b57cec5SDimitry Andric 
73613138422SDimitry Andric     for (auto SFItr = SymbolFlags.begin(), SFEnd = SymbolFlags.end();
73713138422SDimitry Andric          SFItr != SFEnd; ++SFItr) {
7380b57cec5SDimitry Andric 
73913138422SDimitry Andric       auto &Name = SFItr->first;
74013138422SDimitry Andric       auto &Flags = SFItr->second;
7410b57cec5SDimitry Andric 
74213138422SDimitry Andric       auto EntryItr = Symbols.find(Name);
74313138422SDimitry Andric 
74413138422SDimitry Andric       // If the entry already exists...
74513138422SDimitry Andric       if (EntryItr != Symbols.end()) {
74613138422SDimitry Andric 
74713138422SDimitry Andric         // If this is a strong definition then error out.
74813138422SDimitry Andric         if (!Flags.isWeak()) {
7490b57cec5SDimitry Andric           // Remove any symbols already added.
75006c3fb27SDimitry Andric           for (auto &S : AddedSyms)
75106c3fb27SDimitry Andric             Symbols.erase(Symbols.find_as(S));
7520b57cec5SDimitry Andric 
7530b57cec5SDimitry Andric           // FIXME: Return all duplicates.
7545ffd83dbSDimitry Andric           return make_error<DuplicateDefinition>(std::string(*Name));
7550b57cec5SDimitry Andric         }
7560b57cec5SDimitry Andric 
75713138422SDimitry Andric         // Otherwise just make a note to discard this symbol after the loop.
75806c3fb27SDimitry Andric         RejectedWeakDefs.push_back(NonOwningSymbolStringPtr(Name));
75913138422SDimitry Andric         continue;
76013138422SDimitry Andric       } else
76113138422SDimitry Andric         EntryItr =
76213138422SDimitry Andric           Symbols.insert(std::make_pair(Name, SymbolTableEntry(Flags))).first;
76313138422SDimitry Andric 
76406c3fb27SDimitry Andric       AddedSyms.push_back(NonOwningSymbolStringPtr(Name));
76513138422SDimitry Andric       EntryItr->second.setState(SymbolState::Materializing);
76613138422SDimitry Andric     }
76713138422SDimitry Andric 
76813138422SDimitry Andric     // Remove any rejected weak definitions from the SymbolFlags map.
76913138422SDimitry Andric     while (!RejectedWeakDefs.empty()) {
77006c3fb27SDimitry Andric       SymbolFlags.erase(SymbolFlags.find_as(RejectedWeakDefs.back()));
77113138422SDimitry Andric       RejectedWeakDefs.pop_back();
77213138422SDimitry Andric     }
77313138422SDimitry Andric 
77413138422SDimitry Andric     return SymbolFlags;
7750b57cec5SDimitry Andric   });
7760b57cec5SDimitry Andric }
7770b57cec5SDimitry Andric 
778e8d8bef9SDimitry Andric Error JITDylib::replace(MaterializationResponsibility &FromMR,
779e8d8bef9SDimitry Andric                         std::unique_ptr<MaterializationUnit> MU) {
7800b57cec5SDimitry Andric   assert(MU != nullptr && "Can not replace with a null MaterializationUnit");
781e8d8bef9SDimitry Andric   std::unique_ptr<MaterializationUnit> MustRunMU;
782e8d8bef9SDimitry Andric   std::unique_ptr<MaterializationResponsibility> MustRunMR;
7830b57cec5SDimitry Andric 
784e8d8bef9SDimitry Andric   auto Err =
785e8d8bef9SDimitry Andric       ES.runSessionLocked([&, this]() -> Error {
7864824e7fdSDimitry Andric         if (FromMR.RT->isDefunct())
7874824e7fdSDimitry Andric           return make_error<ResourceTrackerDefunct>(std::move(FromMR.RT));
7880b57cec5SDimitry Andric 
7890b57cec5SDimitry Andric #ifndef NDEBUG
7900b57cec5SDimitry Andric         for (auto &KV : MU->getSymbols()) {
7910b57cec5SDimitry Andric           auto SymI = Symbols.find(KV.first);
7920b57cec5SDimitry Andric           assert(SymI != Symbols.end() && "Replacing unknown symbol");
7935ffd83dbSDimitry Andric           assert(SymI->second.getState() == SymbolState::Materializing &&
7945ffd83dbSDimitry Andric                  "Can not replace a symbol that ha is not materializing");
7950b57cec5SDimitry Andric           assert(!SymI->second.hasMaterializerAttached() &&
7960b57cec5SDimitry Andric                  "Symbol should not have materializer attached already");
7970b57cec5SDimitry Andric           assert(UnmaterializedInfos.count(KV.first) == 0 &&
7980b57cec5SDimitry Andric                  "Symbol being replaced should have no UnmaterializedInfo");
7990b57cec5SDimitry Andric         }
8000b57cec5SDimitry Andric #endif // NDEBUG
8010b57cec5SDimitry Andric 
802e8d8bef9SDimitry Andric         // If the tracker is defunct we need to bail out immediately.
803e8d8bef9SDimitry Andric 
8040b57cec5SDimitry Andric         // If any symbol has pending queries against it then we need to
8050b57cec5SDimitry Andric         // materialize MU immediately.
8060b57cec5SDimitry Andric         for (auto &KV : MU->getSymbols()) {
8070b57cec5SDimitry Andric           auto MII = MaterializingInfos.find(KV.first);
8080b57cec5SDimitry Andric           if (MII != MaterializingInfos.end()) {
809e8d8bef9SDimitry Andric             if (MII->second.hasQueriesPending()) {
810e8d8bef9SDimitry Andric               MustRunMR = ES.createMaterializationResponsibility(
8114824e7fdSDimitry Andric                   *FromMR.RT, std::move(MU->SymbolFlags),
8124824e7fdSDimitry Andric                   std::move(MU->InitSymbol));
813e8d8bef9SDimitry Andric               MustRunMU = std::move(MU);
814e8d8bef9SDimitry Andric               return Error::success();
815e8d8bef9SDimitry Andric             }
8160b57cec5SDimitry Andric           }
8170b57cec5SDimitry Andric         }
8180b57cec5SDimitry Andric 
8190b57cec5SDimitry Andric         // Otherwise, make MU responsible for all the symbols.
8204824e7fdSDimitry Andric         auto UMI = std::make_shared<UnmaterializedInfo>(std::move(MU),
8214824e7fdSDimitry Andric                                                         FromMR.RT.get());
8220b57cec5SDimitry Andric         for (auto &KV : UMI->MU->getSymbols()) {
8230b57cec5SDimitry Andric           auto SymI = Symbols.find(KV.first);
8240b57cec5SDimitry Andric           assert(SymI->second.getState() == SymbolState::Materializing &&
8250b57cec5SDimitry Andric                  "Can not replace a symbol that is not materializing");
8260b57cec5SDimitry Andric           assert(!SymI->second.hasMaterializerAttached() &&
8270b57cec5SDimitry Andric                  "Can not replace a symbol that has a materializer attached");
8280b57cec5SDimitry Andric           assert(UnmaterializedInfos.count(KV.first) == 0 &&
8290b57cec5SDimitry Andric                  "Unexpected materializer entry in map");
8300b57cec5SDimitry Andric           SymI->second.setAddress(SymI->second.getAddress());
8310b57cec5SDimitry Andric           SymI->second.setMaterializerAttached(true);
8325ffd83dbSDimitry Andric 
8335ffd83dbSDimitry Andric           auto &UMIEntry = UnmaterializedInfos[KV.first];
8345ffd83dbSDimitry Andric           assert((!UMIEntry || !UMIEntry->MU) &&
8355ffd83dbSDimitry Andric                  "Replacing symbol with materializer still attached");
8365ffd83dbSDimitry Andric           UMIEntry = UMI;
8370b57cec5SDimitry Andric         }
8380b57cec5SDimitry Andric 
839e8d8bef9SDimitry Andric         return Error::success();
8400b57cec5SDimitry Andric       });
8410b57cec5SDimitry Andric 
842e8d8bef9SDimitry Andric   if (Err)
843e8d8bef9SDimitry Andric     return Err;
844e8d8bef9SDimitry Andric 
8455ffd83dbSDimitry Andric   if (MustRunMU) {
846e8d8bef9SDimitry Andric     assert(MustRunMR && "MustRunMU set implies MustRunMR set");
847fe6060f1SDimitry Andric     ES.dispatchTask(std::make_unique<MaterializationTask>(
848fe6060f1SDimitry Andric         std::move(MustRunMU), std::move(MustRunMR)));
849e8d8bef9SDimitry Andric   } else {
850e8d8bef9SDimitry Andric     assert(!MustRunMR && "MustRunMU unset implies MustRunMR unset");
8515ffd83dbSDimitry Andric   }
852e8d8bef9SDimitry Andric 
853e8d8bef9SDimitry Andric   return Error::success();
854e8d8bef9SDimitry Andric }
855e8d8bef9SDimitry Andric 
856e8d8bef9SDimitry Andric Expected<std::unique_ptr<MaterializationResponsibility>>
857e8d8bef9SDimitry Andric JITDylib::delegate(MaterializationResponsibility &FromMR,
858e8d8bef9SDimitry Andric                    SymbolFlagsMap SymbolFlags, SymbolStringPtr InitSymbol) {
859e8d8bef9SDimitry Andric 
860e8d8bef9SDimitry Andric   return ES.runSessionLocked(
861e8d8bef9SDimitry Andric       [&]() -> Expected<std::unique_ptr<MaterializationResponsibility>> {
8624824e7fdSDimitry Andric         if (FromMR.RT->isDefunct())
8634824e7fdSDimitry Andric           return make_error<ResourceTrackerDefunct>(std::move(FromMR.RT));
864e8d8bef9SDimitry Andric 
865e8d8bef9SDimitry Andric         return ES.createMaterializationResponsibility(
8664824e7fdSDimitry Andric             *FromMR.RT, std::move(SymbolFlags), std::move(InitSymbol));
867e8d8bef9SDimitry Andric       });
8680b57cec5SDimitry Andric }
8690b57cec5SDimitry Andric 
8700b57cec5SDimitry Andric SymbolNameSet
8710b57cec5SDimitry Andric JITDylib::getRequestedSymbols(const SymbolFlagsMap &SymbolFlags) const {
8720b57cec5SDimitry Andric   return ES.runSessionLocked([&]() {
8730b57cec5SDimitry Andric     SymbolNameSet RequestedSymbols;
8740b57cec5SDimitry Andric 
8750b57cec5SDimitry Andric     for (auto &KV : SymbolFlags) {
8760b57cec5SDimitry Andric       assert(Symbols.count(KV.first) && "JITDylib does not cover this symbol?");
8775ffd83dbSDimitry Andric       assert(Symbols.find(KV.first)->second.getState() !=
8785ffd83dbSDimitry Andric                  SymbolState::NeverSearched &&
8795ffd83dbSDimitry Andric              Symbols.find(KV.first)->second.getState() != SymbolState::Ready &&
8800b57cec5SDimitry Andric              "getRequestedSymbols can only be called for symbols that have "
8810b57cec5SDimitry Andric              "started materializing");
8820b57cec5SDimitry Andric       auto I = MaterializingInfos.find(KV.first);
8830b57cec5SDimitry Andric       if (I == MaterializingInfos.end())
8840b57cec5SDimitry Andric         continue;
8850b57cec5SDimitry Andric 
8860b57cec5SDimitry Andric       if (I->second.hasQueriesPending())
8870b57cec5SDimitry Andric         RequestedSymbols.insert(KV.first);
8880b57cec5SDimitry Andric     }
8890b57cec5SDimitry Andric 
8900b57cec5SDimitry Andric     return RequestedSymbols;
8910b57cec5SDimitry Andric   });
8920b57cec5SDimitry Andric }
8930b57cec5SDimitry Andric 
894e8d8bef9SDimitry Andric Error JITDylib::resolve(MaterializationResponsibility &MR,
895e8d8bef9SDimitry Andric                         const SymbolMap &Resolved) {
8960b57cec5SDimitry Andric   AsynchronousSymbolQuerySet CompletedQueries;
8978bcb0991SDimitry Andric 
898e8d8bef9SDimitry Andric   if (auto Err = ES.runSessionLocked([&, this]() -> Error {
8994824e7fdSDimitry Andric         if (MR.RT->isDefunct())
9004824e7fdSDimitry Andric           return make_error<ResourceTrackerDefunct>(MR.RT);
9014824e7fdSDimitry Andric 
9024824e7fdSDimitry Andric         if (State != Open)
9034824e7fdSDimitry Andric           return make_error<StringError>("JITDylib " + getName() +
9044824e7fdSDimitry Andric                                              " is defunct",
9054824e7fdSDimitry Andric                                          inconvertibleErrorCode());
906e8d8bef9SDimitry Andric 
9078bcb0991SDimitry Andric         struct WorklistEntry {
9088bcb0991SDimitry Andric           SymbolTable::iterator SymI;
90906c3fb27SDimitry Andric           ExecutorSymbolDef ResolvedSym;
9108bcb0991SDimitry Andric         };
9118bcb0991SDimitry Andric 
912e8d8bef9SDimitry Andric         SymbolNameSet SymbolsInErrorState;
9138bcb0991SDimitry Andric         std::vector<WorklistEntry> Worklist;
9148bcb0991SDimitry Andric         Worklist.reserve(Resolved.size());
9158bcb0991SDimitry Andric 
9168bcb0991SDimitry Andric         // Build worklist and check for any symbols in the error state.
9170b57cec5SDimitry Andric         for (const auto &KV : Resolved) {
9180b57cec5SDimitry Andric 
9198bcb0991SDimitry Andric           assert(!KV.second.getFlags().hasError() &&
9208bcb0991SDimitry Andric                  "Resolution result can not have error flag set");
9210b57cec5SDimitry Andric 
9228bcb0991SDimitry Andric           auto SymI = Symbols.find(KV.first);
9238bcb0991SDimitry Andric 
9248bcb0991SDimitry Andric           assert(SymI != Symbols.end() && "Symbol not found");
9258bcb0991SDimitry Andric           assert(!SymI->second.hasMaterializerAttached() &&
9260b57cec5SDimitry Andric                  "Resolving symbol with materializer attached?");
9278bcb0991SDimitry Andric           assert(SymI->second.getState() == SymbolState::Materializing &&
9280b57cec5SDimitry Andric                  "Symbol should be materializing");
92906c3fb27SDimitry Andric           assert(SymI->second.getAddress() == ExecutorAddr() &&
9308bcb0991SDimitry Andric                  "Symbol has already been resolved");
9310b57cec5SDimitry Andric 
9328bcb0991SDimitry Andric           if (SymI->second.getFlags().hasError())
9338bcb0991SDimitry Andric             SymbolsInErrorState.insert(KV.first);
9348bcb0991SDimitry Andric           else {
9358bcb0991SDimitry Andric             auto Flags = KV.second.getFlags();
936bdd1243dSDimitry Andric             Flags &= ~JITSymbolFlags::Common;
937e8d8bef9SDimitry Andric             assert(Flags ==
938bdd1243dSDimitry Andric                        (SymI->second.getFlags() & ~JITSymbolFlags::Common) &&
9390b57cec5SDimitry Andric                    "Resolved flags should match the declared flags");
9400b57cec5SDimitry Andric 
94106c3fb27SDimitry Andric             Worklist.push_back({SymI, {KV.second.getAddress(), Flags}});
9428bcb0991SDimitry Andric           }
9438bcb0991SDimitry Andric         }
9448bcb0991SDimitry Andric 
9458bcb0991SDimitry Andric         // If any symbols were in the error state then bail out.
946e8d8bef9SDimitry Andric         if (!SymbolsInErrorState.empty()) {
947e8d8bef9SDimitry Andric           auto FailedSymbolsDepMap = std::make_shared<SymbolDependenceMap>();
948e8d8bef9SDimitry Andric           (*FailedSymbolsDepMap)[this] = std::move(SymbolsInErrorState);
949e8d8bef9SDimitry Andric           return make_error<FailedToMaterialize>(
95081ad6265SDimitry Andric               getExecutionSession().getSymbolStringPool(),
951e8d8bef9SDimitry Andric               std::move(FailedSymbolsDepMap));
952e8d8bef9SDimitry Andric         }
9538bcb0991SDimitry Andric 
9548bcb0991SDimitry Andric         while (!Worklist.empty()) {
9558bcb0991SDimitry Andric           auto SymI = Worklist.back().SymI;
9568bcb0991SDimitry Andric           auto ResolvedSym = Worklist.back().ResolvedSym;
9578bcb0991SDimitry Andric           Worklist.pop_back();
9588bcb0991SDimitry Andric 
9598bcb0991SDimitry Andric           auto &Name = SymI->first;
9608bcb0991SDimitry Andric 
9618bcb0991SDimitry Andric           // Resolved symbols can not be weak: discard the weak flag.
9628bcb0991SDimitry Andric           JITSymbolFlags ResolvedFlags = ResolvedSym.getFlags();
9638bcb0991SDimitry Andric           SymI->second.setAddress(ResolvedSym.getAddress());
9648bcb0991SDimitry Andric           SymI->second.setFlags(ResolvedFlags);
9658bcb0991SDimitry Andric           SymI->second.setState(SymbolState::Resolved);
9660b57cec5SDimitry Andric 
9675ffd83dbSDimitry Andric           auto MII = MaterializingInfos.find(Name);
9685ffd83dbSDimitry Andric           if (MII == MaterializingInfos.end())
9695ffd83dbSDimitry Andric             continue;
9705ffd83dbSDimitry Andric 
9715ffd83dbSDimitry Andric           auto &MI = MII->second;
9720b57cec5SDimitry Andric           for (auto &Q : MI.takeQueriesMeeting(SymbolState::Resolved)) {
9738bcb0991SDimitry Andric             Q->notifySymbolMetRequiredState(Name, ResolvedSym);
9748bcb0991SDimitry Andric             Q->removeQueryDependence(*this, Name);
9750b57cec5SDimitry Andric             if (Q->isComplete())
9760b57cec5SDimitry Andric               CompletedQueries.insert(std::move(Q));
9770b57cec5SDimitry Andric           }
9780b57cec5SDimitry Andric         }
9790b57cec5SDimitry Andric 
980e8d8bef9SDimitry Andric         return Error::success();
981e8d8bef9SDimitry Andric       }))
982e8d8bef9SDimitry Andric     return Err;
9838bcb0991SDimitry Andric 
9848bcb0991SDimitry Andric   // Otherwise notify all the completed queries.
9850b57cec5SDimitry Andric   for (auto &Q : CompletedQueries) {
9860b57cec5SDimitry Andric     assert(Q->isComplete() && "Q not completed");
987fe6060f1SDimitry Andric     Q->handleComplete(ES);
9880b57cec5SDimitry Andric   }
9898bcb0991SDimitry Andric 
9908bcb0991SDimitry Andric   return Error::success();
9910b57cec5SDimitry Andric }
9920b57cec5SDimitry Andric 
993e8d8bef9SDimitry Andric void JITDylib::unlinkMaterializationResponsibility(
994e8d8bef9SDimitry Andric     MaterializationResponsibility &MR) {
995e8d8bef9SDimitry Andric   ES.runSessionLocked([&]() {
9964824e7fdSDimitry Andric     auto I = TrackerMRs.find(MR.RT.get());
9974824e7fdSDimitry Andric     assert(I != TrackerMRs.end() && "No MRs in TrackerMRs list for RT");
9984824e7fdSDimitry Andric     assert(I->second.count(&MR) && "MR not in TrackerMRs list for RT");
9994824e7fdSDimitry Andric     I->second.erase(&MR);
10004824e7fdSDimitry Andric     if (I->second.empty())
10014824e7fdSDimitry Andric       TrackerMRs.erase(MR.RT.get());
1002e8d8bef9SDimitry Andric   });
1003e8d8bef9SDimitry Andric }
1004e8d8bef9SDimitry Andric 
10050fca6ea1SDimitry Andric void JITDylib::shrinkMaterializationInfoMemory() {
10060fca6ea1SDimitry Andric   // DenseMap::erase never shrinks its storage; use clear to heuristically free
10070fca6ea1SDimitry Andric   // memory since we may have long-lived JDs after linking is done.
10080b57cec5SDimitry Andric 
10090fca6ea1SDimitry Andric   if (UnmaterializedInfos.empty())
10100fca6ea1SDimitry Andric     UnmaterializedInfos.clear();
10118bcb0991SDimitry Andric 
10120fca6ea1SDimitry Andric   if (MaterializingInfos.empty())
10130fca6ea1SDimitry Andric     MaterializingInfos.clear();
10140b57cec5SDimitry Andric }
10150b57cec5SDimitry Andric 
10165ffd83dbSDimitry Andric void JITDylib::setLinkOrder(JITDylibSearchOrder NewLinkOrder,
10175ffd83dbSDimitry Andric                             bool LinkAgainstThisJITDylibFirst) {
10180b57cec5SDimitry Andric   ES.runSessionLocked([&]() {
10194824e7fdSDimitry Andric     assert(State == Open && "JD is defunct");
10205ffd83dbSDimitry Andric     if (LinkAgainstThisJITDylibFirst) {
10215ffd83dbSDimitry Andric       LinkOrder.clear();
10225ffd83dbSDimitry Andric       if (NewLinkOrder.empty() || NewLinkOrder.front().first != this)
10235ffd83dbSDimitry Andric         LinkOrder.push_back(
1024480093f4SDimitry Andric             std::make_pair(this, JITDylibLookupFlags::MatchAllSymbols));
1025e8d8bef9SDimitry Andric       llvm::append_range(LinkOrder, NewLinkOrder);
1026480093f4SDimitry Andric     } else
10275ffd83dbSDimitry Andric       LinkOrder = std::move(NewLinkOrder);
10280b57cec5SDimitry Andric   });
10290b57cec5SDimitry Andric }
10300b57cec5SDimitry Andric 
103106c3fb27SDimitry Andric void JITDylib::addToLinkOrder(const JITDylibSearchOrder &NewLinks) {
103206c3fb27SDimitry Andric   ES.runSessionLocked([&]() {
103306c3fb27SDimitry Andric     for (auto &KV : NewLinks) {
103406c3fb27SDimitry Andric       // Skip elements of NewLinks that are already in the link order.
10355f757f3fSDimitry Andric       if (llvm::is_contained(LinkOrder, KV))
103606c3fb27SDimitry Andric         continue;
103706c3fb27SDimitry Andric 
103806c3fb27SDimitry Andric       LinkOrder.push_back(std::move(KV));
103906c3fb27SDimitry Andric     }
104006c3fb27SDimitry Andric   });
104106c3fb27SDimitry Andric }
104206c3fb27SDimitry Andric 
10435ffd83dbSDimitry Andric void JITDylib::addToLinkOrder(JITDylib &JD, JITDylibLookupFlags JDLookupFlags) {
10445ffd83dbSDimitry Andric   ES.runSessionLocked([&]() { LinkOrder.push_back({&JD, JDLookupFlags}); });
1045480093f4SDimitry Andric }
1046480093f4SDimitry Andric 
10475ffd83dbSDimitry Andric void JITDylib::replaceInLinkOrder(JITDylib &OldJD, JITDylib &NewJD,
1048480093f4SDimitry Andric                                   JITDylibLookupFlags JDLookupFlags) {
10490b57cec5SDimitry Andric   ES.runSessionLocked([&]() {
10504824e7fdSDimitry Andric     assert(State == Open && "JD is defunct");
10515ffd83dbSDimitry Andric     for (auto &KV : LinkOrder)
1052480093f4SDimitry Andric       if (KV.first == &OldJD) {
1053480093f4SDimitry Andric         KV = {&NewJD, JDLookupFlags};
1054480093f4SDimitry Andric         break;
1055480093f4SDimitry Andric       }
10560b57cec5SDimitry Andric   });
10570b57cec5SDimitry Andric }
10580b57cec5SDimitry Andric 
10595ffd83dbSDimitry Andric void JITDylib::removeFromLinkOrder(JITDylib &JD) {
10600b57cec5SDimitry Andric   ES.runSessionLocked([&]() {
10614824e7fdSDimitry Andric     assert(State == Open && "JD is defunct");
1062e8d8bef9SDimitry Andric     auto I = llvm::find_if(LinkOrder,
1063480093f4SDimitry Andric                            [&](const JITDylibSearchOrder::value_type &KV) {
10640b57cec5SDimitry Andric                              return KV.first == &JD;
10650b57cec5SDimitry Andric                            });
10665ffd83dbSDimitry Andric     if (I != LinkOrder.end())
10675ffd83dbSDimitry Andric       LinkOrder.erase(I);
10680b57cec5SDimitry Andric   });
10690b57cec5SDimitry Andric }
10700b57cec5SDimitry Andric 
10710b57cec5SDimitry Andric Error JITDylib::remove(const SymbolNameSet &Names) {
10720b57cec5SDimitry Andric   return ES.runSessionLocked([&]() -> Error {
10734824e7fdSDimitry Andric     assert(State == Open && "JD is defunct");
10740b57cec5SDimitry Andric     using SymbolMaterializerItrPair =
10750b57cec5SDimitry Andric         std::pair<SymbolTable::iterator, UnmaterializedInfosMap::iterator>;
10760b57cec5SDimitry Andric     std::vector<SymbolMaterializerItrPair> SymbolsToRemove;
10770b57cec5SDimitry Andric     SymbolNameSet Missing;
10780b57cec5SDimitry Andric     SymbolNameSet Materializing;
10790b57cec5SDimitry Andric 
10800b57cec5SDimitry Andric     for (auto &Name : Names) {
10810b57cec5SDimitry Andric       auto I = Symbols.find(Name);
10820b57cec5SDimitry Andric 
10830b57cec5SDimitry Andric       // Note symbol missing.
10840b57cec5SDimitry Andric       if (I == Symbols.end()) {
10850b57cec5SDimitry Andric         Missing.insert(Name);
10860b57cec5SDimitry Andric         continue;
10870b57cec5SDimitry Andric       }
10880b57cec5SDimitry Andric 
10890b57cec5SDimitry Andric       // Note symbol materializing.
10905ffd83dbSDimitry Andric       if (I->second.getState() != SymbolState::NeverSearched &&
10915ffd83dbSDimitry Andric           I->second.getState() != SymbolState::Ready) {
10920b57cec5SDimitry Andric         Materializing.insert(Name);
10930b57cec5SDimitry Andric         continue;
10940b57cec5SDimitry Andric       }
10950b57cec5SDimitry Andric 
10960b57cec5SDimitry Andric       auto UMII = I->second.hasMaterializerAttached()
10970b57cec5SDimitry Andric                       ? UnmaterializedInfos.find(Name)
10980b57cec5SDimitry Andric                       : UnmaterializedInfos.end();
10990b57cec5SDimitry Andric       SymbolsToRemove.push_back(std::make_pair(I, UMII));
11000b57cec5SDimitry Andric     }
11010b57cec5SDimitry Andric 
11020b57cec5SDimitry Andric     // If any of the symbols are not defined, return an error.
11030b57cec5SDimitry Andric     if (!Missing.empty())
1104349cc55cSDimitry Andric       return make_error<SymbolsNotFound>(ES.getSymbolStringPool(),
1105349cc55cSDimitry Andric                                          std::move(Missing));
11060b57cec5SDimitry Andric 
11070b57cec5SDimitry Andric     // If any of the symbols are currently materializing, return an error.
11080b57cec5SDimitry Andric     if (!Materializing.empty())
1109349cc55cSDimitry Andric       return make_error<SymbolsCouldNotBeRemoved>(ES.getSymbolStringPool(),
1110349cc55cSDimitry Andric                                                   std::move(Materializing));
11110b57cec5SDimitry Andric 
11120b57cec5SDimitry Andric     // Remove the symbols.
11130b57cec5SDimitry Andric     for (auto &SymbolMaterializerItrPair : SymbolsToRemove) {
11140b57cec5SDimitry Andric       auto UMII = SymbolMaterializerItrPair.second;
11150b57cec5SDimitry Andric 
11160b57cec5SDimitry Andric       // If there is a materializer attached, call discard.
11170b57cec5SDimitry Andric       if (UMII != UnmaterializedInfos.end()) {
11180b57cec5SDimitry Andric         UMII->second->MU->doDiscard(*this, UMII->first);
11190b57cec5SDimitry Andric         UnmaterializedInfos.erase(UMII);
11200b57cec5SDimitry Andric       }
11210b57cec5SDimitry Andric 
11220b57cec5SDimitry Andric       auto SymI = SymbolMaterializerItrPair.first;
11230b57cec5SDimitry Andric       Symbols.erase(SymI);
11240b57cec5SDimitry Andric     }
11250b57cec5SDimitry Andric 
11260fca6ea1SDimitry Andric     shrinkMaterializationInfoMemory();
11270fca6ea1SDimitry Andric 
11280b57cec5SDimitry Andric     return Error::success();
11290b57cec5SDimitry Andric   });
11300b57cec5SDimitry Andric }
11310b57cec5SDimitry Andric 
11320b57cec5SDimitry Andric void JITDylib::dump(raw_ostream &OS) {
11330b57cec5SDimitry Andric   ES.runSessionLocked([&, this]() {
11345e801ac6SDimitry Andric     OS << "JITDylib \"" << getName() << "\" (ES: "
11354824e7fdSDimitry Andric        << format("0x%016" PRIx64, reinterpret_cast<uintptr_t>(&ES))
11364824e7fdSDimitry Andric        << ", State = ";
11374824e7fdSDimitry Andric     switch (State) {
11384824e7fdSDimitry Andric     case Open:
11394824e7fdSDimitry Andric       OS << "Open";
11404824e7fdSDimitry Andric       break;
11414824e7fdSDimitry Andric     case Closing:
11424824e7fdSDimitry Andric       OS << "Closing";
11434824e7fdSDimitry Andric       break;
11444824e7fdSDimitry Andric     case Closed:
11454824e7fdSDimitry Andric       OS << "Closed";
11464824e7fdSDimitry Andric       break;
11474824e7fdSDimitry Andric     }
11484824e7fdSDimitry Andric     OS << ")\n";
11494824e7fdSDimitry Andric     if (State == Closed)
11504824e7fdSDimitry Andric       return;
11514824e7fdSDimitry Andric     OS << "Link order: " << LinkOrder << "\n"
11520b57cec5SDimitry Andric        << "Symbol table:\n";
11530b57cec5SDimitry Andric 
115406c3fb27SDimitry Andric     // Sort symbols so we get a deterministic order and can check them in tests.
115506c3fb27SDimitry Andric     std::vector<std::pair<SymbolStringPtr, SymbolTableEntry *>> SymbolsSorted;
115606c3fb27SDimitry Andric     for (auto &KV : Symbols)
115706c3fb27SDimitry Andric       SymbolsSorted.emplace_back(KV.first, &KV.second);
115806c3fb27SDimitry Andric     std::sort(SymbolsSorted.begin(), SymbolsSorted.end(),
115906c3fb27SDimitry Andric               [](const auto &L, const auto &R) { return *L.first < *R.first; });
116006c3fb27SDimitry Andric 
116106c3fb27SDimitry Andric     for (auto &KV : SymbolsSorted) {
11620b57cec5SDimitry Andric       OS << "    \"" << *KV.first << "\": ";
116306c3fb27SDimitry Andric       if (auto Addr = KV.second->getAddress())
116406c3fb27SDimitry Andric         OS << Addr;
11650b57cec5SDimitry Andric       else
11660b57cec5SDimitry Andric         OS << "<not resolved> ";
11670b57cec5SDimitry Andric 
116806c3fb27SDimitry Andric       OS << " " << KV.second->getFlags() << " " << KV.second->getState();
11690b57cec5SDimitry Andric 
117006c3fb27SDimitry Andric       if (KV.second->hasMaterializerAttached()) {
11710b57cec5SDimitry Andric         OS << " (Materializer ";
11720b57cec5SDimitry Andric         auto I = UnmaterializedInfos.find(KV.first);
11730b57cec5SDimitry Andric         assert(I != UnmaterializedInfos.end() &&
11740b57cec5SDimitry Andric                "Lazy symbol should have UnmaterializedInfo");
11755ffd83dbSDimitry Andric         OS << I->second->MU.get() << ", " << I->second->MU->getName() << ")\n";
11760b57cec5SDimitry Andric       } else
11770b57cec5SDimitry Andric         OS << "\n";
11780b57cec5SDimitry Andric     }
11790b57cec5SDimitry Andric 
11800b57cec5SDimitry Andric     if (!MaterializingInfos.empty())
11810b57cec5SDimitry Andric       OS << "  MaterializingInfos entries:\n";
11820b57cec5SDimitry Andric     for (auto &KV : MaterializingInfos) {
11830b57cec5SDimitry Andric       OS << "    \"" << *KV.first << "\":\n"
11840b57cec5SDimitry Andric          << "      " << KV.second.pendingQueries().size()
11850b57cec5SDimitry Andric          << " pending queries: { ";
11860b57cec5SDimitry Andric       for (const auto &Q : KV.second.pendingQueries())
11870b57cec5SDimitry Andric         OS << Q.get() << " (" << Q->getRequiredState() << ") ";
11880fca6ea1SDimitry Andric       OS << "}\n      Defining EDU: ";
11890fca6ea1SDimitry Andric       if (KV.second.DefiningEDU) {
11900fca6ea1SDimitry Andric         OS << KV.second.DefiningEDU.get() << " { ";
11910fca6ea1SDimitry Andric         for (auto &[Name, Flags] : KV.second.DefiningEDU->Symbols)
11920fca6ea1SDimitry Andric           OS << Name << " ";
11930fca6ea1SDimitry Andric         OS << "}\n";
11940fca6ea1SDimitry Andric         OS << "        Dependencies:\n";
11950fca6ea1SDimitry Andric         if (!KV.second.DefiningEDU->Dependencies.empty()) {
11960fca6ea1SDimitry Andric           for (auto &[DepJD, Deps] : KV.second.DefiningEDU->Dependencies) {
11970fca6ea1SDimitry Andric             OS << "          " << DepJD->getName() << ": [ ";
11980fca6ea1SDimitry Andric             for (auto &Dep : Deps)
11990fca6ea1SDimitry Andric               OS << Dep << " ";
12000fca6ea1SDimitry Andric             OS << "]\n";
12010fca6ea1SDimitry Andric           }
12020fca6ea1SDimitry Andric         } else
12030fca6ea1SDimitry Andric           OS << "          none\n";
12040fca6ea1SDimitry Andric       } else
12050fca6ea1SDimitry Andric         OS << "none\n";
12060fca6ea1SDimitry Andric       OS << "      Dependant EDUs:\n";
12070fca6ea1SDimitry Andric       if (!KV.second.DependantEDUs.empty()) {
12080fca6ea1SDimitry Andric         for (auto &DependantEDU : KV.second.DependantEDUs) {
12090fca6ea1SDimitry Andric           OS << "        " << DependantEDU << ": "
12100fca6ea1SDimitry Andric              << DependantEDU->JD->getName() << " { ";
12110fca6ea1SDimitry Andric           for (auto &[Name, Flags] : DependantEDU->Symbols)
12120fca6ea1SDimitry Andric             OS << Name << " ";
12130fca6ea1SDimitry Andric           OS << "}\n";
12140fca6ea1SDimitry Andric         }
12150fca6ea1SDimitry Andric       } else
12160fca6ea1SDimitry Andric         OS << "        none\n";
1217fe6060f1SDimitry Andric       assert((Symbols[KV.first].getState() != SymbolState::Ready ||
12180fca6ea1SDimitry Andric               (KV.second.pendingQueries().empty() && !KV.second.DefiningEDU &&
12190fca6ea1SDimitry Andric                !KV.second.DependantEDUs.empty())) &&
1220fe6060f1SDimitry Andric              "Stale materializing info entry");
12210b57cec5SDimitry Andric     }
12220b57cec5SDimitry Andric   });
12230b57cec5SDimitry Andric }
12240b57cec5SDimitry Andric 
12250b57cec5SDimitry Andric void JITDylib::MaterializingInfo::addQuery(
12260b57cec5SDimitry Andric     std::shared_ptr<AsynchronousSymbolQuery> Q) {
12270b57cec5SDimitry Andric 
1228bdd1243dSDimitry Andric   auto I = llvm::lower_bound(
1229bdd1243dSDimitry Andric       llvm::reverse(PendingQueries), Q->getRequiredState(),
12300b57cec5SDimitry Andric       [](const std::shared_ptr<AsynchronousSymbolQuery> &V, SymbolState S) {
12310b57cec5SDimitry Andric         return V->getRequiredState() <= S;
12320b57cec5SDimitry Andric       });
12330b57cec5SDimitry Andric   PendingQueries.insert(I.base(), std::move(Q));
12340b57cec5SDimitry Andric }
12350b57cec5SDimitry Andric 
12360b57cec5SDimitry Andric void JITDylib::MaterializingInfo::removeQuery(
12370b57cec5SDimitry Andric     const AsynchronousSymbolQuery &Q) {
12380b57cec5SDimitry Andric   // FIXME: Implement 'find_as' for shared_ptr<T>/T*.
1239e8d8bef9SDimitry Andric   auto I = llvm::find_if(
1240e8d8bef9SDimitry Andric       PendingQueries, [&Q](const std::shared_ptr<AsynchronousSymbolQuery> &V) {
12410b57cec5SDimitry Andric         return V.get() == &Q;
12420b57cec5SDimitry Andric       });
12430b57cec5SDimitry Andric   assert(I != PendingQueries.end() &&
12440b57cec5SDimitry Andric          "Query is not attached to this MaterializingInfo");
12450b57cec5SDimitry Andric   PendingQueries.erase(I);
12460b57cec5SDimitry Andric }
12470b57cec5SDimitry Andric 
12480b57cec5SDimitry Andric JITDylib::AsynchronousSymbolQueryList
12490b57cec5SDimitry Andric JITDylib::MaterializingInfo::takeQueriesMeeting(SymbolState RequiredState) {
12500b57cec5SDimitry Andric   AsynchronousSymbolQueryList Result;
12510b57cec5SDimitry Andric   while (!PendingQueries.empty()) {
12520b57cec5SDimitry Andric     if (PendingQueries.back()->getRequiredState() > RequiredState)
12530b57cec5SDimitry Andric       break;
12540b57cec5SDimitry Andric 
12550b57cec5SDimitry Andric     Result.push_back(std::move(PendingQueries.back()));
12560b57cec5SDimitry Andric     PendingQueries.pop_back();
12570b57cec5SDimitry Andric   }
12580b57cec5SDimitry Andric 
12590b57cec5SDimitry Andric   return Result;
12600b57cec5SDimitry Andric }
12610b57cec5SDimitry Andric 
12620b57cec5SDimitry Andric JITDylib::JITDylib(ExecutionSession &ES, std::string Name)
12635e801ac6SDimitry Andric     : JITLinkDylib(std::move(Name)), ES(ES) {
12645ffd83dbSDimitry Andric   LinkOrder.push_back({this, JITDylibLookupFlags::MatchAllSymbols});
12650b57cec5SDimitry Andric }
12660b57cec5SDimitry Andric 
1267e8d8bef9SDimitry Andric std::pair<JITDylib::AsynchronousSymbolQuerySet,
1268e8d8bef9SDimitry Andric           std::shared_ptr<SymbolDependenceMap>>
12690fca6ea1SDimitry Andric JITDylib::IL_removeTracker(ResourceTracker &RT) {
1270e8d8bef9SDimitry Andric   // Note: Should be called under the session lock.
12714824e7fdSDimitry Andric   assert(State != Closed && "JD is defunct");
1272e8d8bef9SDimitry Andric 
1273e8d8bef9SDimitry Andric   SymbolNameVector SymbolsToRemove;
12740fca6ea1SDimitry Andric   SymbolNameVector SymbolsToFail;
1275e8d8bef9SDimitry Andric 
1276e8d8bef9SDimitry Andric   if (&RT == DefaultTracker.get()) {
1277e8d8bef9SDimitry Andric     SymbolNameSet TrackedSymbols;
1278e8d8bef9SDimitry Andric     for (auto &KV : TrackerSymbols)
1279e8d8bef9SDimitry Andric       for (auto &Sym : KV.second)
1280e8d8bef9SDimitry Andric         TrackedSymbols.insert(Sym);
1281e8d8bef9SDimitry Andric 
1282e8d8bef9SDimitry Andric     for (auto &KV : Symbols) {
1283e8d8bef9SDimitry Andric       auto &Sym = KV.first;
1284e8d8bef9SDimitry Andric       if (!TrackedSymbols.count(Sym))
1285e8d8bef9SDimitry Andric         SymbolsToRemove.push_back(Sym);
1286e8d8bef9SDimitry Andric     }
1287e8d8bef9SDimitry Andric 
1288e8d8bef9SDimitry Andric     DefaultTracker.reset();
1289e8d8bef9SDimitry Andric   } else {
1290e8d8bef9SDimitry Andric     /// Check for a non-default tracker.
1291e8d8bef9SDimitry Andric     auto I = TrackerSymbols.find(&RT);
1292e8d8bef9SDimitry Andric     if (I != TrackerSymbols.end()) {
1293e8d8bef9SDimitry Andric       SymbolsToRemove = std::move(I->second);
1294e8d8bef9SDimitry Andric       TrackerSymbols.erase(I);
1295e8d8bef9SDimitry Andric     }
1296e8d8bef9SDimitry Andric     // ... if not found this tracker was already defunct. Nothing to do.
1297e8d8bef9SDimitry Andric   }
1298e8d8bef9SDimitry Andric 
1299e8d8bef9SDimitry Andric   for (auto &Sym : SymbolsToRemove) {
1300e8d8bef9SDimitry Andric     assert(Symbols.count(Sym) && "Symbol not in symbol table");
1301e8d8bef9SDimitry Andric 
1302e8d8bef9SDimitry Andric     // If there is a MaterializingInfo then collect any queries to fail.
1303e8d8bef9SDimitry Andric     auto MII = MaterializingInfos.find(Sym);
1304e8d8bef9SDimitry Andric     if (MII != MaterializingInfos.end())
13050fca6ea1SDimitry Andric       SymbolsToFail.push_back(Sym);
1306e8d8bef9SDimitry Andric   }
1307e8d8bef9SDimitry Andric 
13080fca6ea1SDimitry Andric   auto Result = ES.IL_failSymbols(*this, std::move(SymbolsToFail));
1309e8d8bef9SDimitry Andric 
1310e8d8bef9SDimitry Andric   // Removed symbols should be taken out of the table altogether.
1311e8d8bef9SDimitry Andric   for (auto &Sym : SymbolsToRemove) {
1312e8d8bef9SDimitry Andric     auto I = Symbols.find(Sym);
1313e8d8bef9SDimitry Andric     assert(I != Symbols.end() && "Symbol not present in table");
1314e8d8bef9SDimitry Andric 
1315e8d8bef9SDimitry Andric     // Remove Materializer if present.
1316e8d8bef9SDimitry Andric     if (I->second.hasMaterializerAttached()) {
1317e8d8bef9SDimitry Andric       // FIXME: Should this discard the symbols?
1318e8d8bef9SDimitry Andric       UnmaterializedInfos.erase(Sym);
1319e8d8bef9SDimitry Andric     } else {
1320e8d8bef9SDimitry Andric       assert(!UnmaterializedInfos.count(Sym) &&
1321e8d8bef9SDimitry Andric              "Symbol has materializer attached");
1322e8d8bef9SDimitry Andric     }
1323e8d8bef9SDimitry Andric 
1324e8d8bef9SDimitry Andric     Symbols.erase(I);
1325e8d8bef9SDimitry Andric   }
1326e8d8bef9SDimitry Andric 
13270fca6ea1SDimitry Andric   shrinkMaterializationInfoMemory();
13280fca6ea1SDimitry Andric 
1329e8d8bef9SDimitry Andric   return Result;
1330e8d8bef9SDimitry Andric }
1331e8d8bef9SDimitry Andric 
1332e8d8bef9SDimitry Andric void JITDylib::transferTracker(ResourceTracker &DstRT, ResourceTracker &SrcRT) {
13334824e7fdSDimitry Andric   assert(State != Closed && "JD is defunct");
1334e8d8bef9SDimitry Andric   assert(&DstRT != &SrcRT && "No-op transfers shouldn't call transferTracker");
1335e8d8bef9SDimitry Andric   assert(&DstRT.getJITDylib() == this && "DstRT is not for this JITDylib");
1336e8d8bef9SDimitry Andric   assert(&SrcRT.getJITDylib() == this && "SrcRT is not for this JITDylib");
1337e8d8bef9SDimitry Andric 
1338e8d8bef9SDimitry Andric   // Update trackers for any not-yet materialized units.
1339e8d8bef9SDimitry Andric   for (auto &KV : UnmaterializedInfos) {
1340e8d8bef9SDimitry Andric     if (KV.second->RT == &SrcRT)
1341e8d8bef9SDimitry Andric       KV.second->RT = &DstRT;
1342e8d8bef9SDimitry Andric   }
1343e8d8bef9SDimitry Andric 
1344e8d8bef9SDimitry Andric   // Update trackers for any active materialization responsibilities.
13454824e7fdSDimitry Andric   {
13464824e7fdSDimitry Andric     auto I = TrackerMRs.find(&SrcRT);
13474824e7fdSDimitry Andric     if (I != TrackerMRs.end()) {
13484824e7fdSDimitry Andric       auto &SrcMRs = I->second;
13494824e7fdSDimitry Andric       auto &DstMRs = TrackerMRs[&DstRT];
13504824e7fdSDimitry Andric       for (auto *MR : SrcMRs)
13514824e7fdSDimitry Andric         MR->RT = &DstRT;
13524824e7fdSDimitry Andric       if (DstMRs.empty())
13534824e7fdSDimitry Andric         DstMRs = std::move(SrcMRs);
13544824e7fdSDimitry Andric       else
13554824e7fdSDimitry Andric         for (auto *MR : SrcMRs)
13564824e7fdSDimitry Andric           DstMRs.insert(MR);
13574824e7fdSDimitry Andric       // Erase SrcRT entry in TrackerMRs. Use &SrcRT key rather than iterator I
13584824e7fdSDimitry Andric       // for this, since I may have been invalidated by 'TrackerMRs[&DstRT]'.
13594824e7fdSDimitry Andric       TrackerMRs.erase(&SrcRT);
13604824e7fdSDimitry Andric     }
1361e8d8bef9SDimitry Andric   }
1362e8d8bef9SDimitry Andric 
1363e8d8bef9SDimitry Andric   // If we're transfering to the default tracker we just need to delete the
1364e8d8bef9SDimitry Andric   // tracked symbols for the source tracker.
1365e8d8bef9SDimitry Andric   if (&DstRT == DefaultTracker.get()) {
1366e8d8bef9SDimitry Andric     TrackerSymbols.erase(&SrcRT);
1367e8d8bef9SDimitry Andric     return;
1368e8d8bef9SDimitry Andric   }
1369e8d8bef9SDimitry Andric 
1370e8d8bef9SDimitry Andric   // If we're transferring from the default tracker we need to find all
1371e8d8bef9SDimitry Andric   // currently untracked symbols.
1372e8d8bef9SDimitry Andric   if (&SrcRT == DefaultTracker.get()) {
1373e8d8bef9SDimitry Andric     assert(!TrackerSymbols.count(&SrcRT) &&
1374e8d8bef9SDimitry Andric            "Default tracker should not appear in TrackerSymbols");
1375e8d8bef9SDimitry Andric 
1376e8d8bef9SDimitry Andric     SymbolNameVector SymbolsToTrack;
1377e8d8bef9SDimitry Andric 
1378e8d8bef9SDimitry Andric     SymbolNameSet CurrentlyTrackedSymbols;
1379e8d8bef9SDimitry Andric     for (auto &KV : TrackerSymbols)
1380e8d8bef9SDimitry Andric       for (auto &Sym : KV.second)
1381e8d8bef9SDimitry Andric         CurrentlyTrackedSymbols.insert(Sym);
1382e8d8bef9SDimitry Andric 
1383e8d8bef9SDimitry Andric     for (auto &KV : Symbols) {
1384e8d8bef9SDimitry Andric       auto &Sym = KV.first;
1385e8d8bef9SDimitry Andric       if (!CurrentlyTrackedSymbols.count(Sym))
1386e8d8bef9SDimitry Andric         SymbolsToTrack.push_back(Sym);
1387e8d8bef9SDimitry Andric     }
1388e8d8bef9SDimitry Andric 
1389e8d8bef9SDimitry Andric     TrackerSymbols[&DstRT] = std::move(SymbolsToTrack);
1390e8d8bef9SDimitry Andric     return;
1391e8d8bef9SDimitry Andric   }
1392e8d8bef9SDimitry Andric 
1393e8d8bef9SDimitry Andric   auto &DstTrackedSymbols = TrackerSymbols[&DstRT];
1394e8d8bef9SDimitry Andric 
1395e8d8bef9SDimitry Andric   // Finally if neither SrtRT or DstRT are the default tracker then
1396e8d8bef9SDimitry Andric   // just append DstRT's tracked symbols to SrtRT's.
1397e8d8bef9SDimitry Andric   auto SI = TrackerSymbols.find(&SrcRT);
1398e8d8bef9SDimitry Andric   if (SI == TrackerSymbols.end())
1399e8d8bef9SDimitry Andric     return;
1400e8d8bef9SDimitry Andric 
1401e8d8bef9SDimitry Andric   DstTrackedSymbols.reserve(DstTrackedSymbols.size() + SI->second.size());
1402e8d8bef9SDimitry Andric   for (auto &Sym : SI->second)
1403e8d8bef9SDimitry Andric     DstTrackedSymbols.push_back(std::move(Sym));
1404e8d8bef9SDimitry Andric   TrackerSymbols.erase(SI);
1405e8d8bef9SDimitry Andric }
1406e8d8bef9SDimitry Andric 
14070b57cec5SDimitry Andric Error JITDylib::defineImpl(MaterializationUnit &MU) {
14085ffd83dbSDimitry Andric   LLVM_DEBUG({ dbgs() << "  " << MU.getSymbols() << "\n"; });
14095ffd83dbSDimitry Andric 
14100b57cec5SDimitry Andric   SymbolNameSet Duplicates;
14110b57cec5SDimitry Andric   std::vector<SymbolStringPtr> ExistingDefsOverridden;
14120b57cec5SDimitry Andric   std::vector<SymbolStringPtr> MUDefsOverridden;
14130b57cec5SDimitry Andric 
14140b57cec5SDimitry Andric   for (const auto &KV : MU.getSymbols()) {
14150b57cec5SDimitry Andric     auto I = Symbols.find(KV.first);
14160b57cec5SDimitry Andric 
14170b57cec5SDimitry Andric     if (I != Symbols.end()) {
14180b57cec5SDimitry Andric       if (KV.second.isStrong()) {
14190b57cec5SDimitry Andric         if (I->second.getFlags().isStrong() ||
14200b57cec5SDimitry Andric             I->second.getState() > SymbolState::NeverSearched)
14210b57cec5SDimitry Andric           Duplicates.insert(KV.first);
14220b57cec5SDimitry Andric         else {
14230b57cec5SDimitry Andric           assert(I->second.getState() == SymbolState::NeverSearched &&
14240b57cec5SDimitry Andric                  "Overridden existing def should be in the never-searched "
14250b57cec5SDimitry Andric                  "state");
14260b57cec5SDimitry Andric           ExistingDefsOverridden.push_back(KV.first);
14270b57cec5SDimitry Andric         }
14280b57cec5SDimitry Andric       } else
14290b57cec5SDimitry Andric         MUDefsOverridden.push_back(KV.first);
14300b57cec5SDimitry Andric     }
14310b57cec5SDimitry Andric   }
14320b57cec5SDimitry Andric 
14330b57cec5SDimitry Andric   // If there were any duplicate definitions then bail out.
14345ffd83dbSDimitry Andric   if (!Duplicates.empty()) {
14355ffd83dbSDimitry Andric     LLVM_DEBUG(
14365ffd83dbSDimitry Andric         { dbgs() << "  Error: Duplicate symbols " << Duplicates << "\n"; });
14375ffd83dbSDimitry Andric     return make_error<DuplicateDefinition>(std::string(**Duplicates.begin()));
14385ffd83dbSDimitry Andric   }
14390b57cec5SDimitry Andric 
14400b57cec5SDimitry Andric   // Discard any overridden defs in this MU.
14415ffd83dbSDimitry Andric   LLVM_DEBUG({
14425ffd83dbSDimitry Andric     if (!MUDefsOverridden.empty())
14435ffd83dbSDimitry Andric       dbgs() << "  Defs in this MU overridden: " << MUDefsOverridden << "\n";
14445ffd83dbSDimitry Andric   });
14450b57cec5SDimitry Andric   for (auto &S : MUDefsOverridden)
14460b57cec5SDimitry Andric     MU.doDiscard(*this, S);
14470b57cec5SDimitry Andric 
14480b57cec5SDimitry Andric   // Discard existing overridden defs.
14495ffd83dbSDimitry Andric   LLVM_DEBUG({
14505ffd83dbSDimitry Andric     if (!ExistingDefsOverridden.empty())
14515ffd83dbSDimitry Andric       dbgs() << "  Existing defs overridden by this MU: " << MUDefsOverridden
14525ffd83dbSDimitry Andric              << "\n";
14535ffd83dbSDimitry Andric   });
14540b57cec5SDimitry Andric   for (auto &S : ExistingDefsOverridden) {
14550b57cec5SDimitry Andric 
14560b57cec5SDimitry Andric     auto UMII = UnmaterializedInfos.find(S);
14570b57cec5SDimitry Andric     assert(UMII != UnmaterializedInfos.end() &&
14580b57cec5SDimitry Andric            "Overridden existing def should have an UnmaterializedInfo");
14590b57cec5SDimitry Andric     UMII->second->MU->doDiscard(*this, S);
14600b57cec5SDimitry Andric   }
14610b57cec5SDimitry Andric 
14620b57cec5SDimitry Andric   // Finally, add the defs from this MU.
14630b57cec5SDimitry Andric   for (auto &KV : MU.getSymbols()) {
14640b57cec5SDimitry Andric     auto &SymEntry = Symbols[KV.first];
14650b57cec5SDimitry Andric     SymEntry.setFlags(KV.second);
14660b57cec5SDimitry Andric     SymEntry.setState(SymbolState::NeverSearched);
14670b57cec5SDimitry Andric     SymEntry.setMaterializerAttached(true);
14680b57cec5SDimitry Andric   }
14690b57cec5SDimitry Andric 
14700b57cec5SDimitry Andric   return Error::success();
14710b57cec5SDimitry Andric }
14720b57cec5SDimitry Andric 
1473e8d8bef9SDimitry Andric void JITDylib::installMaterializationUnit(
1474e8d8bef9SDimitry Andric     std::unique_ptr<MaterializationUnit> MU, ResourceTracker &RT) {
1475e8d8bef9SDimitry Andric 
1476e8d8bef9SDimitry Andric   /// defineImpl succeeded.
1477e8d8bef9SDimitry Andric   if (&RT != DefaultTracker.get()) {
1478e8d8bef9SDimitry Andric     auto &TS = TrackerSymbols[&RT];
1479e8d8bef9SDimitry Andric     TS.reserve(TS.size() + MU->getSymbols().size());
1480e8d8bef9SDimitry Andric     for (auto &KV : MU->getSymbols())
1481e8d8bef9SDimitry Andric       TS.push_back(KV.first);
1482e8d8bef9SDimitry Andric   }
1483e8d8bef9SDimitry Andric 
1484e8d8bef9SDimitry Andric   auto UMI = std::make_shared<UnmaterializedInfo>(std::move(MU), &RT);
1485e8d8bef9SDimitry Andric   for (auto &KV : UMI->MU->getSymbols())
1486e8d8bef9SDimitry Andric     UnmaterializedInfos[KV.first] = UMI;
1487e8d8bef9SDimitry Andric }
1488e8d8bef9SDimitry Andric 
14890b57cec5SDimitry Andric void JITDylib::detachQueryHelper(AsynchronousSymbolQuery &Q,
14900b57cec5SDimitry Andric                                  const SymbolNameSet &QuerySymbols) {
14910b57cec5SDimitry Andric   for (auto &QuerySymbol : QuerySymbols) {
14920b57cec5SDimitry Andric     assert(MaterializingInfos.count(QuerySymbol) &&
14930b57cec5SDimitry Andric            "QuerySymbol does not have MaterializingInfo");
14940b57cec5SDimitry Andric     auto &MI = MaterializingInfos[QuerySymbol];
14950b57cec5SDimitry Andric     MI.removeQuery(Q);
14960b57cec5SDimitry Andric   }
14970b57cec5SDimitry Andric }
14980b57cec5SDimitry Andric 
149981ad6265SDimitry Andric Platform::~Platform() = default;
15005ffd83dbSDimitry Andric 
15015ffd83dbSDimitry Andric Expected<DenseMap<JITDylib *, SymbolMap>> Platform::lookupInitSymbols(
15025ffd83dbSDimitry Andric     ExecutionSession &ES,
15035ffd83dbSDimitry Andric     const DenseMap<JITDylib *, SymbolLookupSet> &InitSyms) {
15045ffd83dbSDimitry Andric 
15055ffd83dbSDimitry Andric   DenseMap<JITDylib *, SymbolMap> CompoundResult;
15065ffd83dbSDimitry Andric   Error CompoundErr = Error::success();
15075ffd83dbSDimitry Andric   std::mutex LookupMutex;
15085ffd83dbSDimitry Andric   std::condition_variable CV;
15095ffd83dbSDimitry Andric   uint64_t Count = InitSyms.size();
15105ffd83dbSDimitry Andric 
15115ffd83dbSDimitry Andric   LLVM_DEBUG({
15125ffd83dbSDimitry Andric     dbgs() << "Issuing init-symbol lookup:\n";
15135ffd83dbSDimitry Andric     for (auto &KV : InitSyms)
15145ffd83dbSDimitry Andric       dbgs() << "  " << KV.first->getName() << ": " << KV.second << "\n";
15155ffd83dbSDimitry Andric   });
15165ffd83dbSDimitry Andric 
15175ffd83dbSDimitry Andric   for (auto &KV : InitSyms) {
15185ffd83dbSDimitry Andric     auto *JD = KV.first;
15195ffd83dbSDimitry Andric     auto Names = std::move(KV.second);
15205ffd83dbSDimitry Andric     ES.lookup(
15215ffd83dbSDimitry Andric         LookupKind::Static,
15225ffd83dbSDimitry Andric         JITDylibSearchOrder({{JD, JITDylibLookupFlags::MatchAllSymbols}}),
15235ffd83dbSDimitry Andric         std::move(Names), SymbolState::Ready,
15245ffd83dbSDimitry Andric         [&, JD](Expected<SymbolMap> Result) {
15255ffd83dbSDimitry Andric           {
15265ffd83dbSDimitry Andric             std::lock_guard<std::mutex> Lock(LookupMutex);
15275ffd83dbSDimitry Andric             --Count;
15285ffd83dbSDimitry Andric             if (Result) {
15295ffd83dbSDimitry Andric               assert(!CompoundResult.count(JD) &&
15305ffd83dbSDimitry Andric                      "Duplicate JITDylib in lookup?");
15315ffd83dbSDimitry Andric               CompoundResult[JD] = std::move(*Result);
15325ffd83dbSDimitry Andric             } else
15335ffd83dbSDimitry Andric               CompoundErr =
15345ffd83dbSDimitry Andric                   joinErrors(std::move(CompoundErr), Result.takeError());
15355ffd83dbSDimitry Andric           }
15365ffd83dbSDimitry Andric           CV.notify_one();
15375ffd83dbSDimitry Andric         },
15385ffd83dbSDimitry Andric         NoDependenciesToRegister);
15395ffd83dbSDimitry Andric   }
15405ffd83dbSDimitry Andric 
15415ffd83dbSDimitry Andric   std::unique_lock<std::mutex> Lock(LookupMutex);
15425ffd83dbSDimitry Andric   CV.wait(Lock, [&] { return Count == 0 || CompoundErr; });
15435ffd83dbSDimitry Andric 
15445ffd83dbSDimitry Andric   if (CompoundErr)
15455ffd83dbSDimitry Andric     return std::move(CompoundErr);
15465ffd83dbSDimitry Andric 
15475ffd83dbSDimitry Andric   return std::move(CompoundResult);
15485ffd83dbSDimitry Andric }
15495ffd83dbSDimitry Andric 
1550fe6060f1SDimitry Andric void Platform::lookupInitSymbolsAsync(
1551fe6060f1SDimitry Andric     unique_function<void(Error)> OnComplete, ExecutionSession &ES,
1552fe6060f1SDimitry Andric     const DenseMap<JITDylib *, SymbolLookupSet> &InitSyms) {
1553fe6060f1SDimitry Andric 
1554fe6060f1SDimitry Andric   class TriggerOnComplete {
1555fe6060f1SDimitry Andric   public:
1556fe6060f1SDimitry Andric     using OnCompleteFn = unique_function<void(Error)>;
1557fe6060f1SDimitry Andric     TriggerOnComplete(OnCompleteFn OnComplete)
1558fe6060f1SDimitry Andric         : OnComplete(std::move(OnComplete)) {}
1559fe6060f1SDimitry Andric     ~TriggerOnComplete() { OnComplete(std::move(LookupResult)); }
1560fe6060f1SDimitry Andric     void reportResult(Error Err) {
1561fe6060f1SDimitry Andric       std::lock_guard<std::mutex> Lock(ResultMutex);
1562fe6060f1SDimitry Andric       LookupResult = joinErrors(std::move(LookupResult), std::move(Err));
1563fe6060f1SDimitry Andric     }
1564fe6060f1SDimitry Andric 
1565fe6060f1SDimitry Andric   private:
1566fe6060f1SDimitry Andric     std::mutex ResultMutex;
1567fe6060f1SDimitry Andric     Error LookupResult{Error::success()};
1568fe6060f1SDimitry Andric     OnCompleteFn OnComplete;
1569fe6060f1SDimitry Andric   };
1570fe6060f1SDimitry Andric 
1571fe6060f1SDimitry Andric   LLVM_DEBUG({
1572fe6060f1SDimitry Andric     dbgs() << "Issuing init-symbol lookup:\n";
1573fe6060f1SDimitry Andric     for (auto &KV : InitSyms)
1574fe6060f1SDimitry Andric       dbgs() << "  " << KV.first->getName() << ": " << KV.second << "\n";
1575fe6060f1SDimitry Andric   });
1576fe6060f1SDimitry Andric 
1577fe6060f1SDimitry Andric   auto TOC = std::make_shared<TriggerOnComplete>(std::move(OnComplete));
1578fe6060f1SDimitry Andric 
1579fe6060f1SDimitry Andric   for (auto &KV : InitSyms) {
1580fe6060f1SDimitry Andric     auto *JD = KV.first;
1581fe6060f1SDimitry Andric     auto Names = std::move(KV.second);
1582fe6060f1SDimitry Andric     ES.lookup(
1583fe6060f1SDimitry Andric         LookupKind::Static,
1584fe6060f1SDimitry Andric         JITDylibSearchOrder({{JD, JITDylibLookupFlags::MatchAllSymbols}}),
1585fe6060f1SDimitry Andric         std::move(Names), SymbolState::Ready,
1586fe6060f1SDimitry Andric         [TOC](Expected<SymbolMap> Result) {
1587fe6060f1SDimitry Andric           TOC->reportResult(Result.takeError());
1588fe6060f1SDimitry Andric         },
1589fe6060f1SDimitry Andric         NoDependenciesToRegister);
1590fe6060f1SDimitry Andric   }
1591fe6060f1SDimitry Andric }
1592fe6060f1SDimitry Andric 
1593fe6060f1SDimitry Andric void MaterializationTask::printDescription(raw_ostream &OS) {
1594fe6060f1SDimitry Andric   OS << "Materialization task: " << MU->getName() << " in "
1595fe6060f1SDimitry Andric      << MR->getTargetJITDylib().getName();
1596fe6060f1SDimitry Andric }
1597fe6060f1SDimitry Andric 
1598fe6060f1SDimitry Andric void MaterializationTask::run() { MU->materialize(std::move(MR)); }
1599fe6060f1SDimitry Andric 
16005f757f3fSDimitry Andric void LookupTask::printDescription(raw_ostream &OS) { OS << "Lookup task"; }
16015f757f3fSDimitry Andric 
16025f757f3fSDimitry Andric void LookupTask::run() { LS.continueLookup(Error::success()); }
16035f757f3fSDimitry Andric 
1604fe6060f1SDimitry Andric ExecutionSession::ExecutionSession(std::unique_ptr<ExecutorProcessControl> EPC)
1605fe6060f1SDimitry Andric     : EPC(std::move(EPC)) {
1606fe6060f1SDimitry Andric   // Associated EPC and this.
1607fe6060f1SDimitry Andric   this->EPC->ES = this;
1608fe6060f1SDimitry Andric }
1609e8d8bef9SDimitry Andric 
161081ad6265SDimitry Andric ExecutionSession::~ExecutionSession() {
161181ad6265SDimitry Andric   // You must call endSession prior to destroying the session.
161281ad6265SDimitry Andric   assert(!SessionOpen &&
161381ad6265SDimitry Andric          "Session still open. Did you forget to call endSession?");
161481ad6265SDimitry Andric }
161581ad6265SDimitry Andric 
1616e8d8bef9SDimitry Andric Error ExecutionSession::endSession() {
1617e8d8bef9SDimitry Andric   LLVM_DEBUG(dbgs() << "Ending ExecutionSession " << this << "\n");
1618e8d8bef9SDimitry Andric 
16195f757f3fSDimitry Andric   auto JDsToRemove = runSessionLocked([&] {
16200fca6ea1SDimitry Andric 
16210fca6ea1SDimitry Andric #ifdef EXPENSIVE_CHECKS
16220fca6ea1SDimitry Andric     verifySessionState("Entering ExecutionSession::endSession");
16230fca6ea1SDimitry Andric #endif
16240fca6ea1SDimitry Andric 
1625e8d8bef9SDimitry Andric     SessionOpen = false;
16265f757f3fSDimitry Andric     return JDs;
1627e8d8bef9SDimitry Andric   });
1628e8d8bef9SDimitry Andric 
16295f757f3fSDimitry Andric   std::reverse(JDsToRemove.begin(), JDsToRemove.end());
1630e8d8bef9SDimitry Andric 
16315f757f3fSDimitry Andric   auto Err = removeJITDylibs(std::move(JDsToRemove));
1632fe6060f1SDimitry Andric 
1633fe6060f1SDimitry Andric   Err = joinErrors(std::move(Err), EPC->disconnect());
1634fe6060f1SDimitry Andric 
1635e8d8bef9SDimitry Andric   return Err;
1636e8d8bef9SDimitry Andric }
1637e8d8bef9SDimitry Andric 
1638e8d8bef9SDimitry Andric void ExecutionSession::registerResourceManager(ResourceManager &RM) {
1639e8d8bef9SDimitry Andric   runSessionLocked([&] { ResourceManagers.push_back(&RM); });
1640e8d8bef9SDimitry Andric }
1641e8d8bef9SDimitry Andric 
1642e8d8bef9SDimitry Andric void ExecutionSession::deregisterResourceManager(ResourceManager &RM) {
1643e8d8bef9SDimitry Andric   runSessionLocked([&] {
1644e8d8bef9SDimitry Andric     assert(!ResourceManagers.empty() && "No managers registered");
1645e8d8bef9SDimitry Andric     if (ResourceManagers.back() == &RM)
1646e8d8bef9SDimitry Andric       ResourceManagers.pop_back();
1647e8d8bef9SDimitry Andric     else {
1648e8d8bef9SDimitry Andric       auto I = llvm::find(ResourceManagers, &RM);
1649e8d8bef9SDimitry Andric       assert(I != ResourceManagers.end() && "RM not registered");
1650e8d8bef9SDimitry Andric       ResourceManagers.erase(I);
1651e8d8bef9SDimitry Andric     }
1652e8d8bef9SDimitry Andric   });
16530b57cec5SDimitry Andric }
16540b57cec5SDimitry Andric 
16550b57cec5SDimitry Andric JITDylib *ExecutionSession::getJITDylibByName(StringRef Name) {
16560b57cec5SDimitry Andric   return runSessionLocked([&, this]() -> JITDylib * {
16570b57cec5SDimitry Andric     for (auto &JD : JDs)
16580b57cec5SDimitry Andric       if (JD->getName() == Name)
16590b57cec5SDimitry Andric         return JD.get();
16600b57cec5SDimitry Andric     return nullptr;
16610b57cec5SDimitry Andric   });
16620b57cec5SDimitry Andric }
16630b57cec5SDimitry Andric 
16645ffd83dbSDimitry Andric JITDylib &ExecutionSession::createBareJITDylib(std::string Name) {
16650b57cec5SDimitry Andric   assert(!getJITDylibByName(Name) && "JITDylib with that name already exists");
16660b57cec5SDimitry Andric   return runSessionLocked([&, this]() -> JITDylib & {
166706c3fb27SDimitry Andric     assert(SessionOpen && "Cannot create JITDylib after session is closed");
1668e8d8bef9SDimitry Andric     JDs.push_back(new JITDylib(*this, std::move(Name)));
16690b57cec5SDimitry Andric     return *JDs.back();
16700b57cec5SDimitry Andric   });
16710b57cec5SDimitry Andric }
16720b57cec5SDimitry Andric 
16735ffd83dbSDimitry Andric Expected<JITDylib &> ExecutionSession::createJITDylib(std::string Name) {
16745ffd83dbSDimitry Andric   auto &JD = createBareJITDylib(Name);
16755ffd83dbSDimitry Andric   if (P)
16765ffd83dbSDimitry Andric     if (auto Err = P->setupJITDylib(JD))
16775ffd83dbSDimitry Andric       return std::move(Err);
16785ffd83dbSDimitry Andric   return JD;
16795ffd83dbSDimitry Andric }
16805ffd83dbSDimitry Andric 
16815f757f3fSDimitry Andric Error ExecutionSession::removeJITDylibs(std::vector<JITDylibSP> JDsToRemove) {
16824824e7fdSDimitry Andric   // Set JD to 'Closing' state and remove JD from the ExecutionSession.
16834824e7fdSDimitry Andric   runSessionLocked([&] {
16845f757f3fSDimitry Andric     for (auto &JD : JDsToRemove) {
16855f757f3fSDimitry Andric       assert(JD->State == JITDylib::Open && "JD already closed");
16865f757f3fSDimitry Andric       JD->State = JITDylib::Closing;
16875f757f3fSDimitry Andric       auto I = llvm::find(JDs, JD);
16884824e7fdSDimitry Andric       assert(I != JDs.end() && "JD does not appear in session JDs");
16894824e7fdSDimitry Andric       JDs.erase(I);
16905f757f3fSDimitry Andric     }
16914824e7fdSDimitry Andric   });
16924824e7fdSDimitry Andric 
16935f757f3fSDimitry Andric   // Clear JITDylibs and notify the platform.
16945f757f3fSDimitry Andric   Error Err = Error::success();
16955f757f3fSDimitry Andric   for (auto JD : JDsToRemove) {
16965f757f3fSDimitry Andric     Err = joinErrors(std::move(Err), JD->clear());
169704eeddc0SDimitry Andric     if (P)
16985f757f3fSDimitry Andric       Err = joinErrors(std::move(Err), P->teardownJITDylib(*JD));
16995f757f3fSDimitry Andric   }
170004eeddc0SDimitry Andric 
17014824e7fdSDimitry Andric   // Set JD to closed state. Clear remaining data structures.
17024824e7fdSDimitry Andric   runSessionLocked([&] {
17035f757f3fSDimitry Andric     for (auto &JD : JDsToRemove) {
17045f757f3fSDimitry Andric       assert(JD->State == JITDylib::Closing && "JD should be closing");
17055f757f3fSDimitry Andric       JD->State = JITDylib::Closed;
17065f757f3fSDimitry Andric       assert(JD->Symbols.empty() && "JD.Symbols is not empty after clear");
17075f757f3fSDimitry Andric       assert(JD->UnmaterializedInfos.empty() &&
17084824e7fdSDimitry Andric              "JD.UnmaterializedInfos is not empty after clear");
17095f757f3fSDimitry Andric       assert(JD->MaterializingInfos.empty() &&
17104824e7fdSDimitry Andric              "JD.MaterializingInfos is not empty after clear");
17115f757f3fSDimitry Andric       assert(JD->TrackerSymbols.empty() &&
17124824e7fdSDimitry Andric              "TrackerSymbols is not empty after clear");
17135f757f3fSDimitry Andric       JD->DefGenerators.clear();
17145f757f3fSDimitry Andric       JD->LinkOrder.clear();
17155f757f3fSDimitry Andric     }
17164824e7fdSDimitry Andric   });
17175f757f3fSDimitry Andric 
17184824e7fdSDimitry Andric   return Err;
17194824e7fdSDimitry Andric }
17204824e7fdSDimitry Andric 
172104eeddc0SDimitry Andric Expected<std::vector<JITDylibSP>>
172204eeddc0SDimitry Andric JITDylib::getDFSLinkOrder(ArrayRef<JITDylibSP> JDs) {
1723e8d8bef9SDimitry Andric   if (JDs.empty())
172404eeddc0SDimitry Andric     return std::vector<JITDylibSP>();
17250b57cec5SDimitry Andric 
1726e8d8bef9SDimitry Andric   auto &ES = JDs.front()->getExecutionSession();
172704eeddc0SDimitry Andric   return ES.runSessionLocked([&]() -> Expected<std::vector<JITDylibSP>> {
1728e8d8bef9SDimitry Andric     DenseSet<JITDylib *> Visited;
1729e8d8bef9SDimitry Andric     std::vector<JITDylibSP> Result;
17300b57cec5SDimitry Andric 
1731e8d8bef9SDimitry Andric     for (auto &JD : JDs) {
1732e8d8bef9SDimitry Andric 
173304eeddc0SDimitry Andric       if (JD->State != Open)
173404eeddc0SDimitry Andric         return make_error<StringError>(
173504eeddc0SDimitry Andric             "Error building link order: " + JD->getName() + " is defunct",
173604eeddc0SDimitry Andric             inconvertibleErrorCode());
1737e8d8bef9SDimitry Andric       if (Visited.count(JD.get()))
1738e8d8bef9SDimitry Andric         continue;
1739e8d8bef9SDimitry Andric 
1740e8d8bef9SDimitry Andric       SmallVector<JITDylibSP, 64> WorkStack;
1741e8d8bef9SDimitry Andric       WorkStack.push_back(JD);
1742e8d8bef9SDimitry Andric       Visited.insert(JD.get());
1743e8d8bef9SDimitry Andric 
1744e8d8bef9SDimitry Andric       while (!WorkStack.empty()) {
1745e8d8bef9SDimitry Andric         Result.push_back(std::move(WorkStack.back()));
1746e8d8bef9SDimitry Andric         WorkStack.pop_back();
1747e8d8bef9SDimitry Andric 
1748e8d8bef9SDimitry Andric         for (auto &KV : llvm::reverse(Result.back()->LinkOrder)) {
1749e8d8bef9SDimitry Andric           auto &JD = *KV.first;
175081ad6265SDimitry Andric           if (!Visited.insert(&JD).second)
1751e8d8bef9SDimitry Andric             continue;
1752e8d8bef9SDimitry Andric           WorkStack.push_back(&JD);
17530b57cec5SDimitry Andric         }
17540b57cec5SDimitry Andric       }
17550b57cec5SDimitry Andric     }
17560b57cec5SDimitry Andric     return Result;
1757e8d8bef9SDimitry Andric   });
1758e8d8bef9SDimitry Andric }
1759e8d8bef9SDimitry Andric 
176004eeddc0SDimitry Andric Expected<std::vector<JITDylibSP>>
1761e8d8bef9SDimitry Andric JITDylib::getReverseDFSLinkOrder(ArrayRef<JITDylibSP> JDs) {
176204eeddc0SDimitry Andric   auto Result = getDFSLinkOrder(JDs);
176304eeddc0SDimitry Andric   if (Result)
176404eeddc0SDimitry Andric     std::reverse(Result->begin(), Result->end());
176504eeddc0SDimitry Andric   return Result;
1766e8d8bef9SDimitry Andric }
1767e8d8bef9SDimitry Andric 
176804eeddc0SDimitry Andric Expected<std::vector<JITDylibSP>> JITDylib::getDFSLinkOrder() {
1769e8d8bef9SDimitry Andric   return getDFSLinkOrder({this});
1770e8d8bef9SDimitry Andric }
1771e8d8bef9SDimitry Andric 
177204eeddc0SDimitry Andric Expected<std::vector<JITDylibSP>> JITDylib::getReverseDFSLinkOrder() {
1773e8d8bef9SDimitry Andric   return getReverseDFSLinkOrder({this});
1774e8d8bef9SDimitry Andric }
1775e8d8bef9SDimitry Andric 
1776e8d8bef9SDimitry Andric void ExecutionSession::lookupFlags(
1777e8d8bef9SDimitry Andric     LookupKind K, JITDylibSearchOrder SearchOrder, SymbolLookupSet LookupSet,
1778e8d8bef9SDimitry Andric     unique_function<void(Expected<SymbolFlagsMap>)> OnComplete) {
1779e8d8bef9SDimitry Andric 
1780e8d8bef9SDimitry Andric   OL_applyQueryPhase1(std::make_unique<InProgressLookupFlagsState>(
1781e8d8bef9SDimitry Andric                           K, std::move(SearchOrder), std::move(LookupSet),
1782e8d8bef9SDimitry Andric                           std::move(OnComplete)),
1783e8d8bef9SDimitry Andric                       Error::success());
1784e8d8bef9SDimitry Andric }
1785e8d8bef9SDimitry Andric 
1786e8d8bef9SDimitry Andric Expected<SymbolFlagsMap>
1787e8d8bef9SDimitry Andric ExecutionSession::lookupFlags(LookupKind K, JITDylibSearchOrder SearchOrder,
1788e8d8bef9SDimitry Andric                               SymbolLookupSet LookupSet) {
1789e8d8bef9SDimitry Andric 
1790e8d8bef9SDimitry Andric   std::promise<MSVCPExpected<SymbolFlagsMap>> ResultP;
1791e8d8bef9SDimitry Andric   OL_applyQueryPhase1(std::make_unique<InProgressLookupFlagsState>(
1792e8d8bef9SDimitry Andric                           K, std::move(SearchOrder), std::move(LookupSet),
1793e8d8bef9SDimitry Andric                           [&ResultP](Expected<SymbolFlagsMap> Result) {
1794e8d8bef9SDimitry Andric                             ResultP.set_value(std::move(Result));
1795e8d8bef9SDimitry Andric                           }),
1796e8d8bef9SDimitry Andric                       Error::success());
1797e8d8bef9SDimitry Andric 
1798e8d8bef9SDimitry Andric   auto ResultF = ResultP.get_future();
1799e8d8bef9SDimitry Andric   return ResultF.get();
18000b57cec5SDimitry Andric }
18010b57cec5SDimitry Andric 
18020b57cec5SDimitry Andric void ExecutionSession::lookup(
1803480093f4SDimitry Andric     LookupKind K, const JITDylibSearchOrder &SearchOrder,
1804480093f4SDimitry Andric     SymbolLookupSet Symbols, SymbolState RequiredState,
1805480093f4SDimitry Andric     SymbolsResolvedCallback NotifyComplete,
18060b57cec5SDimitry Andric     RegisterDependenciesFunction RegisterDependencies) {
18070b57cec5SDimitry Andric 
18080b57cec5SDimitry Andric   LLVM_DEBUG({
18090b57cec5SDimitry Andric     runSessionLocked([&]() {
18100b57cec5SDimitry Andric       dbgs() << "Looking up " << Symbols << " in " << SearchOrder
18110b57cec5SDimitry Andric              << " (required state: " << RequiredState << ")\n";
18120b57cec5SDimitry Andric     });
18130b57cec5SDimitry Andric   });
18140b57cec5SDimitry Andric 
18150b57cec5SDimitry Andric   // lookup can be re-entered recursively if running on a single thread. Run any
18160b57cec5SDimitry Andric   // outstanding MUs in case this query depends on them, otherwise this lookup
18170b57cec5SDimitry Andric   // will starve waiting for a result from an MU that is stuck in the queue.
1818e8d8bef9SDimitry Andric   dispatchOutstandingMUs();
18190b57cec5SDimitry Andric 
18200b57cec5SDimitry Andric   auto Unresolved = std::move(Symbols);
18210b57cec5SDimitry Andric   auto Q = std::make_shared<AsynchronousSymbolQuery>(Unresolved, RequiredState,
18220b57cec5SDimitry Andric                                                      std::move(NotifyComplete));
18230b57cec5SDimitry Andric 
1824e8d8bef9SDimitry Andric   auto IPLS = std::make_unique<InProgressFullLookupState>(
1825e8d8bef9SDimitry Andric       K, SearchOrder, std::move(Unresolved), RequiredState, std::move(Q),
1826e8d8bef9SDimitry Andric       std::move(RegisterDependencies));
18270b57cec5SDimitry Andric 
1828e8d8bef9SDimitry Andric   OL_applyQueryPhase1(std::move(IPLS), Error::success());
18290b57cec5SDimitry Andric }
18300b57cec5SDimitry Andric 
18310b57cec5SDimitry Andric Expected<SymbolMap>
1832480093f4SDimitry Andric ExecutionSession::lookup(const JITDylibSearchOrder &SearchOrder,
183381ad6265SDimitry Andric                          SymbolLookupSet Symbols, LookupKind K,
18340b57cec5SDimitry Andric                          SymbolState RequiredState,
18350b57cec5SDimitry Andric                          RegisterDependenciesFunction RegisterDependencies) {
18360b57cec5SDimitry Andric #if LLVM_ENABLE_THREADS
18370b57cec5SDimitry Andric   // In the threaded case we use promises to return the results.
18380b57cec5SDimitry Andric   std::promise<SymbolMap> PromisedResult;
18390b57cec5SDimitry Andric   Error ResolutionError = Error::success();
18400b57cec5SDimitry Andric 
18410b57cec5SDimitry Andric   auto NotifyComplete = [&](Expected<SymbolMap> R) {
18420b57cec5SDimitry Andric     if (R)
18430b57cec5SDimitry Andric       PromisedResult.set_value(std::move(*R));
18440b57cec5SDimitry Andric     else {
18450b57cec5SDimitry Andric       ErrorAsOutParameter _(&ResolutionError);
18460b57cec5SDimitry Andric       ResolutionError = R.takeError();
18470b57cec5SDimitry Andric       PromisedResult.set_value(SymbolMap());
18480b57cec5SDimitry Andric     }
18490b57cec5SDimitry Andric   };
18500b57cec5SDimitry Andric 
18510b57cec5SDimitry Andric #else
18520b57cec5SDimitry Andric   SymbolMap Result;
18530b57cec5SDimitry Andric   Error ResolutionError = Error::success();
18540b57cec5SDimitry Andric 
18550b57cec5SDimitry Andric   auto NotifyComplete = [&](Expected<SymbolMap> R) {
18560b57cec5SDimitry Andric     ErrorAsOutParameter _(&ResolutionError);
18570b57cec5SDimitry Andric     if (R)
18580b57cec5SDimitry Andric       Result = std::move(*R);
18590b57cec5SDimitry Andric     else
18600b57cec5SDimitry Andric       ResolutionError = R.takeError();
18610b57cec5SDimitry Andric   };
18620b57cec5SDimitry Andric #endif
18630b57cec5SDimitry Andric 
18640b57cec5SDimitry Andric   // Perform the asynchronous lookup.
186581ad6265SDimitry Andric   lookup(K, SearchOrder, std::move(Symbols), RequiredState, NotifyComplete,
18660b57cec5SDimitry Andric          RegisterDependencies);
18670b57cec5SDimitry Andric 
18680b57cec5SDimitry Andric #if LLVM_ENABLE_THREADS
18690b57cec5SDimitry Andric   auto ResultFuture = PromisedResult.get_future();
18700b57cec5SDimitry Andric   auto Result = ResultFuture.get();
18710b57cec5SDimitry Andric 
18720b57cec5SDimitry Andric   if (ResolutionError)
18730b57cec5SDimitry Andric     return std::move(ResolutionError);
18740b57cec5SDimitry Andric 
18750b57cec5SDimitry Andric   return std::move(Result);
18760b57cec5SDimitry Andric 
18770b57cec5SDimitry Andric #else
18780b57cec5SDimitry Andric   if (ResolutionError)
18790b57cec5SDimitry Andric     return std::move(ResolutionError);
18800b57cec5SDimitry Andric 
18810b57cec5SDimitry Andric   return Result;
18820b57cec5SDimitry Andric #endif
18830b57cec5SDimitry Andric }
18840b57cec5SDimitry Andric 
188506c3fb27SDimitry Andric Expected<ExecutorSymbolDef>
1886480093f4SDimitry Andric ExecutionSession::lookup(const JITDylibSearchOrder &SearchOrder,
18875ffd83dbSDimitry Andric                          SymbolStringPtr Name, SymbolState RequiredState) {
1888480093f4SDimitry Andric   SymbolLookupSet Names({Name});
18890b57cec5SDimitry Andric 
1890480093f4SDimitry Andric   if (auto ResultMap = lookup(SearchOrder, std::move(Names), LookupKind::Static,
18915ffd83dbSDimitry Andric                               RequiredState, NoDependenciesToRegister)) {
18920b57cec5SDimitry Andric     assert(ResultMap->size() == 1 && "Unexpected number of results");
18930b57cec5SDimitry Andric     assert(ResultMap->count(Name) && "Missing result for symbol");
18940b57cec5SDimitry Andric     return std::move(ResultMap->begin()->second);
18950b57cec5SDimitry Andric   } else
18960b57cec5SDimitry Andric     return ResultMap.takeError();
18970b57cec5SDimitry Andric }
18980b57cec5SDimitry Andric 
189906c3fb27SDimitry Andric Expected<ExecutorSymbolDef>
19005ffd83dbSDimitry Andric ExecutionSession::lookup(ArrayRef<JITDylib *> SearchOrder, SymbolStringPtr Name,
19015ffd83dbSDimitry Andric                          SymbolState RequiredState) {
19025ffd83dbSDimitry Andric   return lookup(makeJITDylibSearchOrder(SearchOrder), Name, RequiredState);
19030b57cec5SDimitry Andric }
19040b57cec5SDimitry Andric 
190506c3fb27SDimitry Andric Expected<ExecutorSymbolDef>
19065ffd83dbSDimitry Andric ExecutionSession::lookup(ArrayRef<JITDylib *> SearchOrder, StringRef Name,
19075ffd83dbSDimitry Andric                          SymbolState RequiredState) {
19085ffd83dbSDimitry Andric   return lookup(SearchOrder, intern(Name), RequiredState);
19090b57cec5SDimitry Andric }
19100b57cec5SDimitry Andric 
1911fe6060f1SDimitry Andric Error ExecutionSession::registerJITDispatchHandlers(
1912fe6060f1SDimitry Andric     JITDylib &JD, JITDispatchHandlerAssociationMap WFs) {
1913fe6060f1SDimitry Andric 
1914fe6060f1SDimitry Andric   auto TagAddrs = lookup({{&JD, JITDylibLookupFlags::MatchAllSymbols}},
1915fe6060f1SDimitry Andric                          SymbolLookupSet::fromMapKeys(
1916fe6060f1SDimitry Andric                              WFs, SymbolLookupFlags::WeaklyReferencedSymbol));
1917fe6060f1SDimitry Andric   if (!TagAddrs)
1918fe6060f1SDimitry Andric     return TagAddrs.takeError();
1919fe6060f1SDimitry Andric 
1920fe6060f1SDimitry Andric   // Associate tag addresses with implementations.
1921fe6060f1SDimitry Andric   std::lock_guard<std::mutex> Lock(JITDispatchHandlersMutex);
1922fe6060f1SDimitry Andric   for (auto &KV : *TagAddrs) {
1923fe6060f1SDimitry Andric     auto TagAddr = KV.second.getAddress();
1924fe6060f1SDimitry Andric     if (JITDispatchHandlers.count(TagAddr))
1925fe6060f1SDimitry Andric       return make_error<StringError>("Tag " + formatv("{0:x16}", TagAddr) +
1926fe6060f1SDimitry Andric                                          " (for " + *KV.first +
1927fe6060f1SDimitry Andric                                          ") already registered",
1928fe6060f1SDimitry Andric                                      inconvertibleErrorCode());
1929fe6060f1SDimitry Andric     auto I = WFs.find(KV.first);
1930fe6060f1SDimitry Andric     assert(I != WFs.end() && I->second &&
1931fe6060f1SDimitry Andric            "JITDispatchHandler implementation missing");
1932fe6060f1SDimitry Andric     JITDispatchHandlers[KV.second.getAddress()] =
1933fe6060f1SDimitry Andric         std::make_shared<JITDispatchHandlerFunction>(std::move(I->second));
1934fe6060f1SDimitry Andric     LLVM_DEBUG({
1935fe6060f1SDimitry Andric       dbgs() << "Associated function tag \"" << *KV.first << "\" ("
1936fe6060f1SDimitry Andric              << formatv("{0:x}", KV.second.getAddress()) << ") with handler\n";
1937fe6060f1SDimitry Andric     });
1938fe6060f1SDimitry Andric   }
1939fe6060f1SDimitry Andric   return Error::success();
1940fe6060f1SDimitry Andric }
1941fe6060f1SDimitry Andric 
194206c3fb27SDimitry Andric void ExecutionSession::runJITDispatchHandler(SendResultFunction SendResult,
194306c3fb27SDimitry Andric                                              ExecutorAddr HandlerFnTagAddr,
1944349cc55cSDimitry Andric                                              ArrayRef<char> ArgBuffer) {
1945fe6060f1SDimitry Andric 
1946fe6060f1SDimitry Andric   std::shared_ptr<JITDispatchHandlerFunction> F;
1947fe6060f1SDimitry Andric   {
1948fe6060f1SDimitry Andric     std::lock_guard<std::mutex> Lock(JITDispatchHandlersMutex);
1949fe6060f1SDimitry Andric     auto I = JITDispatchHandlers.find(HandlerFnTagAddr);
1950fe6060f1SDimitry Andric     if (I != JITDispatchHandlers.end())
1951fe6060f1SDimitry Andric       F = I->second;
1952fe6060f1SDimitry Andric   }
1953fe6060f1SDimitry Andric 
1954fe6060f1SDimitry Andric   if (F)
1955fe6060f1SDimitry Andric     (*F)(std::move(SendResult), ArgBuffer.data(), ArgBuffer.size());
1956fe6060f1SDimitry Andric   else
1957fe6060f1SDimitry Andric     SendResult(shared::WrapperFunctionResult::createOutOfBandError(
1958fe6060f1SDimitry Andric         ("No function registered for tag " +
1959fe6060f1SDimitry Andric          formatv("{0:x16}", HandlerFnTagAddr))
1960fe6060f1SDimitry Andric             .str()));
1961fe6060f1SDimitry Andric }
1962fe6060f1SDimitry Andric 
19630b57cec5SDimitry Andric void ExecutionSession::dump(raw_ostream &OS) {
19640b57cec5SDimitry Andric   runSessionLocked([this, &OS]() {
19650b57cec5SDimitry Andric     for (auto &JD : JDs)
19660b57cec5SDimitry Andric       JD->dump(OS);
19670b57cec5SDimitry Andric   });
19680b57cec5SDimitry Andric }
19690b57cec5SDimitry Andric 
19700fca6ea1SDimitry Andric #ifdef EXPENSIVE_CHECKS
19710fca6ea1SDimitry Andric bool ExecutionSession::verifySessionState(Twine Phase) {
19720fca6ea1SDimitry Andric   return runSessionLocked([&]() {
19730fca6ea1SDimitry Andric     bool AllOk = true;
19740fca6ea1SDimitry Andric 
19750fca6ea1SDimitry Andric     // We'll collect these and verify them later to avoid redundant checks.
19760fca6ea1SDimitry Andric     DenseSet<JITDylib::EmissionDepUnit *> EDUsToCheck;
19770fca6ea1SDimitry Andric 
19780fca6ea1SDimitry Andric     for (auto &JD : JDs) {
19790fca6ea1SDimitry Andric 
19800fca6ea1SDimitry Andric       auto LogFailure = [&]() -> raw_fd_ostream & {
19810fca6ea1SDimitry Andric         auto &Stream = errs();
19820fca6ea1SDimitry Andric         if (AllOk)
19830fca6ea1SDimitry Andric           Stream << "ERROR: Bad ExecutionSession state detected " << Phase
19840fca6ea1SDimitry Andric                  << "\n";
19850fca6ea1SDimitry Andric         Stream << "  In JITDylib " << JD->getName() << ", ";
19860fca6ea1SDimitry Andric         AllOk = false;
19870fca6ea1SDimitry Andric         return Stream;
19880fca6ea1SDimitry Andric       };
19890fca6ea1SDimitry Andric 
19900fca6ea1SDimitry Andric       if (JD->State != JITDylib::Open) {
19910fca6ea1SDimitry Andric         LogFailure()
19920fca6ea1SDimitry Andric             << "state is not Open, but JD is in ExecutionSession list.";
19930fca6ea1SDimitry Andric       }
19940fca6ea1SDimitry Andric 
19950fca6ea1SDimitry Andric       // Check symbol table.
19960fca6ea1SDimitry Andric       // 1. If the entry state isn't resolved then check that no address has
19970fca6ea1SDimitry Andric       //    been set.
19980fca6ea1SDimitry Andric       // 2. Check that if the hasMaterializerAttached flag is set then there is
19990fca6ea1SDimitry Andric       //    an UnmaterializedInfo entry, and vice-versa.
20000fca6ea1SDimitry Andric       for (auto &[Sym, Entry] : JD->Symbols) {
20010fca6ea1SDimitry Andric         // Check that unresolved symbols have null addresses.
20020fca6ea1SDimitry Andric         if (Entry.getState() < SymbolState::Resolved) {
20030fca6ea1SDimitry Andric           if (Entry.getAddress()) {
20040fca6ea1SDimitry Andric             LogFailure() << "symbol " << Sym << " has state "
20050fca6ea1SDimitry Andric                          << Entry.getState()
20060fca6ea1SDimitry Andric                          << " (not-yet-resolved) but non-null address "
20070fca6ea1SDimitry Andric                          << Entry.getAddress() << ".\n";
20080fca6ea1SDimitry Andric           }
20090fca6ea1SDimitry Andric         }
20100fca6ea1SDimitry Andric 
20110fca6ea1SDimitry Andric         // Check that the hasMaterializerAttached flag is correct.
20120fca6ea1SDimitry Andric         auto UMIItr = JD->UnmaterializedInfos.find(Sym);
20130fca6ea1SDimitry Andric         if (Entry.hasMaterializerAttached()) {
20140fca6ea1SDimitry Andric           if (UMIItr == JD->UnmaterializedInfos.end()) {
20150fca6ea1SDimitry Andric             LogFailure() << "symbol " << Sym
20160fca6ea1SDimitry Andric                          << " entry claims materializer attached, but "
20170fca6ea1SDimitry Andric                             "UnmaterializedInfos has no corresponding entry.\n";
20180fca6ea1SDimitry Andric           }
20190fca6ea1SDimitry Andric         } else if (UMIItr != JD->UnmaterializedInfos.end()) {
20200fca6ea1SDimitry Andric           LogFailure()
20210fca6ea1SDimitry Andric               << "symbol " << Sym
20220fca6ea1SDimitry Andric               << " entry claims no materializer attached, but "
20230fca6ea1SDimitry Andric                  "UnmaterializedInfos has an unexpected entry for it.\n";
20240fca6ea1SDimitry Andric         }
20250fca6ea1SDimitry Andric       }
20260fca6ea1SDimitry Andric 
20270fca6ea1SDimitry Andric       // Check that every UnmaterializedInfo entry has a corresponding entry
20280fca6ea1SDimitry Andric       // in the Symbols table.
20290fca6ea1SDimitry Andric       for (auto &[Sym, UMI] : JD->UnmaterializedInfos) {
20300fca6ea1SDimitry Andric         auto SymItr = JD->Symbols.find(Sym);
20310fca6ea1SDimitry Andric         if (SymItr == JD->Symbols.end()) {
20320fca6ea1SDimitry Andric           LogFailure()
20330fca6ea1SDimitry Andric               << "symbol " << Sym
20340fca6ea1SDimitry Andric               << " has UnmaterializedInfos entry, but no Symbols entry.\n";
20350fca6ea1SDimitry Andric         }
20360fca6ea1SDimitry Andric       }
20370fca6ea1SDimitry Andric 
20380fca6ea1SDimitry Andric       // Check consistency of the MaterializingInfos table.
20390fca6ea1SDimitry Andric       for (auto &[Sym, MII] : JD->MaterializingInfos) {
20400fca6ea1SDimitry Andric 
20410fca6ea1SDimitry Andric         auto SymItr = JD->Symbols.find(Sym);
20420fca6ea1SDimitry Andric         if (SymItr == JD->Symbols.end()) {
20430fca6ea1SDimitry Andric           // If there's no Symbols entry for this MaterializingInfos entry then
20440fca6ea1SDimitry Andric           // report that.
20450fca6ea1SDimitry Andric           LogFailure()
20460fca6ea1SDimitry Andric               << "symbol " << Sym
20470fca6ea1SDimitry Andric               << " has MaterializingInfos entry, but no Symbols entry.\n";
20480fca6ea1SDimitry Andric         } else {
20490fca6ea1SDimitry Andric           // Otherwise check consistency between Symbols and MaterializingInfos.
20500fca6ea1SDimitry Andric 
20510fca6ea1SDimitry Andric           // Ready symbols should not have MaterializingInfos.
20520fca6ea1SDimitry Andric           if (SymItr->second.getState() == SymbolState::Ready) {
20530fca6ea1SDimitry Andric             LogFailure()
20540fca6ea1SDimitry Andric                 << "symbol " << Sym
20550fca6ea1SDimitry Andric                 << " is in Ready state, should not have MaterializingInfo.\n";
20560fca6ea1SDimitry Andric           }
20570fca6ea1SDimitry Andric 
20580fca6ea1SDimitry Andric           // Pending queries should be for subsequent states.
20590fca6ea1SDimitry Andric           auto CurState = static_cast<SymbolState>(
20600fca6ea1SDimitry Andric               static_cast<std::underlying_type_t<SymbolState>>(
20610fca6ea1SDimitry Andric                   SymItr->second.getState()) + 1);
20620fca6ea1SDimitry Andric           for (auto &Q : MII.PendingQueries) {
20630fca6ea1SDimitry Andric             if (Q->getRequiredState() != CurState) {
20640fca6ea1SDimitry Andric               if (Q->getRequiredState() > CurState)
20650fca6ea1SDimitry Andric                 CurState = Q->getRequiredState();
20660fca6ea1SDimitry Andric               else
20670fca6ea1SDimitry Andric                 LogFailure() << "symbol " << Sym
20680fca6ea1SDimitry Andric                              << " has stale or misordered queries.\n";
20690fca6ea1SDimitry Andric             }
20700fca6ea1SDimitry Andric           }
20710fca6ea1SDimitry Andric 
20720fca6ea1SDimitry Andric           // If there's a DefiningEDU then check that...
20730fca6ea1SDimitry Andric           // 1. The JD matches.
20740fca6ea1SDimitry Andric           // 2. The symbol is in the EDU's Symbols map.
20750fca6ea1SDimitry Andric           // 3. The symbol table entry is in the Emitted state.
20760fca6ea1SDimitry Andric           if (MII.DefiningEDU) {
20770fca6ea1SDimitry Andric 
20780fca6ea1SDimitry Andric             EDUsToCheck.insert(MII.DefiningEDU.get());
20790fca6ea1SDimitry Andric 
20800fca6ea1SDimitry Andric             if (MII.DefiningEDU->JD != JD.get()) {
20810fca6ea1SDimitry Andric               LogFailure() << "symbol " << Sym
20820fca6ea1SDimitry Andric                            << " has DefiningEDU with incorrect JD"
20830fca6ea1SDimitry Andric                            << (llvm::is_contained(JDs, MII.DefiningEDU->JD)
20840fca6ea1SDimitry Andric                                    ? " (JD not currently in ExecutionSession"
20850fca6ea1SDimitry Andric                                    : "")
20860fca6ea1SDimitry Andric                            << "\n";
20870fca6ea1SDimitry Andric             }
20880fca6ea1SDimitry Andric 
20890fca6ea1SDimitry Andric             if (SymItr->second.getState() != SymbolState::Emitted) {
20900fca6ea1SDimitry Andric               LogFailure()
20910fca6ea1SDimitry Andric                   << "symbol " << Sym
20920fca6ea1SDimitry Andric                   << " has DefiningEDU, but is not in Emitted state.\n";
20930fca6ea1SDimitry Andric             }
20940fca6ea1SDimitry Andric           }
20950fca6ea1SDimitry Andric 
20960fca6ea1SDimitry Andric           // Check that JDs for any DependantEDUs are also in the session --
20970fca6ea1SDimitry Andric           // that guarantees that we'll also visit them during this loop.
20980fca6ea1SDimitry Andric           for (auto &DepEDU : MII.DependantEDUs) {
20990fca6ea1SDimitry Andric             if (!llvm::is_contained(JDs, DepEDU->JD)) {
21000fca6ea1SDimitry Andric               LogFailure() << "symbol " << Sym << " has DependantEDU "
21010fca6ea1SDimitry Andric                            << (void *)DepEDU << " with JD (" << DepEDU->JD
21020fca6ea1SDimitry Andric                            << ") that isn't in ExecutionSession.\n";
21030fca6ea1SDimitry Andric             }
21040fca6ea1SDimitry Andric           }
21050fca6ea1SDimitry Andric         }
21060fca6ea1SDimitry Andric       }
21070fca6ea1SDimitry Andric     }
21080fca6ea1SDimitry Andric 
21090fca6ea1SDimitry Andric     // Check EDUs.
21100fca6ea1SDimitry Andric     for (auto *EDU : EDUsToCheck) {
21110fca6ea1SDimitry Andric       assert(EDU->JD->State == JITDylib::Open && "EDU->JD is not Open");
21120fca6ea1SDimitry Andric 
21130fca6ea1SDimitry Andric       auto LogFailure = [&]() -> raw_fd_ostream & {
21140fca6ea1SDimitry Andric         AllOk = false;
21150fca6ea1SDimitry Andric         auto &Stream = errs();
21160fca6ea1SDimitry Andric         Stream << "In EDU defining " << EDU->JD->getName() << ": { ";
21170fca6ea1SDimitry Andric         for (auto &[Sym, Flags] : EDU->Symbols)
21180fca6ea1SDimitry Andric           Stream << Sym << " ";
21190fca6ea1SDimitry Andric         Stream << "}, ";
21200fca6ea1SDimitry Andric         return Stream;
21210fca6ea1SDimitry Andric       };
21220fca6ea1SDimitry Andric 
21230fca6ea1SDimitry Andric       if (EDU->Symbols.empty())
21240fca6ea1SDimitry Andric         LogFailure() << "no symbols defined.\n";
21250fca6ea1SDimitry Andric       else {
21260fca6ea1SDimitry Andric         for (auto &[Sym, Flags] : EDU->Symbols) {
21270fca6ea1SDimitry Andric           if (!Sym)
21280fca6ea1SDimitry Andric             LogFailure() << "null symbol defined.\n";
21290fca6ea1SDimitry Andric           else {
21300fca6ea1SDimitry Andric             if (!EDU->JD->Symbols.count(SymbolStringPtr(Sym))) {
21310fca6ea1SDimitry Andric               LogFailure() << "symbol " << Sym
21320fca6ea1SDimitry Andric                            << " isn't present in JD's symbol table.\n";
21330fca6ea1SDimitry Andric             }
21340fca6ea1SDimitry Andric           }
21350fca6ea1SDimitry Andric         }
21360fca6ea1SDimitry Andric       }
21370fca6ea1SDimitry Andric 
21380fca6ea1SDimitry Andric       for (auto &[DepJD, Symbols] : EDU->Dependencies) {
21390fca6ea1SDimitry Andric         if (!llvm::is_contained(JDs, DepJD)) {
21400fca6ea1SDimitry Andric           LogFailure() << "dependant symbols listed for JD that isn't in "
21410fca6ea1SDimitry Andric                           "ExecutionSession.\n";
21420fca6ea1SDimitry Andric         } else {
21430fca6ea1SDimitry Andric           for (auto &DepSym : Symbols) {
21440fca6ea1SDimitry Andric             if (!DepJD->Symbols.count(SymbolStringPtr(DepSym))) {
21450fca6ea1SDimitry Andric               LogFailure()
21460fca6ea1SDimitry Andric                   << "dependant symbol " << DepSym
21470fca6ea1SDimitry Andric                   << " does not appear in symbol table for dependant JD "
21480fca6ea1SDimitry Andric                   << DepJD->getName() << ".\n";
21490fca6ea1SDimitry Andric             }
21500fca6ea1SDimitry Andric           }
21510fca6ea1SDimitry Andric         }
21520fca6ea1SDimitry Andric       }
21530fca6ea1SDimitry Andric     }
21540fca6ea1SDimitry Andric 
21550fca6ea1SDimitry Andric     return AllOk;
21560fca6ea1SDimitry Andric   });
21570fca6ea1SDimitry Andric }
21580fca6ea1SDimitry Andric #endif // EXPENSIVE_CHECKS
21590fca6ea1SDimitry Andric 
2160e8d8bef9SDimitry Andric void ExecutionSession::dispatchOutstandingMUs() {
2161e8d8bef9SDimitry Andric   LLVM_DEBUG(dbgs() << "Dispatching MaterializationUnits...\n");
216204eeddc0SDimitry Andric   while (true) {
2163bdd1243dSDimitry Andric     std::optional<std::pair<std::unique_ptr<MaterializationUnit>,
2164e8d8bef9SDimitry Andric                             std::unique_ptr<MaterializationResponsibility>>>
21655ffd83dbSDimitry Andric         JMU;
21660b57cec5SDimitry Andric 
21670b57cec5SDimitry Andric     {
21680b57cec5SDimitry Andric       std::lock_guard<std::recursive_mutex> Lock(OutstandingMUsMutex);
21690b57cec5SDimitry Andric       if (!OutstandingMUs.empty()) {
21705ffd83dbSDimitry Andric         JMU.emplace(std::move(OutstandingMUs.back()));
21710b57cec5SDimitry Andric         OutstandingMUs.pop_back();
21720b57cec5SDimitry Andric       }
21730b57cec5SDimitry Andric     }
21740b57cec5SDimitry Andric 
21755ffd83dbSDimitry Andric     if (!JMU)
21760b57cec5SDimitry Andric       break;
21775ffd83dbSDimitry Andric 
21785ffd83dbSDimitry Andric     assert(JMU->first && "No MU?");
2179e8d8bef9SDimitry Andric     LLVM_DEBUG(dbgs() << "  Dispatching \"" << JMU->first->getName() << "\"\n");
2180fe6060f1SDimitry Andric     dispatchTask(std::make_unique<MaterializationTask>(std::move(JMU->first),
2181fe6060f1SDimitry Andric                                                        std::move(JMU->second)));
21820b57cec5SDimitry Andric   }
2183e8d8bef9SDimitry Andric   LLVM_DEBUG(dbgs() << "Done dispatching MaterializationUnits.\n");
2184e8d8bef9SDimitry Andric }
2185e8d8bef9SDimitry Andric 
2186e8d8bef9SDimitry Andric Error ExecutionSession::removeResourceTracker(ResourceTracker &RT) {
2187e8d8bef9SDimitry Andric   LLVM_DEBUG({
2188e8d8bef9SDimitry Andric     dbgs() << "In " << RT.getJITDylib().getName() << " removing tracker "
2189e8d8bef9SDimitry Andric            << formatv("{0:x}", RT.getKeyUnsafe()) << "\n";
2190e8d8bef9SDimitry Andric   });
2191e8d8bef9SDimitry Andric   std::vector<ResourceManager *> CurrentResourceManagers;
2192e8d8bef9SDimitry Andric 
2193e8d8bef9SDimitry Andric   JITDylib::AsynchronousSymbolQuerySet QueriesToFail;
2194e8d8bef9SDimitry Andric   std::shared_ptr<SymbolDependenceMap> FailedSymbols;
2195e8d8bef9SDimitry Andric 
2196e8d8bef9SDimitry Andric   runSessionLocked([&] {
2197e8d8bef9SDimitry Andric     CurrentResourceManagers = ResourceManagers;
2198e8d8bef9SDimitry Andric     RT.makeDefunct();
21990fca6ea1SDimitry Andric     std::tie(QueriesToFail, FailedSymbols) =
22000fca6ea1SDimitry Andric         RT.getJITDylib().IL_removeTracker(RT);
2201e8d8bef9SDimitry Andric   });
2202e8d8bef9SDimitry Andric 
2203e8d8bef9SDimitry Andric   Error Err = Error::success();
2204e8d8bef9SDimitry Andric 
2205bdd1243dSDimitry Andric   auto &JD = RT.getJITDylib();
2206e8d8bef9SDimitry Andric   for (auto *L : reverse(CurrentResourceManagers))
2207bdd1243dSDimitry Andric     Err = joinErrors(std::move(Err),
2208bdd1243dSDimitry Andric                      L->handleRemoveResources(JD, RT.getKeyUnsafe()));
2209e8d8bef9SDimitry Andric 
2210e8d8bef9SDimitry Andric   for (auto &Q : QueriesToFail)
221181ad6265SDimitry Andric     Q->handleFailed(
221281ad6265SDimitry Andric         make_error<FailedToMaterialize>(getSymbolStringPool(), FailedSymbols));
2213e8d8bef9SDimitry Andric 
2214e8d8bef9SDimitry Andric   return Err;
2215e8d8bef9SDimitry Andric }
2216e8d8bef9SDimitry Andric 
2217e8d8bef9SDimitry Andric void ExecutionSession::transferResourceTracker(ResourceTracker &DstRT,
2218e8d8bef9SDimitry Andric                                                ResourceTracker &SrcRT) {
2219e8d8bef9SDimitry Andric   LLVM_DEBUG({
2220e8d8bef9SDimitry Andric     dbgs() << "In " << SrcRT.getJITDylib().getName()
2221e8d8bef9SDimitry Andric            << " transfering resources from tracker "
2222e8d8bef9SDimitry Andric            << formatv("{0:x}", SrcRT.getKeyUnsafe()) << " to tracker "
2223e8d8bef9SDimitry Andric            << formatv("{0:x}", DstRT.getKeyUnsafe()) << "\n";
2224e8d8bef9SDimitry Andric   });
2225e8d8bef9SDimitry Andric 
2226e8d8bef9SDimitry Andric   // No-op transfers are allowed and do not invalidate the source.
2227e8d8bef9SDimitry Andric   if (&DstRT == &SrcRT)
2228e8d8bef9SDimitry Andric     return;
2229e8d8bef9SDimitry Andric 
2230e8d8bef9SDimitry Andric   assert(&DstRT.getJITDylib() == &SrcRT.getJITDylib() &&
2231e8d8bef9SDimitry Andric          "Can't transfer resources between JITDylibs");
2232e8d8bef9SDimitry Andric   runSessionLocked([&]() {
2233e8d8bef9SDimitry Andric     SrcRT.makeDefunct();
2234e8d8bef9SDimitry Andric     auto &JD = DstRT.getJITDylib();
2235e8d8bef9SDimitry Andric     JD.transferTracker(DstRT, SrcRT);
2236e8d8bef9SDimitry Andric     for (auto *L : reverse(ResourceManagers))
2237bdd1243dSDimitry Andric       L->handleTransferResources(JD, DstRT.getKeyUnsafe(),
2238bdd1243dSDimitry Andric                                  SrcRT.getKeyUnsafe());
2239e8d8bef9SDimitry Andric   });
2240e8d8bef9SDimitry Andric }
2241e8d8bef9SDimitry Andric 
2242e8d8bef9SDimitry Andric void ExecutionSession::destroyResourceTracker(ResourceTracker &RT) {
2243e8d8bef9SDimitry Andric   runSessionLocked([&]() {
2244e8d8bef9SDimitry Andric     LLVM_DEBUG({
2245e8d8bef9SDimitry Andric       dbgs() << "In " << RT.getJITDylib().getName() << " destroying tracker "
2246e8d8bef9SDimitry Andric              << formatv("{0:x}", RT.getKeyUnsafe()) << "\n";
2247e8d8bef9SDimitry Andric     });
2248e8d8bef9SDimitry Andric     if (!RT.isDefunct())
2249e8d8bef9SDimitry Andric       transferResourceTracker(*RT.getJITDylib().getDefaultResourceTracker(),
2250e8d8bef9SDimitry Andric                               RT);
2251e8d8bef9SDimitry Andric   });
2252e8d8bef9SDimitry Andric }
2253e8d8bef9SDimitry Andric 
2254e8d8bef9SDimitry Andric Error ExecutionSession::IL_updateCandidatesFor(
2255e8d8bef9SDimitry Andric     JITDylib &JD, JITDylibLookupFlags JDLookupFlags,
2256e8d8bef9SDimitry Andric     SymbolLookupSet &Candidates, SymbolLookupSet *NonCandidates) {
2257e8d8bef9SDimitry Andric   return Candidates.forEachWithRemoval(
2258e8d8bef9SDimitry Andric       [&](const SymbolStringPtr &Name,
2259e8d8bef9SDimitry Andric           SymbolLookupFlags SymLookupFlags) -> Expected<bool> {
2260e8d8bef9SDimitry Andric         /// Search for the symbol. If not found then continue without
2261e8d8bef9SDimitry Andric         /// removal.
2262e8d8bef9SDimitry Andric         auto SymI = JD.Symbols.find(Name);
2263e8d8bef9SDimitry Andric         if (SymI == JD.Symbols.end())
2264e8d8bef9SDimitry Andric           return false;
2265e8d8bef9SDimitry Andric 
2266e8d8bef9SDimitry Andric         // If this is a non-exported symbol and we're matching exported
2267e8d8bef9SDimitry Andric         // symbols only then remove this symbol from the candidates list.
2268e8d8bef9SDimitry Andric         //
2269e8d8bef9SDimitry Andric         // If we're tracking non-candidates then add this to the non-candidate
2270e8d8bef9SDimitry Andric         // list.
2271e8d8bef9SDimitry Andric         if (!SymI->second.getFlags().isExported() &&
2272e8d8bef9SDimitry Andric             JDLookupFlags == JITDylibLookupFlags::MatchExportedSymbolsOnly) {
2273e8d8bef9SDimitry Andric           if (NonCandidates)
2274e8d8bef9SDimitry Andric             NonCandidates->add(Name, SymLookupFlags);
2275e8d8bef9SDimitry Andric           return true;
2276e8d8bef9SDimitry Andric         }
2277e8d8bef9SDimitry Andric 
2278e8d8bef9SDimitry Andric         // If we match against a materialization-side-effects only symbol
2279e8d8bef9SDimitry Andric         // then make sure it is weakly-referenced. Otherwise bail out with
2280e8d8bef9SDimitry Andric         // an error.
2281e8d8bef9SDimitry Andric         // FIXME: Use a "materialization-side-effects-only symbols must be
2282e8d8bef9SDimitry Andric         // weakly referenced" specific error here to reduce confusion.
2283e8d8bef9SDimitry Andric         if (SymI->second.getFlags().hasMaterializationSideEffectsOnly() &&
2284e8d8bef9SDimitry Andric             SymLookupFlags != SymbolLookupFlags::WeaklyReferencedSymbol)
2285349cc55cSDimitry Andric           return make_error<SymbolsNotFound>(getSymbolStringPool(),
2286349cc55cSDimitry Andric                                              SymbolNameVector({Name}));
2287e8d8bef9SDimitry Andric 
2288e8d8bef9SDimitry Andric         // If we matched against this symbol but it is in the error state
2289e8d8bef9SDimitry Andric         // then bail out and treat it as a failure to materialize.
2290e8d8bef9SDimitry Andric         if (SymI->second.getFlags().hasError()) {
2291e8d8bef9SDimitry Andric           auto FailedSymbolsMap = std::make_shared<SymbolDependenceMap>();
2292e8d8bef9SDimitry Andric           (*FailedSymbolsMap)[&JD] = {Name};
229381ad6265SDimitry Andric           return make_error<FailedToMaterialize>(getSymbolStringPool(),
229481ad6265SDimitry Andric                                                  std::move(FailedSymbolsMap));
2295e8d8bef9SDimitry Andric         }
2296e8d8bef9SDimitry Andric 
2297e8d8bef9SDimitry Andric         // Otherwise this is a match. Remove it from the candidate set.
2298e8d8bef9SDimitry Andric         return true;
2299e8d8bef9SDimitry Andric       });
2300e8d8bef9SDimitry Andric }
2301e8d8bef9SDimitry Andric 
23025f757f3fSDimitry Andric void ExecutionSession::OL_resumeLookupAfterGeneration(
23035f757f3fSDimitry Andric     InProgressLookupState &IPLS) {
23045f757f3fSDimitry Andric 
23055f757f3fSDimitry Andric   assert(IPLS.GenState != InProgressLookupState::NotInGenerator &&
23065f757f3fSDimitry Andric          "Should not be called for not-in-generator lookups");
23075f757f3fSDimitry Andric   IPLS.GenState = InProgressLookupState::NotInGenerator;
23085f757f3fSDimitry Andric 
23095f757f3fSDimitry Andric   LookupState LS;
23105f757f3fSDimitry Andric 
23115f757f3fSDimitry Andric   if (auto DG = IPLS.CurDefGeneratorStack.back().lock()) {
23125f757f3fSDimitry Andric     IPLS.CurDefGeneratorStack.pop_back();
23135f757f3fSDimitry Andric     std::lock_guard<std::mutex> Lock(DG->M);
23145f757f3fSDimitry Andric 
23155f757f3fSDimitry Andric     // If there are no pending lookups then mark the generator as free and
23165f757f3fSDimitry Andric     // return.
23175f757f3fSDimitry Andric     if (DG->PendingLookups.empty()) {
23185f757f3fSDimitry Andric       DG->InUse = false;
23195f757f3fSDimitry Andric       return;
23205f757f3fSDimitry Andric     }
23215f757f3fSDimitry Andric 
23225f757f3fSDimitry Andric     // Otherwise resume the next lookup.
23235f757f3fSDimitry Andric     LS = std::move(DG->PendingLookups.front());
23245f757f3fSDimitry Andric     DG->PendingLookups.pop_front();
23255f757f3fSDimitry Andric   }
23265f757f3fSDimitry Andric 
23275f757f3fSDimitry Andric   if (LS.IPLS) {
23285f757f3fSDimitry Andric     LS.IPLS->GenState = InProgressLookupState::ResumedForGenerator;
23295f757f3fSDimitry Andric     dispatchTask(std::make_unique<LookupTask>(std::move(LS)));
23305f757f3fSDimitry Andric   }
23315f757f3fSDimitry Andric }
23325f757f3fSDimitry Andric 
2333e8d8bef9SDimitry Andric void ExecutionSession::OL_applyQueryPhase1(
2334e8d8bef9SDimitry Andric     std::unique_ptr<InProgressLookupState> IPLS, Error Err) {
2335e8d8bef9SDimitry Andric 
2336e8d8bef9SDimitry Andric   LLVM_DEBUG({
2337e8d8bef9SDimitry Andric     dbgs() << "Entering OL_applyQueryPhase1:\n"
2338e8d8bef9SDimitry Andric            << "  Lookup kind: " << IPLS->K << "\n"
2339e8d8bef9SDimitry Andric            << "  Search order: " << IPLS->SearchOrder
2340e8d8bef9SDimitry Andric            << ", Current index = " << IPLS->CurSearchOrderIndex
2341e8d8bef9SDimitry Andric            << (IPLS->NewJITDylib ? " (entering new JITDylib)" : "") << "\n"
2342e8d8bef9SDimitry Andric            << "  Lookup set: " << IPLS->LookupSet << "\n"
2343e8d8bef9SDimitry Andric            << "  Definition generator candidates: "
2344e8d8bef9SDimitry Andric            << IPLS->DefGeneratorCandidates << "\n"
2345e8d8bef9SDimitry Andric            << "  Definition generator non-candidates: "
2346e8d8bef9SDimitry Andric            << IPLS->DefGeneratorNonCandidates << "\n";
2347e8d8bef9SDimitry Andric   });
2348e8d8bef9SDimitry Andric 
23495f757f3fSDimitry Andric   if (IPLS->GenState == InProgressLookupState::InGenerator)
23505f757f3fSDimitry Andric     OL_resumeLookupAfterGeneration(*IPLS);
23515f757f3fSDimitry Andric 
23525f757f3fSDimitry Andric   assert(IPLS->GenState != InProgressLookupState::InGenerator &&
23535f757f3fSDimitry Andric          "Lookup should not be in InGenerator state here");
23545f757f3fSDimitry Andric 
2355e8d8bef9SDimitry Andric   // FIXME: We should attach the query as we go: This provides a result in a
2356e8d8bef9SDimitry Andric   // single pass in the common case where all symbols have already reached the
2357e8d8bef9SDimitry Andric   // required state. The query could be detached again in the 'fail' method on
2358e8d8bef9SDimitry Andric   // IPLS. Phase 2 would be reduced to collecting and dispatching the MUs.
2359e8d8bef9SDimitry Andric 
2360e8d8bef9SDimitry Andric   while (IPLS->CurSearchOrderIndex != IPLS->SearchOrder.size()) {
2361e8d8bef9SDimitry Andric 
2362e8d8bef9SDimitry Andric     // If we've been handed an error or received one back from a generator then
2363e8d8bef9SDimitry Andric     // fail the query. We don't need to unlink: At this stage the query hasn't
2364e8d8bef9SDimitry Andric     // actually been lodged.
2365e8d8bef9SDimitry Andric     if (Err)
2366e8d8bef9SDimitry Andric       return IPLS->fail(std::move(Err));
2367e8d8bef9SDimitry Andric 
2368e8d8bef9SDimitry Andric     // Get the next JITDylib and lookup flags.
2369e8d8bef9SDimitry Andric     auto &KV = IPLS->SearchOrder[IPLS->CurSearchOrderIndex];
2370e8d8bef9SDimitry Andric     auto &JD = *KV.first;
2371e8d8bef9SDimitry Andric     auto JDLookupFlags = KV.second;
2372e8d8bef9SDimitry Andric 
2373e8d8bef9SDimitry Andric     LLVM_DEBUG({
2374e8d8bef9SDimitry Andric       dbgs() << "Visiting \"" << JD.getName() << "\" (" << JDLookupFlags
2375e8d8bef9SDimitry Andric              << ") with lookup set " << IPLS->LookupSet << ":\n";
2376e8d8bef9SDimitry Andric     });
2377e8d8bef9SDimitry Andric 
2378e8d8bef9SDimitry Andric     // If we've just reached a new JITDylib then perform some setup.
2379e8d8bef9SDimitry Andric     if (IPLS->NewJITDylib) {
2380e8d8bef9SDimitry Andric       // Add any non-candidates from the last JITDylib (if any) back on to the
2381e8d8bef9SDimitry Andric       // list of definition candidates for this JITDylib, reset definition
2382bdd1243dSDimitry Andric       // non-candidates to the empty set.
2383e8d8bef9SDimitry Andric       SymbolLookupSet Tmp;
2384e8d8bef9SDimitry Andric       std::swap(IPLS->DefGeneratorNonCandidates, Tmp);
2385e8d8bef9SDimitry Andric       IPLS->DefGeneratorCandidates.append(std::move(Tmp));
2386e8d8bef9SDimitry Andric 
2387e8d8bef9SDimitry Andric       LLVM_DEBUG({
2388e8d8bef9SDimitry Andric         dbgs() << "  First time visiting " << JD.getName()
2389e8d8bef9SDimitry Andric                << ", resetting candidate sets and building generator stack\n";
2390e8d8bef9SDimitry Andric       });
2391e8d8bef9SDimitry Andric 
2392e8d8bef9SDimitry Andric       // Build the definition generator stack for this JITDylib.
23934824e7fdSDimitry Andric       runSessionLocked([&] {
23944824e7fdSDimitry Andric         IPLS->CurDefGeneratorStack.reserve(JD.DefGenerators.size());
2395e8d8bef9SDimitry Andric         for (auto &DG : reverse(JD.DefGenerators))
2396e8d8bef9SDimitry Andric           IPLS->CurDefGeneratorStack.push_back(DG);
23974824e7fdSDimitry Andric       });
2398e8d8bef9SDimitry Andric 
2399e8d8bef9SDimitry Andric       // Flag that we've done our initialization.
2400e8d8bef9SDimitry Andric       IPLS->NewJITDylib = false;
2401e8d8bef9SDimitry Andric     }
2402e8d8bef9SDimitry Andric 
2403e8d8bef9SDimitry Andric     // Remove any generation candidates that are already defined (and match) in
2404e8d8bef9SDimitry Andric     // this JITDylib.
2405e8d8bef9SDimitry Andric     runSessionLocked([&] {
2406e8d8bef9SDimitry Andric       // Update the list of candidates (and non-candidates) for definition
2407e8d8bef9SDimitry Andric       // generation.
2408e8d8bef9SDimitry Andric       LLVM_DEBUG(dbgs() << "  Updating candidate set...\n");
2409e8d8bef9SDimitry Andric       Err = IL_updateCandidatesFor(
2410e8d8bef9SDimitry Andric           JD, JDLookupFlags, IPLS->DefGeneratorCandidates,
2411e8d8bef9SDimitry Andric           JD.DefGenerators.empty() ? nullptr
2412e8d8bef9SDimitry Andric                                    : &IPLS->DefGeneratorNonCandidates);
2413e8d8bef9SDimitry Andric       LLVM_DEBUG({
2414e8d8bef9SDimitry Andric         dbgs() << "    Remaining candidates = " << IPLS->DefGeneratorCandidates
2415e8d8bef9SDimitry Andric                << "\n";
2416e8d8bef9SDimitry Andric       });
24175f757f3fSDimitry Andric 
24185f757f3fSDimitry Andric       // If this lookup was resumed after auto-suspension but all candidates
24195f757f3fSDimitry Andric       // have already been generated (by some previous call to the generator)
24205f757f3fSDimitry Andric       // treat the lookup as if it had completed generation.
24215f757f3fSDimitry Andric       if (IPLS->GenState == InProgressLookupState::ResumedForGenerator &&
24225f757f3fSDimitry Andric           IPLS->DefGeneratorCandidates.empty())
24235f757f3fSDimitry Andric         OL_resumeLookupAfterGeneration(*IPLS);
2424e8d8bef9SDimitry Andric     });
2425e8d8bef9SDimitry Andric 
2426e8d8bef9SDimitry Andric     // If we encountered an error while filtering generation candidates then
2427e8d8bef9SDimitry Andric     // bail out.
2428e8d8bef9SDimitry Andric     if (Err)
2429e8d8bef9SDimitry Andric       return IPLS->fail(std::move(Err));
2430e8d8bef9SDimitry Andric 
2431e8d8bef9SDimitry Andric     /// Apply any definition generators on the stack.
2432e8d8bef9SDimitry Andric     LLVM_DEBUG({
2433e8d8bef9SDimitry Andric       if (IPLS->CurDefGeneratorStack.empty())
2434e8d8bef9SDimitry Andric         LLVM_DEBUG(dbgs() << "  No generators to run for this JITDylib.\n");
2435e8d8bef9SDimitry Andric       else if (IPLS->DefGeneratorCandidates.empty())
2436e8d8bef9SDimitry Andric         LLVM_DEBUG(dbgs() << "  No candidates to generate.\n");
2437e8d8bef9SDimitry Andric       else
2438e8d8bef9SDimitry Andric         dbgs() << "  Running " << IPLS->CurDefGeneratorStack.size()
2439e8d8bef9SDimitry Andric                << " remaining generators for "
2440e8d8bef9SDimitry Andric                << IPLS->DefGeneratorCandidates.size() << " candidates\n";
2441e8d8bef9SDimitry Andric     });
2442e8d8bef9SDimitry Andric     while (!IPLS->CurDefGeneratorStack.empty() &&
2443e8d8bef9SDimitry Andric            !IPLS->DefGeneratorCandidates.empty()) {
2444e8d8bef9SDimitry Andric       auto DG = IPLS->CurDefGeneratorStack.back().lock();
2445e8d8bef9SDimitry Andric 
2446e8d8bef9SDimitry Andric       if (!DG)
2447e8d8bef9SDimitry Andric         return IPLS->fail(make_error<StringError>(
2448e8d8bef9SDimitry Andric             "DefinitionGenerator removed while lookup in progress",
2449e8d8bef9SDimitry Andric             inconvertibleErrorCode()));
2450e8d8bef9SDimitry Andric 
24515f757f3fSDimitry Andric       // At this point the lookup is in either the NotInGenerator state, or in
24525f757f3fSDimitry Andric       // the ResumedForGenerator state.
24535f757f3fSDimitry Andric       // If this lookup is in the NotInGenerator state then check whether the
24545f757f3fSDimitry Andric       // generator is in use. If the generator is not in use then move the
24555f757f3fSDimitry Andric       // lookup to the InGenerator state and continue. If the generator is
24565f757f3fSDimitry Andric       // already in use then just add this lookup to the pending lookups list
24575f757f3fSDimitry Andric       // and bail out.
24585f757f3fSDimitry Andric       // If this lookup is in the ResumedForGenerator state then just move it
24595f757f3fSDimitry Andric       // to InGenerator and continue.
24605f757f3fSDimitry Andric       if (IPLS->GenState == InProgressLookupState::NotInGenerator) {
24615f757f3fSDimitry Andric         std::lock_guard<std::mutex> Lock(DG->M);
24625f757f3fSDimitry Andric         if (DG->InUse) {
24635f757f3fSDimitry Andric           DG->PendingLookups.push_back(std::move(IPLS));
24645f757f3fSDimitry Andric           return;
24655f757f3fSDimitry Andric         }
24665f757f3fSDimitry Andric         DG->InUse = true;
24675f757f3fSDimitry Andric       }
24685f757f3fSDimitry Andric 
24695f757f3fSDimitry Andric       IPLS->GenState = InProgressLookupState::InGenerator;
24705f757f3fSDimitry Andric 
2471e8d8bef9SDimitry Andric       auto K = IPLS->K;
2472e8d8bef9SDimitry Andric       auto &LookupSet = IPLS->DefGeneratorCandidates;
2473e8d8bef9SDimitry Andric 
2474e8d8bef9SDimitry Andric       // Run the generator. If the generator takes ownership of QA then this
2475e8d8bef9SDimitry Andric       // will break the loop.
2476e8d8bef9SDimitry Andric       {
2477e8d8bef9SDimitry Andric         LLVM_DEBUG(dbgs() << "  Attempting to generate " << LookupSet << "\n");
2478e8d8bef9SDimitry Andric         LookupState LS(std::move(IPLS));
2479e8d8bef9SDimitry Andric         Err = DG->tryToGenerate(LS, K, JD, JDLookupFlags, LookupSet);
2480e8d8bef9SDimitry Andric         IPLS = std::move(LS.IPLS);
2481e8d8bef9SDimitry Andric       }
2482e8d8bef9SDimitry Andric 
24835f757f3fSDimitry Andric       // If the lookup returned then pop the generator stack and unblock the
24845f757f3fSDimitry Andric       // next lookup on this generator (if any).
24855f757f3fSDimitry Andric       if (IPLS)
24865f757f3fSDimitry Andric         OL_resumeLookupAfterGeneration(*IPLS);
24875f757f3fSDimitry Andric 
2488e8d8bef9SDimitry Andric       // If there was an error then fail the query.
2489e8d8bef9SDimitry Andric       if (Err) {
2490e8d8bef9SDimitry Andric         LLVM_DEBUG({
2491e8d8bef9SDimitry Andric           dbgs() << "  Error attempting to generate " << LookupSet << "\n";
2492e8d8bef9SDimitry Andric         });
2493e8d8bef9SDimitry Andric         assert(IPLS && "LS cannot be retained if error is returned");
2494e8d8bef9SDimitry Andric         return IPLS->fail(std::move(Err));
2495e8d8bef9SDimitry Andric       }
2496e8d8bef9SDimitry Andric 
2497e8d8bef9SDimitry Andric       // Otherwise if QA was captured then break the loop.
2498e8d8bef9SDimitry Andric       if (!IPLS) {
2499e8d8bef9SDimitry Andric         LLVM_DEBUG(
2500e8d8bef9SDimitry Andric             { dbgs() << "  LookupState captured. Exiting phase1 for now.\n"; });
2501e8d8bef9SDimitry Andric         return;
2502e8d8bef9SDimitry Andric       }
2503e8d8bef9SDimitry Andric 
2504e8d8bef9SDimitry Andric       // Otherwise if we're continuing around the loop then update candidates
2505e8d8bef9SDimitry Andric       // for the next round.
2506e8d8bef9SDimitry Andric       runSessionLocked([&] {
2507e8d8bef9SDimitry Andric         LLVM_DEBUG(dbgs() << "  Updating candidate set post-generation\n");
2508e8d8bef9SDimitry Andric         Err = IL_updateCandidatesFor(
2509e8d8bef9SDimitry Andric             JD, JDLookupFlags, IPLS->DefGeneratorCandidates,
2510e8d8bef9SDimitry Andric             JD.DefGenerators.empty() ? nullptr
2511e8d8bef9SDimitry Andric                                      : &IPLS->DefGeneratorNonCandidates);
2512e8d8bef9SDimitry Andric       });
2513e8d8bef9SDimitry Andric 
2514e8d8bef9SDimitry Andric       // If updating candidates failed then fail the query.
2515e8d8bef9SDimitry Andric       if (Err) {
2516e8d8bef9SDimitry Andric         LLVM_DEBUG(dbgs() << "  Error encountered while updating candidates\n");
2517e8d8bef9SDimitry Andric         return IPLS->fail(std::move(Err));
2518e8d8bef9SDimitry Andric       }
2519e8d8bef9SDimitry Andric     }
2520e8d8bef9SDimitry Andric 
25210eae32dcSDimitry Andric     if (IPLS->DefGeneratorCandidates.empty() &&
25220eae32dcSDimitry Andric         IPLS->DefGeneratorNonCandidates.empty()) {
25230eae32dcSDimitry Andric       // Early out if there are no remaining symbols.
25240eae32dcSDimitry Andric       LLVM_DEBUG(dbgs() << "All symbols matched.\n");
25250eae32dcSDimitry Andric       IPLS->CurSearchOrderIndex = IPLS->SearchOrder.size();
25260eae32dcSDimitry Andric       break;
25270eae32dcSDimitry Andric     } else {
25280eae32dcSDimitry Andric       // If we get here then we've moved on to the next JITDylib with candidates
25290eae32dcSDimitry Andric       // remaining.
2530e8d8bef9SDimitry Andric       LLVM_DEBUG(dbgs() << "Phase 1 moving to next JITDylib.\n");
2531e8d8bef9SDimitry Andric       ++IPLS->CurSearchOrderIndex;
2532e8d8bef9SDimitry Andric       IPLS->NewJITDylib = true;
2533e8d8bef9SDimitry Andric     }
25340eae32dcSDimitry Andric   }
2535e8d8bef9SDimitry Andric 
2536e8d8bef9SDimitry Andric   // Remove any weakly referenced candidates that could not be found/generated.
2537e8d8bef9SDimitry Andric   IPLS->DefGeneratorCandidates.remove_if(
2538e8d8bef9SDimitry Andric       [](const SymbolStringPtr &Name, SymbolLookupFlags SymLookupFlags) {
2539e8d8bef9SDimitry Andric         return SymLookupFlags == SymbolLookupFlags::WeaklyReferencedSymbol;
2540e8d8bef9SDimitry Andric       });
2541e8d8bef9SDimitry Andric 
2542e8d8bef9SDimitry Andric   // If we get here then we've finished searching all JITDylibs.
2543e8d8bef9SDimitry Andric   // If we matched all symbols then move to phase 2, otherwise fail the query
2544e8d8bef9SDimitry Andric   // with a SymbolsNotFound error.
2545e8d8bef9SDimitry Andric   if (IPLS->DefGeneratorCandidates.empty()) {
2546e8d8bef9SDimitry Andric     LLVM_DEBUG(dbgs() << "Phase 1 succeeded.\n");
2547e8d8bef9SDimitry Andric     IPLS->complete(std::move(IPLS));
2548e8d8bef9SDimitry Andric   } else {
2549e8d8bef9SDimitry Andric     LLVM_DEBUG(dbgs() << "Phase 1 failed with unresolved symbols.\n");
2550e8d8bef9SDimitry Andric     IPLS->fail(make_error<SymbolsNotFound>(
2551349cc55cSDimitry Andric         getSymbolStringPool(), IPLS->DefGeneratorCandidates.getSymbolNames()));
2552e8d8bef9SDimitry Andric   }
2553e8d8bef9SDimitry Andric }
2554e8d8bef9SDimitry Andric 
2555e8d8bef9SDimitry Andric void ExecutionSession::OL_completeLookup(
2556e8d8bef9SDimitry Andric     std::unique_ptr<InProgressLookupState> IPLS,
2557e8d8bef9SDimitry Andric     std::shared_ptr<AsynchronousSymbolQuery> Q,
2558e8d8bef9SDimitry Andric     RegisterDependenciesFunction RegisterDependencies) {
2559e8d8bef9SDimitry Andric 
2560e8d8bef9SDimitry Andric   LLVM_DEBUG({
2561e8d8bef9SDimitry Andric     dbgs() << "Entering OL_completeLookup:\n"
2562e8d8bef9SDimitry Andric            << "  Lookup kind: " << IPLS->K << "\n"
2563e8d8bef9SDimitry Andric            << "  Search order: " << IPLS->SearchOrder
2564e8d8bef9SDimitry Andric            << ", Current index = " << IPLS->CurSearchOrderIndex
2565e8d8bef9SDimitry Andric            << (IPLS->NewJITDylib ? " (entering new JITDylib)" : "") << "\n"
2566e8d8bef9SDimitry Andric            << "  Lookup set: " << IPLS->LookupSet << "\n"
2567e8d8bef9SDimitry Andric            << "  Definition generator candidates: "
2568e8d8bef9SDimitry Andric            << IPLS->DefGeneratorCandidates << "\n"
2569e8d8bef9SDimitry Andric            << "  Definition generator non-candidates: "
2570e8d8bef9SDimitry Andric            << IPLS->DefGeneratorNonCandidates << "\n";
2571e8d8bef9SDimitry Andric   });
2572e8d8bef9SDimitry Andric 
2573e8d8bef9SDimitry Andric   bool QueryComplete = false;
2574e8d8bef9SDimitry Andric   DenseMap<JITDylib *, JITDylib::UnmaterializedInfosList> CollectedUMIs;
2575e8d8bef9SDimitry Andric 
2576e8d8bef9SDimitry Andric   auto LodgingErr = runSessionLocked([&]() -> Error {
2577e8d8bef9SDimitry Andric     for (auto &KV : IPLS->SearchOrder) {
2578e8d8bef9SDimitry Andric       auto &JD = *KV.first;
2579e8d8bef9SDimitry Andric       auto JDLookupFlags = KV.second;
2580e8d8bef9SDimitry Andric       LLVM_DEBUG({
2581e8d8bef9SDimitry Andric         dbgs() << "Visiting \"" << JD.getName() << "\" (" << JDLookupFlags
2582e8d8bef9SDimitry Andric                << ") with lookup set " << IPLS->LookupSet << ":\n";
2583e8d8bef9SDimitry Andric       });
2584e8d8bef9SDimitry Andric 
2585e8d8bef9SDimitry Andric       auto Err = IPLS->LookupSet.forEachWithRemoval(
2586e8d8bef9SDimitry Andric           [&](const SymbolStringPtr &Name,
2587e8d8bef9SDimitry Andric               SymbolLookupFlags SymLookupFlags) -> Expected<bool> {
2588e8d8bef9SDimitry Andric             LLVM_DEBUG({
2589e8d8bef9SDimitry Andric               dbgs() << "  Attempting to match \"" << Name << "\" ("
2590e8d8bef9SDimitry Andric                      << SymLookupFlags << ")... ";
2591e8d8bef9SDimitry Andric             });
2592e8d8bef9SDimitry Andric 
2593e8d8bef9SDimitry Andric             /// Search for the symbol. If not found then continue without
2594e8d8bef9SDimitry Andric             /// removal.
2595e8d8bef9SDimitry Andric             auto SymI = JD.Symbols.find(Name);
2596e8d8bef9SDimitry Andric             if (SymI == JD.Symbols.end()) {
2597e8d8bef9SDimitry Andric               LLVM_DEBUG(dbgs() << "skipping: not present\n");
2598e8d8bef9SDimitry Andric               return false;
2599e8d8bef9SDimitry Andric             }
2600e8d8bef9SDimitry Andric 
2601e8d8bef9SDimitry Andric             // If this is a non-exported symbol and we're matching exported
2602e8d8bef9SDimitry Andric             // symbols only then skip this symbol without removal.
2603e8d8bef9SDimitry Andric             if (!SymI->second.getFlags().isExported() &&
2604e8d8bef9SDimitry Andric                 JDLookupFlags ==
2605e8d8bef9SDimitry Andric                     JITDylibLookupFlags::MatchExportedSymbolsOnly) {
2606e8d8bef9SDimitry Andric               LLVM_DEBUG(dbgs() << "skipping: not exported\n");
2607e8d8bef9SDimitry Andric               return false;
2608e8d8bef9SDimitry Andric             }
2609e8d8bef9SDimitry Andric 
2610e8d8bef9SDimitry Andric             // If we match against a materialization-side-effects only symbol
2611e8d8bef9SDimitry Andric             // then make sure it is weakly-referenced. Otherwise bail out with
2612e8d8bef9SDimitry Andric             // an error.
2613e8d8bef9SDimitry Andric             // FIXME: Use a "materialization-side-effects-only symbols must be
2614e8d8bef9SDimitry Andric             // weakly referenced" specific error here to reduce confusion.
2615e8d8bef9SDimitry Andric             if (SymI->second.getFlags().hasMaterializationSideEffectsOnly() &&
2616e8d8bef9SDimitry Andric                 SymLookupFlags != SymbolLookupFlags::WeaklyReferencedSymbol) {
2617e8d8bef9SDimitry Andric               LLVM_DEBUG({
2618e8d8bef9SDimitry Andric                 dbgs() << "error: "
2619e8d8bef9SDimitry Andric                           "required, but symbol is has-side-effects-only\n";
2620e8d8bef9SDimitry Andric               });
2621349cc55cSDimitry Andric               return make_error<SymbolsNotFound>(getSymbolStringPool(),
2622349cc55cSDimitry Andric                                                  SymbolNameVector({Name}));
2623e8d8bef9SDimitry Andric             }
2624e8d8bef9SDimitry Andric 
2625e8d8bef9SDimitry Andric             // If we matched against this symbol but it is in the error state
2626e8d8bef9SDimitry Andric             // then bail out and treat it as a failure to materialize.
2627e8d8bef9SDimitry Andric             if (SymI->second.getFlags().hasError()) {
2628e8d8bef9SDimitry Andric               LLVM_DEBUG(dbgs() << "error: symbol is in error state\n");
2629e8d8bef9SDimitry Andric               auto FailedSymbolsMap = std::make_shared<SymbolDependenceMap>();
2630e8d8bef9SDimitry Andric               (*FailedSymbolsMap)[&JD] = {Name};
2631e8d8bef9SDimitry Andric               return make_error<FailedToMaterialize>(
263281ad6265SDimitry Andric                   getSymbolStringPool(), std::move(FailedSymbolsMap));
2633e8d8bef9SDimitry Andric             }
2634e8d8bef9SDimitry Andric 
2635e8d8bef9SDimitry Andric             // Otherwise this is a match.
2636e8d8bef9SDimitry Andric 
26375f757f3fSDimitry Andric             // If this symbol is already in the required state then notify the
2638e8d8bef9SDimitry Andric             // query, remove the symbol and continue.
2639e8d8bef9SDimitry Andric             if (SymI->second.getState() >= Q->getRequiredState()) {
2640e8d8bef9SDimitry Andric               LLVM_DEBUG(dbgs()
2641e8d8bef9SDimitry Andric                          << "matched, symbol already in required state\n");
2642e8d8bef9SDimitry Andric               Q->notifySymbolMetRequiredState(Name, SymI->second.getSymbol());
2643e8d8bef9SDimitry Andric               return true;
2644e8d8bef9SDimitry Andric             }
2645e8d8bef9SDimitry Andric 
2646e8d8bef9SDimitry Andric             // Otherwise this symbol does not yet meet the required state. Check
2647e8d8bef9SDimitry Andric             // whether it has a materializer attached, and if so prepare to run
2648e8d8bef9SDimitry Andric             // it.
2649e8d8bef9SDimitry Andric             if (SymI->second.hasMaterializerAttached()) {
265006c3fb27SDimitry Andric               assert(SymI->second.getAddress() == ExecutorAddr() &&
2651e8d8bef9SDimitry Andric                      "Symbol not resolved but already has address?");
2652e8d8bef9SDimitry Andric               auto UMII = JD.UnmaterializedInfos.find(Name);
2653e8d8bef9SDimitry Andric               assert(UMII != JD.UnmaterializedInfos.end() &&
2654e8d8bef9SDimitry Andric                      "Lazy symbol should have UnmaterializedInfo");
2655e8d8bef9SDimitry Andric 
2656e8d8bef9SDimitry Andric               auto UMI = UMII->second;
2657e8d8bef9SDimitry Andric               assert(UMI->MU && "Materializer should not be null");
2658e8d8bef9SDimitry Andric               assert(UMI->RT && "Tracker should not be null");
2659e8d8bef9SDimitry Andric               LLVM_DEBUG({
2660e8d8bef9SDimitry Andric                 dbgs() << "matched, preparing to dispatch MU@" << UMI->MU.get()
2661e8d8bef9SDimitry Andric                        << " (" << UMI->MU->getName() << ")\n";
2662e8d8bef9SDimitry Andric               });
2663e8d8bef9SDimitry Andric 
2664e8d8bef9SDimitry Andric               // Move all symbols associated with this MaterializationUnit into
2665e8d8bef9SDimitry Andric               // materializing state.
2666e8d8bef9SDimitry Andric               for (auto &KV : UMI->MU->getSymbols()) {
2667e8d8bef9SDimitry Andric                 auto SymK = JD.Symbols.find(KV.first);
2668e8d8bef9SDimitry Andric                 assert(SymK != JD.Symbols.end() &&
2669e8d8bef9SDimitry Andric                        "No entry for symbol covered by MaterializationUnit");
2670e8d8bef9SDimitry Andric                 SymK->second.setMaterializerAttached(false);
2671e8d8bef9SDimitry Andric                 SymK->second.setState(SymbolState::Materializing);
2672e8d8bef9SDimitry Andric                 JD.UnmaterializedInfos.erase(KV.first);
2673e8d8bef9SDimitry Andric               }
2674e8d8bef9SDimitry Andric 
2675e8d8bef9SDimitry Andric               // Add MU to the list of MaterializationUnits to be materialized.
2676e8d8bef9SDimitry Andric               CollectedUMIs[&JD].push_back(std::move(UMI));
2677e8d8bef9SDimitry Andric             } else
2678e8d8bef9SDimitry Andric               LLVM_DEBUG(dbgs() << "matched, registering query");
2679e8d8bef9SDimitry Andric 
2680e8d8bef9SDimitry Andric             // Add the query to the PendingQueries list and continue, deleting
2681e8d8bef9SDimitry Andric             // the element from the lookup set.
2682e8d8bef9SDimitry Andric             assert(SymI->second.getState() != SymbolState::NeverSearched &&
2683e8d8bef9SDimitry Andric                    SymI->second.getState() != SymbolState::Ready &&
2684e8d8bef9SDimitry Andric                    "By this line the symbol should be materializing");
2685e8d8bef9SDimitry Andric             auto &MI = JD.MaterializingInfos[Name];
2686e8d8bef9SDimitry Andric             MI.addQuery(Q);
2687e8d8bef9SDimitry Andric             Q->addQueryDependence(JD, Name);
2688e8d8bef9SDimitry Andric 
2689e8d8bef9SDimitry Andric             return true;
2690e8d8bef9SDimitry Andric           });
2691e8d8bef9SDimitry Andric 
26920fca6ea1SDimitry Andric       JD.shrinkMaterializationInfoMemory();
26930fca6ea1SDimitry Andric 
2694e8d8bef9SDimitry Andric       // Handle failure.
2695e8d8bef9SDimitry Andric       if (Err) {
2696e8d8bef9SDimitry Andric 
2697e8d8bef9SDimitry Andric         LLVM_DEBUG({
2698e8d8bef9SDimitry Andric           dbgs() << "Lookup failed. Detaching query and replacing MUs.\n";
2699e8d8bef9SDimitry Andric         });
2700e8d8bef9SDimitry Andric 
2701e8d8bef9SDimitry Andric         // Detach the query.
2702e8d8bef9SDimitry Andric         Q->detach();
2703e8d8bef9SDimitry Andric 
2704e8d8bef9SDimitry Andric         // Replace the MUs.
2705e8d8bef9SDimitry Andric         for (auto &KV : CollectedUMIs) {
2706e8d8bef9SDimitry Andric           auto &JD = *KV.first;
2707e8d8bef9SDimitry Andric           for (auto &UMI : KV.second)
2708e8d8bef9SDimitry Andric             for (auto &KV2 : UMI->MU->getSymbols()) {
2709e8d8bef9SDimitry Andric               assert(!JD.UnmaterializedInfos.count(KV2.first) &&
2710e8d8bef9SDimitry Andric                      "Unexpected materializer in map");
2711e8d8bef9SDimitry Andric               auto SymI = JD.Symbols.find(KV2.first);
2712e8d8bef9SDimitry Andric               assert(SymI != JD.Symbols.end() && "Missing symbol entry");
2713e8d8bef9SDimitry Andric               assert(SymI->second.getState() == SymbolState::Materializing &&
2714e8d8bef9SDimitry Andric                      "Can not replace symbol that is not materializing");
2715e8d8bef9SDimitry Andric               assert(!SymI->second.hasMaterializerAttached() &&
2716e8d8bef9SDimitry Andric                      "MaterializerAttached flag should not be set");
2717e8d8bef9SDimitry Andric               SymI->second.setMaterializerAttached(true);
2718e8d8bef9SDimitry Andric               JD.UnmaterializedInfos[KV2.first] = UMI;
2719e8d8bef9SDimitry Andric             }
2720e8d8bef9SDimitry Andric         }
2721e8d8bef9SDimitry Andric 
2722e8d8bef9SDimitry Andric         return Err;
2723e8d8bef9SDimitry Andric       }
2724e8d8bef9SDimitry Andric     }
2725e8d8bef9SDimitry Andric 
2726349cc55cSDimitry Andric     LLVM_DEBUG(dbgs() << "Stripping unmatched weakly-referenced symbols\n");
2727e8d8bef9SDimitry Andric     IPLS->LookupSet.forEachWithRemoval(
2728e8d8bef9SDimitry Andric         [&](const SymbolStringPtr &Name, SymbolLookupFlags SymLookupFlags) {
2729e8d8bef9SDimitry Andric           if (SymLookupFlags == SymbolLookupFlags::WeaklyReferencedSymbol) {
2730e8d8bef9SDimitry Andric             Q->dropSymbol(Name);
2731e8d8bef9SDimitry Andric             return true;
2732e8d8bef9SDimitry Andric           } else
2733e8d8bef9SDimitry Andric             return false;
2734e8d8bef9SDimitry Andric         });
2735e8d8bef9SDimitry Andric 
2736e8d8bef9SDimitry Andric     if (!IPLS->LookupSet.empty()) {
2737e8d8bef9SDimitry Andric       LLVM_DEBUG(dbgs() << "Failing due to unresolved symbols\n");
2738349cc55cSDimitry Andric       return make_error<SymbolsNotFound>(getSymbolStringPool(),
2739349cc55cSDimitry Andric                                          IPLS->LookupSet.getSymbolNames());
2740e8d8bef9SDimitry Andric     }
2741e8d8bef9SDimitry Andric 
2742e8d8bef9SDimitry Andric     // Record whether the query completed.
2743e8d8bef9SDimitry Andric     QueryComplete = Q->isComplete();
2744e8d8bef9SDimitry Andric 
2745e8d8bef9SDimitry Andric     LLVM_DEBUG({
2746e8d8bef9SDimitry Andric       dbgs() << "Query successfully "
2747e8d8bef9SDimitry Andric              << (QueryComplete ? "completed" : "lodged") << "\n";
2748e8d8bef9SDimitry Andric     });
2749e8d8bef9SDimitry Andric 
2750e8d8bef9SDimitry Andric     // Move the collected MUs to the OutstandingMUs list.
2751e8d8bef9SDimitry Andric     if (!CollectedUMIs.empty()) {
2752e8d8bef9SDimitry Andric       std::lock_guard<std::recursive_mutex> Lock(OutstandingMUsMutex);
2753e8d8bef9SDimitry Andric 
2754e8d8bef9SDimitry Andric       LLVM_DEBUG(dbgs() << "Adding MUs to dispatch:\n");
2755e8d8bef9SDimitry Andric       for (auto &KV : CollectedUMIs) {
2756e8d8bef9SDimitry Andric         LLVM_DEBUG({
27574824e7fdSDimitry Andric           auto &JD = *KV.first;
2758e8d8bef9SDimitry Andric           dbgs() << "  For " << JD.getName() << ": Adding " << KV.second.size()
2759e8d8bef9SDimitry Andric                  << " MUs.\n";
2760e8d8bef9SDimitry Andric         });
2761e8d8bef9SDimitry Andric         for (auto &UMI : KV.second) {
27624824e7fdSDimitry Andric           auto MR = createMaterializationResponsibility(
27634824e7fdSDimitry Andric               *UMI->RT, std::move(UMI->MU->SymbolFlags),
27644824e7fdSDimitry Andric               std::move(UMI->MU->InitSymbol));
2765e8d8bef9SDimitry Andric           OutstandingMUs.push_back(
2766e8d8bef9SDimitry Andric               std::make_pair(std::move(UMI->MU), std::move(MR)));
2767e8d8bef9SDimitry Andric         }
2768e8d8bef9SDimitry Andric       }
2769e8d8bef9SDimitry Andric     } else
2770e8d8bef9SDimitry Andric       LLVM_DEBUG(dbgs() << "No MUs to dispatch.\n");
2771e8d8bef9SDimitry Andric 
2772e8d8bef9SDimitry Andric     if (RegisterDependencies && !Q->QueryRegistrations.empty()) {
2773e8d8bef9SDimitry Andric       LLVM_DEBUG(dbgs() << "Registering dependencies\n");
2774e8d8bef9SDimitry Andric       RegisterDependencies(Q->QueryRegistrations);
2775e8d8bef9SDimitry Andric     } else
2776e8d8bef9SDimitry Andric       LLVM_DEBUG(dbgs() << "No dependencies to register\n");
2777e8d8bef9SDimitry Andric 
2778e8d8bef9SDimitry Andric     return Error::success();
2779e8d8bef9SDimitry Andric   });
2780e8d8bef9SDimitry Andric 
2781e8d8bef9SDimitry Andric   if (LodgingErr) {
2782e8d8bef9SDimitry Andric     LLVM_DEBUG(dbgs() << "Failing query\n");
2783e8d8bef9SDimitry Andric     Q->detach();
2784e8d8bef9SDimitry Andric     Q->handleFailed(std::move(LodgingErr));
2785e8d8bef9SDimitry Andric     return;
2786e8d8bef9SDimitry Andric   }
2787e8d8bef9SDimitry Andric 
2788e8d8bef9SDimitry Andric   if (QueryComplete) {
2789e8d8bef9SDimitry Andric     LLVM_DEBUG(dbgs() << "Completing query\n");
2790fe6060f1SDimitry Andric     Q->handleComplete(*this);
2791e8d8bef9SDimitry Andric   }
2792e8d8bef9SDimitry Andric 
2793e8d8bef9SDimitry Andric   dispatchOutstandingMUs();
2794e8d8bef9SDimitry Andric }
2795e8d8bef9SDimitry Andric 
2796e8d8bef9SDimitry Andric void ExecutionSession::OL_completeLookupFlags(
2797e8d8bef9SDimitry Andric     std::unique_ptr<InProgressLookupState> IPLS,
2798e8d8bef9SDimitry Andric     unique_function<void(Expected<SymbolFlagsMap>)> OnComplete) {
2799e8d8bef9SDimitry Andric 
2800e8d8bef9SDimitry Andric   auto Result = runSessionLocked([&]() -> Expected<SymbolFlagsMap> {
2801e8d8bef9SDimitry Andric     LLVM_DEBUG({
2802e8d8bef9SDimitry Andric       dbgs() << "Entering OL_completeLookupFlags:\n"
2803e8d8bef9SDimitry Andric              << "  Lookup kind: " << IPLS->K << "\n"
2804e8d8bef9SDimitry Andric              << "  Search order: " << IPLS->SearchOrder
2805e8d8bef9SDimitry Andric              << ", Current index = " << IPLS->CurSearchOrderIndex
2806e8d8bef9SDimitry Andric              << (IPLS->NewJITDylib ? " (entering new JITDylib)" : "") << "\n"
2807e8d8bef9SDimitry Andric              << "  Lookup set: " << IPLS->LookupSet << "\n"
2808e8d8bef9SDimitry Andric              << "  Definition generator candidates: "
2809e8d8bef9SDimitry Andric              << IPLS->DefGeneratorCandidates << "\n"
2810e8d8bef9SDimitry Andric              << "  Definition generator non-candidates: "
2811e8d8bef9SDimitry Andric              << IPLS->DefGeneratorNonCandidates << "\n";
2812e8d8bef9SDimitry Andric     });
2813e8d8bef9SDimitry Andric 
2814e8d8bef9SDimitry Andric     SymbolFlagsMap Result;
2815e8d8bef9SDimitry Andric 
2816e8d8bef9SDimitry Andric     // Attempt to find flags for each symbol.
2817e8d8bef9SDimitry Andric     for (auto &KV : IPLS->SearchOrder) {
2818e8d8bef9SDimitry Andric       auto &JD = *KV.first;
2819e8d8bef9SDimitry Andric       auto JDLookupFlags = KV.second;
2820e8d8bef9SDimitry Andric       LLVM_DEBUG({
2821e8d8bef9SDimitry Andric         dbgs() << "Visiting \"" << JD.getName() << "\" (" << JDLookupFlags
2822e8d8bef9SDimitry Andric                << ") with lookup set " << IPLS->LookupSet << ":\n";
2823e8d8bef9SDimitry Andric       });
2824e8d8bef9SDimitry Andric 
2825e8d8bef9SDimitry Andric       IPLS->LookupSet.forEachWithRemoval([&](const SymbolStringPtr &Name,
2826e8d8bef9SDimitry Andric                                              SymbolLookupFlags SymLookupFlags) {
2827e8d8bef9SDimitry Andric         LLVM_DEBUG({
2828e8d8bef9SDimitry Andric           dbgs() << "  Attempting to match \"" << Name << "\" ("
2829e8d8bef9SDimitry Andric                  << SymLookupFlags << ")... ";
2830e8d8bef9SDimitry Andric         });
2831e8d8bef9SDimitry Andric 
2832e8d8bef9SDimitry Andric         // Search for the symbol. If not found then continue without removing
2833e8d8bef9SDimitry Andric         // from the lookup set.
2834e8d8bef9SDimitry Andric         auto SymI = JD.Symbols.find(Name);
2835e8d8bef9SDimitry Andric         if (SymI == JD.Symbols.end()) {
2836e8d8bef9SDimitry Andric           LLVM_DEBUG(dbgs() << "skipping: not present\n");
2837e8d8bef9SDimitry Andric           return false;
2838e8d8bef9SDimitry Andric         }
2839e8d8bef9SDimitry Andric 
2840e8d8bef9SDimitry Andric         // If this is a non-exported symbol then it doesn't match. Skip it.
2841e8d8bef9SDimitry Andric         if (!SymI->second.getFlags().isExported() &&
2842e8d8bef9SDimitry Andric             JDLookupFlags == JITDylibLookupFlags::MatchExportedSymbolsOnly) {
2843e8d8bef9SDimitry Andric           LLVM_DEBUG(dbgs() << "skipping: not exported\n");
2844e8d8bef9SDimitry Andric           return false;
2845e8d8bef9SDimitry Andric         }
2846e8d8bef9SDimitry Andric 
2847e8d8bef9SDimitry Andric         LLVM_DEBUG({
2848e8d8bef9SDimitry Andric           dbgs() << "matched, \"" << Name << "\" -> " << SymI->second.getFlags()
2849e8d8bef9SDimitry Andric                  << "\n";
2850e8d8bef9SDimitry Andric         });
2851e8d8bef9SDimitry Andric         Result[Name] = SymI->second.getFlags();
2852e8d8bef9SDimitry Andric         return true;
2853e8d8bef9SDimitry Andric       });
2854e8d8bef9SDimitry Andric     }
2855e8d8bef9SDimitry Andric 
2856e8d8bef9SDimitry Andric     // Remove any weakly referenced symbols that haven't been resolved.
2857e8d8bef9SDimitry Andric     IPLS->LookupSet.remove_if(
2858e8d8bef9SDimitry Andric         [](const SymbolStringPtr &Name, SymbolLookupFlags SymLookupFlags) {
2859e8d8bef9SDimitry Andric           return SymLookupFlags == SymbolLookupFlags::WeaklyReferencedSymbol;
2860e8d8bef9SDimitry Andric         });
2861e8d8bef9SDimitry Andric 
2862e8d8bef9SDimitry Andric     if (!IPLS->LookupSet.empty()) {
2863e8d8bef9SDimitry Andric       LLVM_DEBUG(dbgs() << "Failing due to unresolved symbols\n");
2864349cc55cSDimitry Andric       return make_error<SymbolsNotFound>(getSymbolStringPool(),
2865349cc55cSDimitry Andric                                          IPLS->LookupSet.getSymbolNames());
2866e8d8bef9SDimitry Andric     }
2867e8d8bef9SDimitry Andric 
2868e8d8bef9SDimitry Andric     LLVM_DEBUG(dbgs() << "Succeded, result = " << Result << "\n");
2869e8d8bef9SDimitry Andric     return Result;
2870e8d8bef9SDimitry Andric   });
2871e8d8bef9SDimitry Andric 
2872e8d8bef9SDimitry Andric   // Run the callback on the result.
2873e8d8bef9SDimitry Andric   LLVM_DEBUG(dbgs() << "Sending result to handler.\n");
2874e8d8bef9SDimitry Andric   OnComplete(std::move(Result));
2875e8d8bef9SDimitry Andric }
2876e8d8bef9SDimitry Andric 
2877e8d8bef9SDimitry Andric void ExecutionSession::OL_destroyMaterializationResponsibility(
2878e8d8bef9SDimitry Andric     MaterializationResponsibility &MR) {
2879e8d8bef9SDimitry Andric 
2880e8d8bef9SDimitry Andric   assert(MR.SymbolFlags.empty() &&
2881e8d8bef9SDimitry Andric          "All symbols should have been explicitly materialized or failed");
28824824e7fdSDimitry Andric   MR.JD.unlinkMaterializationResponsibility(MR);
2883e8d8bef9SDimitry Andric }
2884e8d8bef9SDimitry Andric 
2885e8d8bef9SDimitry Andric SymbolNameSet ExecutionSession::OL_getRequestedSymbols(
2886e8d8bef9SDimitry Andric     const MaterializationResponsibility &MR) {
28874824e7fdSDimitry Andric   return MR.JD.getRequestedSymbols(MR.SymbolFlags);
2888e8d8bef9SDimitry Andric }
2889e8d8bef9SDimitry Andric 
2890e8d8bef9SDimitry Andric Error ExecutionSession::OL_notifyResolved(MaterializationResponsibility &MR,
2891e8d8bef9SDimitry Andric                                           const SymbolMap &Symbols) {
2892e8d8bef9SDimitry Andric   LLVM_DEBUG({
28934824e7fdSDimitry Andric     dbgs() << "In " << MR.JD.getName() << " resolving " << Symbols << "\n";
2894e8d8bef9SDimitry Andric   });
2895e8d8bef9SDimitry Andric #ifndef NDEBUG
2896e8d8bef9SDimitry Andric   for (auto &KV : Symbols) {
2897e8d8bef9SDimitry Andric     auto I = MR.SymbolFlags.find(KV.first);
2898e8d8bef9SDimitry Andric     assert(I != MR.SymbolFlags.end() &&
2899e8d8bef9SDimitry Andric            "Resolving symbol outside this responsibility set");
2900e8d8bef9SDimitry Andric     assert(!I->second.hasMaterializationSideEffectsOnly() &&
2901e8d8bef9SDimitry Andric            "Can't resolve materialization-side-effects-only symbol");
2902bdd1243dSDimitry Andric     assert((KV.second.getFlags() & ~JITSymbolFlags::Common) ==
2903bdd1243dSDimitry Andric                (I->second & ~JITSymbolFlags::Common) &&
2904e8d8bef9SDimitry Andric            "Resolving symbol with incorrect flags");
2905e8d8bef9SDimitry Andric   }
2906e8d8bef9SDimitry Andric #endif
2907e8d8bef9SDimitry Andric 
29084824e7fdSDimitry Andric   return MR.JD.resolve(MR, Symbols);
2909e8d8bef9SDimitry Andric }
2910e8d8bef9SDimitry Andric 
29110fca6ea1SDimitry Andric template <typename HandleNewDepFn>
29120fca6ea1SDimitry Andric void ExecutionSession::propagateExtraEmitDeps(
29130fca6ea1SDimitry Andric     std::deque<JITDylib::EmissionDepUnit *> Worklist, EDUInfosMap &EDUInfos,
29140fca6ea1SDimitry Andric     HandleNewDepFn HandleNewDep) {
29150fca6ea1SDimitry Andric 
29160fca6ea1SDimitry Andric   // Iterate to a fixed-point to propagate extra-emit dependencies through the
29170fca6ea1SDimitry Andric   // EDU graph.
29180fca6ea1SDimitry Andric   while (!Worklist.empty()) {
29190fca6ea1SDimitry Andric     auto &EDU = *Worklist.front();
29200fca6ea1SDimitry Andric     Worklist.pop_front();
29210fca6ea1SDimitry Andric 
29220fca6ea1SDimitry Andric     assert(EDUInfos.count(&EDU) && "No info entry for EDU");
29230fca6ea1SDimitry Andric     auto &EDUInfo = EDUInfos[&EDU];
29240fca6ea1SDimitry Andric 
29250fca6ea1SDimitry Andric     // Propagate new dependencies to users.
29260fca6ea1SDimitry Andric     for (auto *UserEDU : EDUInfo.IntraEmitUsers) {
29270fca6ea1SDimitry Andric 
29280fca6ea1SDimitry Andric       // UserEDUInfo only present if UserEDU has its own users.
29290fca6ea1SDimitry Andric       JITDylib::EmissionDepUnitInfo *UserEDUInfo = nullptr;
29300fca6ea1SDimitry Andric       {
29310fca6ea1SDimitry Andric         auto UserEDUInfoItr = EDUInfos.find(UserEDU);
29320fca6ea1SDimitry Andric         if (UserEDUInfoItr != EDUInfos.end())
29330fca6ea1SDimitry Andric           UserEDUInfo = &UserEDUInfoItr->second;
29340fca6ea1SDimitry Andric       }
29350fca6ea1SDimitry Andric 
29360fca6ea1SDimitry Andric       for (auto &[DepJD, Deps] : EDUInfo.NewDeps) {
29370fca6ea1SDimitry Andric         auto &UserEDUDepsForJD = UserEDU->Dependencies[DepJD];
29380fca6ea1SDimitry Andric         DenseSet<NonOwningSymbolStringPtr> *UserEDUNewDepsForJD = nullptr;
29390fca6ea1SDimitry Andric         for (auto Dep : Deps) {
29400fca6ea1SDimitry Andric           if (UserEDUDepsForJD.insert(Dep).second) {
29410fca6ea1SDimitry Andric             HandleNewDep(*UserEDU, *DepJD, Dep);
29420fca6ea1SDimitry Andric             if (UserEDUInfo) {
29430fca6ea1SDimitry Andric               if (!UserEDUNewDepsForJD) {
29440fca6ea1SDimitry Andric                 // If UserEDU has no new deps then it's not in the worklist
29450fca6ea1SDimitry Andric                 // yet, so add it.
29460fca6ea1SDimitry Andric                 if (UserEDUInfo->NewDeps.empty())
29470fca6ea1SDimitry Andric                   Worklist.push_back(UserEDU);
29480fca6ea1SDimitry Andric                 UserEDUNewDepsForJD = &UserEDUInfo->NewDeps[DepJD];
29490fca6ea1SDimitry Andric               }
29500fca6ea1SDimitry Andric               // Add (DepJD, Dep) to NewDeps.
29510fca6ea1SDimitry Andric               UserEDUNewDepsForJD->insert(Dep);
29520fca6ea1SDimitry Andric             }
29530fca6ea1SDimitry Andric           }
29540fca6ea1SDimitry Andric         }
29550fca6ea1SDimitry Andric       }
29560fca6ea1SDimitry Andric     }
29570fca6ea1SDimitry Andric 
29580fca6ea1SDimitry Andric     EDUInfo.NewDeps.clear();
29590fca6ea1SDimitry Andric   }
29600fca6ea1SDimitry Andric }
29610fca6ea1SDimitry Andric 
29620fca6ea1SDimitry Andric // Note: This method modifies the emitted set.
29630fca6ea1SDimitry Andric ExecutionSession::EDUInfosMap ExecutionSession::simplifyDepGroups(
29640fca6ea1SDimitry Andric     MaterializationResponsibility &MR,
29650fca6ea1SDimitry Andric     ArrayRef<SymbolDependenceGroup> EmittedDeps) {
29660fca6ea1SDimitry Andric 
29670fca6ea1SDimitry Andric   auto &TargetJD = MR.getTargetJITDylib();
29680fca6ea1SDimitry Andric 
29690fca6ea1SDimitry Andric   // 1. Build initial EmissionDepUnit -> EmissionDepUnitInfo and
29700fca6ea1SDimitry Andric   //    Symbol -> EmissionDepUnit mappings.
29710fca6ea1SDimitry Andric   DenseMap<JITDylib::EmissionDepUnit *, JITDylib::EmissionDepUnitInfo> EDUInfos;
29720fca6ea1SDimitry Andric   EDUInfos.reserve(EmittedDeps.size());
29730fca6ea1SDimitry Andric   DenseMap<NonOwningSymbolStringPtr, JITDylib::EmissionDepUnit *> EDUForSymbol;
29740fca6ea1SDimitry Andric   for (auto &DG : EmittedDeps) {
29750fca6ea1SDimitry Andric     assert(!DG.Symbols.empty() && "DepGroup does not cover any symbols");
29760fca6ea1SDimitry Andric 
29770fca6ea1SDimitry Andric     // Skip empty EDUs.
29780fca6ea1SDimitry Andric     if (DG.Dependencies.empty())
29790fca6ea1SDimitry Andric       continue;
29800fca6ea1SDimitry Andric 
29810fca6ea1SDimitry Andric     auto TmpEDU = std::make_shared<JITDylib::EmissionDepUnit>(TargetJD);
29820fca6ea1SDimitry Andric     auto &EDUInfo = EDUInfos[TmpEDU.get()];
29830fca6ea1SDimitry Andric     EDUInfo.EDU = std::move(TmpEDU);
29840fca6ea1SDimitry Andric     for (const auto &Symbol : DG.Symbols) {
29850fca6ea1SDimitry Andric       NonOwningSymbolStringPtr NonOwningSymbol(Symbol);
29860fca6ea1SDimitry Andric       assert(!EDUForSymbol.count(NonOwningSymbol) &&
29870fca6ea1SDimitry Andric              "Symbol should not appear in more than one SymbolDependenceGroup");
29880fca6ea1SDimitry Andric       assert(MR.getSymbols().count(Symbol) &&
29890fca6ea1SDimitry Andric              "Symbol in DepGroups not in the emitted set");
29900fca6ea1SDimitry Andric       auto NewlyEmittedItr = MR.getSymbols().find(Symbol);
29910fca6ea1SDimitry Andric       EDUInfo.EDU->Symbols[NonOwningSymbol] = NewlyEmittedItr->second;
29920fca6ea1SDimitry Andric       EDUForSymbol[NonOwningSymbol] = EDUInfo.EDU.get();
29930fca6ea1SDimitry Andric     }
29940fca6ea1SDimitry Andric   }
29950fca6ea1SDimitry Andric 
29960fca6ea1SDimitry Andric   // 2. Build a "residual" EDU to cover all symbols that have no dependencies.
29970fca6ea1SDimitry Andric   {
29980fca6ea1SDimitry Andric     DenseMap<NonOwningSymbolStringPtr, JITSymbolFlags> ResidualSymbolFlags;
29990fca6ea1SDimitry Andric     for (auto &[Sym, Flags] : MR.getSymbols()) {
30000fca6ea1SDimitry Andric       if (!EDUForSymbol.count(NonOwningSymbolStringPtr(Sym)))
30010fca6ea1SDimitry Andric         ResidualSymbolFlags[NonOwningSymbolStringPtr(Sym)] = Flags;
30020fca6ea1SDimitry Andric     }
30030fca6ea1SDimitry Andric     if (!ResidualSymbolFlags.empty()) {
30040fca6ea1SDimitry Andric       auto ResidualEDU = std::make_shared<JITDylib::EmissionDepUnit>(TargetJD);
30050fca6ea1SDimitry Andric       ResidualEDU->Symbols = std::move(ResidualSymbolFlags);
30060fca6ea1SDimitry Andric       auto &ResidualEDUInfo = EDUInfos[ResidualEDU.get()];
30070fca6ea1SDimitry Andric       ResidualEDUInfo.EDU = std::move(ResidualEDU);
30080fca6ea1SDimitry Andric 
30090fca6ea1SDimitry Andric       // If the residual EDU is the only one then bail out early.
30100fca6ea1SDimitry Andric       if (EDUInfos.size() == 1)
30110fca6ea1SDimitry Andric         return EDUInfos;
30120fca6ea1SDimitry Andric 
30130fca6ea1SDimitry Andric       // Otherwise add the residual EDU to the EDUForSymbol map.
30140fca6ea1SDimitry Andric       for (auto &[Sym, Flags] : ResidualEDUInfo.EDU->Symbols)
30150fca6ea1SDimitry Andric         EDUForSymbol[Sym] = ResidualEDUInfo.EDU.get();
30160fca6ea1SDimitry Andric     }
30170fca6ea1SDimitry Andric   }
30180fca6ea1SDimitry Andric 
30190fca6ea1SDimitry Andric #ifndef NDEBUG
30200fca6ea1SDimitry Andric   assert(EDUForSymbol.size() == MR.getSymbols().size() &&
30210fca6ea1SDimitry Andric          "MR symbols not fully covered by EDUs?");
30220fca6ea1SDimitry Andric   for (auto &[Sym, Flags] : MR.getSymbols()) {
30230fca6ea1SDimitry Andric     assert(EDUForSymbol.count(NonOwningSymbolStringPtr(Sym)) &&
30240fca6ea1SDimitry Andric            "Sym in MR not covered by EDU");
30250fca6ea1SDimitry Andric   }
30260fca6ea1SDimitry Andric #endif // NDEBUG
30270fca6ea1SDimitry Andric 
30280fca6ea1SDimitry Andric   // 3. Use the DepGroups array to build a graph of dependencies between
30290fca6ea1SDimitry Andric   //    EmissionDepUnits in this finalization. We want to remove these
30300fca6ea1SDimitry Andric   //    intra-finalization uses, propagating dependencies on symbols outside
30310fca6ea1SDimitry Andric   //    this finalization. Add EDUs to the worklist.
30320fca6ea1SDimitry Andric   for (auto &DG : EmittedDeps) {
30330fca6ea1SDimitry Andric 
30340fca6ea1SDimitry Andric     // Skip SymbolDependenceGroups with no dependencies.
30350fca6ea1SDimitry Andric     if (DG.Dependencies.empty())
30360fca6ea1SDimitry Andric       continue;
30370fca6ea1SDimitry Andric 
30380fca6ea1SDimitry Andric     assert(EDUForSymbol.count(NonOwningSymbolStringPtr(*DG.Symbols.begin())) &&
30390fca6ea1SDimitry Andric            "No EDU for DG");
30400fca6ea1SDimitry Andric     auto &EDU =
30410fca6ea1SDimitry Andric         *EDUForSymbol.find(NonOwningSymbolStringPtr(*DG.Symbols.begin()))
30420fca6ea1SDimitry Andric              ->second;
30430fca6ea1SDimitry Andric 
30440fca6ea1SDimitry Andric     for (auto &[DepJD, Deps] : DG.Dependencies) {
30450fca6ea1SDimitry Andric       DenseSet<NonOwningSymbolStringPtr> NewDepsForJD;
30460fca6ea1SDimitry Andric 
30470fca6ea1SDimitry Andric       assert(!Deps.empty() && "Dependence set for DepJD is empty");
30480fca6ea1SDimitry Andric 
30490fca6ea1SDimitry Andric       if (DepJD != &TargetJD) {
30500fca6ea1SDimitry Andric         // DepJD is some other JITDylib.There can't be any intra-finalization
30510fca6ea1SDimitry Andric         // edges here, so just skip.
30520fca6ea1SDimitry Andric         for (auto &Dep : Deps)
30530fca6ea1SDimitry Andric           NewDepsForJD.insert(NonOwningSymbolStringPtr(Dep));
30540fca6ea1SDimitry Andric       } else {
30550fca6ea1SDimitry Andric         // DepJD is the Target JITDylib. Check for intra-finaliztaion edges,
30560fca6ea1SDimitry Andric         // skipping any and recording the intra-finalization use instead.
30570fca6ea1SDimitry Andric         for (auto &Dep : Deps) {
30580fca6ea1SDimitry Andric           NonOwningSymbolStringPtr NonOwningDep(Dep);
30590fca6ea1SDimitry Andric           auto I = EDUForSymbol.find(NonOwningDep);
30600fca6ea1SDimitry Andric           if (I == EDUForSymbol.end()) {
30610fca6ea1SDimitry Andric             if (!MR.getSymbols().count(Dep))
30620fca6ea1SDimitry Andric               NewDepsForJD.insert(NonOwningDep);
30630fca6ea1SDimitry Andric             continue;
30640fca6ea1SDimitry Andric           }
30650fca6ea1SDimitry Andric 
30660fca6ea1SDimitry Andric           if (I->second != &EDU)
30670fca6ea1SDimitry Andric             EDUInfos[I->second].IntraEmitUsers.insert(&EDU);
30680fca6ea1SDimitry Andric         }
30690fca6ea1SDimitry Andric       }
30700fca6ea1SDimitry Andric 
30710fca6ea1SDimitry Andric       if (!NewDepsForJD.empty())
30720fca6ea1SDimitry Andric         EDU.Dependencies[DepJD] = std::move(NewDepsForJD);
30730fca6ea1SDimitry Andric     }
30740fca6ea1SDimitry Andric   }
30750fca6ea1SDimitry Andric 
30760fca6ea1SDimitry Andric   // 4. Build the worklist.
30770fca6ea1SDimitry Andric   std::deque<JITDylib::EmissionDepUnit *> Worklist;
30780fca6ea1SDimitry Andric   for (auto &[EDU, EDUInfo] : EDUInfos) {
30790fca6ea1SDimitry Andric     // If this EDU has extra-finalization dependencies and intra-finalization
30800fca6ea1SDimitry Andric     // users then add it to the worklist.
30810fca6ea1SDimitry Andric     if (!EDU->Dependencies.empty()) {
30820fca6ea1SDimitry Andric       auto I = EDUInfos.find(EDU);
30830fca6ea1SDimitry Andric       if (I != EDUInfos.end()) {
30840fca6ea1SDimitry Andric         auto &EDUInfo = I->second;
30850fca6ea1SDimitry Andric         if (!EDUInfo.IntraEmitUsers.empty()) {
30860fca6ea1SDimitry Andric           EDUInfo.NewDeps = EDU->Dependencies;
30870fca6ea1SDimitry Andric           Worklist.push_back(EDU);
30880fca6ea1SDimitry Andric         }
30890fca6ea1SDimitry Andric       }
30900fca6ea1SDimitry Andric     }
30910fca6ea1SDimitry Andric   }
30920fca6ea1SDimitry Andric 
30930fca6ea1SDimitry Andric   // 4. Propagate dependencies through the EDU graph.
30940fca6ea1SDimitry Andric   propagateExtraEmitDeps(
30950fca6ea1SDimitry Andric       Worklist, EDUInfos,
30960fca6ea1SDimitry Andric       [](JITDylib::EmissionDepUnit &, JITDylib &, NonOwningSymbolStringPtr) {});
30970fca6ea1SDimitry Andric 
30980fca6ea1SDimitry Andric   return EDUInfos;
30990fca6ea1SDimitry Andric }
31000fca6ea1SDimitry Andric 
31010fca6ea1SDimitry Andric void ExecutionSession::IL_makeEDUReady(
31020fca6ea1SDimitry Andric     std::shared_ptr<JITDylib::EmissionDepUnit> EDU,
31030fca6ea1SDimitry Andric     JITDylib::AsynchronousSymbolQuerySet &Queries) {
31040fca6ea1SDimitry Andric 
31050fca6ea1SDimitry Andric   // The symbols for this EDU are ready.
31060fca6ea1SDimitry Andric   auto &JD = *EDU->JD;
31070fca6ea1SDimitry Andric 
31080fca6ea1SDimitry Andric   for (auto &[Sym, Flags] : EDU->Symbols) {
31090fca6ea1SDimitry Andric     assert(JD.Symbols.count(SymbolStringPtr(Sym)) &&
31100fca6ea1SDimitry Andric            "JD does not have an entry for Sym");
31110fca6ea1SDimitry Andric     auto &Entry = JD.Symbols[SymbolStringPtr(Sym)];
31120fca6ea1SDimitry Andric 
31130fca6ea1SDimitry Andric     assert(((Entry.getFlags().hasMaterializationSideEffectsOnly() &&
31140fca6ea1SDimitry Andric              Entry.getState() == SymbolState::Materializing) ||
31150fca6ea1SDimitry Andric             Entry.getState() == SymbolState::Resolved ||
31160fca6ea1SDimitry Andric             Entry.getState() == SymbolState::Emitted) &&
31170fca6ea1SDimitry Andric            "Emitting from state other than Resolved");
31180fca6ea1SDimitry Andric 
31190fca6ea1SDimitry Andric     Entry.setState(SymbolState::Ready);
31200fca6ea1SDimitry Andric 
31210fca6ea1SDimitry Andric     auto MII = JD.MaterializingInfos.find(SymbolStringPtr(Sym));
31220fca6ea1SDimitry Andric 
31230fca6ea1SDimitry Andric     // Check for pending queries.
31240fca6ea1SDimitry Andric     if (MII == JD.MaterializingInfos.end())
31250fca6ea1SDimitry Andric       continue;
31260fca6ea1SDimitry Andric     auto &MI = MII->second;
31270fca6ea1SDimitry Andric 
31280fca6ea1SDimitry Andric     for (auto &Q : MI.takeQueriesMeeting(SymbolState::Ready)) {
31290fca6ea1SDimitry Andric       Q->notifySymbolMetRequiredState(SymbolStringPtr(Sym), Entry.getSymbol());
31300fca6ea1SDimitry Andric       if (Q->isComplete())
31310fca6ea1SDimitry Andric         Queries.insert(Q);
31320fca6ea1SDimitry Andric       Q->removeQueryDependence(JD, SymbolStringPtr(Sym));
31330fca6ea1SDimitry Andric     }
31340fca6ea1SDimitry Andric 
31350fca6ea1SDimitry Andric     JD.MaterializingInfos.erase(MII);
31360fca6ea1SDimitry Andric   }
31370fca6ea1SDimitry Andric 
31380fca6ea1SDimitry Andric   JD.shrinkMaterializationInfoMemory();
31390fca6ea1SDimitry Andric }
31400fca6ea1SDimitry Andric 
31410fca6ea1SDimitry Andric void ExecutionSession::IL_makeEDUEmitted(
31420fca6ea1SDimitry Andric     std::shared_ptr<JITDylib::EmissionDepUnit> EDU,
31430fca6ea1SDimitry Andric     JITDylib::AsynchronousSymbolQuerySet &Queries) {
31440fca6ea1SDimitry Andric 
31450fca6ea1SDimitry Andric   // The symbols for this EDU are emitted, but not ready.
31460fca6ea1SDimitry Andric   auto &JD = *EDU->JD;
31470fca6ea1SDimitry Andric 
31480fca6ea1SDimitry Andric   for (auto &[Sym, Flags] : EDU->Symbols) {
31490fca6ea1SDimitry Andric     assert(JD.Symbols.count(SymbolStringPtr(Sym)) &&
31500fca6ea1SDimitry Andric            "JD does not have an entry for Sym");
31510fca6ea1SDimitry Andric     auto &Entry = JD.Symbols[SymbolStringPtr(Sym)];
31520fca6ea1SDimitry Andric 
31530fca6ea1SDimitry Andric     assert(((Entry.getFlags().hasMaterializationSideEffectsOnly() &&
31540fca6ea1SDimitry Andric              Entry.getState() == SymbolState::Materializing) ||
31550fca6ea1SDimitry Andric             Entry.getState() == SymbolState::Resolved ||
31560fca6ea1SDimitry Andric             Entry.getState() == SymbolState::Emitted) &&
31570fca6ea1SDimitry Andric            "Emitting from state other than Resolved");
31580fca6ea1SDimitry Andric 
31590fca6ea1SDimitry Andric     if (Entry.getState() == SymbolState::Emitted) {
31600fca6ea1SDimitry Andric       // This was already emitted, so we can skip the rest of this loop.
31610fca6ea1SDimitry Andric #ifndef NDEBUG
31620fca6ea1SDimitry Andric       for (auto &[Sym, Flags] : EDU->Symbols) {
31630fca6ea1SDimitry Andric         assert(JD.Symbols.count(SymbolStringPtr(Sym)) &&
31640fca6ea1SDimitry Andric                "JD does not have an entry for Sym");
31650fca6ea1SDimitry Andric         auto &Entry = JD.Symbols[SymbolStringPtr(Sym)];
31660fca6ea1SDimitry Andric         assert(Entry.getState() == SymbolState::Emitted &&
31670fca6ea1SDimitry Andric                "Symbols for EDU in inconsistent state");
31680fca6ea1SDimitry Andric         assert(JD.MaterializingInfos.count(SymbolStringPtr(Sym)) &&
31690fca6ea1SDimitry Andric                "Emitted symbol has no MI");
31700fca6ea1SDimitry Andric         auto MI = JD.MaterializingInfos[SymbolStringPtr(Sym)];
31710fca6ea1SDimitry Andric         assert(MI.takeQueriesMeeting(SymbolState::Emitted).empty() &&
31720fca6ea1SDimitry Andric                "Already-emitted symbol has waiting-on-emitted queries");
31730fca6ea1SDimitry Andric       }
31740fca6ea1SDimitry Andric #endif // NDEBUG
31750fca6ea1SDimitry Andric       break;
31760fca6ea1SDimitry Andric     }
31770fca6ea1SDimitry Andric 
31780fca6ea1SDimitry Andric     Entry.setState(SymbolState::Emitted);
31790fca6ea1SDimitry Andric     auto &MI = JD.MaterializingInfos[SymbolStringPtr(Sym)];
31800fca6ea1SDimitry Andric     MI.DefiningEDU = EDU;
31810fca6ea1SDimitry Andric 
31820fca6ea1SDimitry Andric     for (auto &Q : MI.takeQueriesMeeting(SymbolState::Emitted)) {
31830fca6ea1SDimitry Andric       Q->notifySymbolMetRequiredState(SymbolStringPtr(Sym), Entry.getSymbol());
31840fca6ea1SDimitry Andric       if (Q->isComplete())
31850fca6ea1SDimitry Andric         Queries.insert(Q);
31860fca6ea1SDimitry Andric       Q->removeQueryDependence(JD, SymbolStringPtr(Sym));
31870fca6ea1SDimitry Andric     }
31880fca6ea1SDimitry Andric   }
31890fca6ea1SDimitry Andric 
31900fca6ea1SDimitry Andric   for (auto &[DepJD, Deps] : EDU->Dependencies) {
31910fca6ea1SDimitry Andric     for (auto &Dep : Deps)
31920fca6ea1SDimitry Andric       DepJD->MaterializingInfos[SymbolStringPtr(Dep)].DependantEDUs.insert(
31930fca6ea1SDimitry Andric           EDU.get());
31940fca6ea1SDimitry Andric   }
31950fca6ea1SDimitry Andric }
31960fca6ea1SDimitry Andric 
31970fca6ea1SDimitry Andric /// Removes the given dependence from EDU. If EDU's dependence set becomes
31980fca6ea1SDimitry Andric /// empty then this function adds an entry for it to the EDUInfos map.
31990fca6ea1SDimitry Andric /// Returns true if a new EDUInfosMap entry is added.
32000fca6ea1SDimitry Andric bool ExecutionSession::IL_removeEDUDependence(JITDylib::EmissionDepUnit &EDU,
32010fca6ea1SDimitry Andric                                               JITDylib &DepJD,
32020fca6ea1SDimitry Andric                                               NonOwningSymbolStringPtr DepSym,
32030fca6ea1SDimitry Andric                                               EDUInfosMap &EDUInfos) {
32040fca6ea1SDimitry Andric   assert(EDU.Dependencies.count(&DepJD) &&
32050fca6ea1SDimitry Andric          "JD does not appear in Dependencies of DependantEDU");
32060fca6ea1SDimitry Andric   assert(EDU.Dependencies[&DepJD].count(DepSym) &&
32070fca6ea1SDimitry Andric          "Symbol does not appear in Dependencies of DependantEDU");
32080fca6ea1SDimitry Andric   auto &JDDeps = EDU.Dependencies[&DepJD];
32090fca6ea1SDimitry Andric   JDDeps.erase(DepSym);
32100fca6ea1SDimitry Andric   if (JDDeps.empty()) {
32110fca6ea1SDimitry Andric     EDU.Dependencies.erase(&DepJD);
32120fca6ea1SDimitry Andric     if (EDU.Dependencies.empty()) {
32130fca6ea1SDimitry Andric       // If the dependencies set has become empty then EDU _may_ be ready
32140fca6ea1SDimitry Andric       // (we won't know for sure until we've propagated the extra-emit deps).
32150fca6ea1SDimitry Andric       // Create an EDUInfo for it (if it doesn't have one already) so that
32160fca6ea1SDimitry Andric       // it'll be visited after propagation.
32170fca6ea1SDimitry Andric       auto &DepEDUInfo = EDUInfos[&EDU];
32180fca6ea1SDimitry Andric       if (!DepEDUInfo.EDU) {
32190fca6ea1SDimitry Andric         assert(EDU.JD->Symbols.count(
32200fca6ea1SDimitry Andric                    SymbolStringPtr(EDU.Symbols.begin()->first)) &&
32210fca6ea1SDimitry Andric                "Missing symbol entry for first symbol in EDU");
32220fca6ea1SDimitry Andric         auto DepEDUFirstMI = EDU.JD->MaterializingInfos.find(
32230fca6ea1SDimitry Andric             SymbolStringPtr(EDU.Symbols.begin()->first));
32240fca6ea1SDimitry Andric         assert(DepEDUFirstMI != EDU.JD->MaterializingInfos.end() &&
32250fca6ea1SDimitry Andric                "Missing MI for first symbol in DependantEDU");
32260fca6ea1SDimitry Andric         DepEDUInfo.EDU = DepEDUFirstMI->second.DefiningEDU;
32270fca6ea1SDimitry Andric         return true;
32280fca6ea1SDimitry Andric       }
32290fca6ea1SDimitry Andric     }
32300fca6ea1SDimitry Andric   }
32310fca6ea1SDimitry Andric   return false;
32320fca6ea1SDimitry Andric }
32330fca6ea1SDimitry Andric 
32340fca6ea1SDimitry Andric Error ExecutionSession::makeJDClosedError(JITDylib::EmissionDepUnit &EDU,
32350fca6ea1SDimitry Andric                                           JITDylib &ClosedJD) {
32360fca6ea1SDimitry Andric   SymbolNameSet FailedSymbols;
32370fca6ea1SDimitry Andric   for (auto &[Sym, Flags] : EDU.Symbols)
32380fca6ea1SDimitry Andric     FailedSymbols.insert(SymbolStringPtr(Sym));
32390fca6ea1SDimitry Andric   SymbolDependenceMap BadDeps;
32400fca6ea1SDimitry Andric   for (auto &Dep : EDU.Dependencies[&ClosedJD])
32410fca6ea1SDimitry Andric     BadDeps[&ClosedJD].insert(SymbolStringPtr(Dep));
32420fca6ea1SDimitry Andric   return make_error<UnsatisfiedSymbolDependencies>(
32430fca6ea1SDimitry Andric       ClosedJD.getExecutionSession().getSymbolStringPool(), EDU.JD,
32440fca6ea1SDimitry Andric       std::move(FailedSymbols), std::move(BadDeps),
32450fca6ea1SDimitry Andric       ClosedJD.getName() + " is closed");
32460fca6ea1SDimitry Andric }
32470fca6ea1SDimitry Andric 
32480fca6ea1SDimitry Andric Error ExecutionSession::makeUnsatisfiedDepsError(JITDylib::EmissionDepUnit &EDU,
32490fca6ea1SDimitry Andric                                                  JITDylib &BadJD,
32500fca6ea1SDimitry Andric                                                  SymbolNameSet BadDeps) {
32510fca6ea1SDimitry Andric   SymbolNameSet FailedSymbols;
32520fca6ea1SDimitry Andric   for (auto &[Sym, Flags] : EDU.Symbols)
32530fca6ea1SDimitry Andric     FailedSymbols.insert(SymbolStringPtr(Sym));
32540fca6ea1SDimitry Andric   SymbolDependenceMap BadDepsMap;
32550fca6ea1SDimitry Andric   BadDepsMap[&BadJD] = std::move(BadDeps);
32560fca6ea1SDimitry Andric   return make_error<UnsatisfiedSymbolDependencies>(
32570fca6ea1SDimitry Andric       BadJD.getExecutionSession().getSymbolStringPool(), &BadJD,
32580fca6ea1SDimitry Andric       std::move(FailedSymbols), std::move(BadDepsMap),
32590fca6ea1SDimitry Andric       "dependencies removed or in error state");
32600fca6ea1SDimitry Andric }
32610fca6ea1SDimitry Andric 
32620fca6ea1SDimitry Andric Expected<JITDylib::AsynchronousSymbolQuerySet>
32630fca6ea1SDimitry Andric ExecutionSession::IL_emit(MaterializationResponsibility &MR,
32640fca6ea1SDimitry Andric                           EDUInfosMap EDUInfos) {
32650fca6ea1SDimitry Andric 
32660fca6ea1SDimitry Andric   if (MR.RT->isDefunct())
32670fca6ea1SDimitry Andric     return make_error<ResourceTrackerDefunct>(MR.RT);
32680fca6ea1SDimitry Andric 
32690fca6ea1SDimitry Andric   auto &TargetJD = MR.getTargetJITDylib();
32700fca6ea1SDimitry Andric   if (TargetJD.State != JITDylib::Open)
32710fca6ea1SDimitry Andric     return make_error<StringError>("JITDylib " + TargetJD.getName() +
32720fca6ea1SDimitry Andric                                        " is defunct",
32730fca6ea1SDimitry Andric                                    inconvertibleErrorCode());
32740fca6ea1SDimitry Andric #ifdef EXPENSIVE_CHECKS
32750fca6ea1SDimitry Andric   verifySessionState("entering ExecutionSession::IL_emit");
32760fca6ea1SDimitry Andric #endif
32770fca6ea1SDimitry Andric 
32780fca6ea1SDimitry Andric   // Walk all EDUs:
32790fca6ea1SDimitry Andric   // 1. Verifying that dependencies are available (not removed or in the error
32800fca6ea1SDimitry Andric   //    state.
32810fca6ea1SDimitry Andric   // 2. Removing any dependencies that are already Ready.
32820fca6ea1SDimitry Andric   // 3. Lifting any EDUs for Emitted symbols into the EDUInfos map.
32830fca6ea1SDimitry Andric   // 4. Finding any dependant EDUs and lifting them into the EDUInfos map.
32840fca6ea1SDimitry Andric   std::deque<JITDylib::EmissionDepUnit *> Worklist;
32850fca6ea1SDimitry Andric   for (auto &[EDU, _] : EDUInfos)
32860fca6ea1SDimitry Andric     Worklist.push_back(EDU);
32870fca6ea1SDimitry Andric 
32880fca6ea1SDimitry Andric   for (auto *EDU : Worklist) {
32890fca6ea1SDimitry Andric     auto *EDUInfo = &EDUInfos[EDU];
32900fca6ea1SDimitry Andric 
32910fca6ea1SDimitry Andric     SmallVector<JITDylib *> DepJDsToRemove;
32920fca6ea1SDimitry Andric     for (auto &[DepJD, Deps] : EDU->Dependencies) {
32930fca6ea1SDimitry Andric       if (DepJD->State != JITDylib::Open)
32940fca6ea1SDimitry Andric         return makeJDClosedError(*EDU, *DepJD);
32950fca6ea1SDimitry Andric 
32960fca6ea1SDimitry Andric       SymbolNameSet BadDeps;
32970fca6ea1SDimitry Andric       SmallVector<NonOwningSymbolStringPtr> DepsToRemove;
32980fca6ea1SDimitry Andric       for (auto &Dep : Deps) {
32990fca6ea1SDimitry Andric         auto DepEntryItr = DepJD->Symbols.find(SymbolStringPtr(Dep));
33000fca6ea1SDimitry Andric 
33010fca6ea1SDimitry Andric         // If this dep has been removed or moved to the error state then add it
33020fca6ea1SDimitry Andric         // to the bad deps set. We aggregate these bad deps for more
33030fca6ea1SDimitry Andric         // comprehensive error messages.
33040fca6ea1SDimitry Andric         if (DepEntryItr == DepJD->Symbols.end() ||
33050fca6ea1SDimitry Andric             DepEntryItr->second.getFlags().hasError()) {
33060fca6ea1SDimitry Andric           BadDeps.insert(SymbolStringPtr(Dep));
33070fca6ea1SDimitry Andric           continue;
33080fca6ea1SDimitry Andric         }
33090fca6ea1SDimitry Andric 
33100fca6ea1SDimitry Andric         // If this dep isn't emitted yet then just add it to the NewDeps set to
33110fca6ea1SDimitry Andric         // be propagated.
33120fca6ea1SDimitry Andric         auto &DepEntry = DepEntryItr->second;
33130fca6ea1SDimitry Andric         if (DepEntry.getState() < SymbolState::Emitted) {
33140fca6ea1SDimitry Andric           EDUInfo->NewDeps[DepJD].insert(Dep);
33150fca6ea1SDimitry Andric           continue;
33160fca6ea1SDimitry Andric         }
33170fca6ea1SDimitry Andric 
33180fca6ea1SDimitry Andric         // This dep has been emitted, so add it to the list to be removed from
33190fca6ea1SDimitry Andric         // EDU.
33200fca6ea1SDimitry Andric         DepsToRemove.push_back(Dep);
33210fca6ea1SDimitry Andric 
33220fca6ea1SDimitry Andric         // If Dep is Ready then there's nothing further to do.
33230fca6ea1SDimitry Andric         if (DepEntry.getState() == SymbolState::Ready) {
33240fca6ea1SDimitry Andric           assert(!DepJD->MaterializingInfos.count(SymbolStringPtr(Dep)) &&
33250fca6ea1SDimitry Andric                  "Unexpected MaterializationInfo attached to ready symbol");
33260fca6ea1SDimitry Andric           continue;
33270fca6ea1SDimitry Andric         }
33280fca6ea1SDimitry Andric 
33290fca6ea1SDimitry Andric         // If we get here thene Dep is Emitted. We need to look up its defining
33300fca6ea1SDimitry Andric         // EDU and add this EDU to the defining EDU's list of users (this means
33310fca6ea1SDimitry Andric         // creating an EDUInfos entry if the defining EDU doesn't have one
33320fca6ea1SDimitry Andric         // already).
33330fca6ea1SDimitry Andric         assert(DepJD->MaterializingInfos.count(SymbolStringPtr(Dep)) &&
33340fca6ea1SDimitry Andric                "Expected MaterializationInfo for emitted dependency");
33350fca6ea1SDimitry Andric         auto &DepMI = DepJD->MaterializingInfos[SymbolStringPtr(Dep)];
33360fca6ea1SDimitry Andric         assert(DepMI.DefiningEDU &&
33370fca6ea1SDimitry Andric                "Emitted symbol does not have a defining EDU");
33380fca6ea1SDimitry Andric         assert(!DepMI.DefiningEDU->Dependencies.empty() &&
33390fca6ea1SDimitry Andric                "Emitted symbol has empty dependencies (should be ready)");
33400fca6ea1SDimitry Andric         assert(DepMI.DependantEDUs.empty() &&
33410fca6ea1SDimitry Andric                "Already-emitted symbol has dependant EDUs?");
33420fca6ea1SDimitry Andric         auto &DepEDUInfo = EDUInfos[DepMI.DefiningEDU.get()];
33430fca6ea1SDimitry Andric         if (!DepEDUInfo.EDU) {
33440fca6ea1SDimitry Andric           // No EDUInfo yet -- build initial entry, and reset the EDUInfo
33450fca6ea1SDimitry Andric           // pointer, which we will have invalidated.
33460fca6ea1SDimitry Andric           EDUInfo = &EDUInfos[EDU];
33470fca6ea1SDimitry Andric           DepEDUInfo.EDU = DepMI.DefiningEDU;
33480fca6ea1SDimitry Andric           for (auto &[DepDepJD, DepDeps] : DepEDUInfo.EDU->Dependencies) {
33490fca6ea1SDimitry Andric             if (DepDepJD == &TargetJD) {
33500fca6ea1SDimitry Andric               for (auto &DepDep : DepDeps)
33510fca6ea1SDimitry Andric                 if (!MR.getSymbols().count(SymbolStringPtr(DepDep)))
33520fca6ea1SDimitry Andric                   DepEDUInfo.NewDeps[DepDepJD].insert(DepDep);
33530fca6ea1SDimitry Andric             } else
33540fca6ea1SDimitry Andric               DepEDUInfo.NewDeps[DepDepJD] = DepDeps;
33550fca6ea1SDimitry Andric           }
33560fca6ea1SDimitry Andric         }
33570fca6ea1SDimitry Andric         DepEDUInfo.IntraEmitUsers.insert(EDU);
33580fca6ea1SDimitry Andric       }
33590fca6ea1SDimitry Andric 
33600fca6ea1SDimitry Andric       // Some dependencies were removed or in an error state -- error out.
33610fca6ea1SDimitry Andric       if (!BadDeps.empty())
33620fca6ea1SDimitry Andric         return makeUnsatisfiedDepsError(*EDU, *DepJD, std::move(BadDeps));
33630fca6ea1SDimitry Andric 
33640fca6ea1SDimitry Andric       // Remove the emitted / ready deps from DepJD.
33650fca6ea1SDimitry Andric       for (auto &Dep : DepsToRemove)
33660fca6ea1SDimitry Andric         Deps.erase(Dep);
33670fca6ea1SDimitry Andric 
33680fca6ea1SDimitry Andric       // If there are no further deps in DepJD then flag it for removal too.
33690fca6ea1SDimitry Andric       if (Deps.empty())
33700fca6ea1SDimitry Andric         DepJDsToRemove.push_back(DepJD);
33710fca6ea1SDimitry Andric     }
33720fca6ea1SDimitry Andric 
33730fca6ea1SDimitry Andric     // Remove any JDs whose dependence sets have become empty.
33740fca6ea1SDimitry Andric     for (auto &DepJD : DepJDsToRemove) {
33750fca6ea1SDimitry Andric       assert(EDU->Dependencies.count(DepJD) &&
33760fca6ea1SDimitry Andric              "Trying to remove non-existent dep entries");
33770fca6ea1SDimitry Andric       EDU->Dependencies.erase(DepJD);
33780fca6ea1SDimitry Andric     }
33790fca6ea1SDimitry Andric 
33800fca6ea1SDimitry Andric     // Now look for users of this EDU.
33810fca6ea1SDimitry Andric     for (auto &[Sym, Flags] : EDU->Symbols) {
33820fca6ea1SDimitry Andric       assert(TargetJD.Symbols.count(SymbolStringPtr(Sym)) &&
33830fca6ea1SDimitry Andric              "Sym not present in symbol table");
33840fca6ea1SDimitry Andric       assert((TargetJD.Symbols[SymbolStringPtr(Sym)].getState() ==
33850fca6ea1SDimitry Andric                   SymbolState::Resolved ||
33860fca6ea1SDimitry Andric               TargetJD.Symbols[SymbolStringPtr(Sym)]
33870fca6ea1SDimitry Andric                   .getFlags()
33880fca6ea1SDimitry Andric                   .hasMaterializationSideEffectsOnly()) &&
33890fca6ea1SDimitry Andric              "Emitting symbol not in the resolved state");
33900fca6ea1SDimitry Andric       assert(!TargetJD.Symbols[SymbolStringPtr(Sym)].getFlags().hasError() &&
33910fca6ea1SDimitry Andric              "Symbol is already in an error state");
33920fca6ea1SDimitry Andric 
33930fca6ea1SDimitry Andric       auto MII = TargetJD.MaterializingInfos.find(SymbolStringPtr(Sym));
33940fca6ea1SDimitry Andric       if (MII == TargetJD.MaterializingInfos.end() ||
33950fca6ea1SDimitry Andric           MII->second.DependantEDUs.empty())
33960fca6ea1SDimitry Andric         continue;
33970fca6ea1SDimitry Andric 
33980fca6ea1SDimitry Andric       for (auto &DependantEDU : MII->second.DependantEDUs) {
33990fca6ea1SDimitry Andric         if (IL_removeEDUDependence(*DependantEDU, TargetJD, Sym, EDUInfos))
34000fca6ea1SDimitry Andric           EDUInfo = &EDUInfos[EDU];
34010fca6ea1SDimitry Andric         EDUInfo->IntraEmitUsers.insert(DependantEDU);
34020fca6ea1SDimitry Andric       }
34030fca6ea1SDimitry Andric       MII->second.DependantEDUs.clear();
34040fca6ea1SDimitry Andric     }
34050fca6ea1SDimitry Andric   }
34060fca6ea1SDimitry Andric 
34070fca6ea1SDimitry Andric   Worklist.clear();
34080fca6ea1SDimitry Andric   for (auto &[EDU, EDUInfo] : EDUInfos) {
34090fca6ea1SDimitry Andric     if (!EDUInfo.IntraEmitUsers.empty() && !EDU->Dependencies.empty()) {
34100fca6ea1SDimitry Andric       if (EDUInfo.NewDeps.empty())
34110fca6ea1SDimitry Andric         EDUInfo.NewDeps = EDU->Dependencies;
34120fca6ea1SDimitry Andric       Worklist.push_back(EDU);
34130fca6ea1SDimitry Andric     }
34140fca6ea1SDimitry Andric   }
34150fca6ea1SDimitry Andric 
34160fca6ea1SDimitry Andric   propagateExtraEmitDeps(
34170fca6ea1SDimitry Andric       Worklist, EDUInfos,
34180fca6ea1SDimitry Andric       [](JITDylib::EmissionDepUnit &EDU, JITDylib &JD,
34190fca6ea1SDimitry Andric          NonOwningSymbolStringPtr Sym) {
34200fca6ea1SDimitry Andric         JD.MaterializingInfos[SymbolStringPtr(Sym)].DependantEDUs.insert(&EDU);
34210fca6ea1SDimitry Andric       });
34220fca6ea1SDimitry Andric 
34230fca6ea1SDimitry Andric   JITDylib::AsynchronousSymbolQuerySet CompletedQueries;
34240fca6ea1SDimitry Andric 
34250fca6ea1SDimitry Andric   // Extract completed queries and lodge not-yet-ready EDUs in the
34260fca6ea1SDimitry Andric   // session.
34270fca6ea1SDimitry Andric   for (auto &[EDU, EDUInfo] : EDUInfos) {
34280fca6ea1SDimitry Andric     if (EDU->Dependencies.empty())
34290fca6ea1SDimitry Andric       IL_makeEDUReady(std::move(EDUInfo.EDU), CompletedQueries);
34300fca6ea1SDimitry Andric     else
34310fca6ea1SDimitry Andric       IL_makeEDUEmitted(std::move(EDUInfo.EDU), CompletedQueries);
34320fca6ea1SDimitry Andric   }
34330fca6ea1SDimitry Andric 
34340fca6ea1SDimitry Andric #ifdef EXPENSIVE_CHECKS
34350fca6ea1SDimitry Andric   verifySessionState("exiting ExecutionSession::IL_emit");
34360fca6ea1SDimitry Andric #endif
34370fca6ea1SDimitry Andric 
34380fca6ea1SDimitry Andric   return std::move(CompletedQueries);
34390fca6ea1SDimitry Andric }
34400fca6ea1SDimitry Andric 
34410fca6ea1SDimitry Andric Error ExecutionSession::OL_notifyEmitted(
34420fca6ea1SDimitry Andric     MaterializationResponsibility &MR,
34430fca6ea1SDimitry Andric     ArrayRef<SymbolDependenceGroup> DepGroups) {
3444e8d8bef9SDimitry Andric   LLVM_DEBUG({
34454824e7fdSDimitry Andric     dbgs() << "In " << MR.JD.getName() << " emitting " << MR.SymbolFlags
34464824e7fdSDimitry Andric            << "\n";
34470fca6ea1SDimitry Andric     if (!DepGroups.empty()) {
34480fca6ea1SDimitry Andric       dbgs() << "  Initial dependencies:\n";
34490fca6ea1SDimitry Andric       for (auto &SDG : DepGroups) {
34500fca6ea1SDimitry Andric         dbgs() << "    Symbols: " << SDG.Symbols
34510fca6ea1SDimitry Andric                << ", Dependencies: " << SDG.Dependencies << "\n";
34520fca6ea1SDimitry Andric       }
34530fca6ea1SDimitry Andric     }
3454e8d8bef9SDimitry Andric   });
3455e8d8bef9SDimitry Andric 
34560fca6ea1SDimitry Andric #ifndef NDEBUG
34570fca6ea1SDimitry Andric   SymbolNameSet Visited;
34580fca6ea1SDimitry Andric   for (auto &DG : DepGroups) {
34590fca6ea1SDimitry Andric     for (auto &Sym : DG.Symbols) {
34600fca6ea1SDimitry Andric       assert(MR.SymbolFlags.count(Sym) &&
34610fca6ea1SDimitry Andric              "DG contains dependence for symbol outside this MR");
34620fca6ea1SDimitry Andric       assert(Visited.insert(Sym).second &&
34630fca6ea1SDimitry Andric              "DG contains duplicate entries for Name");
34640fca6ea1SDimitry Andric     }
34650fca6ea1SDimitry Andric   }
34660fca6ea1SDimitry Andric #endif // NDEBUG
34670fca6ea1SDimitry Andric 
34680fca6ea1SDimitry Andric   auto EDUInfos = simplifyDepGroups(MR, DepGroups);
34690fca6ea1SDimitry Andric 
34700fca6ea1SDimitry Andric   LLVM_DEBUG({
34710fca6ea1SDimitry Andric     dbgs() << "  Simplified dependencies:\n";
34720fca6ea1SDimitry Andric     for (auto &[EDU, EDUInfo] : EDUInfos) {
34730fca6ea1SDimitry Andric       dbgs() << "    Symbols: { ";
34740fca6ea1SDimitry Andric       for (auto &[Sym, Flags] : EDU->Symbols)
34750fca6ea1SDimitry Andric         dbgs() << Sym << " ";
34760fca6ea1SDimitry Andric       dbgs() << "}, Dependencies: { ";
34770fca6ea1SDimitry Andric       for (auto &[DepJD, Deps] : EDU->Dependencies) {
34780fca6ea1SDimitry Andric         dbgs() << "(" << DepJD->getName() << ", { ";
34790fca6ea1SDimitry Andric         for (auto &Dep : Deps)
34800fca6ea1SDimitry Andric           dbgs() << Dep << " ";
34810fca6ea1SDimitry Andric         dbgs() << "}) ";
34820fca6ea1SDimitry Andric       }
34830fca6ea1SDimitry Andric       dbgs() << "}\n";
34840fca6ea1SDimitry Andric     }
34850fca6ea1SDimitry Andric   });
34860fca6ea1SDimitry Andric 
34870fca6ea1SDimitry Andric   auto CompletedQueries =
34880fca6ea1SDimitry Andric       runSessionLocked([&]() { return IL_emit(MR, EDUInfos); });
34890fca6ea1SDimitry Andric 
34900fca6ea1SDimitry Andric   // On error bail out.
34910fca6ea1SDimitry Andric   if (!CompletedQueries)
34920fca6ea1SDimitry Andric     return CompletedQueries.takeError();
3493e8d8bef9SDimitry Andric 
3494e8d8bef9SDimitry Andric   MR.SymbolFlags.clear();
34950fca6ea1SDimitry Andric 
34960fca6ea1SDimitry Andric   // Otherwise notify all the completed queries.
34970fca6ea1SDimitry Andric   for (auto &Q : *CompletedQueries) {
34980fca6ea1SDimitry Andric     assert(Q->isComplete() && "Q is not complete");
34990fca6ea1SDimitry Andric     Q->handleComplete(*this);
35000fca6ea1SDimitry Andric   }
35010fca6ea1SDimitry Andric 
3502e8d8bef9SDimitry Andric   return Error::success();
3503e8d8bef9SDimitry Andric }
3504e8d8bef9SDimitry Andric 
3505e8d8bef9SDimitry Andric Error ExecutionSession::OL_defineMaterializing(
3506e8d8bef9SDimitry Andric     MaterializationResponsibility &MR, SymbolFlagsMap NewSymbolFlags) {
3507e8d8bef9SDimitry Andric 
3508e8d8bef9SDimitry Andric   LLVM_DEBUG({
35094824e7fdSDimitry Andric     dbgs() << "In " << MR.JD.getName() << " defining materializing symbols "
3510e8d8bef9SDimitry Andric            << NewSymbolFlags << "\n";
3511e8d8bef9SDimitry Andric   });
35124824e7fdSDimitry Andric   if (auto AcceptedDefs =
351306c3fb27SDimitry Andric           MR.JD.defineMaterializing(MR, std::move(NewSymbolFlags))) {
3514e8d8bef9SDimitry Andric     // Add all newly accepted symbols to this responsibility object.
3515e8d8bef9SDimitry Andric     for (auto &KV : *AcceptedDefs)
3516e8d8bef9SDimitry Andric       MR.SymbolFlags.insert(KV);
3517e8d8bef9SDimitry Andric     return Error::success();
3518e8d8bef9SDimitry Andric   } else
3519e8d8bef9SDimitry Andric     return AcceptedDefs.takeError();
3520e8d8bef9SDimitry Andric }
3521e8d8bef9SDimitry Andric 
35220fca6ea1SDimitry Andric std::pair<JITDylib::AsynchronousSymbolQuerySet,
35230fca6ea1SDimitry Andric           std::shared_ptr<SymbolDependenceMap>>
35240fca6ea1SDimitry Andric ExecutionSession::IL_failSymbols(JITDylib &JD,
35250fca6ea1SDimitry Andric                                  const SymbolNameVector &SymbolsToFail) {
35260fca6ea1SDimitry Andric 
35270fca6ea1SDimitry Andric #ifdef EXPENSIVE_CHECKS
35280fca6ea1SDimitry Andric   verifySessionState("entering ExecutionSession::IL_failSymbols");
35290fca6ea1SDimitry Andric #endif
35300fca6ea1SDimitry Andric 
35310fca6ea1SDimitry Andric   JITDylib::AsynchronousSymbolQuerySet FailedQueries;
35320fca6ea1SDimitry Andric   auto FailedSymbolsMap = std::make_shared<SymbolDependenceMap>();
35330fca6ea1SDimitry Andric   auto ExtractFailedQueries = [&](JITDylib::MaterializingInfo &MI) {
35340fca6ea1SDimitry Andric     JITDylib::AsynchronousSymbolQueryList ToDetach;
35350fca6ea1SDimitry Andric     for (auto &Q : MI.pendingQueries()) {
35360fca6ea1SDimitry Andric       // Add the query to the list to be failed and detach it.
35370fca6ea1SDimitry Andric       FailedQueries.insert(Q);
35380fca6ea1SDimitry Andric       ToDetach.push_back(Q);
35390fca6ea1SDimitry Andric     }
35400fca6ea1SDimitry Andric     for (auto &Q : ToDetach)
35410fca6ea1SDimitry Andric       Q->detach();
35420fca6ea1SDimitry Andric     assert(!MI.hasQueriesPending() && "Queries still pending after detach");
35430fca6ea1SDimitry Andric   };
35440fca6ea1SDimitry Andric 
35450fca6ea1SDimitry Andric   for (auto &Name : SymbolsToFail) {
35460fca6ea1SDimitry Andric     (*FailedSymbolsMap)[&JD].insert(Name);
35470fca6ea1SDimitry Andric 
35480fca6ea1SDimitry Andric     // Look up the symbol to fail.
35490fca6ea1SDimitry Andric     auto SymI = JD.Symbols.find(Name);
35500fca6ea1SDimitry Andric 
35510fca6ea1SDimitry Andric     // FIXME: Revisit this. We should be able to assert sequencing between
35520fca6ea1SDimitry Andric     //        ResourceTracker removal and symbol failure.
35530fca6ea1SDimitry Andric     //
35540fca6ea1SDimitry Andric     // It's possible that this symbol has already been removed, e.g. if a
35550fca6ea1SDimitry Andric     // materialization failure happens concurrently with a ResourceTracker or
35560fca6ea1SDimitry Andric     // JITDylib removal. In that case we can safely skip this symbol and
35570fca6ea1SDimitry Andric     // continue.
35580fca6ea1SDimitry Andric     if (SymI == JD.Symbols.end())
35590fca6ea1SDimitry Andric       continue;
35600fca6ea1SDimitry Andric     auto &Sym = SymI->second;
35610fca6ea1SDimitry Andric 
35620fca6ea1SDimitry Andric     // If the symbol is already in the error state then we must have visited
35630fca6ea1SDimitry Andric     // it earlier.
35640fca6ea1SDimitry Andric     if (Sym.getFlags().hasError()) {
35650fca6ea1SDimitry Andric       assert(!JD.MaterializingInfos.count(Name) &&
35660fca6ea1SDimitry Andric              "Symbol in error state still has MaterializingInfo");
35670fca6ea1SDimitry Andric       continue;
35680fca6ea1SDimitry Andric     }
35690fca6ea1SDimitry Andric 
35700fca6ea1SDimitry Andric     // Move the symbol into the error state.
35710fca6ea1SDimitry Andric     Sym.setFlags(Sym.getFlags() | JITSymbolFlags::HasError);
35720fca6ea1SDimitry Andric 
35730fca6ea1SDimitry Andric     // FIXME: Come up with a sane mapping of state to
35740fca6ea1SDimitry Andric     // presence-of-MaterializingInfo so that we can assert presence / absence
35750fca6ea1SDimitry Andric     // here, rather than testing it.
35760fca6ea1SDimitry Andric     auto MII = JD.MaterializingInfos.find(Name);
35770fca6ea1SDimitry Andric     if (MII == JD.MaterializingInfos.end())
35780fca6ea1SDimitry Andric       continue;
35790fca6ea1SDimitry Andric 
35800fca6ea1SDimitry Andric     auto &MI = MII->second;
35810fca6ea1SDimitry Andric 
35820fca6ea1SDimitry Andric     // Collect queries to be failed for this MII.
35830fca6ea1SDimitry Andric     ExtractFailedQueries(MI);
35840fca6ea1SDimitry Andric 
35850fca6ea1SDimitry Andric     if (MI.DefiningEDU) {
35860fca6ea1SDimitry Andric       // If there is a DefiningEDU for this symbol then remove this
35870fca6ea1SDimitry Andric       // symbol from it.
35880fca6ea1SDimitry Andric       assert(MI.DependantEDUs.empty() &&
35890fca6ea1SDimitry Andric              "Symbol with DefiningEDU should not have DependantEDUs");
35900fca6ea1SDimitry Andric       assert(Sym.getState() >= SymbolState::Emitted &&
35910fca6ea1SDimitry Andric              "Symbol has EDU, should have been emitted");
35920fca6ea1SDimitry Andric       assert(MI.DefiningEDU->Symbols.count(NonOwningSymbolStringPtr(Name)) &&
35930fca6ea1SDimitry Andric              "Symbol does not appear in its DefiningEDU");
35940fca6ea1SDimitry Andric       MI.DefiningEDU->Symbols.erase(NonOwningSymbolStringPtr(Name));
3595*6e516c87SDimitry Andric 
3596*6e516c87SDimitry Andric       // Remove this EDU from the dependants lists of its dependencies.
3597*6e516c87SDimitry Andric       for (auto &[DepJD, DepSyms] : MI.DefiningEDU->Dependencies) {
3598*6e516c87SDimitry Andric         for (auto DepSym : DepSyms) {
3599*6e516c87SDimitry Andric           assert(DepJD->Symbols.count(SymbolStringPtr(DepSym)) &&
3600*6e516c87SDimitry Andric                  "DepSym not in DepJD");
3601*6e516c87SDimitry Andric           assert(DepJD->MaterializingInfos.count(SymbolStringPtr(DepSym)) &&
3602*6e516c87SDimitry Andric                  "DepSym has not MaterializingInfo");
3603*6e516c87SDimitry Andric           auto &SymMI = DepJD->MaterializingInfos[SymbolStringPtr(DepSym)];
3604*6e516c87SDimitry Andric           assert(SymMI.DependantEDUs.count(MI.DefiningEDU.get()) &&
3605*6e516c87SDimitry Andric                  "DefiningEDU missing from DependantEDUs list of dependency");
3606*6e516c87SDimitry Andric           SymMI.DependantEDUs.erase(MI.DefiningEDU.get());
3607*6e516c87SDimitry Andric         }
3608*6e516c87SDimitry Andric       }
3609*6e516c87SDimitry Andric 
36100fca6ea1SDimitry Andric       MI.DefiningEDU = nullptr;
36110fca6ea1SDimitry Andric     } else {
36120fca6ea1SDimitry Andric       // Otherwise if there are any EDUs waiting on this symbol then move
36130fca6ea1SDimitry Andric       // those symbols to the error state too, and deregister them from the
36140fca6ea1SDimitry Andric       // symbols that they depend on.
36150fca6ea1SDimitry Andric       // Note: We use a copy of DependantEDUs here since we'll be removing
36160fca6ea1SDimitry Andric       // from the original set as we go.
36170fca6ea1SDimitry Andric       for (auto &DependantEDU : MI.DependantEDUs) {
36180fca6ea1SDimitry Andric 
36190fca6ea1SDimitry Andric         // Remove DependantEDU from all of its users DependantEDUs lists.
36200fca6ea1SDimitry Andric         for (auto &[DepJD, DepSyms] : DependantEDU->Dependencies) {
36210fca6ea1SDimitry Andric           for (auto DepSym : DepSyms) {
36220fca6ea1SDimitry Andric             // Skip self-reference to avoid invalidating the MI.DependantEDUs
36230fca6ea1SDimitry Andric             // map. We'll clear this later.
36240fca6ea1SDimitry Andric             if (DepJD == &JD && DepSym == Name)
36250fca6ea1SDimitry Andric               continue;
36260fca6ea1SDimitry Andric             assert(DepJD->Symbols.count(SymbolStringPtr(DepSym)) &&
36270fca6ea1SDimitry Andric                    "DepSym not in DepJD?");
36280fca6ea1SDimitry Andric             assert(DepJD->MaterializingInfos.count(SymbolStringPtr(DepSym)) &&
36290fca6ea1SDimitry Andric                    "DependantEDU not registered with symbol it depends on");
36300fca6ea1SDimitry Andric             auto &SymMI = DepJD->MaterializingInfos[SymbolStringPtr(DepSym)];
36310fca6ea1SDimitry Andric             assert(SymMI.DependantEDUs.count(DependantEDU) &&
36320fca6ea1SDimitry Andric                    "DependantEDU missing from DependantEDUs list");
36330fca6ea1SDimitry Andric             SymMI.DependantEDUs.erase(DependantEDU);
36340fca6ea1SDimitry Andric           }
36350fca6ea1SDimitry Andric         }
36360fca6ea1SDimitry Andric 
36370fca6ea1SDimitry Andric         // Move any symbols defined by DependantEDU into the error state and
36380fca6ea1SDimitry Andric         // fail any queries waiting on them.
36390fca6ea1SDimitry Andric         auto &DepJD = *DependantEDU->JD;
36400fca6ea1SDimitry Andric         auto DepEDUSymbols = std::move(DependantEDU->Symbols);
36410fca6ea1SDimitry Andric         for (auto &[DepName, Flags] : DepEDUSymbols) {
36420fca6ea1SDimitry Andric           auto DepSymItr = DepJD.Symbols.find(SymbolStringPtr(DepName));
36430fca6ea1SDimitry Andric           assert(DepSymItr != DepJD.Symbols.end() &&
36440fca6ea1SDimitry Andric                  "Symbol not present in table");
36450fca6ea1SDimitry Andric           auto &DepSym = DepSymItr->second;
36460fca6ea1SDimitry Andric 
36470fca6ea1SDimitry Andric           assert(DepSym.getState() >= SymbolState::Emitted &&
36480fca6ea1SDimitry Andric                  "Symbol has EDU, should have been emitted");
36490fca6ea1SDimitry Andric           assert(!DepSym.getFlags().hasError() &&
36500fca6ea1SDimitry Andric                  "Symbol is already in the error state?");
36510fca6ea1SDimitry Andric           DepSym.setFlags(DepSym.getFlags() | JITSymbolFlags::HasError);
36520fca6ea1SDimitry Andric           (*FailedSymbolsMap)[&DepJD].insert(SymbolStringPtr(DepName));
36530fca6ea1SDimitry Andric 
36540fca6ea1SDimitry Andric           // This symbol has a defining EDU so its MaterializingInfo object must
36550fca6ea1SDimitry Andric           // exist.
36560fca6ea1SDimitry Andric           auto DepMIItr =
36570fca6ea1SDimitry Andric               DepJD.MaterializingInfos.find(SymbolStringPtr(DepName));
36580fca6ea1SDimitry Andric           assert(DepMIItr != DepJD.MaterializingInfos.end() &&
36590fca6ea1SDimitry Andric                  "Symbol has defining EDU but not MaterializingInfo");
36600fca6ea1SDimitry Andric           auto &DepMI = DepMIItr->second;
36610fca6ea1SDimitry Andric           assert(DepMI.DefiningEDU.get() == DependantEDU &&
36620fca6ea1SDimitry Andric                  "Bad EDU dependence edge");
36630fca6ea1SDimitry Andric           assert(DepMI.DependantEDUs.empty() &&
36640fca6ea1SDimitry Andric                  "Symbol was emitted, should not have any DependantEDUs");
36650fca6ea1SDimitry Andric           ExtractFailedQueries(DepMI);
36660fca6ea1SDimitry Andric           DepJD.MaterializingInfos.erase(SymbolStringPtr(DepName));
36670fca6ea1SDimitry Andric         }
36680fca6ea1SDimitry Andric 
36690fca6ea1SDimitry Andric         DepJD.shrinkMaterializationInfoMemory();
36700fca6ea1SDimitry Andric       }
36710fca6ea1SDimitry Andric 
36720fca6ea1SDimitry Andric       MI.DependantEDUs.clear();
36730fca6ea1SDimitry Andric     }
36740fca6ea1SDimitry Andric 
36750fca6ea1SDimitry Andric     assert(!MI.DefiningEDU && "DefiningEDU should have been reset");
36760fca6ea1SDimitry Andric     assert(MI.DependantEDUs.empty() &&
36770fca6ea1SDimitry Andric            "DependantEDUs should have been removed above");
36780fca6ea1SDimitry Andric     assert(!MI.hasQueriesPending() &&
36790fca6ea1SDimitry Andric            "Can not delete MaterializingInfo with queries pending");
36800fca6ea1SDimitry Andric     JD.MaterializingInfos.erase(Name);
36810fca6ea1SDimitry Andric   }
36820fca6ea1SDimitry Andric 
36830fca6ea1SDimitry Andric   JD.shrinkMaterializationInfoMemory();
36840fca6ea1SDimitry Andric 
36850fca6ea1SDimitry Andric #ifdef EXPENSIVE_CHECKS
36860fca6ea1SDimitry Andric   verifySessionState("exiting ExecutionSession::IL_failSymbols");
36870fca6ea1SDimitry Andric #endif
36880fca6ea1SDimitry Andric 
36890fca6ea1SDimitry Andric   return std::make_pair(std::move(FailedQueries), std::move(FailedSymbolsMap));
36900fca6ea1SDimitry Andric }
36910fca6ea1SDimitry Andric 
3692e8d8bef9SDimitry Andric void ExecutionSession::OL_notifyFailed(MaterializationResponsibility &MR) {
3693e8d8bef9SDimitry Andric 
3694e8d8bef9SDimitry Andric   LLVM_DEBUG({
36954824e7fdSDimitry Andric     dbgs() << "In " << MR.JD.getName() << " failing materialization for "
3696e8d8bef9SDimitry Andric            << MR.SymbolFlags << "\n";
3697e8d8bef9SDimitry Andric   });
3698e8d8bef9SDimitry Andric 
36990fca6ea1SDimitry Andric   if (MR.SymbolFlags.empty())
3700e8d8bef9SDimitry Andric     return;
3701e8d8bef9SDimitry Andric 
37020fca6ea1SDimitry Andric   SymbolNameVector SymbolsToFail;
37030fca6ea1SDimitry Andric   for (auto &[Name, Flags] : MR.SymbolFlags)
37040fca6ea1SDimitry Andric     SymbolsToFail.push_back(Name);
37050fca6ea1SDimitry Andric   MR.SymbolFlags.clear();
37060fca6ea1SDimitry Andric 
3707e8d8bef9SDimitry Andric   JITDylib::AsynchronousSymbolQuerySet FailedQueries;
3708e8d8bef9SDimitry Andric   std::shared_ptr<SymbolDependenceMap> FailedSymbols;
3709e8d8bef9SDimitry Andric 
37100fca6ea1SDimitry Andric   std::tie(FailedQueries, FailedSymbols) = runSessionLocked([&]() {
37114824e7fdSDimitry Andric     // If the tracker is defunct then there's nothing to do here.
37124824e7fdSDimitry Andric     if (MR.RT->isDefunct())
37130fca6ea1SDimitry Andric       return std::pair<JITDylib::AsynchronousSymbolQuerySet,
37140fca6ea1SDimitry Andric                        std::shared_ptr<SymbolDependenceMap>>();
37150fca6ea1SDimitry Andric     return IL_failSymbols(MR.getTargetJITDylib(), SymbolsToFail);
3716e8d8bef9SDimitry Andric   });
3717e8d8bef9SDimitry Andric 
3718e8d8bef9SDimitry Andric   for (auto &Q : FailedQueries)
371981ad6265SDimitry Andric     Q->handleFailed(
372081ad6265SDimitry Andric         make_error<FailedToMaterialize>(getSymbolStringPool(), FailedSymbols));
3721e8d8bef9SDimitry Andric }
3722e8d8bef9SDimitry Andric 
3723e8d8bef9SDimitry Andric Error ExecutionSession::OL_replace(MaterializationResponsibility &MR,
3724e8d8bef9SDimitry Andric                                    std::unique_ptr<MaterializationUnit> MU) {
3725e8d8bef9SDimitry Andric   for (auto &KV : MU->getSymbols()) {
3726e8d8bef9SDimitry Andric     assert(MR.SymbolFlags.count(KV.first) &&
3727e8d8bef9SDimitry Andric            "Replacing definition outside this responsibility set");
3728e8d8bef9SDimitry Andric     MR.SymbolFlags.erase(KV.first);
3729e8d8bef9SDimitry Andric   }
3730e8d8bef9SDimitry Andric 
3731e8d8bef9SDimitry Andric   if (MU->getInitializerSymbol() == MR.InitSymbol)
3732e8d8bef9SDimitry Andric     MR.InitSymbol = nullptr;
3733e8d8bef9SDimitry Andric 
37344824e7fdSDimitry Andric   LLVM_DEBUG(MR.JD.getExecutionSession().runSessionLocked([&]() {
37354824e7fdSDimitry Andric     dbgs() << "In " << MR.JD.getName() << " replacing symbols with " << *MU
3736e8d8bef9SDimitry Andric            << "\n";
3737e8d8bef9SDimitry Andric   }););
3738e8d8bef9SDimitry Andric 
37394824e7fdSDimitry Andric   return MR.JD.replace(MR, std::move(MU));
3740e8d8bef9SDimitry Andric }
3741e8d8bef9SDimitry Andric 
3742e8d8bef9SDimitry Andric Expected<std::unique_ptr<MaterializationResponsibility>>
3743e8d8bef9SDimitry Andric ExecutionSession::OL_delegate(MaterializationResponsibility &MR,
3744e8d8bef9SDimitry Andric                               const SymbolNameSet &Symbols) {
3745e8d8bef9SDimitry Andric 
3746e8d8bef9SDimitry Andric   SymbolStringPtr DelegatedInitSymbol;
3747e8d8bef9SDimitry Andric   SymbolFlagsMap DelegatedFlags;
3748e8d8bef9SDimitry Andric 
3749e8d8bef9SDimitry Andric   for (auto &Name : Symbols) {
3750e8d8bef9SDimitry Andric     auto I = MR.SymbolFlags.find(Name);
3751e8d8bef9SDimitry Andric     assert(I != MR.SymbolFlags.end() &&
3752e8d8bef9SDimitry Andric            "Symbol is not tracked by this MaterializationResponsibility "
3753e8d8bef9SDimitry Andric            "instance");
3754e8d8bef9SDimitry Andric 
3755e8d8bef9SDimitry Andric     DelegatedFlags[Name] = std::move(I->second);
3756e8d8bef9SDimitry Andric     if (Name == MR.InitSymbol)
3757e8d8bef9SDimitry Andric       std::swap(MR.InitSymbol, DelegatedInitSymbol);
3758e8d8bef9SDimitry Andric 
3759e8d8bef9SDimitry Andric     MR.SymbolFlags.erase(I);
3760e8d8bef9SDimitry Andric   }
3761e8d8bef9SDimitry Andric 
37624824e7fdSDimitry Andric   return MR.JD.delegate(MR, std::move(DelegatedFlags),
3763e8d8bef9SDimitry Andric                         std::move(DelegatedInitSymbol));
3764e8d8bef9SDimitry Andric }
3765e8d8bef9SDimitry Andric 
37665ffd83dbSDimitry Andric #ifndef NDEBUG
3767fe6060f1SDimitry Andric void ExecutionSession::dumpDispatchInfo(Task &T) {
37685ffd83dbSDimitry Andric   runSessionLocked([&]() {
3769fe6060f1SDimitry Andric     dbgs() << "Dispatching: ";
3770fe6060f1SDimitry Andric     T.printDescription(dbgs());
3771349cc55cSDimitry Andric     dbgs() << "\n";
37725ffd83dbSDimitry Andric   });
37730b57cec5SDimitry Andric }
37745ffd83dbSDimitry Andric #endif // NDEBUG
37750b57cec5SDimitry Andric 
37760b57cec5SDimitry Andric } // End namespace orc.
37770b57cec5SDimitry Andric } // End namespace llvm.
3778