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