1d5f56c59SLang Hames //===--- Core.cpp - Core ORC APIs (MaterializationUnit, JITDylib, etc.) ---===//
29510447aSLang Hames //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
69510447aSLang Hames //
79510447aSLang Hames //===----------------------------------------------------------------------===//
89510447aSLang Hames 
99510447aSLang Hames #include "llvm/ExecutionEngine/Orc/Core.h"
10674df13bSLang Hames 
11674df13bSLang Hames #include "llvm/ADT/STLExtras.h"
12199a00c3SLang Hames #include "llvm/Config/llvm-config.h"
1338a8760bSLang Hames #include "llvm/ExecutionEngine/Orc/DebugUtils.h"
1424672ddeSLang Hames #include "llvm/ExecutionEngine/Orc/Shared/OrcError.h"
150aec49c8SLang Hames #include "llvm/Support/FormatVariadic.h"
16069919c9SLang Hames #include "llvm/Support/MSVCErrorWorkarounds.h"
179510447aSLang Hames 
181f984c83SHans Wennborg #include <condition_variable>
19817f1f64SLang Hames #include <future>
20817f1f64SLang Hames 
21bfd93e5fSLang Hames #define DEBUG_TYPE "orc"
22bfd93e5fSLang Hames 
239510447aSLang Hames namespace llvm {
249510447aSLang Hames namespace orc {
259510447aSLang Hames 
260aec49c8SLang Hames char ResourceTrackerDefunct::ID = 0;
27199a00c3SLang Hames char FailedToMaterialize::ID = 0;
28199a00c3SLang Hames char SymbolsNotFound::ID = 0;
29199a00c3SLang Hames char SymbolsCouldNotBeRemoved::ID = 0;
3081726894SLang Hames char MissingSymbolDefinitions::ID = 0;
3181726894SLang Hames char UnexpectedSymbolDefinitions::ID = 0;
325344c88dSLang Hames char MaterializationTask::ID = 0;
33199a00c3SLang Hames 
34a48d1083SLang Hames RegisterDependenciesFunction NoDependenciesToRegister =
35a48d1083SLang Hames     RegisterDependenciesFunction();
36a48d1083SLang Hames 
anchor()374cca7d22SLang Hames void MaterializationUnit::anchor() {}
389510447aSLang Hames 
ResourceTracker(JITDylibSP JD)390aec49c8SLang Hames ResourceTracker::ResourceTracker(JITDylibSP JD) {
400aec49c8SLang Hames   assert((reinterpret_cast<uintptr_t>(JD.get()) & 0x1) == 0 &&
410aec49c8SLang Hames          "JITDylib must be two byte aligned");
420aec49c8SLang Hames   JD->Retain();
430aec49c8SLang Hames   JDAndFlag.store(reinterpret_cast<uintptr_t>(JD.get()));
440aec49c8SLang Hames }
450aec49c8SLang Hames 
~ResourceTracker()460aec49c8SLang Hames ResourceTracker::~ResourceTracker() {
470aec49c8SLang Hames   getJITDylib().getExecutionSession().destroyResourceTracker(*this);
480aec49c8SLang Hames   getJITDylib().Release();
490aec49c8SLang Hames }
500aec49c8SLang Hames 
remove()510aec49c8SLang Hames Error ResourceTracker::remove() {
520aec49c8SLang Hames   return getJITDylib().getExecutionSession().removeResourceTracker(*this);
530aec49c8SLang Hames }
540aec49c8SLang Hames 
transferTo(ResourceTracker & DstRT)550aec49c8SLang Hames void ResourceTracker::transferTo(ResourceTracker &DstRT) {
560aec49c8SLang Hames   getJITDylib().getExecutionSession().transferResourceTracker(DstRT, *this);
570aec49c8SLang Hames }
580aec49c8SLang Hames 
makeDefunct()590aec49c8SLang Hames void ResourceTracker::makeDefunct() {
600aec49c8SLang Hames   uintptr_t Val = JDAndFlag.load();
610aec49c8SLang Hames   Val |= 0x1U;
620aec49c8SLang Hames   JDAndFlag.store(Val);
630aec49c8SLang Hames }
640aec49c8SLang Hames 
653a3cb929SKazu Hirata ResourceManager::~ResourceManager() = default;
660aec49c8SLang Hames 
ResourceTrackerDefunct(ResourceTrackerSP RT)670aec49c8SLang Hames ResourceTrackerDefunct::ResourceTrackerDefunct(ResourceTrackerSP RT)
680aec49c8SLang Hames     : RT(std::move(RT)) {}
690aec49c8SLang Hames 
convertToErrorCode() const700aec49c8SLang Hames std::error_code ResourceTrackerDefunct::convertToErrorCode() const {
710aec49c8SLang Hames   return orcError(OrcErrorCode::UnknownORCError);
720aec49c8SLang Hames }
730aec49c8SLang Hames 
log(raw_ostream & OS) const740aec49c8SLang Hames void ResourceTrackerDefunct::log(raw_ostream &OS) const {
750aec49c8SLang Hames   OS << "Resource tracker " << (void *)RT.get() << " became defunct";
760aec49c8SLang Hames }
770aec49c8SLang Hames 
FailedToMaterialize(std::shared_ptr<SymbolStringPool> SSP,std::shared_ptr<SymbolDependenceMap> Symbols)78e00585c7SLang Hames FailedToMaterialize::FailedToMaterialize(
7955e8f721SLang Hames     std::shared_ptr<SymbolStringPool> SSP,
80e00585c7SLang Hames     std::shared_ptr<SymbolDependenceMap> Symbols)
8155e8f721SLang Hames     : SSP(std::move(SSP)), Symbols(std::move(Symbols)) {
8255e8f721SLang Hames   assert(this->SSP && "String pool cannot be null");
83e00585c7SLang Hames   assert(!this->Symbols->empty() && "Can not fail to resolve an empty set");
8455e8f721SLang Hames 
8555e8f721SLang Hames   // FIXME: Use a new dep-map type for FailedToMaterialize errors so that we
8655e8f721SLang Hames   // don't have to manually retain/release.
8755e8f721SLang Hames   for (auto &KV : *this->Symbols)
8855e8f721SLang Hames     KV.first->Retain();
8955e8f721SLang Hames }
9055e8f721SLang Hames 
~FailedToMaterialize()9155e8f721SLang Hames FailedToMaterialize::~FailedToMaterialize() {
9255e8f721SLang Hames   for (auto &KV : *Symbols)
9355e8f721SLang Hames     KV.first->Release();
94199a00c3SLang Hames }
95199a00c3SLang Hames 
convertToErrorCode() const96199a00c3SLang Hames std::error_code FailedToMaterialize::convertToErrorCode() const {
97199a00c3SLang Hames   return orcError(OrcErrorCode::UnknownORCError);
98199a00c3SLang Hames }
99199a00c3SLang Hames 
log(raw_ostream & OS) const100199a00c3SLang Hames void FailedToMaterialize::log(raw_ostream &OS) const {
101e00585c7SLang Hames   OS << "Failed to materialize symbols: " << *Symbols;
102199a00c3SLang Hames }
103199a00c3SLang Hames 
SymbolsNotFound(std::shared_ptr<SymbolStringPool> SSP,SymbolNameSet Symbols)1046fe2e9a9SLang Hames SymbolsNotFound::SymbolsNotFound(std::shared_ptr<SymbolStringPool> SSP,
1056fe2e9a9SLang Hames                                  SymbolNameSet Symbols)
1066fe2e9a9SLang Hames     : SSP(std::move(SSP)) {
107674df13bSLang Hames   for (auto &Sym : Symbols)
108674df13bSLang Hames     this->Symbols.push_back(Sym);
109674df13bSLang Hames   assert(!this->Symbols.empty() && "Can not fail to resolve an empty set");
110674df13bSLang Hames }
111674df13bSLang Hames 
SymbolsNotFound(std::shared_ptr<SymbolStringPool> SSP,SymbolNameVector Symbols)1126fe2e9a9SLang Hames SymbolsNotFound::SymbolsNotFound(std::shared_ptr<SymbolStringPool> SSP,
1136fe2e9a9SLang Hames                                  SymbolNameVector Symbols)
1146fe2e9a9SLang Hames     : SSP(std::move(SSP)), Symbols(std::move(Symbols)) {
115199a00c3SLang Hames   assert(!this->Symbols.empty() && "Can not fail to resolve an empty set");
116199a00c3SLang Hames }
117199a00c3SLang Hames 
convertToErrorCode() const118199a00c3SLang Hames std::error_code SymbolsNotFound::convertToErrorCode() const {
119199a00c3SLang Hames   return orcError(OrcErrorCode::UnknownORCError);
120199a00c3SLang Hames }
121199a00c3SLang Hames 
log(raw_ostream & OS) const122199a00c3SLang Hames void SymbolsNotFound::log(raw_ostream &OS) const {
123199a00c3SLang Hames   OS << "Symbols not found: " << Symbols;
124199a00c3SLang Hames }
125199a00c3SLang Hames 
SymbolsCouldNotBeRemoved(std::shared_ptr<SymbolStringPool> SSP,SymbolNameSet Symbols)1266fe2e9a9SLang Hames SymbolsCouldNotBeRemoved::SymbolsCouldNotBeRemoved(
1276fe2e9a9SLang Hames     std::shared_ptr<SymbolStringPool> SSP, SymbolNameSet Symbols)
1286fe2e9a9SLang Hames     : SSP(std::move(SSP)), Symbols(std::move(Symbols)) {
129199a00c3SLang Hames   assert(!this->Symbols.empty() && "Can not fail to resolve an empty set");
130199a00c3SLang Hames }
131199a00c3SLang Hames 
convertToErrorCode() const132199a00c3SLang Hames std::error_code SymbolsCouldNotBeRemoved::convertToErrorCode() const {
133199a00c3SLang Hames   return orcError(OrcErrorCode::UnknownORCError);
134199a00c3SLang Hames }
135199a00c3SLang Hames 
log(raw_ostream & OS) const136199a00c3SLang Hames void SymbolsCouldNotBeRemoved::log(raw_ostream &OS) const {
137199a00c3SLang Hames   OS << "Symbols could not be removed: " << Symbols;
138199a00c3SLang Hames }
139199a00c3SLang Hames 
convertToErrorCode() const14081726894SLang Hames std::error_code MissingSymbolDefinitions::convertToErrorCode() const {
14181726894SLang Hames   return orcError(OrcErrorCode::MissingSymbolDefinitions);
14281726894SLang Hames }
14381726894SLang Hames 
log(raw_ostream & OS) const14481726894SLang Hames void MissingSymbolDefinitions::log(raw_ostream &OS) const {
14581726894SLang Hames   OS << "Missing definitions in module " << ModuleName
14681726894SLang Hames      << ": " << Symbols;
14781726894SLang Hames }
14881726894SLang Hames 
convertToErrorCode() const14981726894SLang Hames std::error_code UnexpectedSymbolDefinitions::convertToErrorCode() const {
15081726894SLang Hames   return orcError(OrcErrorCode::UnexpectedSymbolDefinitions);
15181726894SLang Hames }
15281726894SLang Hames 
log(raw_ostream & OS) const15381726894SLang Hames void UnexpectedSymbolDefinitions::log(raw_ostream &OS) const {
15481726894SLang Hames   OS << "Unexpected definitions in module " << ModuleName
15581726894SLang Hames      << ": " << Symbols;
15681726894SLang Hames }
15781726894SLang Hames 
AsynchronousSymbolQuery(const SymbolLookupSet & Symbols,SymbolState RequiredState,SymbolsResolvedCallback NotifyComplete)1589510447aSLang Hames AsynchronousSymbolQuery::AsynchronousSymbolQuery(
159674df13bSLang Hames     const SymbolLookupSet &Symbols, SymbolState RequiredState,
160d4a8089fSLang Hames     SymbolsResolvedCallback NotifyComplete)
161d4a8089fSLang Hames     : NotifyComplete(std::move(NotifyComplete)), RequiredState(RequiredState) {
162d4a8089fSLang Hames   assert(RequiredState >= SymbolState::Resolved &&
163d4a8089fSLang Hames          "Cannot query for a symbols that have not reached the resolve state "
164d4a8089fSLang Hames          "yet");
165d4a8089fSLang Hames 
166d4a8089fSLang Hames   OutstandingSymbolsCount = Symbols.size();
167d261e125SLang Hames 
168674df13bSLang Hames   for (auto &KV : Symbols)
169674df13bSLang Hames     ResolvedSymbols[KV.first] = nullptr;
1709510447aSLang Hames }
1719510447aSLang Hames 
notifySymbolMetRequiredState(const SymbolStringPtr & Name,JITEvaluatedSymbol Sym)172d4a8089fSLang Hames void AsynchronousSymbolQuery::notifySymbolMetRequiredState(
173d4a8089fSLang Hames     const SymbolStringPtr &Name, JITEvaluatedSymbol Sym) {
174d261e125SLang Hames   auto I = ResolvedSymbols.find(Name);
175d261e125SLang Hames   assert(I != ResolvedSymbols.end() &&
176d261e125SLang Hames          "Resolving symbol outside the requested set");
177d261e125SLang Hames   assert(I->second.getAddress() == 0 && "Redundantly resolving symbol Name");
178cb84e482SLang Hames 
179cb84e482SLang Hames   // If this is a materialization-side-effects-only symbol then drop it,
180cb84e482SLang Hames   // otherwise update its map entry with its resolved address.
181cb84e482SLang Hames   if (Sym.getFlags().hasMaterializationSideEffectsOnly())
182cb84e482SLang Hames     ResolvedSymbols.erase(I);
183cb84e482SLang Hames   else
184d261e125SLang Hames     I->second = std::move(Sym);
185d4a8089fSLang Hames   --OutstandingSymbolsCount;
1869510447aSLang Hames }
1879510447aSLang Hames 
handleComplete(ExecutionSession & ES)1887f9a89f9SLang Hames void AsynchronousSymbolQuery::handleComplete(ExecutionSession &ES) {
189d4a8089fSLang Hames   assert(OutstandingSymbolsCount == 0 &&
190d4a8089fSLang Hames          "Symbols remain, handleComplete called prematurely");
1918be0d2e3SLang Hames 
1927f9a89f9SLang Hames   class RunQueryCompleteTask : public Task {
1937f9a89f9SLang Hames   public:
1947f9a89f9SLang Hames     RunQueryCompleteTask(SymbolMap ResolvedSymbols,
1957f9a89f9SLang Hames                          SymbolsResolvedCallback NotifyComplete)
1967f9a89f9SLang Hames         : ResolvedSymbols(std::move(ResolvedSymbols)),
1977f9a89f9SLang Hames           NotifyComplete(std::move(NotifyComplete)) {}
1987f9a89f9SLang Hames     void printDescription(raw_ostream &OS) override {
1997f9a89f9SLang Hames       OS << "Execute query complete callback for " << ResolvedSymbols;
2007f9a89f9SLang Hames     }
2017f9a89f9SLang Hames     void run() override { NotifyComplete(std::move(ResolvedSymbols)); }
2027f9a89f9SLang Hames 
2037f9a89f9SLang Hames   private:
2047f9a89f9SLang Hames     SymbolMap ResolvedSymbols;
2057f9a89f9SLang Hames     SymbolsResolvedCallback NotifyComplete;
2067f9a89f9SLang Hames   };
2077f9a89f9SLang Hames 
2087f9a89f9SLang Hames   auto T = std::make_unique<RunQueryCompleteTask>(std::move(ResolvedSymbols),
2097f9a89f9SLang Hames                                                   std::move(NotifyComplete));
210d4a8089fSLang Hames   NotifyComplete = SymbolsResolvedCallback();
2117f9a89f9SLang Hames   ES.dispatchTask(std::move(T));
2128be0d2e3SLang Hames }
2138be0d2e3SLang Hames 
handleFailed(Error Err)214d261e125SLang Hames void AsynchronousSymbolQuery::handleFailed(Error Err) {
215d261e125SLang Hames   assert(QueryRegistrations.empty() && ResolvedSymbols.empty() &&
216d4a8089fSLang Hames          OutstandingSymbolsCount == 0 &&
217d261e125SLang Hames          "Query should already have been abandoned");
218d4a8089fSLang Hames   NotifyComplete(std::move(Err));
219d4a8089fSLang Hames   NotifyComplete = SymbolsResolvedCallback();
220d261e125SLang Hames }
221d261e125SLang Hames 
addQueryDependence(JITDylib & JD,SymbolStringPtr Name)222d5f56c59SLang Hames void AsynchronousSymbolQuery::addQueryDependence(JITDylib &JD,
223d5f56c59SLang Hames                                                  SymbolStringPtr Name) {
224d5f56c59SLang Hames   bool Added = QueryRegistrations[&JD].insert(std::move(Name)).second;
225d261e125SLang Hames   (void)Added;
226d261e125SLang Hames   assert(Added && "Duplicate dependence notification?");
227d261e125SLang Hames }
228d261e125SLang Hames 
removeQueryDependence(JITDylib & JD,const SymbolStringPtr & Name)229d261e125SLang Hames void AsynchronousSymbolQuery::removeQueryDependence(
230d5f56c59SLang Hames     JITDylib &JD, const SymbolStringPtr &Name) {
231d5f56c59SLang Hames   auto QRI = QueryRegistrations.find(&JD);
232d5f56c59SLang Hames   assert(QRI != QueryRegistrations.end() &&
233d5f56c59SLang Hames          "No dependencies registered for JD");
234d5f56c59SLang Hames   assert(QRI->second.count(Name) && "No dependency on Name in JD");
235d261e125SLang Hames   QRI->second.erase(Name);
236d261e125SLang Hames   if (QRI->second.empty())
237d261e125SLang Hames     QueryRegistrations.erase(QRI);
238d261e125SLang Hames }
239d261e125SLang Hames 
dropSymbol(const SymbolStringPtr & Name)240cb84e482SLang Hames void AsynchronousSymbolQuery::dropSymbol(const SymbolStringPtr &Name) {
241cb84e482SLang Hames   auto I = ResolvedSymbols.find(Name);
242cb84e482SLang Hames   assert(I != ResolvedSymbols.end() &&
243cb84e482SLang Hames          "Redundant removal of weakly-referenced symbol");
244cb84e482SLang Hames   ResolvedSymbols.erase(I);
245cb84e482SLang Hames   --OutstandingSymbolsCount;
246cb84e482SLang Hames }
247cb84e482SLang Hames 
detach()248d261e125SLang Hames void AsynchronousSymbolQuery::detach() {
249d261e125SLang Hames   ResolvedSymbols.clear();
250d4a8089fSLang Hames   OutstandingSymbolsCount = 0;
251d261e125SLang Hames   for (auto &KV : QueryRegistrations)
252d261e125SLang Hames     KV.first->detachQueryHelper(*this, KV.second);
253d261e125SLang Hames   QueryRegistrations.clear();
2549510447aSLang Hames }
2559510447aSLang Hames 
AbsoluteSymbolsMaterializationUnit(SymbolMap Symbols)256d261e125SLang Hames AbsoluteSymbolsMaterializationUnit::AbsoluteSymbolsMaterializationUnit(
2570aec49c8SLang Hames     SymbolMap Symbols)
258ae73f3fdSLang Hames     : MaterializationUnit(extractFlags(Symbols)), Symbols(std::move(Symbols)) {}
25967feadb2SLang Hames 
getName() const26046f40a71SLang Hames StringRef AbsoluteSymbolsMaterializationUnit::getName() const {
26146f40a71SLang Hames   return "<Absolute Symbols>";
26246f40a71SLang Hames }
26346f40a71SLang Hames 
materialize(std::unique_ptr<MaterializationResponsibility> R)264d261e125SLang Hames void AbsoluteSymbolsMaterializationUnit::materialize(
2657dcd0042SLang Hames     std::unique_ptr<MaterializationResponsibility> R) {
2667be783abSLang Hames   // Even though these are just absolute symbols we need to check for failure
2677be783abSLang Hames   // to resolve/emit: the tracker for these symbols may have been removed while
2687be783abSLang Hames   // the materialization was in flight (e.g. due to a failure in some action
2697be783abSLang Hames   // triggered by the queries attached to the resolution/emission of these
2707be783abSLang Hames   // symbols).
2717be783abSLang Hames   if (auto Err = R->notifyResolved(Symbols)) {
2727be783abSLang Hames     R->getExecutionSession().reportError(std::move(Err));
2737be783abSLang Hames     R->failMaterialization();
2747be783abSLang Hames     return;
2757be783abSLang Hames   }
2767be783abSLang Hames   if (auto Err = R->notifyEmitted()) {
2777be783abSLang Hames     R->getExecutionSession().reportError(std::move(Err));
2787be783abSLang Hames     R->failMaterialization();
2797be783abSLang Hames     return;
2807be783abSLang Hames   }
28167feadb2SLang Hames }
2829510447aSLang Hames 
discard(const JITDylib & JD,const SymbolStringPtr & Name)283d5f56c59SLang Hames void AbsoluteSymbolsMaterializationUnit::discard(const JITDylib &JD,
284cb5702c3SLang Hames                                                  const SymbolStringPtr &Name) {
285d261e125SLang Hames   assert(Symbols.count(Name) && "Symbol is not part of this MU");
286d261e125SLang Hames   Symbols.erase(Name);
2879510447aSLang Hames }
2889510447aSLang Hames 
289ae73f3fdSLang Hames MaterializationUnit::Interface
extractFlags(const SymbolMap & Symbols)290d261e125SLang Hames AbsoluteSymbolsMaterializationUnit::extractFlags(const SymbolMap &Symbols) {
291d261e125SLang Hames   SymbolFlagsMap Flags;
292d261e125SLang Hames   for (const auto &KV : Symbols)
293d261e125SLang Hames     Flags[KV.first] = KV.second.getFlags();
294ae73f3fdSLang Hames   return MaterializationUnit::Interface(std::move(Flags), nullptr);
2959bbd6530SLang Hames }
2969bbd6530SLang Hames 
ReExportsMaterializationUnit(JITDylib * SourceJD,JITDylibLookupFlags SourceJDLookupFlags,SymbolAliasMap Aliases)297a3c473e6SLang Hames ReExportsMaterializationUnit::ReExportsMaterializationUnit(
298674df13bSLang Hames     JITDylib *SourceJD, JITDylibLookupFlags SourceJDLookupFlags,
2990aec49c8SLang Hames     SymbolAliasMap Aliases)
300ae73f3fdSLang Hames     : MaterializationUnit(extractFlags(Aliases)), SourceJD(SourceJD),
3010aec49c8SLang Hames       SourceJDLookupFlags(SourceJDLookupFlags), Aliases(std::move(Aliases)) {}
302ce72161dSLang Hames 
getName() const30346f40a71SLang Hames StringRef ReExportsMaterializationUnit::getName() const {
30446f40a71SLang Hames   return "<Reexports>";
30546f40a71SLang Hames }
30646f40a71SLang Hames 
materialize(std::unique_ptr<MaterializationResponsibility> R)307a3c473e6SLang Hames void ReExportsMaterializationUnit::materialize(
3087dcd0042SLang Hames     std::unique_ptr<MaterializationResponsibility> R) {
309ce72161dSLang Hames 
3107dcd0042SLang Hames   auto &ES = R->getTargetJITDylib().getExecutionSession();
3117dcd0042SLang Hames   JITDylib &TgtJD = R->getTargetJITDylib();
312d5f56c59SLang Hames   JITDylib &SrcJD = SourceJD ? *SourceJD : TgtJD;
313ce72161dSLang Hames 
314a3c473e6SLang Hames   // Find the set of requested aliases and aliasees. Return any unrequested
315d5f56c59SLang Hames   // aliases back to the JITDylib so as to not prematurely materialize any
316d5f56c59SLang Hames   // aliasees.
3177dcd0042SLang Hames   auto RequestedSymbols = R->getRequestedSymbols();
318a3c473e6SLang Hames   SymbolAliasMap RequestedAliases;
319a3c473e6SLang Hames 
320a3c473e6SLang Hames   for (auto &Name : RequestedSymbols) {
321a3c473e6SLang Hames     auto I = Aliases.find(Name);
322a3c473e6SLang Hames     assert(I != Aliases.end() && "Symbol not found in aliases map?");
323a3c473e6SLang Hames     RequestedAliases[Name] = std::move(I->second);
324a3c473e6SLang Hames     Aliases.erase(I);
325a3c473e6SLang Hames   }
326a3c473e6SLang Hames 
327d4a8089fSLang Hames   LLVM_DEBUG({
328d4a8089fSLang Hames     ES.runSessionLocked([&]() {
329d4a8089fSLang Hames       dbgs() << "materializing reexports: target = " << TgtJD.getName()
330d4a8089fSLang Hames              << ", source = " << SrcJD.getName() << " " << RequestedAliases
331d4a8089fSLang Hames              << "\n";
332d4a8089fSLang Hames     });
333d4a8089fSLang Hames   });
334d4a8089fSLang Hames 
335a3c473e6SLang Hames   if (!Aliases.empty()) {
3360aec49c8SLang Hames     auto Err = SourceJD ? R->replace(reexports(*SourceJD, std::move(Aliases),
3370aec49c8SLang Hames                                                SourceJDLookupFlags))
3380aec49c8SLang Hames                         : R->replace(symbolAliases(std::move(Aliases)));
3390aec49c8SLang Hames 
3400aec49c8SLang Hames     if (Err) {
3410aec49c8SLang Hames       // FIXME: Should this be reported / treated as failure to materialize?
3420aec49c8SLang Hames       // Or should this be treated as a sanctioned bailing-out?
3430aec49c8SLang Hames       ES.reportError(std::move(Err));
3440aec49c8SLang Hames       R->failMaterialization();
3450aec49c8SLang Hames       return;
3460aec49c8SLang Hames     }
347a3c473e6SLang Hames   }
348a3c473e6SLang Hames 
349a3c473e6SLang Hames   // The OnResolveInfo struct will hold the aliases and responsibilty for each
350a3c473e6SLang Hames   // query in the list.
351a3c473e6SLang Hames   struct OnResolveInfo {
3527dcd0042SLang Hames     OnResolveInfo(std::unique_ptr<MaterializationResponsibility> R,
3537dcd0042SLang Hames                   SymbolAliasMap Aliases)
354a3c473e6SLang Hames         : R(std::move(R)), Aliases(std::move(Aliases)) {}
355a3c473e6SLang Hames 
3567dcd0042SLang Hames     std::unique_ptr<MaterializationResponsibility> R;
357a3c473e6SLang Hames     SymbolAliasMap Aliases;
358a3c473e6SLang Hames   };
359a3c473e6SLang Hames 
360cb84e482SLang Hames   // Build a list of queries to issue. In each round we build a query for the
361cb84e482SLang Hames   // largest set of aliases that we can resolve without encountering a chain of
362cb84e482SLang Hames   // aliases (e.g. Foo -> Bar, Bar -> Baz). Such a chain would deadlock as the
363cb84e482SLang Hames   // query would be waiting on a symbol that it itself had to resolve. Creating
364cb84e482SLang Hames   // a new query for each link in such a chain eliminates the possibility of
365cb84e482SLang Hames   // deadlock. In practice chains are likely to be rare, and this algorithm will
366cb84e482SLang Hames   // usually result in a single query to issue.
367a3c473e6SLang Hames 
368674df13bSLang Hames   std::vector<std::pair<SymbolLookupSet, std::shared_ptr<OnResolveInfo>>>
369a3c473e6SLang Hames       QueryInfos;
370a3c473e6SLang Hames   while (!RequestedAliases.empty()) {
371a3c473e6SLang Hames     SymbolNameSet ResponsibilitySymbols;
372674df13bSLang Hames     SymbolLookupSet QuerySymbols;
373a3c473e6SLang Hames     SymbolAliasMap QueryAliases;
374a3c473e6SLang Hames 
3756e66b2a6SLang Hames     // Collect as many aliases as we can without including a chain.
3766e66b2a6SLang Hames     for (auto &KV : RequestedAliases) {
377a3c473e6SLang Hames       // Chain detected. Skip this symbol for this round.
3786e66b2a6SLang Hames       if (&SrcJD == &TgtJD && (QueryAliases.count(KV.second.Aliasee) ||
3796e66b2a6SLang Hames                                RequestedAliases.count(KV.second.Aliasee)))
380a3c473e6SLang Hames         continue;
381a3c473e6SLang Hames 
3826e66b2a6SLang Hames       ResponsibilitySymbols.insert(KV.first);
383cb84e482SLang Hames       QuerySymbols.add(KV.second.Aliasee,
384cb84e482SLang Hames                        KV.second.AliasFlags.hasMaterializationSideEffectsOnly()
385cb84e482SLang Hames                            ? SymbolLookupFlags::WeaklyReferencedSymbol
386cb84e482SLang Hames                            : SymbolLookupFlags::RequiredSymbol);
3876e66b2a6SLang Hames       QueryAliases[KV.first] = std::move(KV.second);
388a3c473e6SLang Hames     }
3896e66b2a6SLang Hames 
3906e66b2a6SLang Hames     // Remove the aliases collected this round from the RequestedAliases map.
3916e66b2a6SLang Hames     for (auto &KV : QueryAliases)
3926e66b2a6SLang Hames       RequestedAliases.erase(KV.first);
3936e66b2a6SLang Hames 
394a3c473e6SLang Hames     assert(!QuerySymbols.empty() && "Alias cycle detected!");
395a3c473e6SLang Hames 
3960aec49c8SLang Hames     auto NewR = R->delegate(ResponsibilitySymbols);
3970aec49c8SLang Hames     if (!NewR) {
3980aec49c8SLang Hames       ES.reportError(NewR.takeError());
3990aec49c8SLang Hames       R->failMaterialization();
4000aec49c8SLang Hames       return;
4010aec49c8SLang Hames     }
4020aec49c8SLang Hames 
4030aec49c8SLang Hames     auto QueryInfo = std::make_shared<OnResolveInfo>(std::move(*NewR),
4040aec49c8SLang Hames                                                      std::move(QueryAliases));
405a3c473e6SLang Hames     QueryInfos.push_back(
406a3c473e6SLang Hames         make_pair(std::move(QuerySymbols), std::move(QueryInfo)));
407a3c473e6SLang Hames   }
408a3c473e6SLang Hames 
409a3c473e6SLang Hames   // Issue the queries.
410a3c473e6SLang Hames   while (!QueryInfos.empty()) {
411a3c473e6SLang Hames     auto QuerySymbols = std::move(QueryInfos.back().first);
412a3c473e6SLang Hames     auto QueryInfo = std::move(QueryInfos.back().second);
413a3c473e6SLang Hames 
414a3c473e6SLang Hames     QueryInfos.pop_back();
415a3c473e6SLang Hames 
416960246dbSLang Hames     auto RegisterDependencies = [QueryInfo,
417d5f56c59SLang Hames                                  &SrcJD](const SymbolDependenceMap &Deps) {
418960246dbSLang Hames       // If there were no materializing symbols, just bail out.
419960246dbSLang Hames       if (Deps.empty())
420960246dbSLang Hames         return;
421960246dbSLang Hames 
422d5f56c59SLang Hames       // Otherwise the only deps should be on SrcJD.
423d5f56c59SLang Hames       assert(Deps.size() == 1 && Deps.count(&SrcJD) &&
424960246dbSLang Hames              "Unexpected dependencies for reexports");
425960246dbSLang Hames 
426d5f56c59SLang Hames       auto &SrcJDDeps = Deps.find(&SrcJD)->second;
427960246dbSLang Hames       SymbolDependenceMap PerAliasDepsMap;
428d5f56c59SLang Hames       auto &PerAliasDeps = PerAliasDepsMap[&SrcJD];
429960246dbSLang Hames 
430960246dbSLang Hames       for (auto &KV : QueryInfo->Aliases)
431d5f56c59SLang Hames         if (SrcJDDeps.count(KV.second.Aliasee)) {
432960246dbSLang Hames           PerAliasDeps = {KV.second.Aliasee};
4337dcd0042SLang Hames           QueryInfo->R->addDependencies(KV.first, PerAliasDepsMap);
434960246dbSLang Hames         }
435a48d1083SLang Hames     };
436a48d1083SLang Hames 
437d4a8089fSLang Hames     auto OnComplete = [QueryInfo](Expected<SymbolMap> Result) {
4387dcd0042SLang Hames       auto &ES = QueryInfo->R->getTargetJITDylib().getExecutionSession();
439a48d1083SLang Hames       if (Result) {
440ce72161dSLang Hames         SymbolMap ResolutionMap;
441a3c473e6SLang Hames         for (auto &KV : QueryInfo->Aliases) {
442cb84e482SLang Hames           assert((KV.second.AliasFlags.hasMaterializationSideEffectsOnly() ||
443cb84e482SLang Hames                   Result->count(KV.second.Aliasee)) &&
444ce72161dSLang Hames                  "Result map missing entry?");
445cb84e482SLang Hames           // Don't try to resolve materialization-side-effects-only symbols.
446cb84e482SLang Hames           if (KV.second.AliasFlags.hasMaterializationSideEffectsOnly())
447cb84e482SLang Hames             continue;
448cb84e482SLang Hames 
449ce72161dSLang Hames           ResolutionMap[KV.first] = JITEvaluatedSymbol(
450a48d1083SLang Hames               (*Result)[KV.second.Aliasee].getAddress(), KV.second.AliasFlags);
451a3c473e6SLang Hames         }
4527dcd0042SLang Hames         if (auto Err = QueryInfo->R->notifyResolved(ResolutionMap)) {
453e00585c7SLang Hames           ES.reportError(std::move(Err));
4547dcd0042SLang Hames           QueryInfo->R->failMaterialization();
455e00585c7SLang Hames           return;
456e00585c7SLang Hames         }
4577dcd0042SLang Hames         if (auto Err = QueryInfo->R->notifyEmitted()) {
458e00585c7SLang Hames           ES.reportError(std::move(Err));
4597dcd0042SLang Hames           QueryInfo->R->failMaterialization();
460e00585c7SLang Hames           return;
461e00585c7SLang Hames         }
462ce72161dSLang Hames       } else {
463a48d1083SLang Hames         ES.reportError(Result.takeError());
4647dcd0042SLang Hames         QueryInfo->R->failMaterialization();
465ce72161dSLang Hames       }
466ce72161dSLang Hames     };
467ce72161dSLang Hames 
468674df13bSLang Hames     ES.lookup(LookupKind::Static,
469674df13bSLang Hames               JITDylibSearchOrder({{&SrcJD, SourceJDLookupFlags}}),
470674df13bSLang Hames               QuerySymbols, SymbolState::Resolved, std::move(OnComplete),
47123cb2e7fSLang Hames               std::move(RegisterDependencies));
472a3c473e6SLang Hames   }
473ce72161dSLang Hames }
474ce72161dSLang Hames 
discard(const JITDylib & JD,const SymbolStringPtr & Name)475d5f56c59SLang Hames void ReExportsMaterializationUnit::discard(const JITDylib &JD,
476cb5702c3SLang Hames                                            const SymbolStringPtr &Name) {
477ce72161dSLang Hames   assert(Aliases.count(Name) &&
478ce72161dSLang Hames          "Symbol not covered by this MaterializationUnit");
479ce72161dSLang Hames   Aliases.erase(Name);
480ce72161dSLang Hames }
481ce72161dSLang Hames 
482ae73f3fdSLang Hames MaterializationUnit::Interface
extractFlags(const SymbolAliasMap & Aliases)483a3c473e6SLang Hames ReExportsMaterializationUnit::extractFlags(const SymbolAliasMap &Aliases) {
484ce72161dSLang Hames   SymbolFlagsMap SymbolFlags;
485ce72161dSLang Hames   for (auto &KV : Aliases)
486ce72161dSLang Hames     SymbolFlags[KV.first] = KV.second.AliasFlags;
487ce72161dSLang Hames 
488ae73f3fdSLang Hames   return MaterializationUnit::Interface(std::move(SymbolFlags), nullptr);
489ce72161dSLang Hames }
490ce72161dSLang Hames 
buildSimpleReexportsAliasMap(JITDylib & SourceJD,SymbolNameSet Symbols)491069919c9SLang Hames Expected<SymbolAliasMap> buildSimpleReexportsAliasMap(JITDylib &SourceJD,
492069919c9SLang Hames                                                       SymbolNameSet Symbols) {
493674df13bSLang Hames   SymbolLookupSet LookupSet(Symbols);
494069919c9SLang Hames   auto Flags = SourceJD.getExecutionSession().lookupFlags(
495069919c9SLang Hames       LookupKind::Static, {{&SourceJD, JITDylibLookupFlags::MatchAllSymbols}},
496069919c9SLang Hames       SymbolLookupSet(std::move(Symbols)));
497a3c473e6SLang Hames 
498b1286723SLang Hames   if (!Flags)
499b1286723SLang Hames     return Flags.takeError();
500b1286723SLang Hames 
501a3c473e6SLang Hames   SymbolAliasMap Result;
502a3c473e6SLang Hames   for (auto &Name : Symbols) {
503b1286723SLang Hames     assert(Flags->count(Name) && "Missing entry in flags map");
504b1286723SLang Hames     Result[Name] = SymbolAliasMapEntry(Name, (*Flags)[Name]);
505a3c473e6SLang Hames   }
506a3c473e6SLang Hames 
507a3c473e6SLang Hames   return Result;
508a3c473e6SLang Hames }
509a3c473e6SLang Hames 
510069919c9SLang Hames class InProgressLookupState {
511069919c9SLang Hames public:
512d27e4bceSLang Hames   // FIXME: Reduce the number of SymbolStringPtrs here. See
513d27e4bceSLang Hames   //        https://github.com/llvm/llvm-project/issues/55576.
514d27e4bceSLang Hames 
InProgressLookupState(LookupKind K,JITDylibSearchOrder SearchOrder,SymbolLookupSet LookupSet,SymbolState RequiredState)515069919c9SLang Hames   InProgressLookupState(LookupKind K, JITDylibSearchOrder SearchOrder,
516069919c9SLang Hames                         SymbolLookupSet LookupSet, SymbolState RequiredState)
517069919c9SLang Hames       : K(K), SearchOrder(std::move(SearchOrder)),
518069919c9SLang Hames         LookupSet(std::move(LookupSet)), RequiredState(RequiredState) {
519069919c9SLang Hames     DefGeneratorCandidates = this->LookupSet;
520069919c9SLang Hames   }
5213a3cb929SKazu Hirata   virtual ~InProgressLookupState() = default;
522069919c9SLang Hames   virtual void complete(std::unique_ptr<InProgressLookupState> IPLS) = 0;
523069919c9SLang Hames   virtual void fail(Error Err) = 0;
524069919c9SLang Hames 
525069919c9SLang Hames   LookupKind K;
526069919c9SLang Hames   JITDylibSearchOrder SearchOrder;
527069919c9SLang Hames   SymbolLookupSet LookupSet;
528069919c9SLang Hames   SymbolState RequiredState;
529069919c9SLang Hames 
530069919c9SLang Hames   std::unique_lock<std::mutex> GeneratorLock;
531069919c9SLang Hames   size_t CurSearchOrderIndex = 0;
532069919c9SLang Hames   bool NewJITDylib = true;
533069919c9SLang Hames   SymbolLookupSet DefGeneratorCandidates;
534069919c9SLang Hames   SymbolLookupSet DefGeneratorNonCandidates;
535069919c9SLang Hames   std::vector<std::weak_ptr<DefinitionGenerator>> CurDefGeneratorStack;
536069919c9SLang Hames };
537069919c9SLang Hames 
538069919c9SLang Hames class InProgressLookupFlagsState : public InProgressLookupState {
539069919c9SLang Hames public:
InProgressLookupFlagsState(LookupKind K,JITDylibSearchOrder SearchOrder,SymbolLookupSet LookupSet,unique_function<void (Expected<SymbolFlagsMap>)> OnComplete)540069919c9SLang Hames   InProgressLookupFlagsState(
541069919c9SLang Hames       LookupKind K, JITDylibSearchOrder SearchOrder, SymbolLookupSet LookupSet,
542069919c9SLang Hames       unique_function<void(Expected<SymbolFlagsMap>)> OnComplete)
543069919c9SLang Hames       : InProgressLookupState(K, std::move(SearchOrder), std::move(LookupSet),
544069919c9SLang Hames                               SymbolState::NeverSearched),
545069919c9SLang Hames         OnComplete(std::move(OnComplete)) {}
546069919c9SLang Hames 
complete(std::unique_ptr<InProgressLookupState> IPLS)547069919c9SLang Hames   void complete(std::unique_ptr<InProgressLookupState> IPLS) override {
548069919c9SLang Hames     GeneratorLock = {}; // Unlock and release.
549069919c9SLang Hames     auto &ES = SearchOrder.front().first->getExecutionSession();
550069919c9SLang Hames     ES.OL_completeLookupFlags(std::move(IPLS), std::move(OnComplete));
551069919c9SLang Hames   }
552069919c9SLang Hames 
fail(Error Err)553069919c9SLang Hames   void fail(Error Err) override {
554069919c9SLang Hames     GeneratorLock = {}; // Unlock and release.
555069919c9SLang Hames     OnComplete(std::move(Err));
556069919c9SLang Hames   }
557069919c9SLang Hames 
558069919c9SLang Hames private:
559069919c9SLang Hames   unique_function<void(Expected<SymbolFlagsMap>)> OnComplete;
560069919c9SLang Hames };
561069919c9SLang Hames 
562069919c9SLang Hames class InProgressFullLookupState : public InProgressLookupState {
563069919c9SLang Hames public:
InProgressFullLookupState(LookupKind K,JITDylibSearchOrder SearchOrder,SymbolLookupSet LookupSet,SymbolState RequiredState,std::shared_ptr<AsynchronousSymbolQuery> Q,RegisterDependenciesFunction RegisterDependencies)564069919c9SLang Hames   InProgressFullLookupState(LookupKind K, JITDylibSearchOrder SearchOrder,
565069919c9SLang Hames                             SymbolLookupSet LookupSet,
566069919c9SLang Hames                             SymbolState RequiredState,
567069919c9SLang Hames                             std::shared_ptr<AsynchronousSymbolQuery> Q,
568069919c9SLang Hames                             RegisterDependenciesFunction RegisterDependencies)
569069919c9SLang Hames       : InProgressLookupState(K, std::move(SearchOrder), std::move(LookupSet),
570069919c9SLang Hames                               RequiredState),
571069919c9SLang Hames         Q(std::move(Q)), RegisterDependencies(std::move(RegisterDependencies)) {
572069919c9SLang Hames   }
573069919c9SLang Hames 
complete(std::unique_ptr<InProgressLookupState> IPLS)574069919c9SLang Hames   void complete(std::unique_ptr<InProgressLookupState> IPLS) override {
575069919c9SLang Hames     GeneratorLock = {}; // Unlock and release.
576069919c9SLang Hames     auto &ES = SearchOrder.front().first->getExecutionSession();
577069919c9SLang Hames     ES.OL_completeLookup(std::move(IPLS), std::move(Q),
578069919c9SLang Hames                          std::move(RegisterDependencies));
579069919c9SLang Hames   }
580069919c9SLang Hames 
fail(Error Err)581069919c9SLang Hames   void fail(Error Err) override {
582069919c9SLang Hames     GeneratorLock = {};
583069919c9SLang Hames     Q->detach();
584069919c9SLang Hames     Q->handleFailed(std::move(Err));
585069919c9SLang Hames   }
586069919c9SLang Hames 
587069919c9SLang Hames private:
588069919c9SLang Hames   std::shared_ptr<AsynchronousSymbolQuery> Q;
589069919c9SLang Hames   RegisterDependenciesFunction RegisterDependencies;
590069919c9SLang Hames };
591069919c9SLang Hames 
ReexportsGenerator(JITDylib & SourceJD,JITDylibLookupFlags SourceJDLookupFlags,SymbolPredicate Allow)592a5157d6fSLang Hames ReexportsGenerator::ReexportsGenerator(JITDylib &SourceJD,
593674df13bSLang Hames                                        JITDylibLookupFlags SourceJDLookupFlags,
594a5157d6fSLang Hames                                        SymbolPredicate Allow)
595674df13bSLang Hames     : SourceJD(SourceJD), SourceJDLookupFlags(SourceJDLookupFlags),
59623cb2e7fSLang Hames       Allow(std::move(Allow)) {}
597be1066deSLang Hames 
tryToGenerate(LookupState & LS,LookupKind K,JITDylib & JD,JITDylibLookupFlags JDLookupFlags,const SymbolLookupSet & LookupSet)598069919c9SLang Hames Error ReexportsGenerator::tryToGenerate(LookupState &LS, LookupKind K,
599069919c9SLang Hames                                         JITDylib &JD,
600674df13bSLang Hames                                         JITDylibLookupFlags JDLookupFlags,
601674df13bSLang Hames                                         const SymbolLookupSet &LookupSet) {
602674df13bSLang Hames   assert(&JD != &SourceJD && "Cannot re-export from the same dylib");
603be1066deSLang Hames 
604674df13bSLang Hames   // Use lookupFlags to find the subset of symbols that match our lookup.
605069919c9SLang Hames   auto Flags = JD.getExecutionSession().lookupFlags(
606069919c9SLang Hames       K, {{&SourceJD, JDLookupFlags}}, LookupSet);
607b1286723SLang Hames   if (!Flags)
608b1286723SLang Hames     return Flags.takeError();
609b1286723SLang Hames 
610674df13bSLang Hames   // Create an alias map.
611674df13bSLang Hames   orc::SymbolAliasMap AliasMap;
612674df13bSLang Hames   for (auto &KV : *Flags)
613674df13bSLang Hames     if (!Allow || Allow(KV.first))
614be1066deSLang Hames       AliasMap[KV.first] = SymbolAliasMapEntry(KV.first, KV.second);
615be1066deSLang Hames 
616674df13bSLang Hames   if (AliasMap.empty())
617674df13bSLang Hames     return Error::success();
618be1066deSLang Hames 
619674df13bSLang Hames   // Define the re-exports.
620674df13bSLang Hames   return JD.define(reexports(SourceJD, AliasMap, SourceJDLookupFlags));
621be1066deSLang Hames }
622be1066deSLang Hames 
LookupState(std::unique_ptr<InProgressLookupState> IPLS)623069919c9SLang Hames LookupState::LookupState(std::unique_ptr<InProgressLookupState> IPLS)
624069919c9SLang Hames     : IPLS(std::move(IPLS)) {}
625069919c9SLang Hames 
reset(InProgressLookupState * IPLS)626b6ca0c7dSLang Hames void LookupState::reset(InProgressLookupState *IPLS) { this->IPLS.reset(IPLS); }
627b6ca0c7dSLang Hames 
628cd8a80deSLang Hames LookupState::LookupState() = default;
629cd8a80deSLang Hames LookupState::LookupState(LookupState &&) = default;
630cd8a80deSLang Hames LookupState &LookupState::operator=(LookupState &&) = default;
631cd8a80deSLang Hames LookupState::~LookupState() = default;
632b6ca0c7dSLang Hames 
continueLookup(Error Err)633069919c9SLang Hames void LookupState::continueLookup(Error Err) {
634069919c9SLang Hames   assert(IPLS && "Cannot call continueLookup on empty LookupState");
635069919c9SLang Hames   auto &ES = IPLS->SearchOrder.begin()->first->getExecutionSession();
636069919c9SLang Hames   ES.OL_applyQueryPhase1(std::move(IPLS), std::move(Err));
637069919c9SLang Hames }
638069919c9SLang Hames 
6393a3cb929SKazu Hirata DefinitionGenerator::~DefinitionGenerator() = default;
64052a34a78SLang Hames 
~JITDylib()641758d54b4SLang Hames JITDylib::~JITDylib() {
642758d54b4SLang Hames   LLVM_DEBUG(dbgs() << "Destroying JITDylib " << getName() << "\n");
643758d54b4SLang Hames }
644758d54b4SLang Hames 
clear()6450aec49c8SLang Hames Error JITDylib::clear() {
6460aec49c8SLang Hames   std::vector<ResourceTrackerSP> TrackersToRemove;
6470aec49c8SLang Hames   ES.runSessionLocked([&]() {
648758d54b4SLang Hames     assert(State != Closed && "JD is defunct");
6490aec49c8SLang Hames     for (auto &KV : TrackerSymbols)
6500aec49c8SLang Hames       TrackersToRemove.push_back(KV.first);
6510aec49c8SLang Hames     TrackersToRemove.push_back(getDefaultResourceTracker());
6520aec49c8SLang Hames   });
6530aec49c8SLang Hames 
6540aec49c8SLang Hames   Error Err = Error::success();
6550aec49c8SLang Hames   for (auto &RT : TrackersToRemove)
6560aec49c8SLang Hames     Err = joinErrors(std::move(Err), RT->remove());
6570aec49c8SLang Hames   return Err;
6580aec49c8SLang Hames }
6590aec49c8SLang Hames 
getDefaultResourceTracker()6600aec49c8SLang Hames ResourceTrackerSP JITDylib::getDefaultResourceTracker() {
6610aec49c8SLang Hames   return ES.runSessionLocked([this] {
662758d54b4SLang Hames     assert(State != Closed && "JD is defunct");
6630aec49c8SLang Hames     if (!DefaultTracker)
6640aec49c8SLang Hames       DefaultTracker = new ResourceTracker(this);
6650aec49c8SLang Hames     return DefaultTracker;
6660aec49c8SLang Hames   });
6670aec49c8SLang Hames }
6680aec49c8SLang Hames 
createResourceTracker()6690aec49c8SLang Hames ResourceTrackerSP JITDylib::createResourceTracker() {
6700aec49c8SLang Hames   return ES.runSessionLocked([this] {
671758d54b4SLang Hames     assert(State == Open && "JD is defunct");
6720aec49c8SLang Hames     ResourceTrackerSP RT = new ResourceTracker(this);
6730aec49c8SLang Hames     return RT;
6740aec49c8SLang Hames   });
6750aec49c8SLang Hames }
6760aec49c8SLang Hames 
removeGenerator(DefinitionGenerator & G)67752a34a78SLang Hames void JITDylib::removeGenerator(DefinitionGenerator &G) {
6789eb591f0SLang Hames   ES.runSessionLocked([&] {
679758d54b4SLang Hames     assert(State == Open && "JD is defunct");
68089e8eb94SKazu Hirata     auto I = llvm::find_if(DefGenerators,
681069919c9SLang Hames                            [&](const std::shared_ptr<DefinitionGenerator> &H) {
68252a34a78SLang Hames                              return H.get() == &G;
68352a34a78SLang Hames                            });
68452a34a78SLang Hames     assert(I != DefGenerators.end() && "Generator not found");
68552a34a78SLang Hames     DefGenerators.erase(I);
6869eb591f0SLang Hames   });
68752a34a78SLang Hames }
68852a34a78SLang Hames 
68984217ad6SLang Hames Expected<SymbolFlagsMap>
defineMaterializing(SymbolFlagsMap SymbolFlags)69084217ad6SLang Hames JITDylib::defineMaterializing(SymbolFlagsMap SymbolFlags) {
69184217ad6SLang Hames 
69284217ad6SLang Hames   return ES.runSessionLocked([&]() -> Expected<SymbolFlagsMap> {
693eb5ee300SLang Hames     std::vector<SymbolTable::iterator> AddedSyms;
69484217ad6SLang Hames     std::vector<SymbolFlagsMap::iterator> RejectedWeakDefs;
69567feadb2SLang Hames 
69684217ad6SLang Hames     for (auto SFItr = SymbolFlags.begin(), SFEnd = SymbolFlags.end();
69784217ad6SLang Hames          SFItr != SFEnd; ++SFItr) {
69867feadb2SLang Hames 
69984217ad6SLang Hames       auto &Name = SFItr->first;
70084217ad6SLang Hames       auto &Flags = SFItr->second;
7019510447aSLang Hames 
70284217ad6SLang Hames       auto EntryItr = Symbols.find(Name);
70384217ad6SLang Hames 
70484217ad6SLang Hames       // If the entry already exists...
70584217ad6SLang Hames       if (EntryItr != Symbols.end()) {
70684217ad6SLang Hames 
70784217ad6SLang Hames         // If this is a strong definition then error out.
70884217ad6SLang Hames         if (!Flags.isWeak()) {
709d261e125SLang Hames           // Remove any symbols already added.
710d261e125SLang Hames           for (auto &SI : AddedSyms)
711d261e125SLang Hames             Symbols.erase(SI);
7129d8877baSLang Hames 
713d261e125SLang Hames           // FIXME: Return all duplicates.
714adcd0268SBenjamin Kramer           return make_error<DuplicateDefinition>(std::string(*Name));
7159d8877baSLang Hames         }
7169d8877baSLang Hames 
71784217ad6SLang Hames         // Otherwise just make a note to discard this symbol after the loop.
71884217ad6SLang Hames         RejectedWeakDefs.push_back(SFItr);
71984217ad6SLang Hames         continue;
72084217ad6SLang Hames       } else
72184217ad6SLang Hames         EntryItr =
72284217ad6SLang Hames           Symbols.insert(std::make_pair(Name, SymbolTableEntry(Flags))).first;
72384217ad6SLang Hames 
72484217ad6SLang Hames       AddedSyms.push_back(EntryItr);
72584217ad6SLang Hames       EntryItr->second.setState(SymbolState::Materializing);
72684217ad6SLang Hames     }
72784217ad6SLang Hames 
72884217ad6SLang Hames     // Remove any rejected weak definitions from the SymbolFlags map.
72984217ad6SLang Hames     while (!RejectedWeakDefs.empty()) {
73084217ad6SLang Hames       SymbolFlags.erase(RejectedWeakDefs.back());
73184217ad6SLang Hames       RejectedWeakDefs.pop_back();
73284217ad6SLang Hames     }
73384217ad6SLang Hames 
73484217ad6SLang Hames     return SymbolFlags;
735d261e125SLang Hames   });
7369510447aSLang Hames }
7379510447aSLang Hames 
replace(MaterializationResponsibility & FromMR,std::unique_ptr<MaterializationUnit> MU)7380aec49c8SLang Hames Error JITDylib::replace(MaterializationResponsibility &FromMR,
7390aec49c8SLang Hames                         std::unique_ptr<MaterializationUnit> MU) {
740d261e125SLang Hames   assert(MU != nullptr && "Can not replace with a null MaterializationUnit");
7410aec49c8SLang Hames   std::unique_ptr<MaterializationUnit> MustRunMU;
7420aec49c8SLang Hames   std::unique_ptr<MaterializationResponsibility> MustRunMR;
7439bbd6530SLang Hames 
7440aec49c8SLang Hames   auto Err =
7450aec49c8SLang Hames       ES.runSessionLocked([&, this]() -> Error {
7469355d115SLang Hames         if (FromMR.RT->isDefunct())
7479355d115SLang Hames           return make_error<ResourceTrackerDefunct>(std::move(FromMR.RT));
7489bbd6530SLang Hames 
749d261e125SLang Hames #ifndef NDEBUG
750d261e125SLang Hames         for (auto &KV : MU->getSymbols()) {
751d261e125SLang Hames           auto SymI = Symbols.find(KV.first);
752d261e125SLang Hames           assert(SymI != Symbols.end() && "Replacing unknown symbol");
753b7aa1cc3SLang Hames           assert(SymI->second.getState() == SymbolState::Materializing &&
754b7aa1cc3SLang Hames                  "Can not replace a symbol that ha is not materializing");
755eb5ee300SLang Hames           assert(!SymI->second.hasMaterializerAttached() &&
756eb5ee300SLang Hames                  "Symbol should not have materializer attached already");
757d261e125SLang Hames           assert(UnmaterializedInfos.count(KV.first) == 0 &&
758d261e125SLang Hames                  "Symbol being replaced should have no UnmaterializedInfo");
759d261e125SLang Hames         }
760d261e125SLang Hames #endif // NDEBUG
761d261e125SLang Hames 
7620aec49c8SLang Hames         // If the tracker is defunct we need to bail out immediately.
7630aec49c8SLang Hames 
764d261e125SLang Hames         // If any symbol has pending queries against it then we need to
765d261e125SLang Hames         // materialize MU immediately.
7666fe6616cSLang Hames         for (auto &KV : MU->getSymbols()) {
7676fe6616cSLang Hames           auto MII = MaterializingInfos.find(KV.first);
7686fe6616cSLang Hames           if (MII != MaterializingInfos.end()) {
7690aec49c8SLang Hames             if (MII->second.hasQueriesPending()) {
7700aec49c8SLang Hames               MustRunMR = ES.createMaterializationResponsibility(
7719355d115SLang Hames                   *FromMR.RT, std::move(MU->SymbolFlags),
7729355d115SLang Hames                   std::move(MU->InitSymbol));
7730aec49c8SLang Hames               MustRunMU = std::move(MU);
7740aec49c8SLang Hames               return Error::success();
7750aec49c8SLang Hames             }
7766fe6616cSLang Hames           }
7776fe6616cSLang Hames         }
778d261e125SLang Hames 
779d261e125SLang Hames         // Otherwise, make MU responsible for all the symbols.
7809355d115SLang Hames         auto UMI = std::make_shared<UnmaterializedInfo>(std::move(MU),
7819355d115SLang Hames                                                         FromMR.RT.get());
782d261e125SLang Hames         for (auto &KV : UMI->MU->getSymbols()) {
783d261e125SLang Hames           auto SymI = Symbols.find(KV.first);
784eb5ee300SLang Hames           assert(SymI->second.getState() == SymbolState::Materializing &&
785eb5ee300SLang Hames                  "Can not replace a symbol that is not materializing");
786eb5ee300SLang Hames           assert(!SymI->second.hasMaterializerAttached() &&
787eb5ee300SLang Hames                  "Can not replace a symbol that has a materializer attached");
788eb5ee300SLang Hames           assert(UnmaterializedInfos.count(KV.first) == 0 &&
789eb5ee300SLang Hames                  "Unexpected materializer entry in map");
790eb5ee300SLang Hames           SymI->second.setAddress(SymI->second.getAddress());
791eb5ee300SLang Hames           SymI->second.setMaterializerAttached(true);
792cd34c057SLang Hames 
793cd34c057SLang Hames           auto &UMIEntry = UnmaterializedInfos[KV.first];
794cd34c057SLang Hames           assert((!UMIEntry || !UMIEntry->MU) &&
795cd34c057SLang Hames                  "Replacing symbol with materializer still attached");
796cd34c057SLang Hames           UMIEntry = UMI;
797d261e125SLang Hames         }
798d261e125SLang Hames 
7990aec49c8SLang Hames         return Error::success();
800d261e125SLang Hames       });
801d261e125SLang Hames 
8020aec49c8SLang Hames   if (Err)
8030aec49c8SLang Hames     return Err;
8040aec49c8SLang Hames 
80541379f1eSLang Hames   if (MustRunMU) {
8060aec49c8SLang Hames     assert(MustRunMR && "MustRunMU set implies MustRunMR set");
8075344c88dSLang Hames     ES.dispatchTask(std::make_unique<MaterializationTask>(
8085344c88dSLang Hames         std::move(MustRunMU), std::move(MustRunMR)));
8090aec49c8SLang Hames   } else {
8100aec49c8SLang Hames     assert(!MustRunMR && "MustRunMU unset implies MustRunMR unset");
81141379f1eSLang Hames   }
8120aec49c8SLang Hames 
8130aec49c8SLang Hames   return Error::success();
8140aec49c8SLang Hames }
8150aec49c8SLang Hames 
8160aec49c8SLang Hames Expected<std::unique_ptr<MaterializationResponsibility>>
delegate(MaterializationResponsibility & FromMR,SymbolFlagsMap SymbolFlags,SymbolStringPtr InitSymbol)8170aec49c8SLang Hames JITDylib::delegate(MaterializationResponsibility &FromMR,
8180aec49c8SLang Hames                    SymbolFlagsMap SymbolFlags, SymbolStringPtr InitSymbol) {
8190aec49c8SLang Hames 
8200aec49c8SLang Hames   return ES.runSessionLocked(
8210aec49c8SLang Hames       [&]() -> Expected<std::unique_ptr<MaterializationResponsibility>> {
8229355d115SLang Hames         if (FromMR.RT->isDefunct())
8239355d115SLang Hames           return make_error<ResourceTrackerDefunct>(std::move(FromMR.RT));
8240aec49c8SLang Hames 
8250aec49c8SLang Hames         return ES.createMaterializationResponsibility(
8269355d115SLang Hames             *FromMR.RT, std::move(SymbolFlags), std::move(InitSymbol));
8270aec49c8SLang Hames       });
828d261e125SLang Hames }
829d261e125SLang Hames 
8302afc22edSLang Hames SymbolNameSet
getRequestedSymbols(const SymbolFlagsMap & SymbolFlags) const8312afc22edSLang Hames JITDylib::getRequestedSymbols(const SymbolFlagsMap &SymbolFlags) const {
8326fe6616cSLang Hames   return ES.runSessionLocked([&]() {
8336fe6616cSLang Hames     SymbolNameSet RequestedSymbols;
8346fe6616cSLang Hames 
8356fe6616cSLang Hames     for (auto &KV : SymbolFlags) {
836d5f56c59SLang Hames       assert(Symbols.count(KV.first) && "JITDylib does not cover this symbol?");
837b7aa1cc3SLang Hames       assert(Symbols.find(KV.first)->second.getState() !=
838b7aa1cc3SLang Hames                  SymbolState::NeverSearched &&
839b7aa1cc3SLang Hames              Symbols.find(KV.first)->second.getState() != SymbolState::Ready &&
840eb5ee300SLang Hames              "getRequestedSymbols can only be called for symbols that have "
841eb5ee300SLang Hames              "started materializing");
8426fe6616cSLang Hames       auto I = MaterializingInfos.find(KV.first);
8436fe6616cSLang Hames       if (I == MaterializingInfos.end())
8446fe6616cSLang Hames         continue;
8456fe6616cSLang Hames 
846d4a8089fSLang Hames       if (I->second.hasQueriesPending())
8476fe6616cSLang Hames         RequestedSymbols.insert(KV.first);
8486fe6616cSLang Hames     }
8496fe6616cSLang Hames 
8506fe6616cSLang Hames     return RequestedSymbols;
8516fe6616cSLang Hames   });
8526fe6616cSLang Hames }
8536fe6616cSLang Hames 
addDependencies(const SymbolStringPtr & Name,const SymbolDependenceMap & Dependencies)854d5f56c59SLang Hames void JITDylib::addDependencies(const SymbolStringPtr &Name,
855d261e125SLang Hames                                const SymbolDependenceMap &Dependencies) {
856aaf026d9SLang Hames   ES.runSessionLocked([&]() {
857d261e125SLang Hames     assert(Symbols.count(Name) && "Name not in symbol table");
858b7aa1cc3SLang Hames     assert(Symbols[Name].getState() < SymbolState::Emitted &&
859eb5ee300SLang Hames            "Can not add dependencies for a symbol that is not materializing");
860d261e125SLang Hames 
86186787f15SLang Hames     LLVM_DEBUG({
862aaf026d9SLang Hames       dbgs() << "In " << getName() << " adding dependencies for " << *Name
863aaf026d9SLang Hames              << ": " << Dependencies << "\n";
86486787f15SLang Hames     });
86586787f15SLang Hames 
866e00585c7SLang Hames     // If Name is already in an error state then just bail out.
867e00585c7SLang Hames     if (Symbols[Name].getFlags().hasError())
868e00585c7SLang Hames       return;
869e00585c7SLang Hames 
870d261e125SLang Hames     auto &MI = MaterializingInfos[Name];
8718853ac7eSLang Hames     assert(Symbols[Name].getState() != SymbolState::Emitted &&
8728853ac7eSLang Hames            "Can not add dependencies to an emitted symbol");
873d261e125SLang Hames 
874e00585c7SLang Hames     bool DependsOnSymbolInErrorState = false;
875e00585c7SLang Hames 
876e00585c7SLang Hames     // Register dependencies, record whether any depenendency is in the error
877e00585c7SLang Hames     // state.
878d261e125SLang Hames     for (auto &KV : Dependencies) {
879d5f56c59SLang Hames       assert(KV.first && "Null JITDylib in dependency?");
880d5f56c59SLang Hames       auto &OtherJITDylib = *KV.first;
88176e21c97SLang Hames       auto &DepsOnOtherJITDylib = MI.UnemittedDependencies[&OtherJITDylib];
882d261e125SLang Hames 
883d261e125SLang Hames       for (auto &OtherSymbol : KV.second) {
884e00585c7SLang Hames 
885e00585c7SLang Hames         // Check the sym entry for the dependency.
8868853ac7eSLang Hames         auto OtherSymI = OtherJITDylib.Symbols.find(OtherSymbol);
887e00585c7SLang Hames 
8888853ac7eSLang Hames         // Assert that this symbol exists and has not reached the ready state
8898853ac7eSLang Hames         // already.
8908853ac7eSLang Hames         assert(OtherSymI != OtherJITDylib.Symbols.end() &&
891b1980164SLang Hames                "Dependency on unknown symbol");
892960246dbSLang Hames 
8938853ac7eSLang Hames         auto &OtherSymEntry = OtherSymI->second;
8948853ac7eSLang Hames 
895b1980164SLang Hames         // If the other symbol is already in the Ready state then there's no
896b1980164SLang Hames         // dependency to add.
897b1980164SLang Hames         if (OtherSymEntry.getState() == SymbolState::Ready)
898b1980164SLang Hames           continue;
899b1980164SLang Hames 
900e00585c7SLang Hames         // If the dependency is in an error state then note this and continue,
901e00585c7SLang Hames         // we will move this symbol to the error state below.
9028853ac7eSLang Hames         if (OtherSymEntry.getFlags().hasError()) {
903e00585c7SLang Hames           DependsOnSymbolInErrorState = true;
904e00585c7SLang Hames           continue;
905e00585c7SLang Hames         }
906e00585c7SLang Hames 
907e00585c7SLang Hames         // If the dependency was not in the error state then add it to
908e00585c7SLang Hames         // our list of dependencies.
909d5f56c59SLang Hames         auto &OtherMI = OtherJITDylib.MaterializingInfos[OtherSymbol];
910d261e125SLang Hames 
9118853ac7eSLang Hames         if (OtherSymEntry.getState() == SymbolState::Emitted)
91276e21c97SLang Hames           transferEmittedNodeDependencies(MI, Name, OtherMI);
913d5f56c59SLang Hames         else if (&OtherJITDylib != this || OtherSymbol != Name) {
914d261e125SLang Hames           OtherMI.Dependants[this].insert(Name);
915d5f56c59SLang Hames           DepsOnOtherJITDylib.insert(OtherSymbol);
916d261e125SLang Hames         }
917d261e125SLang Hames       }
918df5776b1SLang Hames 
919d5f56c59SLang Hames       if (DepsOnOtherJITDylib.empty())
92076e21c97SLang Hames         MI.UnemittedDependencies.erase(&OtherJITDylib);
921d261e125SLang Hames     }
922e00585c7SLang Hames 
923e00585c7SLang Hames     // If this symbol dependended on any symbols in the error state then move
924e00585c7SLang Hames     // this symbol to the error state too.
925e00585c7SLang Hames     if (DependsOnSymbolInErrorState)
926aaf026d9SLang Hames       Symbols[Name].setFlags(Symbols[Name].getFlags() |
927aaf026d9SLang Hames                              JITSymbolFlags::HasError);
928aaf026d9SLang Hames   });
929d261e125SLang Hames }
930d261e125SLang Hames 
resolve(MaterializationResponsibility & MR,const SymbolMap & Resolved)9310aec49c8SLang Hames Error JITDylib::resolve(MaterializationResponsibility &MR,
9320aec49c8SLang Hames                         const SymbolMap &Resolved) {
933d4a8089fSLang Hames   AsynchronousSymbolQuerySet CompletedQueries;
934e00585c7SLang Hames 
9350aec49c8SLang Hames   if (auto Err = ES.runSessionLocked([&, this]() -> Error {
9369355d115SLang Hames         if (MR.RT->isDefunct())
9379355d115SLang Hames           return make_error<ResourceTrackerDefunct>(MR.RT);
9380aec49c8SLang Hames 
939758d54b4SLang Hames         if (State != Open)
940758d54b4SLang Hames           return make_error<StringError>("JITDylib " + getName() +
941758d54b4SLang Hames                                              " is defunct",
942758d54b4SLang Hames                                          inconvertibleErrorCode());
943758d54b4SLang Hames 
944e00585c7SLang Hames         struct WorklistEntry {
945e00585c7SLang Hames           SymbolTable::iterator SymI;
946e00585c7SLang Hames           JITEvaluatedSymbol ResolvedSym;
947e00585c7SLang Hames         };
948e00585c7SLang Hames 
9490aec49c8SLang Hames         SymbolNameSet SymbolsInErrorState;
950e00585c7SLang Hames         std::vector<WorklistEntry> Worklist;
951e00585c7SLang Hames         Worklist.reserve(Resolved.size());
952e00585c7SLang Hames 
953e00585c7SLang Hames         // Build worklist and check for any symbols in the error state.
954d261e125SLang Hames         for (const auto &KV : Resolved) {
955d261e125SLang Hames 
956e00585c7SLang Hames           assert(!KV.second.getFlags().hasError() &&
957e00585c7SLang Hames                  "Resolution result can not have error flag set");
958d261e125SLang Hames 
959e00585c7SLang Hames           auto SymI = Symbols.find(KV.first);
960e00585c7SLang Hames 
961e00585c7SLang Hames           assert(SymI != Symbols.end() && "Symbol not found");
962e00585c7SLang Hames           assert(!SymI->second.hasMaterializerAttached() &&
963eb5ee300SLang Hames                  "Resolving symbol with materializer attached?");
964e00585c7SLang Hames           assert(SymI->second.getState() == SymbolState::Materializing &&
965d261e125SLang Hames                  "Symbol should be materializing");
966e00585c7SLang Hames           assert(SymI->second.getAddress() == 0 &&
967e00585c7SLang Hames                  "Symbol has already been resolved");
968d261e125SLang Hames 
969e00585c7SLang Hames           if (SymI->second.getFlags().hasError())
970e00585c7SLang Hames             SymbolsInErrorState.insert(KV.first);
971e00585c7SLang Hames           else {
9724e920e58SLang Hames             auto Flags = KV.second.getFlags();
9734e920e58SLang Hames             Flags &= ~(JITSymbolFlags::Weak | JITSymbolFlags::Common);
9740aec49c8SLang Hames             assert(Flags ==
9750aec49c8SLang Hames                        (SymI->second.getFlags() &
9764e920e58SLang Hames                         ~(JITSymbolFlags::Weak | JITSymbolFlags::Common)) &&
977d261e125SLang Hames                    "Resolved flags should match the declared flags");
978d261e125SLang Hames 
9794e920e58SLang Hames             Worklist.push_back(
9804e920e58SLang Hames                 {SymI, JITEvaluatedSymbol(KV.second.getAddress(), Flags)});
981e00585c7SLang Hames           }
982e00585c7SLang Hames         }
983e00585c7SLang Hames 
984e00585c7SLang Hames         // If any symbols were in the error state then bail out.
9850aec49c8SLang Hames         if (!SymbolsInErrorState.empty()) {
9860aec49c8SLang Hames           auto FailedSymbolsDepMap = std::make_shared<SymbolDependenceMap>();
9870aec49c8SLang Hames           (*FailedSymbolsDepMap)[this] = std::move(SymbolsInErrorState);
9880aec49c8SLang Hames           return make_error<FailedToMaterialize>(
98955e8f721SLang Hames               getExecutionSession().getSymbolStringPool(),
9900aec49c8SLang Hames               std::move(FailedSymbolsDepMap));
9910aec49c8SLang Hames         }
992e00585c7SLang Hames 
993e00585c7SLang Hames         while (!Worklist.empty()) {
994e00585c7SLang Hames           auto SymI = Worklist.back().SymI;
995e00585c7SLang Hames           auto ResolvedSym = Worklist.back().ResolvedSym;
996e00585c7SLang Hames           Worklist.pop_back();
997e00585c7SLang Hames 
998e00585c7SLang Hames           auto &Name = SymI->first;
999e00585c7SLang Hames 
1000e00585c7SLang Hames           // Resolved symbols can not be weak: discard the weak flag.
1001e00585c7SLang Hames           JITSymbolFlags ResolvedFlags = ResolvedSym.getFlags();
1002e00585c7SLang Hames           SymI->second.setAddress(ResolvedSym.getAddress());
1003e00585c7SLang Hames           SymI->second.setFlags(ResolvedFlags);
1004e00585c7SLang Hames           SymI->second.setState(SymbolState::Resolved);
1005d261e125SLang Hames 
1006d38d06e6SLang Hames           auto MII = MaterializingInfos.find(Name);
1007d38d06e6SLang Hames           if (MII == MaterializingInfos.end())
1008d38d06e6SLang Hames             continue;
1009d38d06e6SLang Hames 
1010d38d06e6SLang Hames           auto &MI = MII->second;
1011d4a8089fSLang Hames           for (auto &Q : MI.takeQueriesMeeting(SymbolState::Resolved)) {
1012e00585c7SLang Hames             Q->notifySymbolMetRequiredState(Name, ResolvedSym);
10137371fb42SLang Hames             Q->removeQueryDependence(*this, Name);
1014d4a8089fSLang Hames             if (Q->isComplete())
1015d4a8089fSLang Hames               CompletedQueries.insert(std::move(Q));
10169bbd6530SLang Hames           }
10179bbd6530SLang Hames         }
10189bbd6530SLang Hames 
10190aec49c8SLang Hames         return Error::success();
10200aec49c8SLang Hames       }))
10210aec49c8SLang Hames     return Err;
1022e00585c7SLang Hames 
1023e00585c7SLang Hames   // Otherwise notify all the completed queries.
1024d4a8089fSLang Hames   for (auto &Q : CompletedQueries) {
1025d4a8089fSLang Hames     assert(Q->isComplete() && "Q not completed");
10267f9a89f9SLang Hames     Q->handleComplete(ES);
1027d261e125SLang Hames   }
1028e00585c7SLang Hames 
1029e00585c7SLang Hames   return Error::success();
1030d261e125SLang Hames }
10319bbd6530SLang Hames 
emit(MaterializationResponsibility & MR,const SymbolFlagsMap & Emitted)10320aec49c8SLang Hames Error JITDylib::emit(MaterializationResponsibility &MR,
10330aec49c8SLang Hames                      const SymbolFlagsMap &Emitted) {
1034d4a8089fSLang Hames   AsynchronousSymbolQuerySet CompletedQueries;
103585fb9976SLang Hames   DenseMap<JITDylib *, SymbolNameVector> ReadySymbols;
1036d261e125SLang Hames 
10370aec49c8SLang Hames   if (auto Err = ES.runSessionLocked([&, this]() -> Error {
10389355d115SLang Hames         if (MR.RT->isDefunct())
10399355d115SLang Hames           return make_error<ResourceTrackerDefunct>(MR.RT);
10400aec49c8SLang Hames 
1041758d54b4SLang Hames         if (State != Open)
1042758d54b4SLang Hames           return make_error<StringError>("JITDylib " + getName() +
1043758d54b4SLang Hames                                              " is defunct",
1044758d54b4SLang Hames                                          inconvertibleErrorCode());
1045758d54b4SLang Hames 
10460aec49c8SLang Hames         SymbolNameSet SymbolsInErrorState;
1047e00585c7SLang Hames         std::vector<SymbolTable::iterator> Worklist;
1048e00585c7SLang Hames 
1049e00585c7SLang Hames         // Scan to build worklist, record any symbols in the erorr state.
105076e21c97SLang Hames         for (const auto &KV : Emitted) {
1051e00585c7SLang Hames           auto &Name = KV.first;
1052e00585c7SLang Hames 
1053e00585c7SLang Hames           auto SymI = Symbols.find(Name);
1054e00585c7SLang Hames           assert(SymI != Symbols.end() && "No symbol table entry for Name");
1055e00585c7SLang Hames 
1056e00585c7SLang Hames           if (SymI->second.getFlags().hasError())
1057e00585c7SLang Hames             SymbolsInErrorState.insert(Name);
1058e00585c7SLang Hames           else
1059e00585c7SLang Hames             Worklist.push_back(SymI);
1060e00585c7SLang Hames         }
1061e00585c7SLang Hames 
1062e00585c7SLang Hames         // If any symbols were in the error state then bail out.
10630aec49c8SLang Hames         if (!SymbolsInErrorState.empty()) {
10640aec49c8SLang Hames           auto FailedSymbolsDepMap = std::make_shared<SymbolDependenceMap>();
10650aec49c8SLang Hames           (*FailedSymbolsDepMap)[this] = std::move(SymbolsInErrorState);
10660aec49c8SLang Hames           return make_error<FailedToMaterialize>(
106755e8f721SLang Hames               getExecutionSession().getSymbolStringPool(),
10680aec49c8SLang Hames               std::move(FailedSymbolsDepMap));
10690aec49c8SLang Hames         }
1070e00585c7SLang Hames 
1071e00585c7SLang Hames         // Otherwise update dependencies and move to the emitted state.
1072e00585c7SLang Hames         while (!Worklist.empty()) {
1073e00585c7SLang Hames           auto SymI = Worklist.back();
1074e00585c7SLang Hames           Worklist.pop_back();
1075e00585c7SLang Hames 
1076e00585c7SLang Hames           auto &Name = SymI->first;
10778853ac7eSLang Hames           auto &SymEntry = SymI->second;
10788853ac7eSLang Hames 
10798853ac7eSLang Hames           // Move symbol to the emitted state.
1080cb84e482SLang Hames           assert(((SymEntry.getFlags().hasMaterializationSideEffectsOnly() &&
1081cb84e482SLang Hames                    SymEntry.getState() == SymbolState::Materializing) ||
1082cb84e482SLang Hames                   SymEntry.getState() == SymbolState::Resolved) &&
10838853ac7eSLang Hames                  "Emitting from state other than Resolved");
10848853ac7eSLang Hames           SymEntry.setState(SymbolState::Emitted);
1085d261e125SLang Hames 
1086d261e125SLang Hames           auto MII = MaterializingInfos.find(Name);
1087d38d06e6SLang Hames 
1088d38d06e6SLang Hames           // If this symbol has no MaterializingInfo then it's trivially ready.
1089d38d06e6SLang Hames           // Update its state and continue.
1090d38d06e6SLang Hames           if (MII == MaterializingInfos.end()) {
1091d38d06e6SLang Hames             SymEntry.setState(SymbolState::Ready);
1092d38d06e6SLang Hames             continue;
1093d38d06e6SLang Hames           }
1094d38d06e6SLang Hames 
1095d261e125SLang Hames           auto &MI = MII->second;
1096d261e125SLang Hames 
109776e21c97SLang Hames           // For each dependant, transfer this node's emitted dependencies to
109876e21c97SLang Hames           // it. If the dependant node is ready (i.e. has no unemitted
109976e21c97SLang Hames           // dependencies) then notify any pending queries.
1100d261e125SLang Hames           for (auto &KV : MI.Dependants) {
1101d5f56c59SLang Hames             auto &DependantJD = *KV.first;
110285fb9976SLang Hames             auto &DependantJDReadySymbols = ReadySymbols[&DependantJD];
1103d261e125SLang Hames             for (auto &DependantName : KV.second) {
1104d261e125SLang Hames               auto DependantMII =
1105d5f56c59SLang Hames                   DependantJD.MaterializingInfos.find(DependantName);
1106d5f56c59SLang Hames               assert(DependantMII != DependantJD.MaterializingInfos.end() &&
1107d261e125SLang Hames                      "Dependant should have MaterializingInfo");
1108d261e125SLang Hames 
1109d261e125SLang Hames               auto &DependantMI = DependantMII->second;
1110d261e125SLang Hames 
1111d261e125SLang Hames               // Remove the dependant's dependency on this node.
1112e00585c7SLang Hames               assert(DependantMI.UnemittedDependencies.count(this) &&
11130aec49c8SLang Hames                      "Dependant does not have an unemitted dependencies record "
11140aec49c8SLang Hames                      "for "
1115e00585c7SLang Hames                      "this JITDylib");
111676e21c97SLang Hames               assert(DependantMI.UnemittedDependencies[this].count(Name) &&
1117d261e125SLang Hames                      "Dependant does not count this symbol as a dependency?");
1118e00585c7SLang Hames 
111976e21c97SLang Hames               DependantMI.UnemittedDependencies[this].erase(Name);
112076e21c97SLang Hames               if (DependantMI.UnemittedDependencies[this].empty())
112176e21c97SLang Hames                 DependantMI.UnemittedDependencies.erase(this);
1122d261e125SLang Hames 
11230aec49c8SLang Hames               // Transfer unemitted dependencies from this node to the
11240aec49c8SLang Hames               // dependant.
112576e21c97SLang Hames               DependantJD.transferEmittedNodeDependencies(DependantMI,
1126d261e125SLang Hames                                                           DependantName, MI);
1127d261e125SLang Hames 
11288853ac7eSLang Hames               auto DependantSymI = DependantJD.Symbols.find(DependantName);
11298853ac7eSLang Hames               assert(DependantSymI != DependantJD.Symbols.end() &&
11308853ac7eSLang Hames                      "Dependant has no entry in the Symbols table");
11318853ac7eSLang Hames               auto &DependantSymEntry = DependantSymI->second;
11328853ac7eSLang Hames 
113376e21c97SLang Hames               // If the dependant is emitted and this node was the last of its
113476e21c97SLang Hames               // unemitted dependencies then the dependant node is now ready, so
113576e21c97SLang Hames               // notify any pending queries on the dependant node.
11368853ac7eSLang Hames               if (DependantSymEntry.getState() == SymbolState::Emitted &&
113776e21c97SLang Hames                   DependantMI.UnemittedDependencies.empty()) {
1138d261e125SLang Hames                 assert(DependantMI.Dependants.empty() &&
1139d261e125SLang Hames                        "Dependants should be empty by now");
1140d261e125SLang Hames 
11410aec49c8SLang Hames                 // Since this dependant is now ready, we erase its
11420aec49c8SLang Hames                 // MaterializingInfo and update its materializing state.
11438853ac7eSLang Hames                 DependantSymEntry.setState(SymbolState::Ready);
114485fb9976SLang Hames                 DependantJDReadySymbols.push_back(DependantName);
1145d4a8089fSLang Hames 
11460aec49c8SLang Hames                 for (auto &Q :
11470aec49c8SLang Hames                      DependantMI.takeQueriesMeeting(SymbolState::Ready)) {
1148d4a8089fSLang Hames                   Q->notifySymbolMetRequiredState(
1149d4a8089fSLang Hames                       DependantName, DependantSymI->second.getSymbol());
1150d4a8089fSLang Hames                   if (Q->isComplete())
1151d4a8089fSLang Hames                     CompletedQueries.insert(Q);
1152d4a8089fSLang Hames                   Q->removeQueryDependence(DependantJD, DependantName);
1153d4a8089fSLang Hames                 }
115486b249c0SLang Hames                 DependantJD.MaterializingInfos.erase(DependantMII);
1155d261e125SLang Hames               }
1156d261e125SLang Hames             }
1157d261e125SLang Hames           }
1158d261e125SLang Hames 
115985fb9976SLang Hames           auto &ThisJDReadySymbols = ReadySymbols[this];
11608853ac7eSLang Hames           MI.Dependants.clear();
116176e21c97SLang Hames           if (MI.UnemittedDependencies.empty()) {
1162d4a8089fSLang Hames             SymI->second.setState(SymbolState::Ready);
116385fb9976SLang Hames             ThisJDReadySymbols.push_back(Name);
1164d4a8089fSLang Hames             for (auto &Q : MI.takeQueriesMeeting(SymbolState::Ready)) {
1165d4a8089fSLang Hames               Q->notifySymbolMetRequiredState(Name, SymI->second.getSymbol());
1166d4a8089fSLang Hames               if (Q->isComplete())
1167d4a8089fSLang Hames                 CompletedQueries.insert(Q);
1168d261e125SLang Hames               Q->removeQueryDependence(*this, Name);
1169d261e125SLang Hames             }
117086b249c0SLang Hames             MaterializingInfos.erase(MII);
1171d261e125SLang Hames           }
1172d261e125SLang Hames         }
1173d261e125SLang Hames 
11740aec49c8SLang Hames         return Error::success();
11750aec49c8SLang Hames       }))
11760aec49c8SLang Hames     return Err;
1177e00585c7SLang Hames 
1178e00585c7SLang Hames   // Otherwise notify all the completed queries.
1179d4a8089fSLang Hames   for (auto &Q : CompletedQueries) {
1180d4a8089fSLang Hames     assert(Q->isComplete() && "Q is not complete");
11817f9a89f9SLang Hames     Q->handleComplete(ES);
1182d261e125SLang Hames   }
1183e00585c7SLang Hames 
1184e00585c7SLang Hames   return Error::success();
1185d261e125SLang Hames }
1186d261e125SLang Hames 
unlinkMaterializationResponsibility(MaterializationResponsibility & MR)11870aec49c8SLang Hames void JITDylib::unlinkMaterializationResponsibility(
11880aec49c8SLang Hames     MaterializationResponsibility &MR) {
11890aec49c8SLang Hames   ES.runSessionLocked([&]() {
11909355d115SLang Hames     auto I = TrackerMRs.find(MR.RT.get());
11919355d115SLang Hames     assert(I != TrackerMRs.end() && "No MRs in TrackerMRs list for RT");
11929355d115SLang Hames     assert(I->second.count(&MR) && "MR not in TrackerMRs list for RT");
11939355d115SLang Hames     I->second.erase(&MR);
11949355d115SLang Hames     if (I->second.empty())
11959355d115SLang Hames       TrackerMRs.erase(MR.RT.get());
11960aec49c8SLang Hames   });
11970aec49c8SLang Hames }
11980aec49c8SLang Hames 
11990aec49c8SLang Hames std::pair<JITDylib::AsynchronousSymbolQuerySet,
12000aec49c8SLang Hames           std::shared_ptr<SymbolDependenceMap>>
failSymbols(FailedSymbolsWorklist Worklist)12010aec49c8SLang Hames JITDylib::failSymbols(FailedSymbolsWorklist Worklist) {
1202d261e125SLang Hames   AsynchronousSymbolQuerySet FailedQueries;
12038853ac7eSLang Hames   auto FailedSymbolsMap = std::make_shared<SymbolDependenceMap>();
12048853ac7eSLang Hames 
12058853ac7eSLang Hames   while (!Worklist.empty()) {
12068853ac7eSLang Hames     assert(Worklist.back().first && "Failed JITDylib can not be null");
12078853ac7eSLang Hames     auto &JD = *Worklist.back().first;
12088853ac7eSLang Hames     auto Name = std::move(Worklist.back().second);
12098853ac7eSLang Hames     Worklist.pop_back();
12108ec96618SLang Hames 
12118853ac7eSLang Hames     (*FailedSymbolsMap)[&JD].insert(Name);
1212d261e125SLang Hames 
1213758d54b4SLang Hames     // Look up the symbol to fail.
1214758d54b4SLang Hames     auto SymI = JD.Symbols.find(Name);
1215758d54b4SLang Hames 
1216758d54b4SLang Hames     // It's possible that this symbol has already been removed, e.g. if a
1217758d54b4SLang Hames     // materialization failure happens concurrently with a ResourceTracker or
1218758d54b4SLang Hames     // JITDylib removal. In that case we can safely skip this symbol and
1219758d54b4SLang Hames     // continue.
1220758d54b4SLang Hames     if (SymI == JD.Symbols.end())
1221758d54b4SLang Hames       continue;
1222758d54b4SLang Hames     auto &Sym = SymI->second;
1223e00585c7SLang Hames 
1224e00585c7SLang Hames     // Move the symbol into the error state.
1225e00585c7SLang Hames     // Note that this may be redundant: The symbol might already have been
1226e00585c7SLang Hames     // moved to this state in response to the failure of a dependence.
1227e00585c7SLang Hames     Sym.setFlags(Sym.getFlags() | JITSymbolFlags::HasError);
1228e00585c7SLang Hames 
1229e00585c7SLang Hames     // FIXME: Come up with a sane mapping of state to
1230e00585c7SLang Hames     // presence-of-MaterializingInfo so that we can assert presence / absence
1231e00585c7SLang Hames     // here, rather than testing it.
12328853ac7eSLang Hames     auto MII = JD.MaterializingInfos.find(Name);
1233d261e125SLang Hames 
12348853ac7eSLang Hames     if (MII == JD.MaterializingInfos.end())
1235d261e125SLang Hames       continue;
1236d261e125SLang Hames 
1237e00585c7SLang Hames     auto &MI = MII->second;
1238e00585c7SLang Hames 
1239e00585c7SLang Hames     // Move all dependants to the error state and disconnect from them.
1240e00585c7SLang Hames     for (auto &KV : MI.Dependants) {
1241e00585c7SLang Hames       auto &DependantJD = *KV.first;
1242e00585c7SLang Hames       for (auto &DependantName : KV.second) {
1243e00585c7SLang Hames         assert(DependantJD.Symbols.count(DependantName) &&
1244e00585c7SLang Hames                "No symbol table entry for DependantName");
1245e00585c7SLang Hames         auto &DependantSym = DependantJD.Symbols[DependantName];
1246e00585c7SLang Hames         DependantSym.setFlags(DependantSym.getFlags() |
1247e00585c7SLang Hames                               JITSymbolFlags::HasError);
1248e00585c7SLang Hames 
1249e00585c7SLang Hames         assert(DependantJD.MaterializingInfos.count(DependantName) &&
1250e00585c7SLang Hames                "No MaterializingInfo for dependant");
1251e00585c7SLang Hames         auto &DependantMI = DependantJD.MaterializingInfos[DependantName];
1252e00585c7SLang Hames 
12538853ac7eSLang Hames         auto UnemittedDepI = DependantMI.UnemittedDependencies.find(&JD);
1254e00585c7SLang Hames         assert(UnemittedDepI != DependantMI.UnemittedDependencies.end() &&
1255e00585c7SLang Hames                "No UnemittedDependencies entry for this JITDylib");
1256e00585c7SLang Hames         assert(UnemittedDepI->second.count(Name) &&
1257e00585c7SLang Hames                "No UnemittedDependencies entry for this symbol");
1258e00585c7SLang Hames         UnemittedDepI->second.erase(Name);
1259e00585c7SLang Hames         if (UnemittedDepI->second.empty())
1260e00585c7SLang Hames           DependantMI.UnemittedDependencies.erase(UnemittedDepI);
12618853ac7eSLang Hames 
12628853ac7eSLang Hames         // If this symbol is already in the emitted state then we need to
12638853ac7eSLang Hames         // take responsibility for failing its queries, so add it to the
12648853ac7eSLang Hames         // worklist.
12658853ac7eSLang Hames         if (DependantSym.getState() == SymbolState::Emitted) {
12668853ac7eSLang Hames           assert(DependantMI.Dependants.empty() &&
12678853ac7eSLang Hames                  "Emitted symbol should not have dependants");
12688853ac7eSLang Hames           Worklist.push_back(std::make_pair(&DependantJD, DependantName));
12694f71049aSLang Hames         }
12704f71049aSLang Hames       }
12718853ac7eSLang Hames     }
12728853ac7eSLang Hames     MI.Dependants.clear();
12734f71049aSLang Hames 
1274e00585c7SLang Hames     // Disconnect from all unemitted depenencies.
1275e00585c7SLang Hames     for (auto &KV : MI.UnemittedDependencies) {
1276e00585c7SLang Hames       auto &UnemittedDepJD = *KV.first;
1277e00585c7SLang Hames       for (auto &UnemittedDepName : KV.second) {
1278e00585c7SLang Hames         auto UnemittedDepMII =
1279e00585c7SLang Hames             UnemittedDepJD.MaterializingInfos.find(UnemittedDepName);
1280e00585c7SLang Hames         assert(UnemittedDepMII != UnemittedDepJD.MaterializingInfos.end() &&
1281e00585c7SLang Hames                "Missing MII for unemitted dependency");
12828853ac7eSLang Hames         assert(UnemittedDepMII->second.Dependants.count(&JD) &&
1283e00585c7SLang Hames                "JD not listed as a dependant of unemitted dependency");
12848853ac7eSLang Hames         assert(UnemittedDepMII->second.Dependants[&JD].count(Name) &&
1285e00585c7SLang Hames                "Name is not listed as a dependant of unemitted dependency");
12868853ac7eSLang Hames         UnemittedDepMII->second.Dependants[&JD].erase(Name);
12878853ac7eSLang Hames         if (UnemittedDepMII->second.Dependants[&JD].empty())
12888853ac7eSLang Hames           UnemittedDepMII->second.Dependants.erase(&JD);
1289e00585c7SLang Hames       }
1290e00585c7SLang Hames     }
12918853ac7eSLang Hames     MI.UnemittedDependencies.clear();
1292e00585c7SLang Hames 
1293e00585c7SLang Hames     // Collect queries to be failed for this MII.
1294007d173eSAlexandre Ganea     AsynchronousSymbolQueryList ToDetach;
12958853ac7eSLang Hames     for (auto &Q : MII->second.pendingQueries()) {
12968853ac7eSLang Hames       // Add the query to the list to be failed and detach it.
1297d261e125SLang Hames       FailedQueries.insert(Q);
1298007d173eSAlexandre Ganea       ToDetach.push_back(Q);
1299d4a8089fSLang Hames     }
1300007d173eSAlexandre Ganea     for (auto &Q : ToDetach)
1301007d173eSAlexandre Ganea       Q->detach();
1302d4a8089fSLang Hames 
13038853ac7eSLang Hames     assert(MI.Dependants.empty() &&
13048853ac7eSLang Hames            "Can not delete MaterializingInfo with dependants still attached");
13058853ac7eSLang Hames     assert(MI.UnemittedDependencies.empty() &&
13068853ac7eSLang Hames            "Can not delete MaterializingInfo with unemitted dependencies "
13078853ac7eSLang Hames            "still attached");
13088853ac7eSLang Hames     assert(!MI.hasQueriesPending() &&
13098853ac7eSLang Hames            "Can not delete MaterializingInfo with queries pending");
13108853ac7eSLang Hames     JD.MaterializingInfos.erase(MII);
13119bbd6530SLang Hames   }
13129bbd6530SLang Hames 
13130aec49c8SLang Hames   return std::make_pair(std::move(FailedQueries), std::move(FailedSymbolsMap));
13149bbd6530SLang Hames }
13159bbd6530SLang Hames 
setLinkOrder(JITDylibSearchOrder NewLinkOrder,bool LinkAgainstThisJITDylibFirst)1316c66f8900SLang Hames void JITDylib::setLinkOrder(JITDylibSearchOrder NewLinkOrder,
1317c66f8900SLang Hames                             bool LinkAgainstThisJITDylibFirst) {
131823cb2e7fSLang Hames   ES.runSessionLocked([&]() {
1319758d54b4SLang Hames     assert(State == Open && "JD is defunct");
1320c66f8900SLang Hames     if (LinkAgainstThisJITDylibFirst) {
1321c66f8900SLang Hames       LinkOrder.clear();
1322c66f8900SLang Hames       if (NewLinkOrder.empty() || NewLinkOrder.front().first != this)
1323c66f8900SLang Hames         LinkOrder.push_back(
1324674df13bSLang Hames             std::make_pair(this, JITDylibLookupFlags::MatchAllSymbols));
13251d0bc055SKazu Hirata       llvm::append_range(LinkOrder, NewLinkOrder);
1326674df13bSLang Hames     } else
1327c66f8900SLang Hames       LinkOrder = std::move(NewLinkOrder);
132823cb2e7fSLang Hames   });
1329fd0c1e71SLang Hames }
1330fd0c1e71SLang Hames 
addToLinkOrder(JITDylib & JD,JITDylibLookupFlags JDLookupFlags)1331c66f8900SLang Hames void JITDylib::addToLinkOrder(JITDylib &JD, JITDylibLookupFlags JDLookupFlags) {
1332c66f8900SLang Hames   ES.runSessionLocked([&]() { LinkOrder.push_back({&JD, JDLookupFlags}); });
1333674df13bSLang Hames }
1334674df13bSLang Hames 
replaceInLinkOrder(JITDylib & OldJD,JITDylib & NewJD,JITDylibLookupFlags JDLookupFlags)1335c66f8900SLang Hames void JITDylib::replaceInLinkOrder(JITDylib &OldJD, JITDylib &NewJD,
1336674df13bSLang Hames                                   JITDylibLookupFlags JDLookupFlags) {
1337fd0c1e71SLang Hames   ES.runSessionLocked([&]() {
1338758d54b4SLang Hames     assert(State == Open && "JD is defunct");
1339c66f8900SLang Hames     for (auto &KV : LinkOrder)
1340674df13bSLang Hames       if (KV.first == &OldJD) {
1341674df13bSLang Hames         KV = {&NewJD, JDLookupFlags};
1342674df13bSLang Hames         break;
1343674df13bSLang Hames       }
1344fd0c1e71SLang Hames   });
1345fd0c1e71SLang Hames }
1346fd0c1e71SLang Hames 
removeFromLinkOrder(JITDylib & JD)1347c66f8900SLang Hames void JITDylib::removeFromLinkOrder(JITDylib &JD) {
1348fd0c1e71SLang Hames   ES.runSessionLocked([&]() {
1349758d54b4SLang Hames     assert(State == Open && "JD is defunct");
135089e8eb94SKazu Hirata     auto I = llvm::find_if(LinkOrder,
1351674df13bSLang Hames                            [&](const JITDylibSearchOrder::value_type &KV) {
135223cb2e7fSLang Hames                              return KV.first == &JD;
135323cb2e7fSLang Hames                            });
1354c66f8900SLang Hames     if (I != LinkOrder.end())
1355c66f8900SLang Hames       LinkOrder.erase(I);
1356fd0c1e71SLang Hames   });
1357fd0c1e71SLang Hames }
1358fd0c1e71SLang Hames 
remove(const SymbolNameSet & Names)1359535448e0SLang Hames Error JITDylib::remove(const SymbolNameSet &Names) {
1360535448e0SLang Hames   return ES.runSessionLocked([&]() -> Error {
1361758d54b4SLang Hames     assert(State == Open && "JD is defunct");
1362535448e0SLang Hames     using SymbolMaterializerItrPair =
1363eb5ee300SLang Hames         std::pair<SymbolTable::iterator, UnmaterializedInfosMap::iterator>;
1364535448e0SLang Hames     std::vector<SymbolMaterializerItrPair> SymbolsToRemove;
1365535448e0SLang Hames     SymbolNameSet Missing;
1366535448e0SLang Hames     SymbolNameSet Materializing;
1367535448e0SLang Hames 
1368535448e0SLang Hames     for (auto &Name : Names) {
1369535448e0SLang Hames       auto I = Symbols.find(Name);
1370535448e0SLang Hames 
1371535448e0SLang Hames       // Note symbol missing.
1372535448e0SLang Hames       if (I == Symbols.end()) {
1373535448e0SLang Hames         Missing.insert(Name);
1374535448e0SLang Hames         continue;
1375535448e0SLang Hames       }
1376535448e0SLang Hames 
1377535448e0SLang Hames       // Note symbol materializing.
1378b7aa1cc3SLang Hames       if (I->second.getState() != SymbolState::NeverSearched &&
1379b7aa1cc3SLang Hames           I->second.getState() != SymbolState::Ready) {
1380535448e0SLang Hames         Materializing.insert(Name);
1381535448e0SLang Hames         continue;
1382535448e0SLang Hames       }
1383535448e0SLang Hames 
1384eb5ee300SLang Hames       auto UMII = I->second.hasMaterializerAttached()
1385eb5ee300SLang Hames                       ? UnmaterializedInfos.find(Name)
1386535448e0SLang Hames                       : UnmaterializedInfos.end();
1387535448e0SLang Hames       SymbolsToRemove.push_back(std::make_pair(I, UMII));
1388535448e0SLang Hames     }
1389535448e0SLang Hames 
1390535448e0SLang Hames     // If any of the symbols are not defined, return an error.
1391535448e0SLang Hames     if (!Missing.empty())
13926fe2e9a9SLang Hames       return make_error<SymbolsNotFound>(ES.getSymbolStringPool(),
13936fe2e9a9SLang Hames                                          std::move(Missing));
1394535448e0SLang Hames 
1395535448e0SLang Hames     // If any of the symbols are currently materializing, return an error.
1396535448e0SLang Hames     if (!Materializing.empty())
13976fe2e9a9SLang Hames       return make_error<SymbolsCouldNotBeRemoved>(ES.getSymbolStringPool(),
13986fe2e9a9SLang Hames                                                   std::move(Materializing));
1399535448e0SLang Hames 
1400535448e0SLang Hames     // Remove the symbols.
1401535448e0SLang Hames     for (auto &SymbolMaterializerItrPair : SymbolsToRemove) {
1402535448e0SLang Hames       auto UMII = SymbolMaterializerItrPair.second;
1403535448e0SLang Hames 
1404535448e0SLang Hames       // If there is a materializer attached, call discard.
1405535448e0SLang Hames       if (UMII != UnmaterializedInfos.end()) {
1406535448e0SLang Hames         UMII->second->MU->doDiscard(*this, UMII->first);
1407535448e0SLang Hames         UnmaterializedInfos.erase(UMII);
1408535448e0SLang Hames       }
1409535448e0SLang Hames 
1410535448e0SLang Hames       auto SymI = SymbolMaterializerItrPair.first;
1411535448e0SLang Hames       Symbols.erase(SymI);
1412535448e0SLang Hames     }
1413535448e0SLang Hames 
1414535448e0SLang Hames     return Error::success();
1415535448e0SLang Hames   });
1416535448e0SLang Hames }
1417535448e0SLang Hames 
dump(raw_ostream & OS)1418d5f56c59SLang Hames void JITDylib::dump(raw_ostream &OS) {
1419d261e125SLang Hames   ES.runSessionLocked([&, this]() {
142043f5f691SLang Hames     OS << "JITDylib \"" << getName() << "\" (ES: "
1421758d54b4SLang Hames        << format("0x%016" PRIx64, reinterpret_cast<uintptr_t>(&ES))
1422758d54b4SLang Hames        << ", State = ";
1423758d54b4SLang Hames     switch (State) {
1424758d54b4SLang Hames     case Open:
1425758d54b4SLang Hames       OS << "Open";
1426758d54b4SLang Hames       break;
1427758d54b4SLang Hames     case Closing:
1428758d54b4SLang Hames       OS << "Closing";
1429758d54b4SLang Hames       break;
1430758d54b4SLang Hames     case Closed:
1431758d54b4SLang Hames       OS << "Closed";
1432758d54b4SLang Hames       break;
1433758d54b4SLang Hames     }
1434758d54b4SLang Hames     OS << ")\n";
1435758d54b4SLang Hames     if (State == Closed)
1436758d54b4SLang Hames       return;
1437758d54b4SLang Hames     OS << "Link order: " << LinkOrder << "\n"
1438d261e125SLang Hames        << "Symbol table:\n";
1439d261e125SLang Hames 
1440d261e125SLang Hames     for (auto &KV : Symbols) {
1441afb8b5d9SLang Hames       OS << "    \"" << *KV.first << "\": ";
1442afb8b5d9SLang Hames       if (auto Addr = KV.second.getAddress())
14434111fafaSLang Hames         OS << format("0x%016" PRIx64, Addr);
1444afb8b5d9SLang Hames       else
1445afb8b5d9SLang Hames         OS << "<not resolved> ";
1446eb5ee300SLang Hames 
14474111fafaSLang Hames       OS << " " << KV.second.getFlags() << " " << KV.second.getState();
1448eb5ee300SLang Hames 
1449eb5ee300SLang Hames       if (KV.second.hasMaterializerAttached()) {
1450eb5ee300SLang Hames         OS << " (Materializer ";
1451d261e125SLang Hames         auto I = UnmaterializedInfos.find(KV.first);
1452d261e125SLang Hames         assert(I != UnmaterializedInfos.end() &&
1453d261e125SLang Hames                "Lazy symbol should have UnmaterializedInfo");
1454981f017cSLang Hames         OS << I->second->MU.get() << ", " << I->second->MU->getName() << ")\n";
1455d261e125SLang Hames       } else
1456d261e125SLang Hames         OS << "\n";
1457d261e125SLang Hames     }
1458d261e125SLang Hames 
1459d261e125SLang Hames     if (!MaterializingInfos.empty())
1460d261e125SLang Hames       OS << "  MaterializingInfos entries:\n";
1461d261e125SLang Hames     for (auto &KV : MaterializingInfos) {
1462d261e125SLang Hames       OS << "    \"" << *KV.first << "\":\n"
1463d4a8089fSLang Hames          << "      " << KV.second.pendingQueries().size()
1464d716a26eSLang Hames          << " pending queries: { ";
1465d4a8089fSLang Hames       for (const auto &Q : KV.second.pendingQueries())
1466d4a8089fSLang Hames         OS << Q.get() << " (" << Q->getRequiredState() << ") ";
1467d716a26eSLang Hames       OS << "}\n      Dependants:\n";
1468d261e125SLang Hames       for (auto &KV2 : KV.second.Dependants)
1469d261e125SLang Hames         OS << "        " << KV2.first->getName() << ": " << KV2.second << "\n";
147076e21c97SLang Hames       OS << "      Unemitted Dependencies:\n";
147176e21c97SLang Hames       for (auto &KV2 : KV.second.UnemittedDependencies)
1472d261e125SLang Hames         OS << "        " << KV2.first->getName() << ": " << KV2.second << "\n";
147386b249c0SLang Hames       assert((Symbols[KV.first].getState() != SymbolState::Ready ||
147486b249c0SLang Hames               !KV.second.pendingQueries().empty() ||
147586b249c0SLang Hames               !KV.second.Dependants.empty() ||
147686b249c0SLang Hames               !KV.second.UnemittedDependencies.empty()) &&
147786b249c0SLang Hames              "Stale materializing info entry");
1478d261e125SLang Hames     }
1479d261e125SLang Hames   });
1480d261e125SLang Hames }
1481d261e125SLang Hames 
addQuery(std::shared_ptr<AsynchronousSymbolQuery> Q)1482d4a8089fSLang Hames void JITDylib::MaterializingInfo::addQuery(
1483d4a8089fSLang Hames     std::shared_ptr<AsynchronousSymbolQuery> Q) {
1484d4a8089fSLang Hames 
1485d4a8089fSLang Hames   auto I = std::lower_bound(
1486d4a8089fSLang Hames       PendingQueries.rbegin(), PendingQueries.rend(), Q->getRequiredState(),
1487d4a8089fSLang Hames       [](const std::shared_ptr<AsynchronousSymbolQuery> &V, SymbolState S) {
1488d4a8089fSLang Hames         return V->getRequiredState() <= S;
1489d4a8089fSLang Hames       });
1490d4a8089fSLang Hames   PendingQueries.insert(I.base(), std::move(Q));
1491d4a8089fSLang Hames }
1492d4a8089fSLang Hames 
removeQuery(const AsynchronousSymbolQuery & Q)1493d4a8089fSLang Hames void JITDylib::MaterializingInfo::removeQuery(
1494d4a8089fSLang Hames     const AsynchronousSymbolQuery &Q) {
1495d4a8089fSLang Hames   // FIXME: Implement 'find_as' for shared_ptr<T>/T*.
149689e8eb94SKazu Hirata   auto I = llvm::find_if(
149789e8eb94SKazu Hirata       PendingQueries, [&Q](const std::shared_ptr<AsynchronousSymbolQuery> &V) {
1498d4a8089fSLang Hames         return V.get() == &Q;
1499d4a8089fSLang Hames       });
1500d4a8089fSLang Hames   assert(I != PendingQueries.end() &&
1501d4a8089fSLang Hames          "Query is not attached to this MaterializingInfo");
1502d4a8089fSLang Hames   PendingQueries.erase(I);
1503d4a8089fSLang Hames }
1504d4a8089fSLang Hames 
1505d4a8089fSLang Hames JITDylib::AsynchronousSymbolQueryList
takeQueriesMeeting(SymbolState RequiredState)1506d4a8089fSLang Hames JITDylib::MaterializingInfo::takeQueriesMeeting(SymbolState RequiredState) {
1507d4a8089fSLang Hames   AsynchronousSymbolQueryList Result;
1508d4a8089fSLang Hames   while (!PendingQueries.empty()) {
1509d4a8089fSLang Hames     if (PendingQueries.back()->getRequiredState() > RequiredState)
1510d4a8089fSLang Hames       break;
1511d4a8089fSLang Hames 
1512d4a8089fSLang Hames     Result.push_back(std::move(PendingQueries.back()));
1513d4a8089fSLang Hames     PendingQueries.pop_back();
1514d4a8089fSLang Hames   }
1515d4a8089fSLang Hames 
1516d4a8089fSLang Hames   return Result;
1517d4a8089fSLang Hames }
1518d4a8089fSLang Hames 
JITDylib(ExecutionSession & ES,std::string Name)15198be0d2e3SLang Hames JITDylib::JITDylib(ExecutionSession &ES, std::string Name)
152043f5f691SLang Hames     : JITLinkDylib(std::move(Name)), ES(ES) {
1521c66f8900SLang Hames   LinkOrder.push_back({this, JITDylibLookupFlags::MatchAllSymbols});
1522fd0c1e71SLang Hames }
1523fd0c1e71SLang Hames 
15240aec49c8SLang Hames std::pair<JITDylib::AsynchronousSymbolQuerySet,
15250aec49c8SLang Hames           std::shared_ptr<SymbolDependenceMap>>
removeTracker(ResourceTracker & RT)15260aec49c8SLang Hames JITDylib::removeTracker(ResourceTracker &RT) {
15270aec49c8SLang Hames   // Note: Should be called under the session lock.
1528758d54b4SLang Hames   assert(State != Closed && "JD is defunct");
15290aec49c8SLang Hames 
15300aec49c8SLang Hames   SymbolNameVector SymbolsToRemove;
15310aec49c8SLang Hames   std::vector<std::pair<JITDylib *, SymbolStringPtr>> SymbolsToFail;
15320aec49c8SLang Hames 
15330aec49c8SLang Hames   if (&RT == DefaultTracker.get()) {
15340aec49c8SLang Hames     SymbolNameSet TrackedSymbols;
15350aec49c8SLang Hames     for (auto &KV : TrackerSymbols)
15360aec49c8SLang Hames       for (auto &Sym : KV.second)
15370aec49c8SLang Hames         TrackedSymbols.insert(Sym);
15380aec49c8SLang Hames 
15390aec49c8SLang Hames     for (auto &KV : Symbols) {
15400aec49c8SLang Hames       auto &Sym = KV.first;
15410aec49c8SLang Hames       if (!TrackedSymbols.count(Sym))
15420aec49c8SLang Hames         SymbolsToRemove.push_back(Sym);
15430aec49c8SLang Hames     }
15440aec49c8SLang Hames 
15450aec49c8SLang Hames     DefaultTracker.reset();
15460aec49c8SLang Hames   } else {
15470aec49c8SLang Hames     /// Check for a non-default tracker.
15480aec49c8SLang Hames     auto I = TrackerSymbols.find(&RT);
15490aec49c8SLang Hames     if (I != TrackerSymbols.end()) {
15500aec49c8SLang Hames       SymbolsToRemove = std::move(I->second);
15510aec49c8SLang Hames       TrackerSymbols.erase(I);
15520aec49c8SLang Hames     }
15530aec49c8SLang Hames     // ... if not found this tracker was already defunct. Nothing to do.
15540aec49c8SLang Hames   }
15550aec49c8SLang Hames 
15560aec49c8SLang Hames   for (auto &Sym : SymbolsToRemove) {
1557c89447b6SLang Hames     assert(Symbols.count(Sym) && "Symbol not in symbol table");
15580aec49c8SLang Hames 
15590aec49c8SLang Hames     // If there is a MaterializingInfo then collect any queries to fail.
15600aec49c8SLang Hames     auto MII = MaterializingInfos.find(Sym);
15610aec49c8SLang Hames     if (MII != MaterializingInfos.end())
15620aec49c8SLang Hames       SymbolsToFail.push_back({this, Sym});
15630aec49c8SLang Hames   }
15640aec49c8SLang Hames 
15650aec49c8SLang Hames   AsynchronousSymbolQuerySet QueriesToFail;
15660aec49c8SLang Hames   auto Result = failSymbols(std::move(SymbolsToFail));
15670aec49c8SLang Hames 
15680aec49c8SLang Hames   // Removed symbols should be taken out of the table altogether.
15690aec49c8SLang Hames   for (auto &Sym : SymbolsToRemove) {
15700aec49c8SLang Hames     auto I = Symbols.find(Sym);
15710aec49c8SLang Hames     assert(I != Symbols.end() && "Symbol not present in table");
15720aec49c8SLang Hames 
15730aec49c8SLang Hames     // Remove Materializer if present.
15740aec49c8SLang Hames     if (I->second.hasMaterializerAttached()) {
15750aec49c8SLang Hames       // FIXME: Should this discard the symbols?
15760aec49c8SLang Hames       UnmaterializedInfos.erase(Sym);
15770aec49c8SLang Hames     } else {
15780aec49c8SLang Hames       assert(!UnmaterializedInfos.count(Sym) &&
15790aec49c8SLang Hames              "Symbol has materializer attached");
15800aec49c8SLang Hames     }
15810aec49c8SLang Hames 
15820aec49c8SLang Hames     Symbols.erase(I);
15830aec49c8SLang Hames   }
15840aec49c8SLang Hames 
15850aec49c8SLang Hames   return Result;
15860aec49c8SLang Hames }
15870aec49c8SLang Hames 
transferTracker(ResourceTracker & DstRT,ResourceTracker & SrcRT)15880aec49c8SLang Hames void JITDylib::transferTracker(ResourceTracker &DstRT, ResourceTracker &SrcRT) {
1589758d54b4SLang Hames   assert(State != Closed && "JD is defunct");
15900aec49c8SLang Hames   assert(&DstRT != &SrcRT && "No-op transfers shouldn't call transferTracker");
15910aec49c8SLang Hames   assert(&DstRT.getJITDylib() == this && "DstRT is not for this JITDylib");
15920aec49c8SLang Hames   assert(&SrcRT.getJITDylib() == this && "SrcRT is not for this JITDylib");
15930aec49c8SLang Hames 
15940aec49c8SLang Hames   // Update trackers for any not-yet materialized units.
15950aec49c8SLang Hames   for (auto &KV : UnmaterializedInfos) {
15960aec49c8SLang Hames     if (KV.second->RT == &SrcRT)
15970aec49c8SLang Hames       KV.second->RT = &DstRT;
15980aec49c8SLang Hames   }
15990aec49c8SLang Hames 
16000aec49c8SLang Hames   // Update trackers for any active materialization responsibilities.
16019355d115SLang Hames   {
16029355d115SLang Hames     auto I = TrackerMRs.find(&SrcRT);
16039355d115SLang Hames     if (I != TrackerMRs.end()) {
16049355d115SLang Hames       auto &SrcMRs = I->second;
16059355d115SLang Hames       auto &DstMRs = TrackerMRs[&DstRT];
16069355d115SLang Hames       for (auto *MR : SrcMRs)
16079355d115SLang Hames         MR->RT = &DstRT;
16089355d115SLang Hames       if (DstMRs.empty())
16099355d115SLang Hames         DstMRs = std::move(SrcMRs);
16109355d115SLang Hames       else
16119355d115SLang Hames         for (auto *MR : SrcMRs)
16129355d115SLang Hames           DstMRs.insert(MR);
16139355d115SLang Hames       // Erase SrcRT entry in TrackerMRs. Use &SrcRT key rather than iterator I
16149355d115SLang Hames       // for this, since I may have been invalidated by 'TrackerMRs[&DstRT]'.
16159355d115SLang Hames       TrackerMRs.erase(&SrcRT);
16169355d115SLang Hames     }
16170aec49c8SLang Hames   }
16180aec49c8SLang Hames 
16190aec49c8SLang Hames   // If we're transfering to the default tracker we just need to delete the
16200aec49c8SLang Hames   // tracked symbols for the source tracker.
16210aec49c8SLang Hames   if (&DstRT == DefaultTracker.get()) {
16220aec49c8SLang Hames     TrackerSymbols.erase(&SrcRT);
16230aec49c8SLang Hames     return;
16240aec49c8SLang Hames   }
16250aec49c8SLang Hames 
16260aec49c8SLang Hames   // If we're transferring from the default tracker we need to find all
16270aec49c8SLang Hames   // currently untracked symbols.
16280aec49c8SLang Hames   if (&SrcRT == DefaultTracker.get()) {
16290aec49c8SLang Hames     assert(!TrackerSymbols.count(&SrcRT) &&
16300aec49c8SLang Hames            "Default tracker should not appear in TrackerSymbols");
16310aec49c8SLang Hames 
16320aec49c8SLang Hames     SymbolNameVector SymbolsToTrack;
16330aec49c8SLang Hames 
16340aec49c8SLang Hames     SymbolNameSet CurrentlyTrackedSymbols;
16350aec49c8SLang Hames     for (auto &KV : TrackerSymbols)
16360aec49c8SLang Hames       for (auto &Sym : KV.second)
16370aec49c8SLang Hames         CurrentlyTrackedSymbols.insert(Sym);
16380aec49c8SLang Hames 
16390aec49c8SLang Hames     for (auto &KV : Symbols) {
16400aec49c8SLang Hames       auto &Sym = KV.first;
16410aec49c8SLang Hames       if (!CurrentlyTrackedSymbols.count(Sym))
16420aec49c8SLang Hames         SymbolsToTrack.push_back(Sym);
16430aec49c8SLang Hames     }
16440aec49c8SLang Hames 
16450aec49c8SLang Hames     TrackerSymbols[&DstRT] = std::move(SymbolsToTrack);
16460aec49c8SLang Hames     return;
16470aec49c8SLang Hames   }
16480aec49c8SLang Hames 
16490aec49c8SLang Hames   auto &DstTrackedSymbols = TrackerSymbols[&DstRT];
16500aec49c8SLang Hames 
16510aec49c8SLang Hames   // Finally if neither SrtRT or DstRT are the default tracker then
16520aec49c8SLang Hames   // just append DstRT's tracked symbols to SrtRT's.
16530aec49c8SLang Hames   auto SI = TrackerSymbols.find(&SrcRT);
16540aec49c8SLang Hames   if (SI == TrackerSymbols.end())
16550aec49c8SLang Hames     return;
16560aec49c8SLang Hames 
16570aec49c8SLang Hames   DstTrackedSymbols.reserve(DstTrackedSymbols.size() + SI->second.size());
16580aec49c8SLang Hames   for (auto &Sym : SI->second)
16590aec49c8SLang Hames     DstTrackedSymbols.push_back(std::move(Sym));
16600aec49c8SLang Hames   TrackerSymbols.erase(SI);
16610aec49c8SLang Hames }
16620aec49c8SLang Hames 
defineImpl(MaterializationUnit & MU)1663d5f56c59SLang Hames Error JITDylib::defineImpl(MaterializationUnit &MU) {
1664cb84e482SLang Hames 
1665cb84e482SLang Hames   LLVM_DEBUG({ dbgs() << "  " << MU.getSymbols() << "\n"; });
1666cb84e482SLang Hames 
1667d261e125SLang Hames   SymbolNameSet Duplicates;
166811c8dfa5SLang Hames   std::vector<SymbolStringPtr> ExistingDefsOverridden;
166911c8dfa5SLang Hames   std::vector<SymbolStringPtr> MUDefsOverridden;
1670ce72161dSLang Hames 
167111c8dfa5SLang Hames   for (const auto &KV : MU.getSymbols()) {
167211c8dfa5SLang Hames     auto I = Symbols.find(KV.first);
1673d261e125SLang Hames 
167411c8dfa5SLang Hames     if (I != Symbols.end()) {
1675d261e125SLang Hames       if (KV.second.isStrong()) {
167611c8dfa5SLang Hames         if (I->second.getFlags().isStrong() ||
1677eb5ee300SLang Hames             I->second.getState() > SymbolState::NeverSearched)
1678d261e125SLang Hames           Duplicates.insert(KV.first);
167911c8dfa5SLang Hames         else {
1680eb5ee300SLang Hames           assert(I->second.getState() == SymbolState::NeverSearched &&
1681eb5ee300SLang Hames                  "Overridden existing def should be in the never-searched "
1682eb5ee300SLang Hames                  "state");
168311c8dfa5SLang Hames           ExistingDefsOverridden.push_back(KV.first);
168411c8dfa5SLang Hames         }
168511c8dfa5SLang Hames       } else
168611c8dfa5SLang Hames         MUDefsOverridden.push_back(KV.first);
168711c8dfa5SLang Hames     }
168811c8dfa5SLang Hames   }
1689d261e125SLang Hames 
169011c8dfa5SLang Hames   // If there were any duplicate definitions then bail out.
1691cb84e482SLang Hames   if (!Duplicates.empty()) {
1692cb84e482SLang Hames     LLVM_DEBUG(
1693cb84e482SLang Hames         { dbgs() << "  Error: Duplicate symbols " << Duplicates << "\n"; });
1694adcd0268SBenjamin Kramer     return make_error<DuplicateDefinition>(std::string(**Duplicates.begin()));
1695cb84e482SLang Hames   }
1696ce72161dSLang Hames 
169711c8dfa5SLang Hames   // Discard any overridden defs in this MU.
1698cb84e482SLang Hames   LLVM_DEBUG({
1699cb84e482SLang Hames     if (!MUDefsOverridden.empty())
1700cb84e482SLang Hames       dbgs() << "  Defs in this MU overridden: " << MUDefsOverridden << "\n";
1701cb84e482SLang Hames   });
170211c8dfa5SLang Hames   for (auto &S : MUDefsOverridden)
170311c8dfa5SLang Hames     MU.doDiscard(*this, S);
170411c8dfa5SLang Hames 
170511c8dfa5SLang Hames   // Discard existing overridden defs.
1706cb84e482SLang Hames   LLVM_DEBUG({
1707cb84e482SLang Hames     if (!ExistingDefsOverridden.empty())
1708cb84e482SLang Hames       dbgs() << "  Existing defs overridden by this MU: " << MUDefsOverridden
1709cb84e482SLang Hames              << "\n";
1710cb84e482SLang Hames   });
171111c8dfa5SLang Hames   for (auto &S : ExistingDefsOverridden) {
171211c8dfa5SLang Hames 
171311c8dfa5SLang Hames     auto UMII = UnmaterializedInfos.find(S);
1714d261e125SLang Hames     assert(UMII != UnmaterializedInfos.end() &&
1715d261e125SLang Hames            "Overridden existing def should have an UnmaterializedInfo");
171611c8dfa5SLang Hames     UMII->second->MU->doDiscard(*this, S);
1717d261e125SLang Hames   }
1718d261e125SLang Hames 
171911c8dfa5SLang Hames   // Finally, add the defs from this MU.
172011c8dfa5SLang Hames   for (auto &KV : MU.getSymbols()) {
1721eb5ee300SLang Hames     auto &SymEntry = Symbols[KV.first];
1722eb5ee300SLang Hames     SymEntry.setFlags(KV.second);
1723eb5ee300SLang Hames     SymEntry.setState(SymbolState::NeverSearched);
1724eb5ee300SLang Hames     SymEntry.setMaterializerAttached(true);
172511c8dfa5SLang Hames   }
1726d261e125SLang Hames 
1727d261e125SLang Hames   return Error::success();
1728d261e125SLang Hames }
1729d261e125SLang Hames 
installMaterializationUnit(std::unique_ptr<MaterializationUnit> MU,ResourceTracker & RT)17300aec49c8SLang Hames void JITDylib::installMaterializationUnit(
17310aec49c8SLang Hames     std::unique_ptr<MaterializationUnit> MU, ResourceTracker &RT) {
17320aec49c8SLang Hames 
17330aec49c8SLang Hames   /// defineImpl succeeded.
17340aec49c8SLang Hames   if (&RT != DefaultTracker.get()) {
17350aec49c8SLang Hames     auto &TS = TrackerSymbols[&RT];
17360aec49c8SLang Hames     TS.reserve(TS.size() + MU->getSymbols().size());
17370aec49c8SLang Hames     for (auto &KV : MU->getSymbols())
17380aec49c8SLang Hames       TS.push_back(KV.first);
17390aec49c8SLang Hames   }
17400aec49c8SLang Hames 
17410aec49c8SLang Hames   auto UMI = std::make_shared<UnmaterializedInfo>(std::move(MU), &RT);
17420aec49c8SLang Hames   for (auto &KV : UMI->MU->getSymbols())
17430aec49c8SLang Hames     UnmaterializedInfos[KV.first] = UMI;
17440aec49c8SLang Hames }
17450aec49c8SLang Hames 
detachQueryHelper(AsynchronousSymbolQuery & Q,const SymbolNameSet & QuerySymbols)1746d5f56c59SLang Hames void JITDylib::detachQueryHelper(AsynchronousSymbolQuery &Q,
1747d261e125SLang Hames                                  const SymbolNameSet &QuerySymbols) {
1748d261e125SLang Hames   for (auto &QuerySymbol : QuerySymbols) {
1749d261e125SLang Hames     assert(MaterializingInfos.count(QuerySymbol) &&
1750d261e125SLang Hames            "QuerySymbol does not have MaterializingInfo");
1751d261e125SLang Hames     auto &MI = MaterializingInfos[QuerySymbol];
1752d4a8089fSLang Hames     MI.removeQuery(Q);
1753d261e125SLang Hames   }
1754d261e125SLang Hames }
1755d261e125SLang Hames 
transferEmittedNodeDependencies(MaterializingInfo & DependantMI,const SymbolStringPtr & DependantName,MaterializingInfo & EmittedMI)175676e21c97SLang Hames void JITDylib::transferEmittedNodeDependencies(
1757d261e125SLang Hames     MaterializingInfo &DependantMI, const SymbolStringPtr &DependantName,
175876e21c97SLang Hames     MaterializingInfo &EmittedMI) {
175976e21c97SLang Hames   for (auto &KV : EmittedMI.UnemittedDependencies) {
1760d5f56c59SLang Hames     auto &DependencyJD = *KV.first;
176176e21c97SLang Hames     SymbolNameSet *UnemittedDependenciesOnDependencyJD = nullptr;
1762d261e125SLang Hames 
1763d261e125SLang Hames     for (auto &DependencyName : KV.second) {
1764d5f56c59SLang Hames       auto &DependencyMI = DependencyJD.MaterializingInfos[DependencyName];
1765d261e125SLang Hames 
1766d261e125SLang Hames       // Do not add self dependencies.
1767d261e125SLang Hames       if (&DependencyMI == &DependantMI)
1768d261e125SLang Hames         continue;
1769d261e125SLang Hames 
1770d5f56c59SLang Hames       // If we haven't looked up the dependencies for DependencyJD yet, do it
1771d261e125SLang Hames       // now and cache the result.
177276e21c97SLang Hames       if (!UnemittedDependenciesOnDependencyJD)
177376e21c97SLang Hames         UnemittedDependenciesOnDependencyJD =
177476e21c97SLang Hames             &DependantMI.UnemittedDependencies[&DependencyJD];
1775d261e125SLang Hames 
1776d261e125SLang Hames       DependencyMI.Dependants[this].insert(DependantName);
177776e21c97SLang Hames       UnemittedDependenciesOnDependencyJD->insert(DependencyName);
1778d261e125SLang Hames     }
1779d261e125SLang Hames   }
1780d261e125SLang Hames }
1781d261e125SLang Hames 
17823a3cb929SKazu Hirata Platform::~Platform() = default;
178385fb9976SLang Hames 
lookupInitSymbols(ExecutionSession & ES,const DenseMap<JITDylib *,SymbolLookupSet> & InitSyms)178485fb9976SLang Hames Expected<DenseMap<JITDylib *, SymbolMap>> Platform::lookupInitSymbols(
178585fb9976SLang Hames     ExecutionSession &ES,
178685fb9976SLang Hames     const DenseMap<JITDylib *, SymbolLookupSet> &InitSyms) {
178785fb9976SLang Hames 
178885fb9976SLang Hames   DenseMap<JITDylib *, SymbolMap> CompoundResult;
178985fb9976SLang Hames   Error CompoundErr = Error::success();
179085fb9976SLang Hames   std::mutex LookupMutex;
179185fb9976SLang Hames   std::condition_variable CV;
179285fb9976SLang Hames   uint64_t Count = InitSyms.size();
179385fb9976SLang Hames 
179485fb9976SLang Hames   LLVM_DEBUG({
179585fb9976SLang Hames     dbgs() << "Issuing init-symbol lookup:\n";
179685fb9976SLang Hames     for (auto &KV : InitSyms)
179785fb9976SLang Hames       dbgs() << "  " << KV.first->getName() << ": " << KV.second << "\n";
179885fb9976SLang Hames   });
179985fb9976SLang Hames 
180085fb9976SLang Hames   for (auto &KV : InitSyms) {
180185fb9976SLang Hames     auto *JD = KV.first;
180285fb9976SLang Hames     auto Names = std::move(KV.second);
180385fb9976SLang Hames     ES.lookup(
180485fb9976SLang Hames         LookupKind::Static,
180585fb9976SLang Hames         JITDylibSearchOrder({{JD, JITDylibLookupFlags::MatchAllSymbols}}),
180685fb9976SLang Hames         std::move(Names), SymbolState::Ready,
180785fb9976SLang Hames         [&, JD](Expected<SymbolMap> Result) {
180885fb9976SLang Hames           {
180985fb9976SLang Hames             std::lock_guard<std::mutex> Lock(LookupMutex);
181085fb9976SLang Hames             --Count;
181185fb9976SLang Hames             if (Result) {
181285fb9976SLang Hames               assert(!CompoundResult.count(JD) &&
181385fb9976SLang Hames                      "Duplicate JITDylib in lookup?");
181485fb9976SLang Hames               CompoundResult[JD] = std::move(*Result);
181585fb9976SLang Hames             } else
181685fb9976SLang Hames               CompoundErr =
181785fb9976SLang Hames                   joinErrors(std::move(CompoundErr), Result.takeError());
181885fb9976SLang Hames           }
181985fb9976SLang Hames           CV.notify_one();
182085fb9976SLang Hames         },
182185fb9976SLang Hames         NoDependenciesToRegister);
182285fb9976SLang Hames   }
182385fb9976SLang Hames 
182485fb9976SLang Hames   std::unique_lock<std::mutex> Lock(LookupMutex);
182585fb9976SLang Hames   CV.wait(Lock, [&] { return Count == 0 || CompoundErr; });
182685fb9976SLang Hames 
182785fb9976SLang Hames   if (CompoundErr)
182885fb9976SLang Hames     return std::move(CompoundErr);
182985fb9976SLang Hames 
183085fb9976SLang Hames   return std::move(CompoundResult);
183185fb9976SLang Hames }
183285fb9976SLang Hames 
lookupInitSymbolsAsync(unique_function<void (Error)> OnComplete,ExecutionSession & ES,const DenseMap<JITDylib *,SymbolLookupSet> & InitSyms)1833bb5f97e3SLang Hames void Platform::lookupInitSymbolsAsync(
1834bb5f97e3SLang Hames     unique_function<void(Error)> OnComplete, ExecutionSession &ES,
1835bb5f97e3SLang Hames     const DenseMap<JITDylib *, SymbolLookupSet> &InitSyms) {
1836bb5f97e3SLang Hames 
1837bb5f97e3SLang Hames   class TriggerOnComplete {
1838bb5f97e3SLang Hames   public:
1839bb5f97e3SLang Hames     using OnCompleteFn = unique_function<void(Error)>;
1840bb5f97e3SLang Hames     TriggerOnComplete(OnCompleteFn OnComplete)
1841bb5f97e3SLang Hames         : OnComplete(std::move(OnComplete)) {}
1842bb5f97e3SLang Hames     ~TriggerOnComplete() { OnComplete(std::move(LookupResult)); }
1843bb5f97e3SLang Hames     void reportResult(Error Err) {
1844bb5f97e3SLang Hames       std::lock_guard<std::mutex> Lock(ResultMutex);
1845bb5f97e3SLang Hames       LookupResult = joinErrors(std::move(LookupResult), std::move(Err));
1846bb5f97e3SLang Hames     }
1847bb5f97e3SLang Hames 
1848bb5f97e3SLang Hames   private:
1849bb5f97e3SLang Hames     std::mutex ResultMutex;
1850bb5f97e3SLang Hames     Error LookupResult{Error::success()};
1851bb5f97e3SLang Hames     OnCompleteFn OnComplete;
1852bb5f97e3SLang Hames   };
1853bb5f97e3SLang Hames 
1854bb5f97e3SLang Hames   LLVM_DEBUG({
1855bb5f97e3SLang Hames     dbgs() << "Issuing init-symbol lookup:\n";
1856bb5f97e3SLang Hames     for (auto &KV : InitSyms)
1857bb5f97e3SLang Hames       dbgs() << "  " << KV.first->getName() << ": " << KV.second << "\n";
1858bb5f97e3SLang Hames   });
1859bb5f97e3SLang Hames 
1860bb5f97e3SLang Hames   auto TOC = std::make_shared<TriggerOnComplete>(std::move(OnComplete));
1861bb5f97e3SLang Hames 
1862bb5f97e3SLang Hames   for (auto &KV : InitSyms) {
1863bb5f97e3SLang Hames     auto *JD = KV.first;
1864bb5f97e3SLang Hames     auto Names = std::move(KV.second);
1865bb5f97e3SLang Hames     ES.lookup(
1866bb5f97e3SLang Hames         LookupKind::Static,
1867bb5f97e3SLang Hames         JITDylibSearchOrder({{JD, JITDylibLookupFlags::MatchAllSymbols}}),
1868bb5f97e3SLang Hames         std::move(Names), SymbolState::Ready,
1869bb5f97e3SLang Hames         [TOC](Expected<SymbolMap> Result) {
1870bb5f97e3SLang Hames           TOC->reportResult(Result.takeError());
1871bb5f97e3SLang Hames         },
1872bb5f97e3SLang Hames         NoDependenciesToRegister);
1873bb5f97e3SLang Hames   }
1874bb5f97e3SLang Hames }
1875bb5f97e3SLang Hames 
printDescription(raw_ostream & OS)18765344c88dSLang Hames void MaterializationTask::printDescription(raw_ostream &OS) {
18775344c88dSLang Hames   OS << "Materialization task: " << MU->getName() << " in "
187820634eceSLang Hames      << MR->getTargetJITDylib().getName();
18795344c88dSLang Hames }
18805344c88dSLang Hames 
run()18815344c88dSLang Hames void MaterializationTask::run() { MU->materialize(std::move(MR)); }
18825344c88dSLang Hames 
ExecutionSession(std::unique_ptr<ExecutorProcessControl> EPC)18832487db1fSLang Hames ExecutionSession::ExecutionSession(std::unique_ptr<ExecutorProcessControl> EPC)
18842487db1fSLang Hames     : EPC(std::move(EPC)) {
18852487db1fSLang Hames   // Associated EPC and this.
18862487db1fSLang Hames   this->EPC->ES = this;
18872487db1fSLang Hames }
18880aec49c8SLang Hames 
~ExecutionSession()1889f3428dafSLang Hames ExecutionSession::~ExecutionSession() {
1890f3428dafSLang Hames   // You must call endSession prior to destroying the session.
1891f3428dafSLang Hames   assert(!SessionOpen &&
1892f3428dafSLang Hames          "Session still open. Did you forget to call endSession?");
1893f3428dafSLang Hames }
1894f3428dafSLang Hames 
endSession()18950aec49c8SLang Hames Error ExecutionSession::endSession() {
18960aec49c8SLang Hames   LLVM_DEBUG(dbgs() << "Ending ExecutionSession " << this << "\n");
18970aec49c8SLang Hames 
18980aec49c8SLang Hames   std::vector<JITDylibSP> JITDylibsToClose = runSessionLocked([&] {
18990aec49c8SLang Hames     SessionOpen = false;
19000aec49c8SLang Hames     return std::move(JDs);
19010aec49c8SLang Hames   });
19020aec49c8SLang Hames 
19030aec49c8SLang Hames   // TODO: notifiy platform? run static deinits?
19040aec49c8SLang Hames 
19050aec49c8SLang Hames   Error Err = Error::success();
1906f9aef477SLang Hames   for (auto &JD : reverse(JITDylibsToClose))
19070aec49c8SLang Hames     Err = joinErrors(std::move(Err), JD->clear());
19082487db1fSLang Hames 
19092487db1fSLang Hames   Err = joinErrors(std::move(Err), EPC->disconnect());
19102487db1fSLang Hames 
19110aec49c8SLang Hames   return Err;
19120aec49c8SLang Hames }
19130aec49c8SLang Hames 
registerResourceManager(ResourceManager & RM)19140aec49c8SLang Hames void ExecutionSession::registerResourceManager(ResourceManager &RM) {
19150aec49c8SLang Hames   runSessionLocked([&] { ResourceManagers.push_back(&RM); });
19160aec49c8SLang Hames }
19170aec49c8SLang Hames 
deregisterResourceManager(ResourceManager & RM)19180aec49c8SLang Hames void ExecutionSession::deregisterResourceManager(ResourceManager &RM) {
19190aec49c8SLang Hames   runSessionLocked([&] {
19200aec49c8SLang Hames     assert(!ResourceManagers.empty() && "No managers registered");
19210aec49c8SLang Hames     if (ResourceManagers.back() == &RM)
19220aec49c8SLang Hames       ResourceManagers.pop_back();
19230aec49c8SLang Hames     else {
19240aec49c8SLang Hames       auto I = llvm::find(ResourceManagers, &RM);
19250aec49c8SLang Hames       assert(I != ResourceManagers.end() && "RM not registered");
19260aec49c8SLang Hames       ResourceManagers.erase(I);
19270aec49c8SLang Hames     }
19280aec49c8SLang Hames   });
192913014d3cSLang Hames }
193013014d3cSLang Hames 
getJITDylibByName(StringRef Name)1931f088e195SLang Hames JITDylib *ExecutionSession::getJITDylibByName(StringRef Name) {
1932f088e195SLang Hames   return runSessionLocked([&, this]() -> JITDylib * {
1933f088e195SLang Hames     for (auto &JD : JDs)
1934f088e195SLang Hames       if (JD->getName() == Name)
1935f088e195SLang Hames         return JD.get();
1936f088e195SLang Hames     return nullptr;
1937f088e195SLang Hames   });
1938f088e195SLang Hames }
1939f088e195SLang Hames 
createBareJITDylib(std::string Name)194085fb9976SLang Hames JITDylib &ExecutionSession::createBareJITDylib(std::string Name) {
1941f088e195SLang Hames   assert(!getJITDylibByName(Name) && "JITDylib with that name already exists");
1942d5f56c59SLang Hames   return runSessionLocked([&, this]() -> JITDylib & {
19430aec49c8SLang Hames     JDs.push_back(new JITDylib(*this, std::move(Name)));
1944d5f56c59SLang Hames     return *JDs.back();
1945d261e125SLang Hames   });
19469bbd6530SLang Hames }
19479bbd6530SLang Hames 
createJITDylib(std::string Name)194885fb9976SLang Hames Expected<JITDylib &> ExecutionSession::createJITDylib(std::string Name) {
194985fb9976SLang Hames   auto &JD = createBareJITDylib(Name);
195085fb9976SLang Hames   if (P)
195185fb9976SLang Hames     if (auto Err = P->setupJITDylib(JD))
195285fb9976SLang Hames       return std::move(Err);
195385fb9976SLang Hames   return JD;
195485fb9976SLang Hames }
195585fb9976SLang Hames 
removeJITDylib(JITDylib & JD)1956758d54b4SLang Hames Error ExecutionSession::removeJITDylib(JITDylib &JD) {
1957758d54b4SLang Hames   // Keep JD alive throughout this routine, even if all other references
1958758d54b4SLang Hames   // have been dropped.
1959758d54b4SLang Hames   JITDylibSP JDKeepAlive = &JD;
1960758d54b4SLang Hames 
1961758d54b4SLang Hames   // Set JD to 'Closing' state and remove JD from the ExecutionSession.
1962758d54b4SLang Hames   runSessionLocked([&] {
1963758d54b4SLang Hames     assert(JD.State == JITDylib::Open && "JD already closed");
1964758d54b4SLang Hames     JD.State = JITDylib::Closing;
1965758d54b4SLang Hames     auto I = llvm::find(JDs, &JD);
1966758d54b4SLang Hames     assert(I != JDs.end() && "JD does not appear in session JDs");
1967758d54b4SLang Hames     JDs.erase(I);
1968758d54b4SLang Hames   });
1969758d54b4SLang Hames 
1970ade71641SLang Hames   // Clear the JITDylib. Hold on to any error while we clean up the
1971ade71641SLang Hames   // JITDylib members below.
1972758d54b4SLang Hames   auto Err = JD.clear();
1973758d54b4SLang Hames 
1974ade71641SLang Hames   // Notify the platform of the teardown.
1975ade71641SLang Hames   if (P)
1976ade71641SLang Hames     Err = joinErrors(std::move(Err), P->teardownJITDylib(JD));
1977ade71641SLang Hames 
1978758d54b4SLang Hames   // Set JD to closed state. Clear remaining data structures.
1979758d54b4SLang Hames   runSessionLocked([&] {
1980758d54b4SLang Hames     assert(JD.State == JITDylib::Closing && "JD should be closing");
1981758d54b4SLang Hames     JD.State = JITDylib::Closed;
1982758d54b4SLang Hames     assert(JD.Symbols.empty() && "JD.Symbols is not empty after clear");
1983758d54b4SLang Hames     assert(JD.UnmaterializedInfos.empty() &&
1984758d54b4SLang Hames            "JD.UnmaterializedInfos is not empty after clear");
1985758d54b4SLang Hames     assert(JD.MaterializingInfos.empty() &&
1986758d54b4SLang Hames            "JD.MaterializingInfos is not empty after clear");
1987758d54b4SLang Hames     assert(JD.TrackerSymbols.empty() &&
1988758d54b4SLang Hames            "TrackerSymbols is not empty after clear");
1989758d54b4SLang Hames     JD.DefGenerators.clear();
1990758d54b4SLang Hames     JD.LinkOrder.clear();
1991758d54b4SLang Hames   });
1992758d54b4SLang Hames   return Err;
1993758d54b4SLang Hames }
1994758d54b4SLang Hames 
19959eb4939bSLang Hames Expected<std::vector<JITDylibSP>>
getDFSLinkOrder(ArrayRef<JITDylibSP> JDs)19969eb4939bSLang Hames JITDylib::getDFSLinkOrder(ArrayRef<JITDylibSP> JDs) {
1997e1d5f7d0SLang Hames   if (JDs.empty())
19989eb4939bSLang Hames     return std::vector<JITDylibSP>();
1999e1d5f7d0SLang Hames 
2000e1d5f7d0SLang Hames   auto &ES = JDs.front()->getExecutionSession();
20019eb4939bSLang Hames   return ES.runSessionLocked([&]() -> Expected<std::vector<JITDylibSP>> {
2002e1d5f7d0SLang Hames     DenseSet<JITDylib *> Visited;
20030aec49c8SLang Hames     std::vector<JITDylibSP> Result;
2004e1d5f7d0SLang Hames 
2005e1d5f7d0SLang Hames     for (auto &JD : JDs) {
2006e1d5f7d0SLang Hames 
20079eb4939bSLang Hames       if (JD->State != Open)
20089eb4939bSLang Hames         return make_error<StringError>(
20099eb4939bSLang Hames             "Error building link order: " + JD->getName() + " is defunct",
20109eb4939bSLang Hames             inconvertibleErrorCode());
2011e1d5f7d0SLang Hames       if (Visited.count(JD.get()))
2012e1d5f7d0SLang Hames         continue;
2013e1d5f7d0SLang Hames 
20140aec49c8SLang Hames       SmallVector<JITDylibSP, 64> WorkStack;
2015e1d5f7d0SLang Hames       WorkStack.push_back(JD);
2016e1d5f7d0SLang Hames       Visited.insert(JD.get());
2017e1d5f7d0SLang Hames 
2018e1d5f7d0SLang Hames       while (!WorkStack.empty()) {
2019e1d5f7d0SLang Hames         Result.push_back(std::move(WorkStack.back()));
2020e1d5f7d0SLang Hames         WorkStack.pop_back();
2021e1d5f7d0SLang Hames 
2022e1d5f7d0SLang Hames         for (auto &KV : llvm::reverse(Result.back()->LinkOrder)) {
2023e1d5f7d0SLang Hames           auto &JD = *KV.first;
2024*b254d671SKazu Hirata           if (!Visited.insert(&JD).second)
2025e1d5f7d0SLang Hames             continue;
20260aec49c8SLang Hames           WorkStack.push_back(&JD);
2027e1d5f7d0SLang Hames         }
2028e1d5f7d0SLang Hames       }
2029e1d5f7d0SLang Hames     }
2030e1d5f7d0SLang Hames     return Result;
2031e1d5f7d0SLang Hames   });
2032db464a27SSourabh Singh Tomar }
2033e1d5f7d0SLang Hames 
20349eb4939bSLang Hames Expected<std::vector<JITDylibSP>>
getReverseDFSLinkOrder(ArrayRef<JITDylibSP> JDs)20350aec49c8SLang Hames JITDylib::getReverseDFSLinkOrder(ArrayRef<JITDylibSP> JDs) {
20369eb4939bSLang Hames   auto Result = getDFSLinkOrder(JDs);
20379eb4939bSLang Hames   if (Result)
20389eb4939bSLang Hames     std::reverse(Result->begin(), Result->end());
20399eb4939bSLang Hames   return Result;
2040e1d5f7d0SLang Hames }
2041e1d5f7d0SLang Hames 
getDFSLinkOrder()20429eb4939bSLang Hames Expected<std::vector<JITDylibSP>> JITDylib::getDFSLinkOrder() {
20430aec49c8SLang Hames   return getDFSLinkOrder({this});
2044e1d5f7d0SLang Hames }
2045e1d5f7d0SLang Hames 
getReverseDFSLinkOrder()20469eb4939bSLang Hames Expected<std::vector<JITDylibSP>> JITDylib::getReverseDFSLinkOrder() {
20470aec49c8SLang Hames   return getReverseDFSLinkOrder({this});
2048e1d5f7d0SLang Hames }
2049e1d5f7d0SLang Hames 
lookupFlags(LookupKind K,JITDylibSearchOrder SearchOrder,SymbolLookupSet LookupSet,unique_function<void (Expected<SymbolFlagsMap>)> OnComplete)2050069919c9SLang Hames void ExecutionSession::lookupFlags(
2051069919c9SLang Hames     LookupKind K, JITDylibSearchOrder SearchOrder, SymbolLookupSet LookupSet,
2052069919c9SLang Hames     unique_function<void(Expected<SymbolFlagsMap>)> OnComplete) {
2053069919c9SLang Hames 
2054069919c9SLang Hames   OL_applyQueryPhase1(std::make_unique<InProgressLookupFlagsState>(
2055069919c9SLang Hames                           K, std::move(SearchOrder), std::move(LookupSet),
2056069919c9SLang Hames                           std::move(OnComplete)),
2057069919c9SLang Hames                       Error::success());
2058069919c9SLang Hames }
2059069919c9SLang Hames 
2060069919c9SLang Hames Expected<SymbolFlagsMap>
lookupFlags(LookupKind K,JITDylibSearchOrder SearchOrder,SymbolLookupSet LookupSet)2061069919c9SLang Hames ExecutionSession::lookupFlags(LookupKind K, JITDylibSearchOrder SearchOrder,
2062069919c9SLang Hames                               SymbolLookupSet LookupSet) {
2063069919c9SLang Hames 
2064069919c9SLang Hames   std::promise<MSVCPExpected<SymbolFlagsMap>> ResultP;
2065069919c9SLang Hames   OL_applyQueryPhase1(std::make_unique<InProgressLookupFlagsState>(
2066069919c9SLang Hames                           K, std::move(SearchOrder), std::move(LookupSet),
2067069919c9SLang Hames                           [&ResultP](Expected<SymbolFlagsMap> Result) {
2068069919c9SLang Hames                             ResultP.set_value(std::move(Result));
2069069919c9SLang Hames                           }),
2070069919c9SLang Hames                       Error::success());
2071069919c9SLang Hames 
2072069919c9SLang Hames   auto ResultF = ResultP.get_future();
2073069919c9SLang Hames   return ResultF.get();
2074069919c9SLang Hames }
2075069919c9SLang Hames 
lookup(LookupKind K,const JITDylibSearchOrder & SearchOrder,SymbolLookupSet Symbols,SymbolState RequiredState,SymbolsResolvedCallback NotifyComplete,RegisterDependenciesFunction RegisterDependencies)207623cb2e7fSLang Hames void ExecutionSession::lookup(
2077674df13bSLang Hames     LookupKind K, const JITDylibSearchOrder &SearchOrder,
2078674df13bSLang Hames     SymbolLookupSet Symbols, SymbolState RequiredState,
2079674df13bSLang Hames     SymbolsResolvedCallback NotifyComplete,
208023cb2e7fSLang Hames     RegisterDependenciesFunction RegisterDependencies) {
20818be0d2e3SLang Hames 
2082d4a8089fSLang Hames   LLVM_DEBUG({
2083d4a8089fSLang Hames     runSessionLocked([&]() {
2084d4a8089fSLang Hames       dbgs() << "Looking up " << Symbols << " in " << SearchOrder
2085d4a8089fSLang Hames              << " (required state: " << RequiredState << ")\n";
2086d4a8089fSLang Hames     });
2087d4a8089fSLang Hames   });
2088d4a8089fSLang Hames 
20898be0d2e3SLang Hames   // lookup can be re-entered recursively if running on a single thread. Run any
20907899ccbcSLang Hames   // outstanding MUs in case this query depends on them, otherwise this lookup
20917899ccbcSLang Hames   // will starve waiting for a result from an MU that is stuck in the queue.
2092069919c9SLang Hames   dispatchOutstandingMUs();
20938be0d2e3SLang Hames 
20948be0d2e3SLang Hames   auto Unresolved = std::move(Symbols);
2095d4a8089fSLang Hames   auto Q = std::make_shared<AsynchronousSymbolQuery>(Unresolved, RequiredState,
2096d4a8089fSLang Hames                                                      std::move(NotifyComplete));
20978be0d2e3SLang Hames 
2098069919c9SLang Hames   auto IPLS = std::make_unique<InProgressFullLookupState>(
2099069919c9SLang Hames       K, SearchOrder, std::move(Unresolved), RequiredState, std::move(Q),
2100069919c9SLang Hames       std::move(RegisterDependencies));
21010aec49c8SLang Hames 
2102069919c9SLang Hames   OL_applyQueryPhase1(std::move(IPLS), Error::success());
21038be0d2e3SLang Hames }
21048be0d2e3SLang Hames 
2105d4a8089fSLang Hames Expected<SymbolMap>
lookup(const JITDylibSearchOrder & SearchOrder,SymbolLookupSet Symbols,LookupKind K,SymbolState RequiredState,RegisterDependenciesFunction RegisterDependencies)2106674df13bSLang Hames ExecutionSession::lookup(const JITDylibSearchOrder &SearchOrder,
21074bb18a89SLang Hames                          SymbolLookupSet Symbols, LookupKind K,
2108d4a8089fSLang Hames                          SymbolState RequiredState,
2109d4a8089fSLang Hames                          RegisterDependenciesFunction RegisterDependencies) {
21108be0d2e3SLang Hames #if LLVM_ENABLE_THREADS
21118be0d2e3SLang Hames   // In the threaded case we use promises to return the results.
21128be0d2e3SLang Hames   std::promise<SymbolMap> PromisedResult;
21138be0d2e3SLang Hames   Error ResolutionError = Error::success();
2114d4a8089fSLang Hames 
2115d4a8089fSLang Hames   auto NotifyComplete = [&](Expected<SymbolMap> R) {
21168be0d2e3SLang Hames     if (R)
21178be0d2e3SLang Hames       PromisedResult.set_value(std::move(*R));
21188be0d2e3SLang Hames     else {
21198be0d2e3SLang Hames       ErrorAsOutParameter _(&ResolutionError);
21208be0d2e3SLang Hames       ResolutionError = R.takeError();
21218be0d2e3SLang Hames       PromisedResult.set_value(SymbolMap());
21228be0d2e3SLang Hames     }
21238be0d2e3SLang Hames   };
21248be0d2e3SLang Hames 
21258be0d2e3SLang Hames #else
21268be0d2e3SLang Hames   SymbolMap Result;
21278be0d2e3SLang Hames   Error ResolutionError = Error::success();
21288be0d2e3SLang Hames 
2129d4a8089fSLang Hames   auto NotifyComplete = [&](Expected<SymbolMap> R) {
21308be0d2e3SLang Hames     ErrorAsOutParameter _(&ResolutionError);
21318be0d2e3SLang Hames     if (R)
21328be0d2e3SLang Hames       Result = std::move(*R);
21338be0d2e3SLang Hames     else
21348be0d2e3SLang Hames       ResolutionError = R.takeError();
21358be0d2e3SLang Hames   };
21368be0d2e3SLang Hames #endif
21378be0d2e3SLang Hames 
21388be0d2e3SLang Hames   // Perform the asynchronous lookup.
21394bb18a89SLang Hames   lookup(K, SearchOrder, std::move(Symbols), RequiredState, NotifyComplete,
2140d4a8089fSLang Hames          RegisterDependencies);
21418be0d2e3SLang Hames 
21428be0d2e3SLang Hames #if LLVM_ENABLE_THREADS
21438be0d2e3SLang Hames   auto ResultFuture = PromisedResult.get_future();
21448be0d2e3SLang Hames   auto Result = ResultFuture.get();
21458be0d2e3SLang Hames 
2146d4a8089fSLang Hames   if (ResolutionError)
2147c55cf4afSBill Wendling     return std::move(ResolutionError);
21488be0d2e3SLang Hames 
2149c55cf4afSBill Wendling   return std::move(Result);
21508be0d2e3SLang Hames 
21518be0d2e3SLang Hames #else
2152d4a8089fSLang Hames   if (ResolutionError)
2153c55cf4afSBill Wendling     return std::move(ResolutionError);
21548be0d2e3SLang Hames 
21558be0d2e3SLang Hames   return Result;
21568be0d2e3SLang Hames #endif
21578be0d2e3SLang Hames }
21588be0d2e3SLang Hames 
215923cb2e7fSLang Hames Expected<JITEvaluatedSymbol>
lookup(const JITDylibSearchOrder & SearchOrder,SymbolStringPtr Name,SymbolState RequiredState)2160674df13bSLang Hames ExecutionSession::lookup(const JITDylibSearchOrder &SearchOrder,
216185fb9976SLang Hames                          SymbolStringPtr Name, SymbolState RequiredState) {
2162674df13bSLang Hames   SymbolLookupSet Names({Name});
21637899ccbcSLang Hames 
2164674df13bSLang Hames   if (auto ResultMap = lookup(SearchOrder, std::move(Names), LookupKind::Static,
216585fb9976SLang Hames                               RequiredState, NoDependenciesToRegister)) {
21667899ccbcSLang Hames     assert(ResultMap->size() == 1 && "Unexpected number of results");
21677899ccbcSLang Hames     assert(ResultMap->count(Name) && "Missing result for symbol");
21687899ccbcSLang Hames     return std::move(ResultMap->begin()->second);
21697899ccbcSLang Hames   } else
21707899ccbcSLang Hames     return ResultMap.takeError();
21717899ccbcSLang Hames }
21727899ccbcSLang Hames 
217323cb2e7fSLang Hames Expected<JITEvaluatedSymbol>
lookup(ArrayRef<JITDylib * > SearchOrder,SymbolStringPtr Name,SymbolState RequiredState)217485fb9976SLang Hames ExecutionSession::lookup(ArrayRef<JITDylib *> SearchOrder, SymbolStringPtr Name,
217585fb9976SLang Hames                          SymbolState RequiredState) {
217685fb9976SLang Hames   return lookup(makeJITDylibSearchOrder(SearchOrder), Name, RequiredState);
217723cb2e7fSLang Hames }
217823cb2e7fSLang Hames 
217923cb2e7fSLang Hames Expected<JITEvaluatedSymbol>
lookup(ArrayRef<JITDylib * > SearchOrder,StringRef Name,SymbolState RequiredState)218085fb9976SLang Hames ExecutionSession::lookup(ArrayRef<JITDylib *> SearchOrder, StringRef Name,
218185fb9976SLang Hames                          SymbolState RequiredState) {
218285fb9976SLang Hames   return lookup(SearchOrder, intern(Name), RequiredState);
21837899ccbcSLang Hames }
21847899ccbcSLang Hames 
registerJITDispatchHandlers(JITDylib & JD,JITDispatchHandlerAssociationMap WFs)21852487db1fSLang Hames Error ExecutionSession::registerJITDispatchHandlers(
21862487db1fSLang Hames     JITDylib &JD, JITDispatchHandlerAssociationMap WFs) {
21872487db1fSLang Hames 
21882487db1fSLang Hames   auto TagAddrs = lookup({{&JD, JITDylibLookupFlags::MatchAllSymbols}},
21892487db1fSLang Hames                          SymbolLookupSet::fromMapKeys(
21902487db1fSLang Hames                              WFs, SymbolLookupFlags::WeaklyReferencedSymbol));
21912487db1fSLang Hames   if (!TagAddrs)
21922487db1fSLang Hames     return TagAddrs.takeError();
21932487db1fSLang Hames 
21942487db1fSLang Hames   // Associate tag addresses with implementations.
21952487db1fSLang Hames   std::lock_guard<std::mutex> Lock(JITDispatchHandlersMutex);
21962487db1fSLang Hames   for (auto &KV : *TagAddrs) {
21972487db1fSLang Hames     auto TagAddr = KV.second.getAddress();
21982487db1fSLang Hames     if (JITDispatchHandlers.count(TagAddr))
21992487db1fSLang Hames       return make_error<StringError>("Tag " + formatv("{0:x16}", TagAddr) +
22002487db1fSLang Hames                                          " (for " + *KV.first +
22012487db1fSLang Hames                                          ") already registered",
22022487db1fSLang Hames                                      inconvertibleErrorCode());
22032487db1fSLang Hames     auto I = WFs.find(KV.first);
22042487db1fSLang Hames     assert(I != WFs.end() && I->second &&
22052487db1fSLang Hames            "JITDispatchHandler implementation missing");
22062487db1fSLang Hames     JITDispatchHandlers[KV.second.getAddress()] =
22072487db1fSLang Hames         std::make_shared<JITDispatchHandlerFunction>(std::move(I->second));
22082487db1fSLang Hames     LLVM_DEBUG({
22092487db1fSLang Hames       dbgs() << "Associated function tag \"" << *KV.first << "\" ("
22102487db1fSLang Hames              << formatv("{0:x}", KV.second.getAddress()) << ") with handler\n";
22112487db1fSLang Hames     });
22122487db1fSLang Hames   }
22132487db1fSLang Hames   return Error::success();
22142487db1fSLang Hames }
22152487db1fSLang Hames 
runJITDispatchHandler(SendResultFunction SendResult,JITTargetAddress HandlerFnTagAddr,ArrayRef<char> ArgBuffer)22162487db1fSLang Hames void ExecutionSession::runJITDispatchHandler(
22174d7cea3dSLang Hames     SendResultFunction SendResult, JITTargetAddress HandlerFnTagAddr,
22184d7cea3dSLang Hames     ArrayRef<char> ArgBuffer) {
22192487db1fSLang Hames 
22202487db1fSLang Hames   std::shared_ptr<JITDispatchHandlerFunction> F;
22212487db1fSLang Hames   {
22222487db1fSLang Hames     std::lock_guard<std::mutex> Lock(JITDispatchHandlersMutex);
22232487db1fSLang Hames     auto I = JITDispatchHandlers.find(HandlerFnTagAddr);
22242487db1fSLang Hames     if (I != JITDispatchHandlers.end())
22252487db1fSLang Hames       F = I->second;
22262487db1fSLang Hames   }
22272487db1fSLang Hames 
22282487db1fSLang Hames   if (F)
22292487db1fSLang Hames     (*F)(std::move(SendResult), ArgBuffer.data(), ArgBuffer.size());
22302487db1fSLang Hames   else
22312487db1fSLang Hames     SendResult(shared::WrapperFunctionResult::createOutOfBandError(
22322487db1fSLang Hames         ("No function registered for tag " +
22332487db1fSLang Hames          formatv("{0:x16}", HandlerFnTagAddr))
22342487db1fSLang Hames             .str()));
22352487db1fSLang Hames }
22362487db1fSLang Hames 
dump(raw_ostream & OS)2237d8048675SLang Hames void ExecutionSession::dump(raw_ostream &OS) {
2238d8048675SLang Hames   runSessionLocked([this, &OS]() {
2239d8048675SLang Hames     for (auto &JD : JDs)
2240d8048675SLang Hames       JD->dump(OS);
2241d8048675SLang Hames   });
2242d8048675SLang Hames }
2243d8048675SLang Hames 
dispatchOutstandingMUs()2244069919c9SLang Hames void ExecutionSession::dispatchOutstandingMUs() {
2245069919c9SLang Hames   LLVM_DEBUG(dbgs() << "Dispatching MaterializationUnits...\n");
22462aed0813SKazu Hirata   while (true) {
224741379f1eSLang Hames     Optional<std::pair<std::unique_ptr<MaterializationUnit>,
22487dcd0042SLang Hames                        std::unique_ptr<MaterializationResponsibility>>>
224941379f1eSLang Hames         JMU;
22508be0d2e3SLang Hames 
22518be0d2e3SLang Hames     {
22528be0d2e3SLang Hames       std::lock_guard<std::recursive_mutex> Lock(OutstandingMUsMutex);
22538be0d2e3SLang Hames       if (!OutstandingMUs.empty()) {
225441379f1eSLang Hames         JMU.emplace(std::move(OutstandingMUs.back()));
22558be0d2e3SLang Hames         OutstandingMUs.pop_back();
22568be0d2e3SLang Hames       }
22578be0d2e3SLang Hames     }
22588be0d2e3SLang Hames 
225941379f1eSLang Hames     if (!JMU)
22608be0d2e3SLang Hames       break;
226141379f1eSLang Hames 
226241379f1eSLang Hames     assert(JMU->first && "No MU?");
2263069919c9SLang Hames     LLVM_DEBUG(dbgs() << "  Dispatching \"" << JMU->first->getName() << "\"\n");
22645344c88dSLang Hames     dispatchTask(std::make_unique<MaterializationTask>(std::move(JMU->first),
22655344c88dSLang Hames                                                        std::move(JMU->second)));
22668be0d2e3SLang Hames   }
2267069919c9SLang Hames   LLVM_DEBUG(dbgs() << "Done dispatching MaterializationUnits.\n");
22688be0d2e3SLang Hames }
22698be0d2e3SLang Hames 
removeResourceTracker(ResourceTracker & RT)22700aec49c8SLang Hames Error ExecutionSession::removeResourceTracker(ResourceTracker &RT) {
22710aec49c8SLang Hames   LLVM_DEBUG({
22720aec49c8SLang Hames     dbgs() << "In " << RT.getJITDylib().getName() << " removing tracker "
22730aec49c8SLang Hames            << formatv("{0:x}", RT.getKeyUnsafe()) << "\n";
22740aec49c8SLang Hames   });
22750aec49c8SLang Hames   std::vector<ResourceManager *> CurrentResourceManagers;
22760aec49c8SLang Hames 
22770aec49c8SLang Hames   JITDylib::AsynchronousSymbolQuerySet QueriesToFail;
22780aec49c8SLang Hames   std::shared_ptr<SymbolDependenceMap> FailedSymbols;
22790aec49c8SLang Hames 
22800aec49c8SLang Hames   runSessionLocked([&] {
22810aec49c8SLang Hames     CurrentResourceManagers = ResourceManagers;
22820aec49c8SLang Hames     RT.makeDefunct();
22830aec49c8SLang Hames     std::tie(QueriesToFail, FailedSymbols) = RT.getJITDylib().removeTracker(RT);
22840aec49c8SLang Hames   });
22850aec49c8SLang Hames 
22860aec49c8SLang Hames   Error Err = Error::success();
22870aec49c8SLang Hames 
22880aec49c8SLang Hames   for (auto *L : reverse(CurrentResourceManagers))
22890aec49c8SLang Hames     Err =
22900aec49c8SLang Hames         joinErrors(std::move(Err), L->handleRemoveResources(RT.getKeyUnsafe()));
22910aec49c8SLang Hames 
22920aec49c8SLang Hames   for (auto &Q : QueriesToFail)
229355e8f721SLang Hames     Q->handleFailed(
229455e8f721SLang Hames         make_error<FailedToMaterialize>(getSymbolStringPool(), FailedSymbols));
22950aec49c8SLang Hames 
22960aec49c8SLang Hames   return Err;
22970aec49c8SLang Hames }
22980aec49c8SLang Hames 
transferResourceTracker(ResourceTracker & DstRT,ResourceTracker & SrcRT)22990aec49c8SLang Hames void ExecutionSession::transferResourceTracker(ResourceTracker &DstRT,
23000aec49c8SLang Hames                                                ResourceTracker &SrcRT) {
23010aec49c8SLang Hames   LLVM_DEBUG({
23020aec49c8SLang Hames     dbgs() << "In " << SrcRT.getJITDylib().getName()
23030aec49c8SLang Hames            << " transfering resources from tracker "
23040aec49c8SLang Hames            << formatv("{0:x}", SrcRT.getKeyUnsafe()) << " to tracker "
23050aec49c8SLang Hames            << formatv("{0:x}", DstRT.getKeyUnsafe()) << "\n";
23060aec49c8SLang Hames   });
23070aec49c8SLang Hames 
23080aec49c8SLang Hames   // No-op transfers are allowed and do not invalidate the source.
23090aec49c8SLang Hames   if (&DstRT == &SrcRT)
23100aec49c8SLang Hames     return;
23110aec49c8SLang Hames 
23120aec49c8SLang Hames   assert(&DstRT.getJITDylib() == &SrcRT.getJITDylib() &&
23130aec49c8SLang Hames          "Can't transfer resources between JITDylibs");
23140aec49c8SLang Hames   runSessionLocked([&]() {
23150aec49c8SLang Hames     SrcRT.makeDefunct();
23160aec49c8SLang Hames     auto &JD = DstRT.getJITDylib();
23170aec49c8SLang Hames     JD.transferTracker(DstRT, SrcRT);
23180aec49c8SLang Hames     for (auto *L : reverse(ResourceManagers))
23190aec49c8SLang Hames       L->handleTransferResources(DstRT.getKeyUnsafe(), SrcRT.getKeyUnsafe());
23200aec49c8SLang Hames   });
23210aec49c8SLang Hames }
23220aec49c8SLang Hames 
destroyResourceTracker(ResourceTracker & RT)23230aec49c8SLang Hames void ExecutionSession::destroyResourceTracker(ResourceTracker &RT) {
23240aec49c8SLang Hames   runSessionLocked([&]() {
23250aec49c8SLang Hames     LLVM_DEBUG({
23260aec49c8SLang Hames       dbgs() << "In " << RT.getJITDylib().getName() << " destroying tracker "
23270aec49c8SLang Hames              << formatv("{0:x}", RT.getKeyUnsafe()) << "\n";
23280aec49c8SLang Hames     });
23290aec49c8SLang Hames     if (!RT.isDefunct())
23300aec49c8SLang Hames       transferResourceTracker(*RT.getJITDylib().getDefaultResourceTracker(),
23310aec49c8SLang Hames                               RT);
23320aec49c8SLang Hames   });
23330aec49c8SLang Hames }
23340aec49c8SLang Hames 
IL_updateCandidatesFor(JITDylib & JD,JITDylibLookupFlags JDLookupFlags,SymbolLookupSet & Candidates,SymbolLookupSet * NonCandidates)2335069919c9SLang Hames Error ExecutionSession::IL_updateCandidatesFor(
2336069919c9SLang Hames     JITDylib &JD, JITDylibLookupFlags JDLookupFlags,
2337069919c9SLang Hames     SymbolLookupSet &Candidates, SymbolLookupSet *NonCandidates) {
2338069919c9SLang Hames   return Candidates.forEachWithRemoval(
2339069919c9SLang Hames       [&](const SymbolStringPtr &Name,
2340069919c9SLang Hames           SymbolLookupFlags SymLookupFlags) -> Expected<bool> {
2341069919c9SLang Hames         /// Search for the symbol. If not found then continue without
2342069919c9SLang Hames         /// removal.
2343069919c9SLang Hames         auto SymI = JD.Symbols.find(Name);
2344069919c9SLang Hames         if (SymI == JD.Symbols.end())
2345069919c9SLang Hames           return false;
2346069919c9SLang Hames 
2347069919c9SLang Hames         // If this is a non-exported symbol and we're matching exported
2348069919c9SLang Hames         // symbols only then remove this symbol from the candidates list.
2349069919c9SLang Hames         //
2350069919c9SLang Hames         // If we're tracking non-candidates then add this to the non-candidate
2351069919c9SLang Hames         // list.
2352069919c9SLang Hames         if (!SymI->second.getFlags().isExported() &&
2353069919c9SLang Hames             JDLookupFlags == JITDylibLookupFlags::MatchExportedSymbolsOnly) {
2354069919c9SLang Hames           if (NonCandidates)
2355069919c9SLang Hames             NonCandidates->add(Name, SymLookupFlags);
2356069919c9SLang Hames           return true;
2357069919c9SLang Hames         }
2358069919c9SLang Hames 
2359069919c9SLang Hames         // If we match against a materialization-side-effects only symbol
2360069919c9SLang Hames         // then make sure it is weakly-referenced. Otherwise bail out with
2361069919c9SLang Hames         // an error.
2362069919c9SLang Hames         // FIXME: Use a "materialization-side-effects-only symbols must be
2363069919c9SLang Hames         // weakly referenced" specific error here to reduce confusion.
2364069919c9SLang Hames         if (SymI->second.getFlags().hasMaterializationSideEffectsOnly() &&
2365069919c9SLang Hames             SymLookupFlags != SymbolLookupFlags::WeaklyReferencedSymbol)
23666fe2e9a9SLang Hames           return make_error<SymbolsNotFound>(getSymbolStringPool(),
23676fe2e9a9SLang Hames                                              SymbolNameVector({Name}));
2368069919c9SLang Hames 
2369069919c9SLang Hames         // If we matched against this symbol but it is in the error state
2370069919c9SLang Hames         // then bail out and treat it as a failure to materialize.
2371069919c9SLang Hames         if (SymI->second.getFlags().hasError()) {
2372069919c9SLang Hames           auto FailedSymbolsMap = std::make_shared<SymbolDependenceMap>();
2373069919c9SLang Hames           (*FailedSymbolsMap)[&JD] = {Name};
237455e8f721SLang Hames           return make_error<FailedToMaterialize>(getSymbolStringPool(),
237555e8f721SLang Hames                                                  std::move(FailedSymbolsMap));
2376069919c9SLang Hames         }
2377069919c9SLang Hames 
2378069919c9SLang Hames         // Otherwise this is a match. Remove it from the candidate set.
2379069919c9SLang Hames         return true;
2380069919c9SLang Hames       });
2381069919c9SLang Hames }
2382069919c9SLang Hames 
OL_applyQueryPhase1(std::unique_ptr<InProgressLookupState> IPLS,Error Err)2383069919c9SLang Hames void ExecutionSession::OL_applyQueryPhase1(
2384069919c9SLang Hames     std::unique_ptr<InProgressLookupState> IPLS, Error Err) {
2385069919c9SLang Hames 
2386069919c9SLang Hames   LLVM_DEBUG({
2387069919c9SLang Hames     dbgs() << "Entering OL_applyQueryPhase1:\n"
2388069919c9SLang Hames            << "  Lookup kind: " << IPLS->K << "\n"
2389069919c9SLang Hames            << "  Search order: " << IPLS->SearchOrder
2390069919c9SLang Hames            << ", Current index = " << IPLS->CurSearchOrderIndex
2391069919c9SLang Hames            << (IPLS->NewJITDylib ? " (entering new JITDylib)" : "") << "\n"
2392069919c9SLang Hames            << "  Lookup set: " << IPLS->LookupSet << "\n"
2393069919c9SLang Hames            << "  Definition generator candidates: "
2394069919c9SLang Hames            << IPLS->DefGeneratorCandidates << "\n"
2395069919c9SLang Hames            << "  Definition generator non-candidates: "
2396069919c9SLang Hames            << IPLS->DefGeneratorNonCandidates << "\n";
2397069919c9SLang Hames   });
2398069919c9SLang Hames 
2399069919c9SLang Hames   // FIXME: We should attach the query as we go: This provides a result in a
2400069919c9SLang Hames   // single pass in the common case where all symbols have already reached the
2401069919c9SLang Hames   // required state. The query could be detached again in the 'fail' method on
2402069919c9SLang Hames   // IPLS. Phase 2 would be reduced to collecting and dispatching the MUs.
2403069919c9SLang Hames 
2404069919c9SLang Hames   while (IPLS->CurSearchOrderIndex != IPLS->SearchOrder.size()) {
2405069919c9SLang Hames 
2406069919c9SLang Hames     // If we've been handed an error or received one back from a generator then
2407069919c9SLang Hames     // fail the query. We don't need to unlink: At this stage the query hasn't
2408069919c9SLang Hames     // actually been lodged.
2409069919c9SLang Hames     if (Err)
2410069919c9SLang Hames       return IPLS->fail(std::move(Err));
2411069919c9SLang Hames 
2412069919c9SLang Hames     // Get the next JITDylib and lookup flags.
2413069919c9SLang Hames     auto &KV = IPLS->SearchOrder[IPLS->CurSearchOrderIndex];
2414069919c9SLang Hames     auto &JD = *KV.first;
2415069919c9SLang Hames     auto JDLookupFlags = KV.second;
2416069919c9SLang Hames 
2417069919c9SLang Hames     LLVM_DEBUG({
2418069919c9SLang Hames       dbgs() << "Visiting \"" << JD.getName() << "\" (" << JDLookupFlags
2419069919c9SLang Hames              << ") with lookup set " << IPLS->LookupSet << ":\n";
2420069919c9SLang Hames     });
2421069919c9SLang Hames 
2422069919c9SLang Hames     // If we've just reached a new JITDylib then perform some setup.
2423069919c9SLang Hames     if (IPLS->NewJITDylib) {
2424069919c9SLang Hames 
2425069919c9SLang Hames       // Acquire the generator lock for this JITDylib.
2426069919c9SLang Hames       IPLS->GeneratorLock = std::unique_lock<std::mutex>(JD.GeneratorsMutex);
2427069919c9SLang Hames 
2428069919c9SLang Hames       // Add any non-candidates from the last JITDylib (if any) back on to the
2429069919c9SLang Hames       // list of definition candidates for this JITDylib, reset definition
2430069919c9SLang Hames       // non-candiates to the empty set.
2431069919c9SLang Hames       SymbolLookupSet Tmp;
2432069919c9SLang Hames       std::swap(IPLS->DefGeneratorNonCandidates, Tmp);
2433069919c9SLang Hames       IPLS->DefGeneratorCandidates.append(std::move(Tmp));
2434069919c9SLang Hames 
2435069919c9SLang Hames       LLVM_DEBUG({
2436069919c9SLang Hames         dbgs() << "  First time visiting " << JD.getName()
2437069919c9SLang Hames                << ", resetting candidate sets and building generator stack\n";
2438069919c9SLang Hames       });
2439069919c9SLang Hames 
2440069919c9SLang Hames       // Build the definition generator stack for this JITDylib.
24419eb591f0SLang Hames       runSessionLocked([&] {
24429eb591f0SLang Hames         IPLS->CurDefGeneratorStack.reserve(JD.DefGenerators.size());
2443069919c9SLang Hames         for (auto &DG : reverse(JD.DefGenerators))
2444069919c9SLang Hames           IPLS->CurDefGeneratorStack.push_back(DG);
24459eb591f0SLang Hames       });
2446069919c9SLang Hames 
2447069919c9SLang Hames       // Flag that we've done our initialization.
2448069919c9SLang Hames       IPLS->NewJITDylib = false;
2449069919c9SLang Hames     }
2450069919c9SLang Hames 
2451069919c9SLang Hames     // Remove any generation candidates that are already defined (and match) in
2452069919c9SLang Hames     // this JITDylib.
2453069919c9SLang Hames     runSessionLocked([&] {
2454069919c9SLang Hames       // Update the list of candidates (and non-candidates) for definition
2455069919c9SLang Hames       // generation.
2456069919c9SLang Hames       LLVM_DEBUG(dbgs() << "  Updating candidate set...\n");
2457069919c9SLang Hames       Err = IL_updateCandidatesFor(
2458069919c9SLang Hames           JD, JDLookupFlags, IPLS->DefGeneratorCandidates,
2459069919c9SLang Hames           JD.DefGenerators.empty() ? nullptr
2460069919c9SLang Hames                                    : &IPLS->DefGeneratorNonCandidates);
2461069919c9SLang Hames       LLVM_DEBUG({
2462069919c9SLang Hames         dbgs() << "    Remaining candidates = " << IPLS->DefGeneratorCandidates
2463069919c9SLang Hames                << "\n";
2464069919c9SLang Hames       });
2465069919c9SLang Hames     });
2466069919c9SLang Hames 
2467069919c9SLang Hames     // If we encountered an error while filtering generation candidates then
2468069919c9SLang Hames     // bail out.
2469069919c9SLang Hames     if (Err)
2470069919c9SLang Hames       return IPLS->fail(std::move(Err));
2471069919c9SLang Hames 
2472069919c9SLang Hames     /// Apply any definition generators on the stack.
2473069919c9SLang Hames     LLVM_DEBUG({
2474069919c9SLang Hames       if (IPLS->CurDefGeneratorStack.empty())
2475069919c9SLang Hames         LLVM_DEBUG(dbgs() << "  No generators to run for this JITDylib.\n");
2476069919c9SLang Hames       else if (IPLS->DefGeneratorCandidates.empty())
2477069919c9SLang Hames         LLVM_DEBUG(dbgs() << "  No candidates to generate.\n");
2478069919c9SLang Hames       else
2479069919c9SLang Hames         dbgs() << "  Running " << IPLS->CurDefGeneratorStack.size()
2480069919c9SLang Hames                << " remaining generators for "
2481069919c9SLang Hames                << IPLS->DefGeneratorCandidates.size() << " candidates\n";
2482069919c9SLang Hames     });
2483069919c9SLang Hames     while (!IPLS->CurDefGeneratorStack.empty() &&
2484069919c9SLang Hames            !IPLS->DefGeneratorCandidates.empty()) {
2485069919c9SLang Hames       auto DG = IPLS->CurDefGeneratorStack.back().lock();
2486069919c9SLang Hames       IPLS->CurDefGeneratorStack.pop_back();
2487069919c9SLang Hames 
2488069919c9SLang Hames       if (!DG)
2489069919c9SLang Hames         return IPLS->fail(make_error<StringError>(
2490069919c9SLang Hames             "DefinitionGenerator removed while lookup in progress",
2491069919c9SLang Hames             inconvertibleErrorCode()));
2492069919c9SLang Hames 
2493069919c9SLang Hames       auto K = IPLS->K;
2494069919c9SLang Hames       auto &LookupSet = IPLS->DefGeneratorCandidates;
2495069919c9SLang Hames 
2496069919c9SLang Hames       // Run the generator. If the generator takes ownership of QA then this
2497069919c9SLang Hames       // will break the loop.
2498069919c9SLang Hames       {
2499069919c9SLang Hames         LLVM_DEBUG(dbgs() << "  Attempting to generate " << LookupSet << "\n");
2500069919c9SLang Hames         LookupState LS(std::move(IPLS));
2501069919c9SLang Hames         Err = DG->tryToGenerate(LS, K, JD, JDLookupFlags, LookupSet);
2502069919c9SLang Hames         IPLS = std::move(LS.IPLS);
2503069919c9SLang Hames       }
2504069919c9SLang Hames 
2505069919c9SLang Hames       // If there was an error then fail the query.
2506069919c9SLang Hames       if (Err) {
2507069919c9SLang Hames         LLVM_DEBUG({
2508069919c9SLang Hames           dbgs() << "  Error attempting to generate " << LookupSet << "\n";
2509069919c9SLang Hames         });
2510069919c9SLang Hames         assert(IPLS && "LS cannot be retained if error is returned");
2511069919c9SLang Hames         return IPLS->fail(std::move(Err));
2512069919c9SLang Hames       }
2513069919c9SLang Hames 
2514069919c9SLang Hames       // Otherwise if QA was captured then break the loop.
2515069919c9SLang Hames       if (!IPLS) {
2516069919c9SLang Hames         LLVM_DEBUG(
2517069919c9SLang Hames             { dbgs() << "  LookupState captured. Exiting phase1 for now.\n"; });
2518069919c9SLang Hames         return;
2519069919c9SLang Hames       }
2520069919c9SLang Hames 
2521069919c9SLang Hames       // Otherwise if we're continuing around the loop then update candidates
2522069919c9SLang Hames       // for the next round.
2523069919c9SLang Hames       runSessionLocked([&] {
2524069919c9SLang Hames         LLVM_DEBUG(dbgs() << "  Updating candidate set post-generation\n");
2525069919c9SLang Hames         Err = IL_updateCandidatesFor(
2526069919c9SLang Hames             JD, JDLookupFlags, IPLS->DefGeneratorCandidates,
2527069919c9SLang Hames             JD.DefGenerators.empty() ? nullptr
2528069919c9SLang Hames                                      : &IPLS->DefGeneratorNonCandidates);
2529069919c9SLang Hames       });
2530069919c9SLang Hames 
2531069919c9SLang Hames       // If updating candidates failed then fail the query.
2532069919c9SLang Hames       if (Err) {
2533069919c9SLang Hames         LLVM_DEBUG(dbgs() << "  Error encountered while updating candidates\n");
2534069919c9SLang Hames         return IPLS->fail(std::move(Err));
2535069919c9SLang Hames       }
2536069919c9SLang Hames     }
2537069919c9SLang Hames 
25383ce1e942SLang Hames     if (IPLS->DefGeneratorCandidates.empty() &&
25393ce1e942SLang Hames         IPLS->DefGeneratorNonCandidates.empty()) {
25403ce1e942SLang Hames       // Early out if there are no remaining symbols.
25413ce1e942SLang Hames       LLVM_DEBUG(dbgs() << "All symbols matched.\n");
25423ce1e942SLang Hames       IPLS->CurSearchOrderIndex = IPLS->SearchOrder.size();
25433ce1e942SLang Hames       break;
25443ce1e942SLang Hames     } else {
25453ce1e942SLang Hames       // If we get here then we've moved on to the next JITDylib with candidates
25463ce1e942SLang Hames       // remaining.
2547069919c9SLang Hames       LLVM_DEBUG(dbgs() << "Phase 1 moving to next JITDylib.\n");
2548069919c9SLang Hames       ++IPLS->CurSearchOrderIndex;
2549069919c9SLang Hames       IPLS->NewJITDylib = true;
2550069919c9SLang Hames     }
25513ce1e942SLang Hames   }
2552069919c9SLang Hames 
2553069919c9SLang Hames   // Remove any weakly referenced candidates that could not be found/generated.
2554069919c9SLang Hames   IPLS->DefGeneratorCandidates.remove_if(
2555069919c9SLang Hames       [](const SymbolStringPtr &Name, SymbolLookupFlags SymLookupFlags) {
2556069919c9SLang Hames         return SymLookupFlags == SymbolLookupFlags::WeaklyReferencedSymbol;
2557069919c9SLang Hames       });
2558069919c9SLang Hames 
2559069919c9SLang Hames   // If we get here then we've finished searching all JITDylibs.
2560069919c9SLang Hames   // If we matched all symbols then move to phase 2, otherwise fail the query
2561069919c9SLang Hames   // with a SymbolsNotFound error.
2562069919c9SLang Hames   if (IPLS->DefGeneratorCandidates.empty()) {
2563069919c9SLang Hames     LLVM_DEBUG(dbgs() << "Phase 1 succeeded.\n");
2564069919c9SLang Hames     IPLS->complete(std::move(IPLS));
2565069919c9SLang Hames   } else {
2566069919c9SLang Hames     LLVM_DEBUG(dbgs() << "Phase 1 failed with unresolved symbols.\n");
2567069919c9SLang Hames     IPLS->fail(make_error<SymbolsNotFound>(
25686fe2e9a9SLang Hames         getSymbolStringPool(), IPLS->DefGeneratorCandidates.getSymbolNames()));
2569069919c9SLang Hames   }
2570069919c9SLang Hames }
2571069919c9SLang Hames 
OL_completeLookup(std::unique_ptr<InProgressLookupState> IPLS,std::shared_ptr<AsynchronousSymbolQuery> Q,RegisterDependenciesFunction RegisterDependencies)2572069919c9SLang Hames void ExecutionSession::OL_completeLookup(
2573069919c9SLang Hames     std::unique_ptr<InProgressLookupState> IPLS,
2574069919c9SLang Hames     std::shared_ptr<AsynchronousSymbolQuery> Q,
2575069919c9SLang Hames     RegisterDependenciesFunction RegisterDependencies) {
2576069919c9SLang Hames 
2577069919c9SLang Hames   LLVM_DEBUG({
2578069919c9SLang Hames     dbgs() << "Entering OL_completeLookup:\n"
2579069919c9SLang Hames            << "  Lookup kind: " << IPLS->K << "\n"
2580069919c9SLang Hames            << "  Search order: " << IPLS->SearchOrder
2581069919c9SLang Hames            << ", Current index = " << IPLS->CurSearchOrderIndex
2582069919c9SLang Hames            << (IPLS->NewJITDylib ? " (entering new JITDylib)" : "") << "\n"
2583069919c9SLang Hames            << "  Lookup set: " << IPLS->LookupSet << "\n"
2584069919c9SLang Hames            << "  Definition generator candidates: "
2585069919c9SLang Hames            << IPLS->DefGeneratorCandidates << "\n"
2586069919c9SLang Hames            << "  Definition generator non-candidates: "
2587069919c9SLang Hames            << IPLS->DefGeneratorNonCandidates << "\n";
2588069919c9SLang Hames   });
2589069919c9SLang Hames 
2590069919c9SLang Hames   bool QueryComplete = false;
2591069919c9SLang Hames   DenseMap<JITDylib *, JITDylib::UnmaterializedInfosList> CollectedUMIs;
2592069919c9SLang Hames 
2593069919c9SLang Hames   auto LodgingErr = runSessionLocked([&]() -> Error {
2594069919c9SLang Hames     for (auto &KV : IPLS->SearchOrder) {
2595069919c9SLang Hames       auto &JD = *KV.first;
2596069919c9SLang Hames       auto JDLookupFlags = KV.second;
2597069919c9SLang Hames       LLVM_DEBUG({
2598069919c9SLang Hames         dbgs() << "Visiting \"" << JD.getName() << "\" (" << JDLookupFlags
2599069919c9SLang Hames                << ") with lookup set " << IPLS->LookupSet << ":\n";
2600069919c9SLang Hames       });
2601069919c9SLang Hames 
2602069919c9SLang Hames       auto Err = IPLS->LookupSet.forEachWithRemoval(
2603069919c9SLang Hames           [&](const SymbolStringPtr &Name,
2604069919c9SLang Hames               SymbolLookupFlags SymLookupFlags) -> Expected<bool> {
2605069919c9SLang Hames             LLVM_DEBUG({
2606069919c9SLang Hames               dbgs() << "  Attempting to match \"" << Name << "\" ("
2607069919c9SLang Hames                      << SymLookupFlags << ")... ";
2608069919c9SLang Hames             });
2609069919c9SLang Hames 
2610069919c9SLang Hames             /// Search for the symbol. If not found then continue without
2611069919c9SLang Hames             /// removal.
2612069919c9SLang Hames             auto SymI = JD.Symbols.find(Name);
2613069919c9SLang Hames             if (SymI == JD.Symbols.end()) {
2614069919c9SLang Hames               LLVM_DEBUG(dbgs() << "skipping: not present\n");
2615069919c9SLang Hames               return false;
2616069919c9SLang Hames             }
2617069919c9SLang Hames 
2618069919c9SLang Hames             // If this is a non-exported symbol and we're matching exported
2619069919c9SLang Hames             // symbols only then skip this symbol without removal.
2620069919c9SLang Hames             if (!SymI->second.getFlags().isExported() &&
2621069919c9SLang Hames                 JDLookupFlags ==
2622069919c9SLang Hames                     JITDylibLookupFlags::MatchExportedSymbolsOnly) {
2623069919c9SLang Hames               LLVM_DEBUG(dbgs() << "skipping: not exported\n");
2624069919c9SLang Hames               return false;
2625069919c9SLang Hames             }
2626069919c9SLang Hames 
2627069919c9SLang Hames             // If we match against a materialization-side-effects only symbol
2628069919c9SLang Hames             // then make sure it is weakly-referenced. Otherwise bail out with
2629069919c9SLang Hames             // an error.
2630069919c9SLang Hames             // FIXME: Use a "materialization-side-effects-only symbols must be
2631069919c9SLang Hames             // weakly referenced" specific error here to reduce confusion.
2632069919c9SLang Hames             if (SymI->second.getFlags().hasMaterializationSideEffectsOnly() &&
2633069919c9SLang Hames                 SymLookupFlags != SymbolLookupFlags::WeaklyReferencedSymbol) {
2634069919c9SLang Hames               LLVM_DEBUG({
2635069919c9SLang Hames                 dbgs() << "error: "
2636069919c9SLang Hames                           "required, but symbol is has-side-effects-only\n";
2637069919c9SLang Hames               });
26386fe2e9a9SLang Hames               return make_error<SymbolsNotFound>(getSymbolStringPool(),
26396fe2e9a9SLang Hames                                                  SymbolNameVector({Name}));
2640069919c9SLang Hames             }
2641069919c9SLang Hames 
2642069919c9SLang Hames             // If we matched against this symbol but it is in the error state
2643069919c9SLang Hames             // then bail out and treat it as a failure to materialize.
2644069919c9SLang Hames             if (SymI->second.getFlags().hasError()) {
2645069919c9SLang Hames               LLVM_DEBUG(dbgs() << "error: symbol is in error state\n");
2646069919c9SLang Hames               auto FailedSymbolsMap = std::make_shared<SymbolDependenceMap>();
2647069919c9SLang Hames               (*FailedSymbolsMap)[&JD] = {Name};
2648069919c9SLang Hames               return make_error<FailedToMaterialize>(
264955e8f721SLang Hames                   getSymbolStringPool(), std::move(FailedSymbolsMap));
2650069919c9SLang Hames             }
2651069919c9SLang Hames 
2652069919c9SLang Hames             // Otherwise this is a match.
2653069919c9SLang Hames 
2654069919c9SLang Hames             // If this symbol is already in the requried state then notify the
2655069919c9SLang Hames             // query, remove the symbol and continue.
2656069919c9SLang Hames             if (SymI->second.getState() >= Q->getRequiredState()) {
2657069919c9SLang Hames               LLVM_DEBUG(dbgs()
2658069919c9SLang Hames                          << "matched, symbol already in required state\n");
2659069919c9SLang Hames               Q->notifySymbolMetRequiredState(Name, SymI->second.getSymbol());
2660069919c9SLang Hames               return true;
2661069919c9SLang Hames             }
2662069919c9SLang Hames 
2663069919c9SLang Hames             // Otherwise this symbol does not yet meet the required state. Check
2664069919c9SLang Hames             // whether it has a materializer attached, and if so prepare to run
2665069919c9SLang Hames             // it.
2666069919c9SLang Hames             if (SymI->second.hasMaterializerAttached()) {
2667069919c9SLang Hames               assert(SymI->second.getAddress() == 0 &&
2668069919c9SLang Hames                      "Symbol not resolved but already has address?");
2669069919c9SLang Hames               auto UMII = JD.UnmaterializedInfos.find(Name);
2670069919c9SLang Hames               assert(UMII != JD.UnmaterializedInfos.end() &&
2671069919c9SLang Hames                      "Lazy symbol should have UnmaterializedInfo");
2672069919c9SLang Hames 
2673069919c9SLang Hames               auto UMI = UMII->second;
2674069919c9SLang Hames               assert(UMI->MU && "Materializer should not be null");
2675069919c9SLang Hames               assert(UMI->RT && "Tracker should not be null");
2676069919c9SLang Hames               LLVM_DEBUG({
2677069919c9SLang Hames                 dbgs() << "matched, preparing to dispatch MU@" << UMI->MU.get()
2678069919c9SLang Hames                        << " (" << UMI->MU->getName() << ")\n";
2679069919c9SLang Hames               });
2680069919c9SLang Hames 
2681069919c9SLang Hames               // Move all symbols associated with this MaterializationUnit into
2682069919c9SLang Hames               // materializing state.
2683069919c9SLang Hames               for (auto &KV : UMI->MU->getSymbols()) {
2684069919c9SLang Hames                 auto SymK = JD.Symbols.find(KV.first);
2685069919c9SLang Hames                 assert(SymK != JD.Symbols.end() &&
2686069919c9SLang Hames                        "No entry for symbol covered by MaterializationUnit");
2687069919c9SLang Hames                 SymK->second.setMaterializerAttached(false);
2688069919c9SLang Hames                 SymK->second.setState(SymbolState::Materializing);
2689069919c9SLang Hames                 JD.UnmaterializedInfos.erase(KV.first);
2690069919c9SLang Hames               }
2691069919c9SLang Hames 
2692069919c9SLang Hames               // Add MU to the list of MaterializationUnits to be materialized.
2693069919c9SLang Hames               CollectedUMIs[&JD].push_back(std::move(UMI));
2694069919c9SLang Hames             } else
2695069919c9SLang Hames               LLVM_DEBUG(dbgs() << "matched, registering query");
2696069919c9SLang Hames 
2697069919c9SLang Hames             // Add the query to the PendingQueries list and continue, deleting
2698069919c9SLang Hames             // the element from the lookup set.
2699069919c9SLang Hames             assert(SymI->second.getState() != SymbolState::NeverSearched &&
2700069919c9SLang Hames                    SymI->second.getState() != SymbolState::Ready &&
2701069919c9SLang Hames                    "By this line the symbol should be materializing");
2702069919c9SLang Hames             auto &MI = JD.MaterializingInfos[Name];
2703069919c9SLang Hames             MI.addQuery(Q);
2704069919c9SLang Hames             Q->addQueryDependence(JD, Name);
2705069919c9SLang Hames 
2706069919c9SLang Hames             return true;
2707069919c9SLang Hames           });
2708069919c9SLang Hames 
2709069919c9SLang Hames       // Handle failure.
2710069919c9SLang Hames       if (Err) {
2711069919c9SLang Hames 
2712069919c9SLang Hames         LLVM_DEBUG({
2713069919c9SLang Hames           dbgs() << "Lookup failed. Detaching query and replacing MUs.\n";
2714069919c9SLang Hames         });
2715069919c9SLang Hames 
2716069919c9SLang Hames         // Detach the query.
2717069919c9SLang Hames         Q->detach();
2718069919c9SLang Hames 
2719069919c9SLang Hames         // Replace the MUs.
2720069919c9SLang Hames         for (auto &KV : CollectedUMIs) {
2721069919c9SLang Hames           auto &JD = *KV.first;
2722069919c9SLang Hames           for (auto &UMI : KV.second)
2723069919c9SLang Hames             for (auto &KV2 : UMI->MU->getSymbols()) {
2724069919c9SLang Hames               assert(!JD.UnmaterializedInfos.count(KV2.first) &&
2725069919c9SLang Hames                      "Unexpected materializer in map");
2726069919c9SLang Hames               auto SymI = JD.Symbols.find(KV2.first);
2727069919c9SLang Hames               assert(SymI != JD.Symbols.end() && "Missing symbol entry");
2728069919c9SLang Hames               assert(SymI->second.getState() == SymbolState::Materializing &&
2729069919c9SLang Hames                      "Can not replace symbol that is not materializing");
2730069919c9SLang Hames               assert(!SymI->second.hasMaterializerAttached() &&
2731069919c9SLang Hames                      "MaterializerAttached flag should not be set");
2732069919c9SLang Hames               SymI->second.setMaterializerAttached(true);
2733069919c9SLang Hames               JD.UnmaterializedInfos[KV2.first] = UMI;
2734069919c9SLang Hames             }
2735069919c9SLang Hames         }
2736069919c9SLang Hames 
2737069919c9SLang Hames         return Err;
2738069919c9SLang Hames       }
2739069919c9SLang Hames     }
2740069919c9SLang Hames 
2741fc3b2675SLang Hames     LLVM_DEBUG(dbgs() << "Stripping unmatched weakly-referenced symbols\n");
2742069919c9SLang Hames     IPLS->LookupSet.forEachWithRemoval(
2743069919c9SLang Hames         [&](const SymbolStringPtr &Name, SymbolLookupFlags SymLookupFlags) {
2744069919c9SLang Hames           if (SymLookupFlags == SymbolLookupFlags::WeaklyReferencedSymbol) {
2745069919c9SLang Hames             Q->dropSymbol(Name);
2746069919c9SLang Hames             return true;
2747069919c9SLang Hames           } else
2748069919c9SLang Hames             return false;
2749069919c9SLang Hames         });
2750069919c9SLang Hames 
2751069919c9SLang Hames     if (!IPLS->LookupSet.empty()) {
2752069919c9SLang Hames       LLVM_DEBUG(dbgs() << "Failing due to unresolved symbols\n");
27536fe2e9a9SLang Hames       return make_error<SymbolsNotFound>(getSymbolStringPool(),
27546fe2e9a9SLang Hames                                          IPLS->LookupSet.getSymbolNames());
2755069919c9SLang Hames     }
2756069919c9SLang Hames 
2757069919c9SLang Hames     // Record whether the query completed.
2758069919c9SLang Hames     QueryComplete = Q->isComplete();
2759069919c9SLang Hames 
2760069919c9SLang Hames     LLVM_DEBUG({
2761069919c9SLang Hames       dbgs() << "Query successfully "
2762069919c9SLang Hames              << (QueryComplete ? "completed" : "lodged") << "\n";
2763069919c9SLang Hames     });
2764069919c9SLang Hames 
2765069919c9SLang Hames     // Move the collected MUs to the OutstandingMUs list.
2766069919c9SLang Hames     if (!CollectedUMIs.empty()) {
2767069919c9SLang Hames       std::lock_guard<std::recursive_mutex> Lock(OutstandingMUsMutex);
2768069919c9SLang Hames 
2769069919c9SLang Hames       LLVM_DEBUG(dbgs() << "Adding MUs to dispatch:\n");
2770069919c9SLang Hames       for (auto &KV : CollectedUMIs) {
2771069919c9SLang Hames         LLVM_DEBUG({
277222d82949SKazu Hirata           auto &JD = *KV.first;
2773069919c9SLang Hames           dbgs() << "  For " << JD.getName() << ": Adding " << KV.second.size()
2774069919c9SLang Hames                  << " MUs.\n";
2775069919c9SLang Hames         });
2776069919c9SLang Hames         for (auto &UMI : KV.second) {
27779355d115SLang Hames           auto MR = createMaterializationResponsibility(
27789355d115SLang Hames               *UMI->RT, std::move(UMI->MU->SymbolFlags),
27799355d115SLang Hames               std::move(UMI->MU->InitSymbol));
2780069919c9SLang Hames           OutstandingMUs.push_back(
2781069919c9SLang Hames               std::make_pair(std::move(UMI->MU), std::move(MR)));
2782069919c9SLang Hames         }
2783069919c9SLang Hames       }
2784069919c9SLang Hames     } else
2785069919c9SLang Hames       LLVM_DEBUG(dbgs() << "No MUs to dispatch.\n");
2786069919c9SLang Hames 
2787069919c9SLang Hames     if (RegisterDependencies && !Q->QueryRegistrations.empty()) {
2788069919c9SLang Hames       LLVM_DEBUG(dbgs() << "Registering dependencies\n");
2789069919c9SLang Hames       RegisterDependencies(Q->QueryRegistrations);
2790069919c9SLang Hames     } else
2791069919c9SLang Hames       LLVM_DEBUG(dbgs() << "No dependencies to register\n");
2792069919c9SLang Hames 
2793069919c9SLang Hames     return Error::success();
2794069919c9SLang Hames   });
2795069919c9SLang Hames 
2796069919c9SLang Hames   if (LodgingErr) {
2797069919c9SLang Hames     LLVM_DEBUG(dbgs() << "Failing query\n");
2798069919c9SLang Hames     Q->detach();
2799069919c9SLang Hames     Q->handleFailed(std::move(LodgingErr));
2800069919c9SLang Hames     return;
2801069919c9SLang Hames   }
2802069919c9SLang Hames 
2803069919c9SLang Hames   if (QueryComplete) {
2804069919c9SLang Hames     LLVM_DEBUG(dbgs() << "Completing query\n");
28057f9a89f9SLang Hames     Q->handleComplete(*this);
2806069919c9SLang Hames   }
2807069919c9SLang Hames 
2808069919c9SLang Hames   dispatchOutstandingMUs();
2809069919c9SLang Hames }
2810069919c9SLang Hames 
OL_completeLookupFlags(std::unique_ptr<InProgressLookupState> IPLS,unique_function<void (Expected<SymbolFlagsMap>)> OnComplete)2811069919c9SLang Hames void ExecutionSession::OL_completeLookupFlags(
2812069919c9SLang Hames     std::unique_ptr<InProgressLookupState> IPLS,
2813069919c9SLang Hames     unique_function<void(Expected<SymbolFlagsMap>)> OnComplete) {
2814069919c9SLang Hames 
2815069919c9SLang Hames   auto Result = runSessionLocked([&]() -> Expected<SymbolFlagsMap> {
2816069919c9SLang Hames     LLVM_DEBUG({
2817069919c9SLang Hames       dbgs() << "Entering OL_completeLookupFlags:\n"
2818069919c9SLang Hames              << "  Lookup kind: " << IPLS->K << "\n"
2819069919c9SLang Hames              << "  Search order: " << IPLS->SearchOrder
2820069919c9SLang Hames              << ", Current index = " << IPLS->CurSearchOrderIndex
2821069919c9SLang Hames              << (IPLS->NewJITDylib ? " (entering new JITDylib)" : "") << "\n"
2822069919c9SLang Hames              << "  Lookup set: " << IPLS->LookupSet << "\n"
2823069919c9SLang Hames              << "  Definition generator candidates: "
2824069919c9SLang Hames              << IPLS->DefGeneratorCandidates << "\n"
2825069919c9SLang Hames              << "  Definition generator non-candidates: "
2826069919c9SLang Hames              << IPLS->DefGeneratorNonCandidates << "\n";
2827069919c9SLang Hames     });
2828069919c9SLang Hames 
2829069919c9SLang Hames     SymbolFlagsMap Result;
2830069919c9SLang Hames 
2831069919c9SLang Hames     // Attempt to find flags for each symbol.
2832069919c9SLang Hames     for (auto &KV : IPLS->SearchOrder) {
2833069919c9SLang Hames       auto &JD = *KV.first;
2834069919c9SLang Hames       auto JDLookupFlags = KV.second;
2835069919c9SLang Hames       LLVM_DEBUG({
2836069919c9SLang Hames         dbgs() << "Visiting \"" << JD.getName() << "\" (" << JDLookupFlags
2837069919c9SLang Hames                << ") with lookup set " << IPLS->LookupSet << ":\n";
2838069919c9SLang Hames       });
2839069919c9SLang Hames 
2840069919c9SLang Hames       IPLS->LookupSet.forEachWithRemoval([&](const SymbolStringPtr &Name,
2841069919c9SLang Hames                                              SymbolLookupFlags SymLookupFlags) {
2842069919c9SLang Hames         LLVM_DEBUG({
2843069919c9SLang Hames           dbgs() << "  Attempting to match \"" << Name << "\" ("
2844069919c9SLang Hames                  << SymLookupFlags << ")... ";
2845069919c9SLang Hames         });
2846069919c9SLang Hames 
2847069919c9SLang Hames         // Search for the symbol. If not found then continue without removing
2848069919c9SLang Hames         // from the lookup set.
2849069919c9SLang Hames         auto SymI = JD.Symbols.find(Name);
2850069919c9SLang Hames         if (SymI == JD.Symbols.end()) {
2851069919c9SLang Hames           LLVM_DEBUG(dbgs() << "skipping: not present\n");
2852069919c9SLang Hames           return false;
2853069919c9SLang Hames         }
2854069919c9SLang Hames 
2855069919c9SLang Hames         // If this is a non-exported symbol then it doesn't match. Skip it.
2856069919c9SLang Hames         if (!SymI->second.getFlags().isExported() &&
2857069919c9SLang Hames             JDLookupFlags == JITDylibLookupFlags::MatchExportedSymbolsOnly) {
2858069919c9SLang Hames           LLVM_DEBUG(dbgs() << "skipping: not exported\n");
2859069919c9SLang Hames           return false;
2860069919c9SLang Hames         }
2861069919c9SLang Hames 
2862069919c9SLang Hames         LLVM_DEBUG({
2863069919c9SLang Hames           dbgs() << "matched, \"" << Name << "\" -> " << SymI->second.getFlags()
2864069919c9SLang Hames                  << "\n";
2865069919c9SLang Hames         });
2866069919c9SLang Hames         Result[Name] = SymI->second.getFlags();
2867069919c9SLang Hames         return true;
2868069919c9SLang Hames       });
2869069919c9SLang Hames     }
2870069919c9SLang Hames 
2871069919c9SLang Hames     // Remove any weakly referenced symbols that haven't been resolved.
2872069919c9SLang Hames     IPLS->LookupSet.remove_if(
2873069919c9SLang Hames         [](const SymbolStringPtr &Name, SymbolLookupFlags SymLookupFlags) {
2874069919c9SLang Hames           return SymLookupFlags == SymbolLookupFlags::WeaklyReferencedSymbol;
2875069919c9SLang Hames         });
2876069919c9SLang Hames 
2877069919c9SLang Hames     if (!IPLS->LookupSet.empty()) {
2878069919c9SLang Hames       LLVM_DEBUG(dbgs() << "Failing due to unresolved symbols\n");
28796fe2e9a9SLang Hames       return make_error<SymbolsNotFound>(getSymbolStringPool(),
28806fe2e9a9SLang Hames                                          IPLS->LookupSet.getSymbolNames());
2881069919c9SLang Hames     }
2882069919c9SLang Hames 
2883069919c9SLang Hames     LLVM_DEBUG(dbgs() << "Succeded, result = " << Result << "\n");
2884069919c9SLang Hames     return Result;
2885069919c9SLang Hames   });
2886069919c9SLang Hames 
2887069919c9SLang Hames   // Run the callback on the result.
2888069919c9SLang Hames   LLVM_DEBUG(dbgs() << "Sending result to handler.\n");
2889069919c9SLang Hames   OnComplete(std::move(Result));
2890069919c9SLang Hames }
2891069919c9SLang Hames 
OL_destroyMaterializationResponsibility(MaterializationResponsibility & MR)2892680845ecSLang Hames void ExecutionSession::OL_destroyMaterializationResponsibility(
2893680845ecSLang Hames     MaterializationResponsibility &MR) {
2894680845ecSLang Hames 
2895680845ecSLang Hames   assert(MR.SymbolFlags.empty() &&
2896680845ecSLang Hames          "All symbols should have been explicitly materialized or failed");
28979355d115SLang Hames   MR.JD.unlinkMaterializationResponsibility(MR);
2898680845ecSLang Hames }
2899680845ecSLang Hames 
OL_getRequestedSymbols(const MaterializationResponsibility & MR)2900680845ecSLang Hames SymbolNameSet ExecutionSession::OL_getRequestedSymbols(
2901680845ecSLang Hames     const MaterializationResponsibility &MR) {
29029355d115SLang Hames   return MR.JD.getRequestedSymbols(MR.SymbolFlags);
2903680845ecSLang Hames }
2904680845ecSLang Hames 
OL_notifyResolved(MaterializationResponsibility & MR,const SymbolMap & Symbols)2905680845ecSLang Hames Error ExecutionSession::OL_notifyResolved(MaterializationResponsibility &MR,
2906680845ecSLang Hames                                           const SymbolMap &Symbols) {
2907680845ecSLang Hames   LLVM_DEBUG({
29089355d115SLang Hames     dbgs() << "In " << MR.JD.getName() << " resolving " << Symbols << "\n";
2909680845ecSLang Hames   });
2910680845ecSLang Hames #ifndef NDEBUG
2911680845ecSLang Hames   for (auto &KV : Symbols) {
2912680845ecSLang Hames     auto WeakFlags = JITSymbolFlags::Weak | JITSymbolFlags::Common;
2913680845ecSLang Hames     auto I = MR.SymbolFlags.find(KV.first);
2914680845ecSLang Hames     assert(I != MR.SymbolFlags.end() &&
2915680845ecSLang Hames            "Resolving symbol outside this responsibility set");
2916680845ecSLang Hames     assert(!I->second.hasMaterializationSideEffectsOnly() &&
2917680845ecSLang Hames            "Can't resolve materialization-side-effects-only symbol");
2918680845ecSLang Hames     assert((KV.second.getFlags() & ~WeakFlags) == (I->second & ~WeakFlags) &&
2919680845ecSLang Hames            "Resolving symbol with incorrect flags");
2920680845ecSLang Hames   }
2921680845ecSLang Hames #endif
2922680845ecSLang Hames 
29239355d115SLang Hames   return MR.JD.resolve(MR, Symbols);
2924680845ecSLang Hames }
2925680845ecSLang Hames 
OL_notifyEmitted(MaterializationResponsibility & MR)2926680845ecSLang Hames Error ExecutionSession::OL_notifyEmitted(MaterializationResponsibility &MR) {
2927680845ecSLang Hames   LLVM_DEBUG({
29289355d115SLang Hames     dbgs() << "In " << MR.JD.getName() << " emitting " << MR.SymbolFlags
29299355d115SLang Hames            << "\n";
2930680845ecSLang Hames   });
2931680845ecSLang Hames 
29329355d115SLang Hames   if (auto Err = MR.JD.emit(MR, MR.SymbolFlags))
2933680845ecSLang Hames     return Err;
2934680845ecSLang Hames 
2935680845ecSLang Hames   MR.SymbolFlags.clear();
2936680845ecSLang Hames   return Error::success();
2937680845ecSLang Hames }
2938680845ecSLang Hames 
OL_defineMaterializing(MaterializationResponsibility & MR,SymbolFlagsMap NewSymbolFlags)2939680845ecSLang Hames Error ExecutionSession::OL_defineMaterializing(
2940680845ecSLang Hames     MaterializationResponsibility &MR, SymbolFlagsMap NewSymbolFlags) {
2941680845ecSLang Hames 
2942680845ecSLang Hames   LLVM_DEBUG({
29439355d115SLang Hames     dbgs() << "In " << MR.JD.getName() << " defining materializing symbols "
2944680845ecSLang Hames            << NewSymbolFlags << "\n";
2945680845ecSLang Hames   });
29469355d115SLang Hames   if (auto AcceptedDefs =
29479355d115SLang Hames           MR.JD.defineMaterializing(std::move(NewSymbolFlags))) {
2948680845ecSLang Hames     // Add all newly accepted symbols to this responsibility object.
2949680845ecSLang Hames     for (auto &KV : *AcceptedDefs)
2950680845ecSLang Hames       MR.SymbolFlags.insert(KV);
2951680845ecSLang Hames     return Error::success();
2952680845ecSLang Hames   } else
2953680845ecSLang Hames     return AcceptedDefs.takeError();
2954680845ecSLang Hames }
2955680845ecSLang Hames 
OL_notifyFailed(MaterializationResponsibility & MR)2956680845ecSLang Hames void ExecutionSession::OL_notifyFailed(MaterializationResponsibility &MR) {
2957680845ecSLang Hames 
2958680845ecSLang Hames   LLVM_DEBUG({
29599355d115SLang Hames     dbgs() << "In " << MR.JD.getName() << " failing materialization for "
2960680845ecSLang Hames            << MR.SymbolFlags << "\n";
2961680845ecSLang Hames   });
2962680845ecSLang Hames 
2963680845ecSLang Hames   JITDylib::FailedSymbolsWorklist Worklist;
2964680845ecSLang Hames 
2965680845ecSLang Hames   for (auto &KV : MR.SymbolFlags)
29669355d115SLang Hames     Worklist.push_back(std::make_pair(&MR.JD, KV.first));
2967680845ecSLang Hames   MR.SymbolFlags.clear();
2968680845ecSLang Hames 
2969680845ecSLang Hames   if (Worklist.empty())
2970680845ecSLang Hames     return;
2971680845ecSLang Hames 
2972680845ecSLang Hames   JITDylib::AsynchronousSymbolQuerySet FailedQueries;
2973680845ecSLang Hames   std::shared_ptr<SymbolDependenceMap> FailedSymbols;
2974680845ecSLang Hames 
2975680845ecSLang Hames   runSessionLocked([&]() {
29769355d115SLang Hames     // If the tracker is defunct then there's nothing to do here.
29779355d115SLang Hames     if (MR.RT->isDefunct())
2978680845ecSLang Hames       return;
2979680845ecSLang Hames 
2980680845ecSLang Hames     std::tie(FailedQueries, FailedSymbols) =
2981680845ecSLang Hames         JITDylib::failSymbols(std::move(Worklist));
2982680845ecSLang Hames   });
2983680845ecSLang Hames 
2984680845ecSLang Hames   for (auto &Q : FailedQueries)
298555e8f721SLang Hames     Q->handleFailed(
298655e8f721SLang Hames         make_error<FailedToMaterialize>(getSymbolStringPool(), FailedSymbols));
2987680845ecSLang Hames }
2988680845ecSLang Hames 
OL_replace(MaterializationResponsibility & MR,std::unique_ptr<MaterializationUnit> MU)2989680845ecSLang Hames Error ExecutionSession::OL_replace(MaterializationResponsibility &MR,
2990680845ecSLang Hames                                    std::unique_ptr<MaterializationUnit> MU) {
2991680845ecSLang Hames   for (auto &KV : MU->getSymbols()) {
2992680845ecSLang Hames     assert(MR.SymbolFlags.count(KV.first) &&
2993680845ecSLang Hames            "Replacing definition outside this responsibility set");
2994680845ecSLang Hames     MR.SymbolFlags.erase(KV.first);
2995680845ecSLang Hames   }
2996680845ecSLang Hames 
2997680845ecSLang Hames   if (MU->getInitializerSymbol() == MR.InitSymbol)
2998680845ecSLang Hames     MR.InitSymbol = nullptr;
2999680845ecSLang Hames 
30009355d115SLang Hames   LLVM_DEBUG(MR.JD.getExecutionSession().runSessionLocked([&]() {
30019355d115SLang Hames     dbgs() << "In " << MR.JD.getName() << " replacing symbols with " << *MU
3002680845ecSLang Hames            << "\n";
3003680845ecSLang Hames   }););
3004680845ecSLang Hames 
30059355d115SLang Hames   return MR.JD.replace(MR, std::move(MU));
3006680845ecSLang Hames }
3007680845ecSLang Hames 
3008680845ecSLang Hames Expected<std::unique_ptr<MaterializationResponsibility>>
OL_delegate(MaterializationResponsibility & MR,const SymbolNameSet & Symbols)3009680845ecSLang Hames ExecutionSession::OL_delegate(MaterializationResponsibility &MR,
3010680845ecSLang Hames                               const SymbolNameSet &Symbols) {
3011680845ecSLang Hames 
3012680845ecSLang Hames   SymbolStringPtr DelegatedInitSymbol;
3013680845ecSLang Hames   SymbolFlagsMap DelegatedFlags;
3014680845ecSLang Hames 
3015680845ecSLang Hames   for (auto &Name : Symbols) {
3016680845ecSLang Hames     auto I = MR.SymbolFlags.find(Name);
3017680845ecSLang Hames     assert(I != MR.SymbolFlags.end() &&
3018680845ecSLang Hames            "Symbol is not tracked by this MaterializationResponsibility "
3019680845ecSLang Hames            "instance");
3020680845ecSLang Hames 
3021680845ecSLang Hames     DelegatedFlags[Name] = std::move(I->second);
3022680845ecSLang Hames     if (Name == MR.InitSymbol)
3023680845ecSLang Hames       std::swap(MR.InitSymbol, DelegatedInitSymbol);
3024680845ecSLang Hames 
3025680845ecSLang Hames     MR.SymbolFlags.erase(I);
3026680845ecSLang Hames   }
3027680845ecSLang Hames 
30289355d115SLang Hames   return MR.JD.delegate(MR, std::move(DelegatedFlags),
3029680845ecSLang Hames                         std::move(DelegatedInitSymbol));
3030680845ecSLang Hames }
3031680845ecSLang Hames 
OL_addDependencies(MaterializationResponsibility & MR,const SymbolStringPtr & Name,const SymbolDependenceMap & Dependencies)3032680845ecSLang Hames void ExecutionSession::OL_addDependencies(
3033680845ecSLang Hames     MaterializationResponsibility &MR, const SymbolStringPtr &Name,
3034680845ecSLang Hames     const SymbolDependenceMap &Dependencies) {
3035680845ecSLang Hames   LLVM_DEBUG({
3036680845ecSLang Hames     dbgs() << "Adding dependencies for " << Name << ": " << Dependencies
3037680845ecSLang Hames            << "\n";
3038680845ecSLang Hames   });
3039680845ecSLang Hames   assert(MR.SymbolFlags.count(Name) &&
3040680845ecSLang Hames          "Symbol not covered by this MaterializationResponsibility instance");
30419355d115SLang Hames   MR.JD.addDependencies(Name, Dependencies);
3042680845ecSLang Hames }
3043680845ecSLang Hames 
OL_addDependenciesForAll(MaterializationResponsibility & MR,const SymbolDependenceMap & Dependencies)3044680845ecSLang Hames void ExecutionSession::OL_addDependenciesForAll(
3045680845ecSLang Hames     MaterializationResponsibility &MR,
3046680845ecSLang Hames     const SymbolDependenceMap &Dependencies) {
3047680845ecSLang Hames   LLVM_DEBUG({
3048680845ecSLang Hames     dbgs() << "Adding dependencies for all symbols in " << MR.SymbolFlags << ": "
3049680845ecSLang Hames            << Dependencies << "\n";
3050680845ecSLang Hames   });
3051680845ecSLang Hames   for (auto &KV : MR.SymbolFlags)
30529355d115SLang Hames     MR.JD.addDependencies(KV.first, Dependencies);
3053680845ecSLang Hames }
3054680845ecSLang Hames 
305538a8760bSLang Hames #ifndef NDEBUG
dumpDispatchInfo(Task & T)30565344c88dSLang Hames void ExecutionSession::dumpDispatchInfo(Task &T) {
305738a8760bSLang Hames   runSessionLocked([&]() {
30585344c88dSLang Hames     dbgs() << "Dispatching: ";
30595344c88dSLang Hames     T.printDescription(dbgs());
30603828ab08SLang Hames     dbgs() << "\n";
306138a8760bSLang Hames   });
306238a8760bSLang Hames }
306338a8760bSLang Hames #endif // NDEBUG
306438a8760bSLang Hames 
30659510447aSLang Hames } // End namespace orc.
30669510447aSLang Hames } // End namespace llvm.
3067