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