1 //===--- Core.cpp - Core ORC APIs (MaterializationUnit, JITDylib, etc.) ---===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "llvm/ExecutionEngine/Orc/Core.h" 10 11 #include "llvm/ADT/STLExtras.h" 12 #include "llvm/Config/llvm-config.h" 13 #include "llvm/ExecutionEngine/Orc/DebugUtils.h" 14 #include "llvm/ExecutionEngine/Orc/Shared/OrcError.h" 15 #include "llvm/Support/FormatVariadic.h" 16 #include "llvm/Support/MSVCErrorWorkarounds.h" 17 18 #include <condition_variable> 19 #include <future> 20 #include <optional> 21 22 #define DEBUG_TYPE "orc" 23 24 namespace llvm { 25 namespace orc { 26 27 char ResourceTrackerDefunct::ID = 0; 28 char FailedToMaterialize::ID = 0; 29 char SymbolsNotFound::ID = 0; 30 char SymbolsCouldNotBeRemoved::ID = 0; 31 char MissingSymbolDefinitions::ID = 0; 32 char UnexpectedSymbolDefinitions::ID = 0; 33 char MaterializationTask::ID = 0; 34 35 RegisterDependenciesFunction NoDependenciesToRegister = 36 RegisterDependenciesFunction(); 37 38 void MaterializationUnit::anchor() {} 39 40 ResourceTracker::ResourceTracker(JITDylibSP JD) { 41 assert((reinterpret_cast<uintptr_t>(JD.get()) & 0x1) == 0 && 42 "JITDylib must be two byte aligned"); 43 JD->Retain(); 44 JDAndFlag.store(reinterpret_cast<uintptr_t>(JD.get())); 45 } 46 47 ResourceTracker::~ResourceTracker() { 48 getJITDylib().getExecutionSession().destroyResourceTracker(*this); 49 getJITDylib().Release(); 50 } 51 52 Error ResourceTracker::remove() { 53 return getJITDylib().getExecutionSession().removeResourceTracker(*this); 54 } 55 56 void ResourceTracker::transferTo(ResourceTracker &DstRT) { 57 getJITDylib().getExecutionSession().transferResourceTracker(DstRT, *this); 58 } 59 60 void ResourceTracker::makeDefunct() { 61 uintptr_t Val = JDAndFlag.load(); 62 Val |= 0x1U; 63 JDAndFlag.store(Val); 64 } 65 66 ResourceManager::~ResourceManager() = default; 67 68 ResourceTrackerDefunct::ResourceTrackerDefunct(ResourceTrackerSP RT) 69 : RT(std::move(RT)) {} 70 71 std::error_code ResourceTrackerDefunct::convertToErrorCode() const { 72 return orcError(OrcErrorCode::UnknownORCError); 73 } 74 75 void ResourceTrackerDefunct::log(raw_ostream &OS) const { 76 OS << "Resource tracker " << (void *)RT.get() << " became defunct"; 77 } 78 79 FailedToMaterialize::FailedToMaterialize( 80 std::shared_ptr<SymbolStringPool> SSP, 81 std::shared_ptr<SymbolDependenceMap> Symbols) 82 : SSP(std::move(SSP)), Symbols(std::move(Symbols)) { 83 assert(this->SSP && "String pool cannot be null"); 84 assert(!this->Symbols->empty() && "Can not fail to resolve an empty set"); 85 86 // FIXME: Use a new dep-map type for FailedToMaterialize errors so that we 87 // don't have to manually retain/release. 88 for (auto &KV : *this->Symbols) 89 KV.first->Retain(); 90 } 91 92 FailedToMaterialize::~FailedToMaterialize() { 93 for (auto &KV : *Symbols) 94 KV.first->Release(); 95 } 96 97 std::error_code FailedToMaterialize::convertToErrorCode() const { 98 return orcError(OrcErrorCode::UnknownORCError); 99 } 100 101 void FailedToMaterialize::log(raw_ostream &OS) const { 102 OS << "Failed to materialize symbols: " << *Symbols; 103 } 104 105 SymbolsNotFound::SymbolsNotFound(std::shared_ptr<SymbolStringPool> SSP, 106 SymbolNameSet Symbols) 107 : SSP(std::move(SSP)) { 108 for (auto &Sym : Symbols) 109 this->Symbols.push_back(Sym); 110 assert(!this->Symbols.empty() && "Can not fail to resolve an empty set"); 111 } 112 113 SymbolsNotFound::SymbolsNotFound(std::shared_ptr<SymbolStringPool> SSP, 114 SymbolNameVector Symbols) 115 : SSP(std::move(SSP)), Symbols(std::move(Symbols)) { 116 assert(!this->Symbols.empty() && "Can not fail to resolve an empty set"); 117 } 118 119 std::error_code SymbolsNotFound::convertToErrorCode() const { 120 return orcError(OrcErrorCode::UnknownORCError); 121 } 122 123 void SymbolsNotFound::log(raw_ostream &OS) const { 124 OS << "Symbols not found: " << Symbols; 125 } 126 127 SymbolsCouldNotBeRemoved::SymbolsCouldNotBeRemoved( 128 std::shared_ptr<SymbolStringPool> SSP, SymbolNameSet Symbols) 129 : SSP(std::move(SSP)), Symbols(std::move(Symbols)) { 130 assert(!this->Symbols.empty() && "Can not fail to resolve an empty set"); 131 } 132 133 std::error_code SymbolsCouldNotBeRemoved::convertToErrorCode() const { 134 return orcError(OrcErrorCode::UnknownORCError); 135 } 136 137 void SymbolsCouldNotBeRemoved::log(raw_ostream &OS) const { 138 OS << "Symbols could not be removed: " << Symbols; 139 } 140 141 std::error_code MissingSymbolDefinitions::convertToErrorCode() const { 142 return orcError(OrcErrorCode::MissingSymbolDefinitions); 143 } 144 145 void MissingSymbolDefinitions::log(raw_ostream &OS) const { 146 OS << "Missing definitions in module " << ModuleName 147 << ": " << Symbols; 148 } 149 150 std::error_code UnexpectedSymbolDefinitions::convertToErrorCode() const { 151 return orcError(OrcErrorCode::UnexpectedSymbolDefinitions); 152 } 153 154 void UnexpectedSymbolDefinitions::log(raw_ostream &OS) const { 155 OS << "Unexpected definitions in module " << ModuleName 156 << ": " << Symbols; 157 } 158 159 AsynchronousSymbolQuery::AsynchronousSymbolQuery( 160 const SymbolLookupSet &Symbols, SymbolState RequiredState, 161 SymbolsResolvedCallback NotifyComplete) 162 : NotifyComplete(std::move(NotifyComplete)), RequiredState(RequiredState) { 163 assert(RequiredState >= SymbolState::Resolved && 164 "Cannot query for a symbols that have not reached the resolve state " 165 "yet"); 166 167 OutstandingSymbolsCount = Symbols.size(); 168 169 for (auto &KV : Symbols) 170 ResolvedSymbols[KV.first] = ExecutorSymbolDef(); 171 } 172 173 void AsynchronousSymbolQuery::notifySymbolMetRequiredState( 174 const SymbolStringPtr &Name, ExecutorSymbolDef Sym) { 175 auto I = ResolvedSymbols.find(Name); 176 assert(I != ResolvedSymbols.end() && 177 "Resolving symbol outside the requested set"); 178 assert(I->second == ExecutorSymbolDef() && 179 "Redundantly resolving symbol Name"); 180 181 // If this is a materialization-side-effects-only symbol then drop it, 182 // otherwise update its map entry with its resolved address. 183 if (Sym.getFlags().hasMaterializationSideEffectsOnly()) 184 ResolvedSymbols.erase(I); 185 else 186 I->second = std::move(Sym); 187 --OutstandingSymbolsCount; 188 } 189 190 void AsynchronousSymbolQuery::handleComplete(ExecutionSession &ES) { 191 assert(OutstandingSymbolsCount == 0 && 192 "Symbols remain, handleComplete called prematurely"); 193 194 class RunQueryCompleteTask : public Task { 195 public: 196 RunQueryCompleteTask(SymbolMap ResolvedSymbols, 197 SymbolsResolvedCallback NotifyComplete) 198 : ResolvedSymbols(std::move(ResolvedSymbols)), 199 NotifyComplete(std::move(NotifyComplete)) {} 200 void printDescription(raw_ostream &OS) override { 201 OS << "Execute query complete callback for " << ResolvedSymbols; 202 } 203 void run() override { NotifyComplete(std::move(ResolvedSymbols)); } 204 205 private: 206 SymbolMap ResolvedSymbols; 207 SymbolsResolvedCallback NotifyComplete; 208 }; 209 210 auto T = std::make_unique<RunQueryCompleteTask>(std::move(ResolvedSymbols), 211 std::move(NotifyComplete)); 212 NotifyComplete = SymbolsResolvedCallback(); 213 ES.dispatchTask(std::move(T)); 214 } 215 216 void AsynchronousSymbolQuery::handleFailed(Error Err) { 217 assert(QueryRegistrations.empty() && ResolvedSymbols.empty() && 218 OutstandingSymbolsCount == 0 && 219 "Query should already have been abandoned"); 220 NotifyComplete(std::move(Err)); 221 NotifyComplete = SymbolsResolvedCallback(); 222 } 223 224 void AsynchronousSymbolQuery::addQueryDependence(JITDylib &JD, 225 SymbolStringPtr Name) { 226 bool Added = QueryRegistrations[&JD].insert(std::move(Name)).second; 227 (void)Added; 228 assert(Added && "Duplicate dependence notification?"); 229 } 230 231 void AsynchronousSymbolQuery::removeQueryDependence( 232 JITDylib &JD, const SymbolStringPtr &Name) { 233 auto QRI = QueryRegistrations.find(&JD); 234 assert(QRI != QueryRegistrations.end() && 235 "No dependencies registered for JD"); 236 assert(QRI->second.count(Name) && "No dependency on Name in JD"); 237 QRI->second.erase(Name); 238 if (QRI->second.empty()) 239 QueryRegistrations.erase(QRI); 240 } 241 242 void AsynchronousSymbolQuery::dropSymbol(const SymbolStringPtr &Name) { 243 auto I = ResolvedSymbols.find(Name); 244 assert(I != ResolvedSymbols.end() && 245 "Redundant removal of weakly-referenced symbol"); 246 ResolvedSymbols.erase(I); 247 --OutstandingSymbolsCount; 248 } 249 250 void AsynchronousSymbolQuery::detach() { 251 ResolvedSymbols.clear(); 252 OutstandingSymbolsCount = 0; 253 for (auto &KV : QueryRegistrations) 254 KV.first->detachQueryHelper(*this, KV.second); 255 QueryRegistrations.clear(); 256 } 257 258 AbsoluteSymbolsMaterializationUnit::AbsoluteSymbolsMaterializationUnit( 259 SymbolMap Symbols) 260 : MaterializationUnit(extractFlags(Symbols)), Symbols(std::move(Symbols)) {} 261 262 StringRef AbsoluteSymbolsMaterializationUnit::getName() const { 263 return "<Absolute Symbols>"; 264 } 265 266 void AbsoluteSymbolsMaterializationUnit::materialize( 267 std::unique_ptr<MaterializationResponsibility> R) { 268 // Even though these are just absolute symbols we need to check for failure 269 // to resolve/emit: the tracker for these symbols may have been removed while 270 // the materialization was in flight (e.g. due to a failure in some action 271 // triggered by the queries attached to the resolution/emission of these 272 // symbols). 273 if (auto Err = R->notifyResolved(Symbols)) { 274 R->getExecutionSession().reportError(std::move(Err)); 275 R->failMaterialization(); 276 return; 277 } 278 if (auto Err = R->notifyEmitted()) { 279 R->getExecutionSession().reportError(std::move(Err)); 280 R->failMaterialization(); 281 return; 282 } 283 } 284 285 void AbsoluteSymbolsMaterializationUnit::discard(const JITDylib &JD, 286 const SymbolStringPtr &Name) { 287 assert(Symbols.count(Name) && "Symbol is not part of this MU"); 288 Symbols.erase(Name); 289 } 290 291 MaterializationUnit::Interface 292 AbsoluteSymbolsMaterializationUnit::extractFlags(const SymbolMap &Symbols) { 293 SymbolFlagsMap Flags; 294 for (const auto &KV : Symbols) 295 Flags[KV.first] = KV.second.getFlags(); 296 return MaterializationUnit::Interface(std::move(Flags), nullptr); 297 } 298 299 ReExportsMaterializationUnit::ReExportsMaterializationUnit( 300 JITDylib *SourceJD, JITDylibLookupFlags SourceJDLookupFlags, 301 SymbolAliasMap Aliases) 302 : MaterializationUnit(extractFlags(Aliases)), SourceJD(SourceJD), 303 SourceJDLookupFlags(SourceJDLookupFlags), Aliases(std::move(Aliases)) {} 304 305 StringRef ReExportsMaterializationUnit::getName() const { 306 return "<Reexports>"; 307 } 308 309 void ReExportsMaterializationUnit::materialize( 310 std::unique_ptr<MaterializationResponsibility> R) { 311 312 auto &ES = R->getTargetJITDylib().getExecutionSession(); 313 JITDylib &TgtJD = R->getTargetJITDylib(); 314 JITDylib &SrcJD = SourceJD ? *SourceJD : TgtJD; 315 316 // Find the set of requested aliases and aliasees. Return any unrequested 317 // aliases back to the JITDylib so as to not prematurely materialize any 318 // aliasees. 319 auto RequestedSymbols = R->getRequestedSymbols(); 320 SymbolAliasMap RequestedAliases; 321 322 for (auto &Name : RequestedSymbols) { 323 auto I = Aliases.find(Name); 324 assert(I != Aliases.end() && "Symbol not found in aliases map?"); 325 RequestedAliases[Name] = std::move(I->second); 326 Aliases.erase(I); 327 } 328 329 LLVM_DEBUG({ 330 ES.runSessionLocked([&]() { 331 dbgs() << "materializing reexports: target = " << TgtJD.getName() 332 << ", source = " << SrcJD.getName() << " " << RequestedAliases 333 << "\n"; 334 }); 335 }); 336 337 if (!Aliases.empty()) { 338 auto Err = SourceJD ? R->replace(reexports(*SourceJD, std::move(Aliases), 339 SourceJDLookupFlags)) 340 : R->replace(symbolAliases(std::move(Aliases))); 341 342 if (Err) { 343 // FIXME: Should this be reported / treated as failure to materialize? 344 // Or should this be treated as a sanctioned bailing-out? 345 ES.reportError(std::move(Err)); 346 R->failMaterialization(); 347 return; 348 } 349 } 350 351 // The OnResolveInfo struct will hold the aliases and responsibilty for each 352 // query in the list. 353 struct OnResolveInfo { 354 OnResolveInfo(std::unique_ptr<MaterializationResponsibility> R, 355 SymbolAliasMap Aliases) 356 : R(std::move(R)), Aliases(std::move(Aliases)) {} 357 358 std::unique_ptr<MaterializationResponsibility> R; 359 SymbolAliasMap Aliases; 360 }; 361 362 // Build a list of queries to issue. In each round we build a query for the 363 // largest set of aliases that we can resolve without encountering a chain of 364 // aliases (e.g. Foo -> Bar, Bar -> Baz). Such a chain would deadlock as the 365 // query would be waiting on a symbol that it itself had to resolve. Creating 366 // a new query for each link in such a chain eliminates the possibility of 367 // deadlock. In practice chains are likely to be rare, and this algorithm will 368 // usually result in a single query to issue. 369 370 std::vector<std::pair<SymbolLookupSet, std::shared_ptr<OnResolveInfo>>> 371 QueryInfos; 372 while (!RequestedAliases.empty()) { 373 SymbolNameSet ResponsibilitySymbols; 374 SymbolLookupSet QuerySymbols; 375 SymbolAliasMap QueryAliases; 376 377 // Collect as many aliases as we can without including a chain. 378 for (auto &KV : RequestedAliases) { 379 // Chain detected. Skip this symbol for this round. 380 if (&SrcJD == &TgtJD && (QueryAliases.count(KV.second.Aliasee) || 381 RequestedAliases.count(KV.second.Aliasee))) 382 continue; 383 384 ResponsibilitySymbols.insert(KV.first); 385 QuerySymbols.add(KV.second.Aliasee, 386 KV.second.AliasFlags.hasMaterializationSideEffectsOnly() 387 ? SymbolLookupFlags::WeaklyReferencedSymbol 388 : SymbolLookupFlags::RequiredSymbol); 389 QueryAliases[KV.first] = std::move(KV.second); 390 } 391 392 // Remove the aliases collected this round from the RequestedAliases map. 393 for (auto &KV : QueryAliases) 394 RequestedAliases.erase(KV.first); 395 396 assert(!QuerySymbols.empty() && "Alias cycle detected!"); 397 398 auto NewR = R->delegate(ResponsibilitySymbols); 399 if (!NewR) { 400 ES.reportError(NewR.takeError()); 401 R->failMaterialization(); 402 return; 403 } 404 405 auto QueryInfo = std::make_shared<OnResolveInfo>(std::move(*NewR), 406 std::move(QueryAliases)); 407 QueryInfos.push_back( 408 make_pair(std::move(QuerySymbols), std::move(QueryInfo))); 409 } 410 411 // Issue the queries. 412 while (!QueryInfos.empty()) { 413 auto QuerySymbols = std::move(QueryInfos.back().first); 414 auto QueryInfo = std::move(QueryInfos.back().second); 415 416 QueryInfos.pop_back(); 417 418 auto RegisterDependencies = [QueryInfo, 419 &SrcJD](const SymbolDependenceMap &Deps) { 420 // If there were no materializing symbols, just bail out. 421 if (Deps.empty()) 422 return; 423 424 // Otherwise the only deps should be on SrcJD. 425 assert(Deps.size() == 1 && Deps.count(&SrcJD) && 426 "Unexpected dependencies for reexports"); 427 428 auto &SrcJDDeps = Deps.find(&SrcJD)->second; 429 SymbolDependenceMap PerAliasDepsMap; 430 auto &PerAliasDeps = PerAliasDepsMap[&SrcJD]; 431 432 for (auto &KV : QueryInfo->Aliases) 433 if (SrcJDDeps.count(KV.second.Aliasee)) { 434 PerAliasDeps = {KV.second.Aliasee}; 435 QueryInfo->R->addDependencies(KV.first, PerAliasDepsMap); 436 } 437 }; 438 439 auto OnComplete = [QueryInfo](Expected<SymbolMap> Result) { 440 auto &ES = QueryInfo->R->getTargetJITDylib().getExecutionSession(); 441 if (Result) { 442 SymbolMap ResolutionMap; 443 for (auto &KV : QueryInfo->Aliases) { 444 assert((KV.second.AliasFlags.hasMaterializationSideEffectsOnly() || 445 Result->count(KV.second.Aliasee)) && 446 "Result map missing entry?"); 447 // Don't try to resolve materialization-side-effects-only symbols. 448 if (KV.second.AliasFlags.hasMaterializationSideEffectsOnly()) 449 continue; 450 451 ResolutionMap[KV.first] = {(*Result)[KV.second.Aliasee].getAddress(), 452 KV.second.AliasFlags}; 453 } 454 if (auto Err = QueryInfo->R->notifyResolved(ResolutionMap)) { 455 ES.reportError(std::move(Err)); 456 QueryInfo->R->failMaterialization(); 457 return; 458 } 459 if (auto Err = QueryInfo->R->notifyEmitted()) { 460 ES.reportError(std::move(Err)); 461 QueryInfo->R->failMaterialization(); 462 return; 463 } 464 } else { 465 ES.reportError(Result.takeError()); 466 QueryInfo->R->failMaterialization(); 467 } 468 }; 469 470 ES.lookup(LookupKind::Static, 471 JITDylibSearchOrder({{&SrcJD, SourceJDLookupFlags}}), 472 QuerySymbols, SymbolState::Resolved, std::move(OnComplete), 473 std::move(RegisterDependencies)); 474 } 475 } 476 477 void ReExportsMaterializationUnit::discard(const JITDylib &JD, 478 const SymbolStringPtr &Name) { 479 assert(Aliases.count(Name) && 480 "Symbol not covered by this MaterializationUnit"); 481 Aliases.erase(Name); 482 } 483 484 MaterializationUnit::Interface 485 ReExportsMaterializationUnit::extractFlags(const SymbolAliasMap &Aliases) { 486 SymbolFlagsMap SymbolFlags; 487 for (auto &KV : Aliases) 488 SymbolFlags[KV.first] = KV.second.AliasFlags; 489 490 return MaterializationUnit::Interface(std::move(SymbolFlags), nullptr); 491 } 492 493 Expected<SymbolAliasMap> buildSimpleReexportsAliasMap(JITDylib &SourceJD, 494 SymbolNameSet Symbols) { 495 SymbolLookupSet LookupSet(Symbols); 496 auto Flags = SourceJD.getExecutionSession().lookupFlags( 497 LookupKind::Static, {{&SourceJD, JITDylibLookupFlags::MatchAllSymbols}}, 498 SymbolLookupSet(std::move(Symbols))); 499 500 if (!Flags) 501 return Flags.takeError(); 502 503 SymbolAliasMap Result; 504 for (auto &Name : Symbols) { 505 assert(Flags->count(Name) && "Missing entry in flags map"); 506 Result[Name] = SymbolAliasMapEntry(Name, (*Flags)[Name]); 507 } 508 509 return Result; 510 } 511 512 class InProgressLookupState { 513 public: 514 // FIXME: Reduce the number of SymbolStringPtrs here. See 515 // https://github.com/llvm/llvm-project/issues/55576. 516 517 InProgressLookupState(LookupKind K, JITDylibSearchOrder SearchOrder, 518 SymbolLookupSet LookupSet, SymbolState RequiredState) 519 : K(K), SearchOrder(std::move(SearchOrder)), 520 LookupSet(std::move(LookupSet)), RequiredState(RequiredState) { 521 DefGeneratorCandidates = this->LookupSet; 522 } 523 virtual ~InProgressLookupState() = default; 524 virtual void complete(std::unique_ptr<InProgressLookupState> IPLS) = 0; 525 virtual void fail(Error Err) = 0; 526 527 LookupKind K; 528 JITDylibSearchOrder SearchOrder; 529 SymbolLookupSet LookupSet; 530 SymbolState RequiredState; 531 532 std::unique_lock<std::mutex> GeneratorLock; 533 size_t CurSearchOrderIndex = 0; 534 bool NewJITDylib = true; 535 SymbolLookupSet DefGeneratorCandidates; 536 SymbolLookupSet DefGeneratorNonCandidates; 537 std::vector<std::weak_ptr<DefinitionGenerator>> CurDefGeneratorStack; 538 }; 539 540 class InProgressLookupFlagsState : public InProgressLookupState { 541 public: 542 InProgressLookupFlagsState( 543 LookupKind K, JITDylibSearchOrder SearchOrder, SymbolLookupSet LookupSet, 544 unique_function<void(Expected<SymbolFlagsMap>)> OnComplete) 545 : InProgressLookupState(K, std::move(SearchOrder), std::move(LookupSet), 546 SymbolState::NeverSearched), 547 OnComplete(std::move(OnComplete)) {} 548 549 void complete(std::unique_ptr<InProgressLookupState> IPLS) override { 550 GeneratorLock = {}; // Unlock and release. 551 auto &ES = SearchOrder.front().first->getExecutionSession(); 552 ES.OL_completeLookupFlags(std::move(IPLS), std::move(OnComplete)); 553 } 554 555 void fail(Error Err) override { 556 GeneratorLock = {}; // Unlock and release. 557 OnComplete(std::move(Err)); 558 } 559 560 private: 561 unique_function<void(Expected<SymbolFlagsMap>)> OnComplete; 562 }; 563 564 class InProgressFullLookupState : public InProgressLookupState { 565 public: 566 InProgressFullLookupState(LookupKind K, JITDylibSearchOrder SearchOrder, 567 SymbolLookupSet LookupSet, 568 SymbolState RequiredState, 569 std::shared_ptr<AsynchronousSymbolQuery> Q, 570 RegisterDependenciesFunction RegisterDependencies) 571 : InProgressLookupState(K, std::move(SearchOrder), std::move(LookupSet), 572 RequiredState), 573 Q(std::move(Q)), RegisterDependencies(std::move(RegisterDependencies)) { 574 } 575 576 void complete(std::unique_ptr<InProgressLookupState> IPLS) override { 577 GeneratorLock = {}; // Unlock and release. 578 auto &ES = SearchOrder.front().first->getExecutionSession(); 579 ES.OL_completeLookup(std::move(IPLS), std::move(Q), 580 std::move(RegisterDependencies)); 581 } 582 583 void fail(Error Err) override { 584 GeneratorLock = {}; 585 Q->detach(); 586 Q->handleFailed(std::move(Err)); 587 } 588 589 private: 590 std::shared_ptr<AsynchronousSymbolQuery> Q; 591 RegisterDependenciesFunction RegisterDependencies; 592 }; 593 594 ReexportsGenerator::ReexportsGenerator(JITDylib &SourceJD, 595 JITDylibLookupFlags SourceJDLookupFlags, 596 SymbolPredicate Allow) 597 : SourceJD(SourceJD), SourceJDLookupFlags(SourceJDLookupFlags), 598 Allow(std::move(Allow)) {} 599 600 Error ReexportsGenerator::tryToGenerate(LookupState &LS, LookupKind K, 601 JITDylib &JD, 602 JITDylibLookupFlags JDLookupFlags, 603 const SymbolLookupSet &LookupSet) { 604 assert(&JD != &SourceJD && "Cannot re-export from the same dylib"); 605 606 // Use lookupFlags to find the subset of symbols that match our lookup. 607 auto Flags = JD.getExecutionSession().lookupFlags( 608 K, {{&SourceJD, JDLookupFlags}}, LookupSet); 609 if (!Flags) 610 return Flags.takeError(); 611 612 // Create an alias map. 613 orc::SymbolAliasMap AliasMap; 614 for (auto &KV : *Flags) 615 if (!Allow || Allow(KV.first)) 616 AliasMap[KV.first] = SymbolAliasMapEntry(KV.first, KV.second); 617 618 if (AliasMap.empty()) 619 return Error::success(); 620 621 // Define the re-exports. 622 return JD.define(reexports(SourceJD, AliasMap, SourceJDLookupFlags)); 623 } 624 625 LookupState::LookupState(std::unique_ptr<InProgressLookupState> IPLS) 626 : IPLS(std::move(IPLS)) {} 627 628 void LookupState::reset(InProgressLookupState *IPLS) { this->IPLS.reset(IPLS); } 629 630 LookupState::LookupState() = default; 631 LookupState::LookupState(LookupState &&) = default; 632 LookupState &LookupState::operator=(LookupState &&) = default; 633 LookupState::~LookupState() = default; 634 635 void LookupState::continueLookup(Error Err) { 636 assert(IPLS && "Cannot call continueLookup on empty LookupState"); 637 auto &ES = IPLS->SearchOrder.begin()->first->getExecutionSession(); 638 ES.OL_applyQueryPhase1(std::move(IPLS), std::move(Err)); 639 } 640 641 DefinitionGenerator::~DefinitionGenerator() = default; 642 643 JITDylib::~JITDylib() { 644 LLVM_DEBUG(dbgs() << "Destroying JITDylib " << getName() << "\n"); 645 } 646 647 Error JITDylib::clear() { 648 std::vector<ResourceTrackerSP> TrackersToRemove; 649 ES.runSessionLocked([&]() { 650 assert(State != Closed && "JD is defunct"); 651 for (auto &KV : TrackerSymbols) 652 TrackersToRemove.push_back(KV.first); 653 TrackersToRemove.push_back(getDefaultResourceTracker()); 654 }); 655 656 Error Err = Error::success(); 657 for (auto &RT : TrackersToRemove) 658 Err = joinErrors(std::move(Err), RT->remove()); 659 return Err; 660 } 661 662 ResourceTrackerSP JITDylib::getDefaultResourceTracker() { 663 return ES.runSessionLocked([this] { 664 assert(State != Closed && "JD is defunct"); 665 if (!DefaultTracker) 666 DefaultTracker = new ResourceTracker(this); 667 return DefaultTracker; 668 }); 669 } 670 671 ResourceTrackerSP JITDylib::createResourceTracker() { 672 return ES.runSessionLocked([this] { 673 assert(State == Open && "JD is defunct"); 674 ResourceTrackerSP RT = new ResourceTracker(this); 675 return RT; 676 }); 677 } 678 679 void JITDylib::removeGenerator(DefinitionGenerator &G) { 680 ES.runSessionLocked([&] { 681 assert(State == Open && "JD is defunct"); 682 auto I = llvm::find_if(DefGenerators, 683 [&](const std::shared_ptr<DefinitionGenerator> &H) { 684 return H.get() == &G; 685 }); 686 assert(I != DefGenerators.end() && "Generator not found"); 687 DefGenerators.erase(I); 688 }); 689 } 690 691 Expected<SymbolFlagsMap> 692 JITDylib::defineMaterializing(MaterializationResponsibility &FromMR, 693 SymbolFlagsMap SymbolFlags) { 694 695 return ES.runSessionLocked([&]() -> Expected<SymbolFlagsMap> { 696 if (FromMR.RT->isDefunct()) 697 return make_error<ResourceTrackerDefunct>(FromMR.RT); 698 699 std::vector<NonOwningSymbolStringPtr> AddedSyms; 700 std::vector<NonOwningSymbolStringPtr> RejectedWeakDefs; 701 702 for (auto SFItr = SymbolFlags.begin(), SFEnd = SymbolFlags.end(); 703 SFItr != SFEnd; ++SFItr) { 704 705 auto &Name = SFItr->first; 706 auto &Flags = SFItr->second; 707 708 auto EntryItr = Symbols.find(Name); 709 710 // If the entry already exists... 711 if (EntryItr != Symbols.end()) { 712 713 // If this is a strong definition then error out. 714 if (!Flags.isWeak()) { 715 // Remove any symbols already added. 716 for (auto &S : AddedSyms) 717 Symbols.erase(Symbols.find_as(S)); 718 719 // FIXME: Return all duplicates. 720 return make_error<DuplicateDefinition>(std::string(*Name)); 721 } 722 723 // Otherwise just make a note to discard this symbol after the loop. 724 RejectedWeakDefs.push_back(NonOwningSymbolStringPtr(Name)); 725 continue; 726 } else 727 EntryItr = 728 Symbols.insert(std::make_pair(Name, SymbolTableEntry(Flags))).first; 729 730 AddedSyms.push_back(NonOwningSymbolStringPtr(Name)); 731 EntryItr->second.setState(SymbolState::Materializing); 732 } 733 734 // Remove any rejected weak definitions from the SymbolFlags map. 735 while (!RejectedWeakDefs.empty()) { 736 SymbolFlags.erase(SymbolFlags.find_as(RejectedWeakDefs.back())); 737 RejectedWeakDefs.pop_back(); 738 } 739 740 return SymbolFlags; 741 }); 742 } 743 744 Error JITDylib::replace(MaterializationResponsibility &FromMR, 745 std::unique_ptr<MaterializationUnit> MU) { 746 assert(MU != nullptr && "Can not replace with a null MaterializationUnit"); 747 std::unique_ptr<MaterializationUnit> MustRunMU; 748 std::unique_ptr<MaterializationResponsibility> MustRunMR; 749 750 auto Err = 751 ES.runSessionLocked([&, this]() -> Error { 752 if (FromMR.RT->isDefunct()) 753 return make_error<ResourceTrackerDefunct>(std::move(FromMR.RT)); 754 755 #ifndef NDEBUG 756 for (auto &KV : MU->getSymbols()) { 757 auto SymI = Symbols.find(KV.first); 758 assert(SymI != Symbols.end() && "Replacing unknown symbol"); 759 assert(SymI->second.getState() == SymbolState::Materializing && 760 "Can not replace a symbol that ha is not materializing"); 761 assert(!SymI->second.hasMaterializerAttached() && 762 "Symbol should not have materializer attached already"); 763 assert(UnmaterializedInfos.count(KV.first) == 0 && 764 "Symbol being replaced should have no UnmaterializedInfo"); 765 } 766 #endif // NDEBUG 767 768 // If the tracker is defunct we need to bail out immediately. 769 770 // If any symbol has pending queries against it then we need to 771 // materialize MU immediately. 772 for (auto &KV : MU->getSymbols()) { 773 auto MII = MaterializingInfos.find(KV.first); 774 if (MII != MaterializingInfos.end()) { 775 if (MII->second.hasQueriesPending()) { 776 MustRunMR = ES.createMaterializationResponsibility( 777 *FromMR.RT, std::move(MU->SymbolFlags), 778 std::move(MU->InitSymbol)); 779 MustRunMU = std::move(MU); 780 return Error::success(); 781 } 782 } 783 } 784 785 // Otherwise, make MU responsible for all the symbols. 786 auto UMI = std::make_shared<UnmaterializedInfo>(std::move(MU), 787 FromMR.RT.get()); 788 for (auto &KV : UMI->MU->getSymbols()) { 789 auto SymI = Symbols.find(KV.first); 790 assert(SymI->second.getState() == SymbolState::Materializing && 791 "Can not replace a symbol that is not materializing"); 792 assert(!SymI->second.hasMaterializerAttached() && 793 "Can not replace a symbol that has a materializer attached"); 794 assert(UnmaterializedInfos.count(KV.first) == 0 && 795 "Unexpected materializer entry in map"); 796 SymI->second.setAddress(SymI->second.getAddress()); 797 SymI->second.setMaterializerAttached(true); 798 799 auto &UMIEntry = UnmaterializedInfos[KV.first]; 800 assert((!UMIEntry || !UMIEntry->MU) && 801 "Replacing symbol with materializer still attached"); 802 UMIEntry = UMI; 803 } 804 805 return Error::success(); 806 }); 807 808 if (Err) 809 return Err; 810 811 if (MustRunMU) { 812 assert(MustRunMR && "MustRunMU set implies MustRunMR set"); 813 ES.dispatchTask(std::make_unique<MaterializationTask>( 814 std::move(MustRunMU), std::move(MustRunMR))); 815 } else { 816 assert(!MustRunMR && "MustRunMU unset implies MustRunMR unset"); 817 } 818 819 return Error::success(); 820 } 821 822 Expected<std::unique_ptr<MaterializationResponsibility>> 823 JITDylib::delegate(MaterializationResponsibility &FromMR, 824 SymbolFlagsMap SymbolFlags, SymbolStringPtr InitSymbol) { 825 826 return ES.runSessionLocked( 827 [&]() -> Expected<std::unique_ptr<MaterializationResponsibility>> { 828 if (FromMR.RT->isDefunct()) 829 return make_error<ResourceTrackerDefunct>(std::move(FromMR.RT)); 830 831 return ES.createMaterializationResponsibility( 832 *FromMR.RT, std::move(SymbolFlags), std::move(InitSymbol)); 833 }); 834 } 835 836 SymbolNameSet 837 JITDylib::getRequestedSymbols(const SymbolFlagsMap &SymbolFlags) const { 838 return ES.runSessionLocked([&]() { 839 SymbolNameSet RequestedSymbols; 840 841 for (auto &KV : SymbolFlags) { 842 assert(Symbols.count(KV.first) && "JITDylib does not cover this symbol?"); 843 assert(Symbols.find(KV.first)->second.getState() != 844 SymbolState::NeverSearched && 845 Symbols.find(KV.first)->second.getState() != SymbolState::Ready && 846 "getRequestedSymbols can only be called for symbols that have " 847 "started materializing"); 848 auto I = MaterializingInfos.find(KV.first); 849 if (I == MaterializingInfos.end()) 850 continue; 851 852 if (I->second.hasQueriesPending()) 853 RequestedSymbols.insert(KV.first); 854 } 855 856 return RequestedSymbols; 857 }); 858 } 859 860 void JITDylib::addDependencies(const SymbolStringPtr &Name, 861 const SymbolDependenceMap &Dependencies) { 862 ES.runSessionLocked([&]() { 863 assert(Symbols.count(Name) && "Name not in symbol table"); 864 assert(Symbols[Name].getState() < SymbolState::Emitted && 865 "Can not add dependencies for a symbol that is not materializing"); 866 867 LLVM_DEBUG({ 868 dbgs() << "In " << getName() << " adding dependencies for " << *Name 869 << ": " << Dependencies << "\n"; 870 }); 871 872 // If Name is already in an error state then just bail out. 873 if (Symbols[Name].getFlags().hasError()) 874 return; 875 876 auto &MI = MaterializingInfos[Name]; 877 assert(Symbols[Name].getState() != SymbolState::Emitted && 878 "Can not add dependencies to an emitted symbol"); 879 880 bool DependsOnSymbolInErrorState = false; 881 882 // Register dependencies, record whether any depenendency is in the error 883 // state. 884 for (auto &KV : Dependencies) { 885 assert(KV.first && "Null JITDylib in dependency?"); 886 auto &OtherJITDylib = *KV.first; 887 auto &DepsOnOtherJITDylib = MI.UnemittedDependencies[&OtherJITDylib]; 888 889 for (auto &OtherSymbol : KV.second) { 890 891 // Check the sym entry for the dependency. 892 auto OtherSymI = OtherJITDylib.Symbols.find(OtherSymbol); 893 894 // Assert that this symbol exists and has not reached the ready state 895 // already. 896 assert(OtherSymI != OtherJITDylib.Symbols.end() && 897 "Dependency on unknown symbol"); 898 899 auto &OtherSymEntry = OtherSymI->second; 900 901 // If the other symbol is already in the Ready state then there's no 902 // dependency to add. 903 if (OtherSymEntry.getState() == SymbolState::Ready) 904 continue; 905 906 // If the dependency is in an error state then note this and continue, 907 // we will move this symbol to the error state below. 908 if (OtherSymEntry.getFlags().hasError()) { 909 DependsOnSymbolInErrorState = true; 910 continue; 911 } 912 913 // If the dependency was not in the error state then add it to 914 // our list of dependencies. 915 auto &OtherMI = OtherJITDylib.MaterializingInfos[OtherSymbol]; 916 917 if (OtherSymEntry.getState() == SymbolState::Emitted) 918 transferEmittedNodeDependencies(MI, Name, OtherMI); 919 else if (&OtherJITDylib != this || OtherSymbol != Name) { 920 OtherMI.Dependants[this].insert(Name); 921 DepsOnOtherJITDylib.insert(OtherSymbol); 922 } 923 } 924 925 if (DepsOnOtherJITDylib.empty()) 926 MI.UnemittedDependencies.erase(&OtherJITDylib); 927 } 928 929 // If this symbol dependended on any symbols in the error state then move 930 // this symbol to the error state too. 931 if (DependsOnSymbolInErrorState) 932 Symbols[Name].setFlags(Symbols[Name].getFlags() | 933 JITSymbolFlags::HasError); 934 }); 935 } 936 937 Error JITDylib::resolve(MaterializationResponsibility &MR, 938 const SymbolMap &Resolved) { 939 AsynchronousSymbolQuerySet CompletedQueries; 940 941 if (auto Err = ES.runSessionLocked([&, this]() -> Error { 942 if (MR.RT->isDefunct()) 943 return make_error<ResourceTrackerDefunct>(MR.RT); 944 945 if (State != Open) 946 return make_error<StringError>("JITDylib " + getName() + 947 " is defunct", 948 inconvertibleErrorCode()); 949 950 struct WorklistEntry { 951 SymbolTable::iterator SymI; 952 ExecutorSymbolDef ResolvedSym; 953 }; 954 955 SymbolNameSet SymbolsInErrorState; 956 std::vector<WorklistEntry> Worklist; 957 Worklist.reserve(Resolved.size()); 958 959 // Build worklist and check for any symbols in the error state. 960 for (const auto &KV : Resolved) { 961 962 assert(!KV.second.getFlags().hasError() && 963 "Resolution result can not have error flag set"); 964 965 auto SymI = Symbols.find(KV.first); 966 967 assert(SymI != Symbols.end() && "Symbol not found"); 968 assert(!SymI->second.hasMaterializerAttached() && 969 "Resolving symbol with materializer attached?"); 970 assert(SymI->second.getState() == SymbolState::Materializing && 971 "Symbol should be materializing"); 972 assert(SymI->second.getAddress() == ExecutorAddr() && 973 "Symbol has already been resolved"); 974 975 if (SymI->second.getFlags().hasError()) 976 SymbolsInErrorState.insert(KV.first); 977 else { 978 auto Flags = KV.second.getFlags(); 979 Flags &= ~JITSymbolFlags::Common; 980 assert(Flags == 981 (SymI->second.getFlags() & ~JITSymbolFlags::Common) && 982 "Resolved flags should match the declared flags"); 983 984 Worklist.push_back({SymI, {KV.second.getAddress(), Flags}}); 985 } 986 } 987 988 // If any symbols were in the error state then bail out. 989 if (!SymbolsInErrorState.empty()) { 990 auto FailedSymbolsDepMap = std::make_shared<SymbolDependenceMap>(); 991 (*FailedSymbolsDepMap)[this] = std::move(SymbolsInErrorState); 992 return make_error<FailedToMaterialize>( 993 getExecutionSession().getSymbolStringPool(), 994 std::move(FailedSymbolsDepMap)); 995 } 996 997 while (!Worklist.empty()) { 998 auto SymI = Worklist.back().SymI; 999 auto ResolvedSym = Worklist.back().ResolvedSym; 1000 Worklist.pop_back(); 1001 1002 auto &Name = SymI->first; 1003 1004 // Resolved symbols can not be weak: discard the weak flag. 1005 JITSymbolFlags ResolvedFlags = ResolvedSym.getFlags(); 1006 SymI->second.setAddress(ResolvedSym.getAddress()); 1007 SymI->second.setFlags(ResolvedFlags); 1008 SymI->second.setState(SymbolState::Resolved); 1009 1010 auto MII = MaterializingInfos.find(Name); 1011 if (MII == MaterializingInfos.end()) 1012 continue; 1013 1014 auto &MI = MII->second; 1015 for (auto &Q : MI.takeQueriesMeeting(SymbolState::Resolved)) { 1016 Q->notifySymbolMetRequiredState(Name, ResolvedSym); 1017 Q->removeQueryDependence(*this, Name); 1018 if (Q->isComplete()) 1019 CompletedQueries.insert(std::move(Q)); 1020 } 1021 } 1022 1023 return Error::success(); 1024 })) 1025 return Err; 1026 1027 // Otherwise notify all the completed queries. 1028 for (auto &Q : CompletedQueries) { 1029 assert(Q->isComplete() && "Q not completed"); 1030 Q->handleComplete(ES); 1031 } 1032 1033 return Error::success(); 1034 } 1035 1036 Error JITDylib::emit(MaterializationResponsibility &MR, 1037 const SymbolFlagsMap &Emitted) { 1038 AsynchronousSymbolQuerySet CompletedQueries; 1039 DenseMap<JITDylib *, SymbolNameVector> ReadySymbols; 1040 1041 if (auto Err = ES.runSessionLocked([&, this]() -> Error { 1042 if (MR.RT->isDefunct()) 1043 return make_error<ResourceTrackerDefunct>(MR.RT); 1044 1045 if (State != Open) 1046 return make_error<StringError>("JITDylib " + getName() + 1047 " is defunct", 1048 inconvertibleErrorCode()); 1049 1050 SymbolNameSet SymbolsInErrorState; 1051 std::vector<SymbolTable::iterator> Worklist; 1052 1053 // Scan to build worklist, record any symbols in the erorr state. 1054 for (const auto &KV : Emitted) { 1055 auto &Name = KV.first; 1056 1057 auto SymI = Symbols.find(Name); 1058 assert(SymI != Symbols.end() && "No symbol table entry for Name"); 1059 1060 if (SymI->second.getFlags().hasError()) 1061 SymbolsInErrorState.insert(Name); 1062 else 1063 Worklist.push_back(SymI); 1064 } 1065 1066 // If any symbols were in the error state then bail out. 1067 if (!SymbolsInErrorState.empty()) { 1068 auto FailedSymbolsDepMap = std::make_shared<SymbolDependenceMap>(); 1069 (*FailedSymbolsDepMap)[this] = std::move(SymbolsInErrorState); 1070 return make_error<FailedToMaterialize>( 1071 getExecutionSession().getSymbolStringPool(), 1072 std::move(FailedSymbolsDepMap)); 1073 } 1074 1075 // Otherwise update dependencies and move to the emitted state. 1076 while (!Worklist.empty()) { 1077 auto SymI = Worklist.back(); 1078 Worklist.pop_back(); 1079 1080 auto &Name = SymI->first; 1081 auto &SymEntry = SymI->second; 1082 1083 // Move symbol to the emitted state. 1084 assert(((SymEntry.getFlags().hasMaterializationSideEffectsOnly() && 1085 SymEntry.getState() == SymbolState::Materializing) || 1086 SymEntry.getState() == SymbolState::Resolved) && 1087 "Emitting from state other than Resolved"); 1088 SymEntry.setState(SymbolState::Emitted); 1089 1090 auto MII = MaterializingInfos.find(Name); 1091 1092 // If this symbol has no MaterializingInfo then it's trivially ready. 1093 // Update its state and continue. 1094 if (MII == MaterializingInfos.end()) { 1095 SymEntry.setState(SymbolState::Ready); 1096 continue; 1097 } 1098 1099 auto &MI = MII->second; 1100 1101 // For each dependant, transfer this node's emitted dependencies to 1102 // it. If the dependant node is ready (i.e. has no unemitted 1103 // dependencies) then notify any pending queries. 1104 for (auto &KV : MI.Dependants) { 1105 auto &DependantJD = *KV.first; 1106 auto &DependantJDReadySymbols = ReadySymbols[&DependantJD]; 1107 for (auto &DependantName : KV.second) { 1108 auto DependantMII = 1109 DependantJD.MaterializingInfos.find(DependantName); 1110 assert(DependantMII != DependantJD.MaterializingInfos.end() && 1111 "Dependant should have MaterializingInfo"); 1112 1113 auto &DependantMI = DependantMII->second; 1114 1115 // Remove the dependant's dependency on this node. 1116 assert(DependantMI.UnemittedDependencies.count(this) && 1117 "Dependant does not have an unemitted dependencies record " 1118 "for " 1119 "this JITDylib"); 1120 assert(DependantMI.UnemittedDependencies[this].count(Name) && 1121 "Dependant does not count this symbol as a dependency?"); 1122 1123 DependantMI.UnemittedDependencies[this].erase(Name); 1124 if (DependantMI.UnemittedDependencies[this].empty()) 1125 DependantMI.UnemittedDependencies.erase(this); 1126 1127 // Transfer unemitted dependencies from this node to the 1128 // dependant. 1129 DependantJD.transferEmittedNodeDependencies(DependantMI, 1130 DependantName, MI); 1131 1132 auto DependantSymI = DependantJD.Symbols.find(DependantName); 1133 assert(DependantSymI != DependantJD.Symbols.end() && 1134 "Dependant has no entry in the Symbols table"); 1135 auto &DependantSymEntry = DependantSymI->second; 1136 1137 // If the dependant is emitted and this node was the last of its 1138 // unemitted dependencies then the dependant node is now ready, so 1139 // notify any pending queries on the dependant node. 1140 if (DependantSymEntry.getState() == SymbolState::Emitted && 1141 DependantMI.UnemittedDependencies.empty()) { 1142 assert(DependantMI.Dependants.empty() && 1143 "Dependants should be empty by now"); 1144 1145 // Since this dependant is now ready, we erase its 1146 // MaterializingInfo and update its materializing state. 1147 DependantSymEntry.setState(SymbolState::Ready); 1148 DependantJDReadySymbols.push_back(DependantName); 1149 1150 for (auto &Q : 1151 DependantMI.takeQueriesMeeting(SymbolState::Ready)) { 1152 Q->notifySymbolMetRequiredState( 1153 DependantName, DependantSymI->second.getSymbol()); 1154 if (Q->isComplete()) 1155 CompletedQueries.insert(Q); 1156 Q->removeQueryDependence(DependantJD, DependantName); 1157 } 1158 DependantJD.MaterializingInfos.erase(DependantMII); 1159 } 1160 } 1161 } 1162 1163 auto &ThisJDReadySymbols = ReadySymbols[this]; 1164 MI.Dependants.clear(); 1165 if (MI.UnemittedDependencies.empty()) { 1166 SymI->second.setState(SymbolState::Ready); 1167 ThisJDReadySymbols.push_back(Name); 1168 for (auto &Q : MI.takeQueriesMeeting(SymbolState::Ready)) { 1169 Q->notifySymbolMetRequiredState(Name, SymI->second.getSymbol()); 1170 if (Q->isComplete()) 1171 CompletedQueries.insert(Q); 1172 Q->removeQueryDependence(*this, Name); 1173 } 1174 MaterializingInfos.erase(MII); 1175 } 1176 } 1177 1178 return Error::success(); 1179 })) 1180 return Err; 1181 1182 // Otherwise notify all the completed queries. 1183 for (auto &Q : CompletedQueries) { 1184 assert(Q->isComplete() && "Q is not complete"); 1185 Q->handleComplete(ES); 1186 } 1187 1188 return Error::success(); 1189 } 1190 1191 void JITDylib::unlinkMaterializationResponsibility( 1192 MaterializationResponsibility &MR) { 1193 ES.runSessionLocked([&]() { 1194 auto I = TrackerMRs.find(MR.RT.get()); 1195 assert(I != TrackerMRs.end() && "No MRs in TrackerMRs list for RT"); 1196 assert(I->second.count(&MR) && "MR not in TrackerMRs list for RT"); 1197 I->second.erase(&MR); 1198 if (I->second.empty()) 1199 TrackerMRs.erase(MR.RT.get()); 1200 }); 1201 } 1202 1203 std::pair<JITDylib::AsynchronousSymbolQuerySet, 1204 std::shared_ptr<SymbolDependenceMap>> 1205 JITDylib::failSymbols(FailedSymbolsWorklist Worklist) { 1206 AsynchronousSymbolQuerySet FailedQueries; 1207 auto FailedSymbolsMap = std::make_shared<SymbolDependenceMap>(); 1208 1209 while (!Worklist.empty()) { 1210 assert(Worklist.back().first && "Failed JITDylib can not be null"); 1211 auto &JD = *Worklist.back().first; 1212 auto Name = std::move(Worklist.back().second); 1213 Worklist.pop_back(); 1214 1215 (*FailedSymbolsMap)[&JD].insert(Name); 1216 1217 // Look up the symbol to fail. 1218 auto SymI = JD.Symbols.find(Name); 1219 1220 // It's possible that this symbol has already been removed, e.g. if a 1221 // materialization failure happens concurrently with a ResourceTracker or 1222 // JITDylib removal. In that case we can safely skip this symbol and 1223 // continue. 1224 if (SymI == JD.Symbols.end()) 1225 continue; 1226 auto &Sym = SymI->second; 1227 1228 // Move the symbol into the error state. 1229 // Note that this may be redundant: The symbol might already have been 1230 // moved to this state in response to the failure of a dependence. 1231 Sym.setFlags(Sym.getFlags() | JITSymbolFlags::HasError); 1232 1233 // FIXME: Come up with a sane mapping of state to 1234 // presence-of-MaterializingInfo so that we can assert presence / absence 1235 // here, rather than testing it. 1236 auto MII = JD.MaterializingInfos.find(Name); 1237 1238 if (MII == JD.MaterializingInfos.end()) 1239 continue; 1240 1241 auto &MI = MII->second; 1242 1243 // Move all dependants to the error state and disconnect from them. 1244 for (auto &KV : MI.Dependants) { 1245 auto &DependantJD = *KV.first; 1246 for (auto &DependantName : KV.second) { 1247 assert(DependantJD.Symbols.count(DependantName) && 1248 "No symbol table entry for DependantName"); 1249 auto &DependantSym = DependantJD.Symbols[DependantName]; 1250 DependantSym.setFlags(DependantSym.getFlags() | 1251 JITSymbolFlags::HasError); 1252 1253 assert(DependantJD.MaterializingInfos.count(DependantName) && 1254 "No MaterializingInfo for dependant"); 1255 auto &DependantMI = DependantJD.MaterializingInfos[DependantName]; 1256 1257 auto UnemittedDepI = DependantMI.UnemittedDependencies.find(&JD); 1258 assert(UnemittedDepI != DependantMI.UnemittedDependencies.end() && 1259 "No UnemittedDependencies entry for this JITDylib"); 1260 assert(UnemittedDepI->second.count(Name) && 1261 "No UnemittedDependencies entry for this symbol"); 1262 UnemittedDepI->second.erase(Name); 1263 if (UnemittedDepI->second.empty()) 1264 DependantMI.UnemittedDependencies.erase(UnemittedDepI); 1265 1266 // If this symbol is already in the emitted state then we need to 1267 // take responsibility for failing its queries, so add it to the 1268 // worklist. 1269 if (DependantSym.getState() == SymbolState::Emitted) { 1270 assert(DependantMI.Dependants.empty() && 1271 "Emitted symbol should not have dependants"); 1272 Worklist.push_back(std::make_pair(&DependantJD, DependantName)); 1273 } 1274 } 1275 } 1276 MI.Dependants.clear(); 1277 1278 // Disconnect from all unemitted depenencies. 1279 for (auto &KV : MI.UnemittedDependencies) { 1280 auto &UnemittedDepJD = *KV.first; 1281 for (auto &UnemittedDepName : KV.second) { 1282 auto UnemittedDepMII = 1283 UnemittedDepJD.MaterializingInfos.find(UnemittedDepName); 1284 assert(UnemittedDepMII != UnemittedDepJD.MaterializingInfos.end() && 1285 "Missing MII for unemitted dependency"); 1286 assert(UnemittedDepMII->second.Dependants.count(&JD) && 1287 "JD not listed as a dependant of unemitted dependency"); 1288 assert(UnemittedDepMII->second.Dependants[&JD].count(Name) && 1289 "Name is not listed as a dependant of unemitted dependency"); 1290 UnemittedDepMII->second.Dependants[&JD].erase(Name); 1291 if (UnemittedDepMII->second.Dependants[&JD].empty()) 1292 UnemittedDepMII->second.Dependants.erase(&JD); 1293 } 1294 } 1295 MI.UnemittedDependencies.clear(); 1296 1297 // Collect queries to be failed for this MII. 1298 AsynchronousSymbolQueryList ToDetach; 1299 for (auto &Q : MII->second.pendingQueries()) { 1300 // Add the query to the list to be failed and detach it. 1301 FailedQueries.insert(Q); 1302 ToDetach.push_back(Q); 1303 } 1304 for (auto &Q : ToDetach) 1305 Q->detach(); 1306 1307 assert(MI.Dependants.empty() && 1308 "Can not delete MaterializingInfo with dependants still attached"); 1309 assert(MI.UnemittedDependencies.empty() && 1310 "Can not delete MaterializingInfo with unemitted dependencies " 1311 "still attached"); 1312 assert(!MI.hasQueriesPending() && 1313 "Can not delete MaterializingInfo with queries pending"); 1314 JD.MaterializingInfos.erase(MII); 1315 } 1316 1317 return std::make_pair(std::move(FailedQueries), std::move(FailedSymbolsMap)); 1318 } 1319 1320 void JITDylib::setLinkOrder(JITDylibSearchOrder NewLinkOrder, 1321 bool LinkAgainstThisJITDylibFirst) { 1322 ES.runSessionLocked([&]() { 1323 assert(State == Open && "JD is defunct"); 1324 if (LinkAgainstThisJITDylibFirst) { 1325 LinkOrder.clear(); 1326 if (NewLinkOrder.empty() || NewLinkOrder.front().first != this) 1327 LinkOrder.push_back( 1328 std::make_pair(this, JITDylibLookupFlags::MatchAllSymbols)); 1329 llvm::append_range(LinkOrder, NewLinkOrder); 1330 } else 1331 LinkOrder = std::move(NewLinkOrder); 1332 }); 1333 } 1334 1335 void JITDylib::addToLinkOrder(const JITDylibSearchOrder &NewLinks) { 1336 ES.runSessionLocked([&]() { 1337 for (auto &KV : NewLinks) { 1338 // Skip elements of NewLinks that are already in the link order. 1339 if (llvm::find(LinkOrder, KV) != LinkOrder.end()) 1340 continue; 1341 1342 LinkOrder.push_back(std::move(KV)); 1343 } 1344 }); 1345 } 1346 1347 void JITDylib::addToLinkOrder(JITDylib &JD, JITDylibLookupFlags JDLookupFlags) { 1348 ES.runSessionLocked([&]() { LinkOrder.push_back({&JD, JDLookupFlags}); }); 1349 } 1350 1351 void JITDylib::replaceInLinkOrder(JITDylib &OldJD, JITDylib &NewJD, 1352 JITDylibLookupFlags JDLookupFlags) { 1353 ES.runSessionLocked([&]() { 1354 assert(State == Open && "JD is defunct"); 1355 for (auto &KV : LinkOrder) 1356 if (KV.first == &OldJD) { 1357 KV = {&NewJD, JDLookupFlags}; 1358 break; 1359 } 1360 }); 1361 } 1362 1363 void JITDylib::removeFromLinkOrder(JITDylib &JD) { 1364 ES.runSessionLocked([&]() { 1365 assert(State == Open && "JD is defunct"); 1366 auto I = llvm::find_if(LinkOrder, 1367 [&](const JITDylibSearchOrder::value_type &KV) { 1368 return KV.first == &JD; 1369 }); 1370 if (I != LinkOrder.end()) 1371 LinkOrder.erase(I); 1372 }); 1373 } 1374 1375 Error JITDylib::remove(const SymbolNameSet &Names) { 1376 return ES.runSessionLocked([&]() -> Error { 1377 assert(State == Open && "JD is defunct"); 1378 using SymbolMaterializerItrPair = 1379 std::pair<SymbolTable::iterator, UnmaterializedInfosMap::iterator>; 1380 std::vector<SymbolMaterializerItrPair> SymbolsToRemove; 1381 SymbolNameSet Missing; 1382 SymbolNameSet Materializing; 1383 1384 for (auto &Name : Names) { 1385 auto I = Symbols.find(Name); 1386 1387 // Note symbol missing. 1388 if (I == Symbols.end()) { 1389 Missing.insert(Name); 1390 continue; 1391 } 1392 1393 // Note symbol materializing. 1394 if (I->second.getState() != SymbolState::NeverSearched && 1395 I->second.getState() != SymbolState::Ready) { 1396 Materializing.insert(Name); 1397 continue; 1398 } 1399 1400 auto UMII = I->second.hasMaterializerAttached() 1401 ? UnmaterializedInfos.find(Name) 1402 : UnmaterializedInfos.end(); 1403 SymbolsToRemove.push_back(std::make_pair(I, UMII)); 1404 } 1405 1406 // If any of the symbols are not defined, return an error. 1407 if (!Missing.empty()) 1408 return make_error<SymbolsNotFound>(ES.getSymbolStringPool(), 1409 std::move(Missing)); 1410 1411 // If any of the symbols are currently materializing, return an error. 1412 if (!Materializing.empty()) 1413 return make_error<SymbolsCouldNotBeRemoved>(ES.getSymbolStringPool(), 1414 std::move(Materializing)); 1415 1416 // Remove the symbols. 1417 for (auto &SymbolMaterializerItrPair : SymbolsToRemove) { 1418 auto UMII = SymbolMaterializerItrPair.second; 1419 1420 // If there is a materializer attached, call discard. 1421 if (UMII != UnmaterializedInfos.end()) { 1422 UMII->second->MU->doDiscard(*this, UMII->first); 1423 UnmaterializedInfos.erase(UMII); 1424 } 1425 1426 auto SymI = SymbolMaterializerItrPair.first; 1427 Symbols.erase(SymI); 1428 } 1429 1430 return Error::success(); 1431 }); 1432 } 1433 1434 void JITDylib::dump(raw_ostream &OS) { 1435 ES.runSessionLocked([&, this]() { 1436 OS << "JITDylib \"" << getName() << "\" (ES: " 1437 << format("0x%016" PRIx64, reinterpret_cast<uintptr_t>(&ES)) 1438 << ", State = "; 1439 switch (State) { 1440 case Open: 1441 OS << "Open"; 1442 break; 1443 case Closing: 1444 OS << "Closing"; 1445 break; 1446 case Closed: 1447 OS << "Closed"; 1448 break; 1449 } 1450 OS << ")\n"; 1451 if (State == Closed) 1452 return; 1453 OS << "Link order: " << LinkOrder << "\n" 1454 << "Symbol table:\n"; 1455 1456 // Sort symbols so we get a deterministic order and can check them in tests. 1457 std::vector<std::pair<SymbolStringPtr, SymbolTableEntry *>> SymbolsSorted; 1458 for (auto &KV : Symbols) 1459 SymbolsSorted.emplace_back(KV.first, &KV.second); 1460 std::sort(SymbolsSorted.begin(), SymbolsSorted.end(), 1461 [](const auto &L, const auto &R) { return *L.first < *R.first; }); 1462 1463 for (auto &KV : SymbolsSorted) { 1464 OS << " \"" << *KV.first << "\": "; 1465 if (auto Addr = KV.second->getAddress()) 1466 OS << Addr; 1467 else 1468 OS << "<not resolved> "; 1469 1470 OS << " " << KV.second->getFlags() << " " << KV.second->getState(); 1471 1472 if (KV.second->hasMaterializerAttached()) { 1473 OS << " (Materializer "; 1474 auto I = UnmaterializedInfos.find(KV.first); 1475 assert(I != UnmaterializedInfos.end() && 1476 "Lazy symbol should have UnmaterializedInfo"); 1477 OS << I->second->MU.get() << ", " << I->second->MU->getName() << ")\n"; 1478 } else 1479 OS << "\n"; 1480 } 1481 1482 if (!MaterializingInfos.empty()) 1483 OS << " MaterializingInfos entries:\n"; 1484 for (auto &KV : MaterializingInfos) { 1485 OS << " \"" << *KV.first << "\":\n" 1486 << " " << KV.second.pendingQueries().size() 1487 << " pending queries: { "; 1488 for (const auto &Q : KV.second.pendingQueries()) 1489 OS << Q.get() << " (" << Q->getRequiredState() << ") "; 1490 OS << "}\n Dependants:\n"; 1491 for (auto &KV2 : KV.second.Dependants) 1492 OS << " " << KV2.first->getName() << ": " << KV2.second << "\n"; 1493 OS << " Unemitted Dependencies:\n"; 1494 for (auto &KV2 : KV.second.UnemittedDependencies) 1495 OS << " " << KV2.first->getName() << ": " << KV2.second << "\n"; 1496 assert((Symbols[KV.first].getState() != SymbolState::Ready || 1497 !KV.second.pendingQueries().empty() || 1498 !KV.second.Dependants.empty() || 1499 !KV.second.UnemittedDependencies.empty()) && 1500 "Stale materializing info entry"); 1501 } 1502 }); 1503 } 1504 1505 void JITDylib::MaterializingInfo::addQuery( 1506 std::shared_ptr<AsynchronousSymbolQuery> Q) { 1507 1508 auto I = llvm::lower_bound( 1509 llvm::reverse(PendingQueries), Q->getRequiredState(), 1510 [](const std::shared_ptr<AsynchronousSymbolQuery> &V, SymbolState S) { 1511 return V->getRequiredState() <= S; 1512 }); 1513 PendingQueries.insert(I.base(), std::move(Q)); 1514 } 1515 1516 void JITDylib::MaterializingInfo::removeQuery( 1517 const AsynchronousSymbolQuery &Q) { 1518 // FIXME: Implement 'find_as' for shared_ptr<T>/T*. 1519 auto I = llvm::find_if( 1520 PendingQueries, [&Q](const std::shared_ptr<AsynchronousSymbolQuery> &V) { 1521 return V.get() == &Q; 1522 }); 1523 assert(I != PendingQueries.end() && 1524 "Query is not attached to this MaterializingInfo"); 1525 PendingQueries.erase(I); 1526 } 1527 1528 JITDylib::AsynchronousSymbolQueryList 1529 JITDylib::MaterializingInfo::takeQueriesMeeting(SymbolState RequiredState) { 1530 AsynchronousSymbolQueryList Result; 1531 while (!PendingQueries.empty()) { 1532 if (PendingQueries.back()->getRequiredState() > RequiredState) 1533 break; 1534 1535 Result.push_back(std::move(PendingQueries.back())); 1536 PendingQueries.pop_back(); 1537 } 1538 1539 return Result; 1540 } 1541 1542 JITDylib::JITDylib(ExecutionSession &ES, std::string Name) 1543 : JITLinkDylib(std::move(Name)), ES(ES) { 1544 LinkOrder.push_back({this, JITDylibLookupFlags::MatchAllSymbols}); 1545 } 1546 1547 std::pair<JITDylib::AsynchronousSymbolQuerySet, 1548 std::shared_ptr<SymbolDependenceMap>> 1549 JITDylib::removeTracker(ResourceTracker &RT) { 1550 // Note: Should be called under the session lock. 1551 assert(State != Closed && "JD is defunct"); 1552 1553 SymbolNameVector SymbolsToRemove; 1554 std::vector<std::pair<JITDylib *, SymbolStringPtr>> SymbolsToFail; 1555 1556 if (&RT == DefaultTracker.get()) { 1557 SymbolNameSet TrackedSymbols; 1558 for (auto &KV : TrackerSymbols) 1559 for (auto &Sym : KV.second) 1560 TrackedSymbols.insert(Sym); 1561 1562 for (auto &KV : Symbols) { 1563 auto &Sym = KV.first; 1564 if (!TrackedSymbols.count(Sym)) 1565 SymbolsToRemove.push_back(Sym); 1566 } 1567 1568 DefaultTracker.reset(); 1569 } else { 1570 /// Check for a non-default tracker. 1571 auto I = TrackerSymbols.find(&RT); 1572 if (I != TrackerSymbols.end()) { 1573 SymbolsToRemove = std::move(I->second); 1574 TrackerSymbols.erase(I); 1575 } 1576 // ... if not found this tracker was already defunct. Nothing to do. 1577 } 1578 1579 for (auto &Sym : SymbolsToRemove) { 1580 assert(Symbols.count(Sym) && "Symbol not in symbol table"); 1581 1582 // If there is a MaterializingInfo then collect any queries to fail. 1583 auto MII = MaterializingInfos.find(Sym); 1584 if (MII != MaterializingInfos.end()) 1585 SymbolsToFail.push_back({this, Sym}); 1586 } 1587 1588 AsynchronousSymbolQuerySet QueriesToFail; 1589 auto Result = failSymbols(std::move(SymbolsToFail)); 1590 1591 // Removed symbols should be taken out of the table altogether. 1592 for (auto &Sym : SymbolsToRemove) { 1593 auto I = Symbols.find(Sym); 1594 assert(I != Symbols.end() && "Symbol not present in table"); 1595 1596 // Remove Materializer if present. 1597 if (I->second.hasMaterializerAttached()) { 1598 // FIXME: Should this discard the symbols? 1599 UnmaterializedInfos.erase(Sym); 1600 } else { 1601 assert(!UnmaterializedInfos.count(Sym) && 1602 "Symbol has materializer attached"); 1603 } 1604 1605 Symbols.erase(I); 1606 } 1607 1608 return Result; 1609 } 1610 1611 void JITDylib::transferTracker(ResourceTracker &DstRT, ResourceTracker &SrcRT) { 1612 assert(State != Closed && "JD is defunct"); 1613 assert(&DstRT != &SrcRT && "No-op transfers shouldn't call transferTracker"); 1614 assert(&DstRT.getJITDylib() == this && "DstRT is not for this JITDylib"); 1615 assert(&SrcRT.getJITDylib() == this && "SrcRT is not for this JITDylib"); 1616 1617 // Update trackers for any not-yet materialized units. 1618 for (auto &KV : UnmaterializedInfos) { 1619 if (KV.second->RT == &SrcRT) 1620 KV.second->RT = &DstRT; 1621 } 1622 1623 // Update trackers for any active materialization responsibilities. 1624 { 1625 auto I = TrackerMRs.find(&SrcRT); 1626 if (I != TrackerMRs.end()) { 1627 auto &SrcMRs = I->second; 1628 auto &DstMRs = TrackerMRs[&DstRT]; 1629 for (auto *MR : SrcMRs) 1630 MR->RT = &DstRT; 1631 if (DstMRs.empty()) 1632 DstMRs = std::move(SrcMRs); 1633 else 1634 for (auto *MR : SrcMRs) 1635 DstMRs.insert(MR); 1636 // Erase SrcRT entry in TrackerMRs. Use &SrcRT key rather than iterator I 1637 // for this, since I may have been invalidated by 'TrackerMRs[&DstRT]'. 1638 TrackerMRs.erase(&SrcRT); 1639 } 1640 } 1641 1642 // If we're transfering to the default tracker we just need to delete the 1643 // tracked symbols for the source tracker. 1644 if (&DstRT == DefaultTracker.get()) { 1645 TrackerSymbols.erase(&SrcRT); 1646 return; 1647 } 1648 1649 // If we're transferring from the default tracker we need to find all 1650 // currently untracked symbols. 1651 if (&SrcRT == DefaultTracker.get()) { 1652 assert(!TrackerSymbols.count(&SrcRT) && 1653 "Default tracker should not appear in TrackerSymbols"); 1654 1655 SymbolNameVector SymbolsToTrack; 1656 1657 SymbolNameSet CurrentlyTrackedSymbols; 1658 for (auto &KV : TrackerSymbols) 1659 for (auto &Sym : KV.second) 1660 CurrentlyTrackedSymbols.insert(Sym); 1661 1662 for (auto &KV : Symbols) { 1663 auto &Sym = KV.first; 1664 if (!CurrentlyTrackedSymbols.count(Sym)) 1665 SymbolsToTrack.push_back(Sym); 1666 } 1667 1668 TrackerSymbols[&DstRT] = std::move(SymbolsToTrack); 1669 return; 1670 } 1671 1672 auto &DstTrackedSymbols = TrackerSymbols[&DstRT]; 1673 1674 // Finally if neither SrtRT or DstRT are the default tracker then 1675 // just append DstRT's tracked symbols to SrtRT's. 1676 auto SI = TrackerSymbols.find(&SrcRT); 1677 if (SI == TrackerSymbols.end()) 1678 return; 1679 1680 DstTrackedSymbols.reserve(DstTrackedSymbols.size() + SI->second.size()); 1681 for (auto &Sym : SI->second) 1682 DstTrackedSymbols.push_back(std::move(Sym)); 1683 TrackerSymbols.erase(SI); 1684 } 1685 1686 Error JITDylib::defineImpl(MaterializationUnit &MU) { 1687 1688 LLVM_DEBUG({ dbgs() << " " << MU.getSymbols() << "\n"; }); 1689 1690 SymbolNameSet Duplicates; 1691 std::vector<SymbolStringPtr> ExistingDefsOverridden; 1692 std::vector<SymbolStringPtr> MUDefsOverridden; 1693 1694 for (const auto &KV : MU.getSymbols()) { 1695 auto I = Symbols.find(KV.first); 1696 1697 if (I != Symbols.end()) { 1698 if (KV.second.isStrong()) { 1699 if (I->second.getFlags().isStrong() || 1700 I->second.getState() > SymbolState::NeverSearched) 1701 Duplicates.insert(KV.first); 1702 else { 1703 assert(I->second.getState() == SymbolState::NeverSearched && 1704 "Overridden existing def should be in the never-searched " 1705 "state"); 1706 ExistingDefsOverridden.push_back(KV.first); 1707 } 1708 } else 1709 MUDefsOverridden.push_back(KV.first); 1710 } 1711 } 1712 1713 // If there were any duplicate definitions then bail out. 1714 if (!Duplicates.empty()) { 1715 LLVM_DEBUG( 1716 { dbgs() << " Error: Duplicate symbols " << Duplicates << "\n"; }); 1717 return make_error<DuplicateDefinition>(std::string(**Duplicates.begin())); 1718 } 1719 1720 // Discard any overridden defs in this MU. 1721 LLVM_DEBUG({ 1722 if (!MUDefsOverridden.empty()) 1723 dbgs() << " Defs in this MU overridden: " << MUDefsOverridden << "\n"; 1724 }); 1725 for (auto &S : MUDefsOverridden) 1726 MU.doDiscard(*this, S); 1727 1728 // Discard existing overridden defs. 1729 LLVM_DEBUG({ 1730 if (!ExistingDefsOverridden.empty()) 1731 dbgs() << " Existing defs overridden by this MU: " << MUDefsOverridden 1732 << "\n"; 1733 }); 1734 for (auto &S : ExistingDefsOverridden) { 1735 1736 auto UMII = UnmaterializedInfos.find(S); 1737 assert(UMII != UnmaterializedInfos.end() && 1738 "Overridden existing def should have an UnmaterializedInfo"); 1739 UMII->second->MU->doDiscard(*this, S); 1740 } 1741 1742 // Finally, add the defs from this MU. 1743 for (auto &KV : MU.getSymbols()) { 1744 auto &SymEntry = Symbols[KV.first]; 1745 SymEntry.setFlags(KV.second); 1746 SymEntry.setState(SymbolState::NeverSearched); 1747 SymEntry.setMaterializerAttached(true); 1748 } 1749 1750 return Error::success(); 1751 } 1752 1753 void JITDylib::installMaterializationUnit( 1754 std::unique_ptr<MaterializationUnit> MU, ResourceTracker &RT) { 1755 1756 /// defineImpl succeeded. 1757 if (&RT != DefaultTracker.get()) { 1758 auto &TS = TrackerSymbols[&RT]; 1759 TS.reserve(TS.size() + MU->getSymbols().size()); 1760 for (auto &KV : MU->getSymbols()) 1761 TS.push_back(KV.first); 1762 } 1763 1764 auto UMI = std::make_shared<UnmaterializedInfo>(std::move(MU), &RT); 1765 for (auto &KV : UMI->MU->getSymbols()) 1766 UnmaterializedInfos[KV.first] = UMI; 1767 } 1768 1769 void JITDylib::detachQueryHelper(AsynchronousSymbolQuery &Q, 1770 const SymbolNameSet &QuerySymbols) { 1771 for (auto &QuerySymbol : QuerySymbols) { 1772 assert(MaterializingInfos.count(QuerySymbol) && 1773 "QuerySymbol does not have MaterializingInfo"); 1774 auto &MI = MaterializingInfos[QuerySymbol]; 1775 MI.removeQuery(Q); 1776 } 1777 } 1778 1779 void JITDylib::transferEmittedNodeDependencies( 1780 MaterializingInfo &DependantMI, const SymbolStringPtr &DependantName, 1781 MaterializingInfo &EmittedMI) { 1782 for (auto &KV : EmittedMI.UnemittedDependencies) { 1783 auto &DependencyJD = *KV.first; 1784 SymbolNameSet *UnemittedDependenciesOnDependencyJD = nullptr; 1785 1786 for (auto &DependencyName : KV.second) { 1787 auto &DependencyMI = DependencyJD.MaterializingInfos[DependencyName]; 1788 1789 // Do not add self dependencies. 1790 if (&DependencyMI == &DependantMI) 1791 continue; 1792 1793 // If we haven't looked up the dependencies for DependencyJD yet, do it 1794 // now and cache the result. 1795 if (!UnemittedDependenciesOnDependencyJD) 1796 UnemittedDependenciesOnDependencyJD = 1797 &DependantMI.UnemittedDependencies[&DependencyJD]; 1798 1799 DependencyMI.Dependants[this].insert(DependantName); 1800 UnemittedDependenciesOnDependencyJD->insert(DependencyName); 1801 } 1802 } 1803 } 1804 1805 Platform::~Platform() = default; 1806 1807 Expected<DenseMap<JITDylib *, SymbolMap>> Platform::lookupInitSymbols( 1808 ExecutionSession &ES, 1809 const DenseMap<JITDylib *, SymbolLookupSet> &InitSyms) { 1810 1811 DenseMap<JITDylib *, SymbolMap> CompoundResult; 1812 Error CompoundErr = Error::success(); 1813 std::mutex LookupMutex; 1814 std::condition_variable CV; 1815 uint64_t Count = InitSyms.size(); 1816 1817 LLVM_DEBUG({ 1818 dbgs() << "Issuing init-symbol lookup:\n"; 1819 for (auto &KV : InitSyms) 1820 dbgs() << " " << KV.first->getName() << ": " << KV.second << "\n"; 1821 }); 1822 1823 for (auto &KV : InitSyms) { 1824 auto *JD = KV.first; 1825 auto Names = std::move(KV.second); 1826 ES.lookup( 1827 LookupKind::Static, 1828 JITDylibSearchOrder({{JD, JITDylibLookupFlags::MatchAllSymbols}}), 1829 std::move(Names), SymbolState::Ready, 1830 [&, JD](Expected<SymbolMap> Result) { 1831 { 1832 std::lock_guard<std::mutex> Lock(LookupMutex); 1833 --Count; 1834 if (Result) { 1835 assert(!CompoundResult.count(JD) && 1836 "Duplicate JITDylib in lookup?"); 1837 CompoundResult[JD] = std::move(*Result); 1838 } else 1839 CompoundErr = 1840 joinErrors(std::move(CompoundErr), Result.takeError()); 1841 } 1842 CV.notify_one(); 1843 }, 1844 NoDependenciesToRegister); 1845 } 1846 1847 std::unique_lock<std::mutex> Lock(LookupMutex); 1848 CV.wait(Lock, [&] { return Count == 0 || CompoundErr; }); 1849 1850 if (CompoundErr) 1851 return std::move(CompoundErr); 1852 1853 return std::move(CompoundResult); 1854 } 1855 1856 void Platform::lookupInitSymbolsAsync( 1857 unique_function<void(Error)> OnComplete, ExecutionSession &ES, 1858 const DenseMap<JITDylib *, SymbolLookupSet> &InitSyms) { 1859 1860 class TriggerOnComplete { 1861 public: 1862 using OnCompleteFn = unique_function<void(Error)>; 1863 TriggerOnComplete(OnCompleteFn OnComplete) 1864 : OnComplete(std::move(OnComplete)) {} 1865 ~TriggerOnComplete() { OnComplete(std::move(LookupResult)); } 1866 void reportResult(Error Err) { 1867 std::lock_guard<std::mutex> Lock(ResultMutex); 1868 LookupResult = joinErrors(std::move(LookupResult), std::move(Err)); 1869 } 1870 1871 private: 1872 std::mutex ResultMutex; 1873 Error LookupResult{Error::success()}; 1874 OnCompleteFn OnComplete; 1875 }; 1876 1877 LLVM_DEBUG({ 1878 dbgs() << "Issuing init-symbol lookup:\n"; 1879 for (auto &KV : InitSyms) 1880 dbgs() << " " << KV.first->getName() << ": " << KV.second << "\n"; 1881 }); 1882 1883 auto TOC = std::make_shared<TriggerOnComplete>(std::move(OnComplete)); 1884 1885 for (auto &KV : InitSyms) { 1886 auto *JD = KV.first; 1887 auto Names = std::move(KV.second); 1888 ES.lookup( 1889 LookupKind::Static, 1890 JITDylibSearchOrder({{JD, JITDylibLookupFlags::MatchAllSymbols}}), 1891 std::move(Names), SymbolState::Ready, 1892 [TOC](Expected<SymbolMap> Result) { 1893 TOC->reportResult(Result.takeError()); 1894 }, 1895 NoDependenciesToRegister); 1896 } 1897 } 1898 1899 void MaterializationTask::printDescription(raw_ostream &OS) { 1900 OS << "Materialization task: " << MU->getName() << " in " 1901 << MR->getTargetJITDylib().getName(); 1902 } 1903 1904 void MaterializationTask::run() { MU->materialize(std::move(MR)); } 1905 1906 ExecutionSession::ExecutionSession(std::unique_ptr<ExecutorProcessControl> EPC) 1907 : EPC(std::move(EPC)) { 1908 // Associated EPC and this. 1909 this->EPC->ES = this; 1910 } 1911 1912 ExecutionSession::~ExecutionSession() { 1913 // You must call endSession prior to destroying the session. 1914 assert(!SessionOpen && 1915 "Session still open. Did you forget to call endSession?"); 1916 } 1917 1918 Error ExecutionSession::endSession() { 1919 LLVM_DEBUG(dbgs() << "Ending ExecutionSession " << this << "\n"); 1920 1921 std::vector<JITDylibSP> JITDylibsToClose = runSessionLocked([&] { 1922 SessionOpen = false; 1923 return std::move(JDs); 1924 }); 1925 1926 // TODO: notifiy platform? run static deinits? 1927 1928 Error Err = Error::success(); 1929 for (auto &JD : reverse(JITDylibsToClose)) 1930 Err = joinErrors(std::move(Err), JD->clear()); 1931 1932 Err = joinErrors(std::move(Err), EPC->disconnect()); 1933 1934 return Err; 1935 } 1936 1937 void ExecutionSession::registerResourceManager(ResourceManager &RM) { 1938 runSessionLocked([&] { ResourceManagers.push_back(&RM); }); 1939 } 1940 1941 void ExecutionSession::deregisterResourceManager(ResourceManager &RM) { 1942 runSessionLocked([&] { 1943 assert(!ResourceManagers.empty() && "No managers registered"); 1944 if (ResourceManagers.back() == &RM) 1945 ResourceManagers.pop_back(); 1946 else { 1947 auto I = llvm::find(ResourceManagers, &RM); 1948 assert(I != ResourceManagers.end() && "RM not registered"); 1949 ResourceManagers.erase(I); 1950 } 1951 }); 1952 } 1953 1954 JITDylib *ExecutionSession::getJITDylibByName(StringRef Name) { 1955 return runSessionLocked([&, this]() -> JITDylib * { 1956 for (auto &JD : JDs) 1957 if (JD->getName() == Name) 1958 return JD.get(); 1959 return nullptr; 1960 }); 1961 } 1962 1963 JITDylib &ExecutionSession::createBareJITDylib(std::string Name) { 1964 assert(!getJITDylibByName(Name) && "JITDylib with that name already exists"); 1965 return runSessionLocked([&, this]() -> JITDylib & { 1966 assert(SessionOpen && "Cannot create JITDylib after session is closed"); 1967 JDs.push_back(new JITDylib(*this, std::move(Name))); 1968 return *JDs.back(); 1969 }); 1970 } 1971 1972 Expected<JITDylib &> ExecutionSession::createJITDylib(std::string Name) { 1973 auto &JD = createBareJITDylib(Name); 1974 if (P) 1975 if (auto Err = P->setupJITDylib(JD)) 1976 return std::move(Err); 1977 return JD; 1978 } 1979 1980 Error ExecutionSession::removeJITDylib(JITDylib &JD) { 1981 // Keep JD alive throughout this routine, even if all other references 1982 // have been dropped. 1983 JITDylibSP JDKeepAlive = &JD; 1984 1985 // Set JD to 'Closing' state and remove JD from the ExecutionSession. 1986 runSessionLocked([&] { 1987 assert(JD.State == JITDylib::Open && "JD already closed"); 1988 JD.State = JITDylib::Closing; 1989 auto I = llvm::find(JDs, &JD); 1990 assert(I != JDs.end() && "JD does not appear in session JDs"); 1991 JDs.erase(I); 1992 }); 1993 1994 // Clear the JITDylib. Hold on to any error while we clean up the 1995 // JITDylib members below. 1996 auto Err = JD.clear(); 1997 1998 // Notify the platform of the teardown. 1999 if (P) 2000 Err = joinErrors(std::move(Err), P->teardownJITDylib(JD)); 2001 2002 // Set JD to closed state. Clear remaining data structures. 2003 runSessionLocked([&] { 2004 assert(JD.State == JITDylib::Closing && "JD should be closing"); 2005 JD.State = JITDylib::Closed; 2006 assert(JD.Symbols.empty() && "JD.Symbols is not empty after clear"); 2007 assert(JD.UnmaterializedInfos.empty() && 2008 "JD.UnmaterializedInfos is not empty after clear"); 2009 assert(JD.MaterializingInfos.empty() && 2010 "JD.MaterializingInfos is not empty after clear"); 2011 assert(JD.TrackerSymbols.empty() && 2012 "TrackerSymbols is not empty after clear"); 2013 JD.DefGenerators.clear(); 2014 JD.LinkOrder.clear(); 2015 }); 2016 return Err; 2017 } 2018 2019 Expected<std::vector<JITDylibSP>> 2020 JITDylib::getDFSLinkOrder(ArrayRef<JITDylibSP> JDs) { 2021 if (JDs.empty()) 2022 return std::vector<JITDylibSP>(); 2023 2024 auto &ES = JDs.front()->getExecutionSession(); 2025 return ES.runSessionLocked([&]() -> Expected<std::vector<JITDylibSP>> { 2026 DenseSet<JITDylib *> Visited; 2027 std::vector<JITDylibSP> Result; 2028 2029 for (auto &JD : JDs) { 2030 2031 if (JD->State != Open) 2032 return make_error<StringError>( 2033 "Error building link order: " + JD->getName() + " is defunct", 2034 inconvertibleErrorCode()); 2035 if (Visited.count(JD.get())) 2036 continue; 2037 2038 SmallVector<JITDylibSP, 64> WorkStack; 2039 WorkStack.push_back(JD); 2040 Visited.insert(JD.get()); 2041 2042 while (!WorkStack.empty()) { 2043 Result.push_back(std::move(WorkStack.back())); 2044 WorkStack.pop_back(); 2045 2046 for (auto &KV : llvm::reverse(Result.back()->LinkOrder)) { 2047 auto &JD = *KV.first; 2048 if (!Visited.insert(&JD).second) 2049 continue; 2050 WorkStack.push_back(&JD); 2051 } 2052 } 2053 } 2054 return Result; 2055 }); 2056 } 2057 2058 Expected<std::vector<JITDylibSP>> 2059 JITDylib::getReverseDFSLinkOrder(ArrayRef<JITDylibSP> JDs) { 2060 auto Result = getDFSLinkOrder(JDs); 2061 if (Result) 2062 std::reverse(Result->begin(), Result->end()); 2063 return Result; 2064 } 2065 2066 Expected<std::vector<JITDylibSP>> JITDylib::getDFSLinkOrder() { 2067 return getDFSLinkOrder({this}); 2068 } 2069 2070 Expected<std::vector<JITDylibSP>> JITDylib::getReverseDFSLinkOrder() { 2071 return getReverseDFSLinkOrder({this}); 2072 } 2073 2074 void ExecutionSession::lookupFlags( 2075 LookupKind K, JITDylibSearchOrder SearchOrder, SymbolLookupSet LookupSet, 2076 unique_function<void(Expected<SymbolFlagsMap>)> OnComplete) { 2077 2078 OL_applyQueryPhase1(std::make_unique<InProgressLookupFlagsState>( 2079 K, std::move(SearchOrder), std::move(LookupSet), 2080 std::move(OnComplete)), 2081 Error::success()); 2082 } 2083 2084 Expected<SymbolFlagsMap> 2085 ExecutionSession::lookupFlags(LookupKind K, JITDylibSearchOrder SearchOrder, 2086 SymbolLookupSet LookupSet) { 2087 2088 std::promise<MSVCPExpected<SymbolFlagsMap>> ResultP; 2089 OL_applyQueryPhase1(std::make_unique<InProgressLookupFlagsState>( 2090 K, std::move(SearchOrder), std::move(LookupSet), 2091 [&ResultP](Expected<SymbolFlagsMap> Result) { 2092 ResultP.set_value(std::move(Result)); 2093 }), 2094 Error::success()); 2095 2096 auto ResultF = ResultP.get_future(); 2097 return ResultF.get(); 2098 } 2099 2100 void ExecutionSession::lookup( 2101 LookupKind K, const JITDylibSearchOrder &SearchOrder, 2102 SymbolLookupSet Symbols, SymbolState RequiredState, 2103 SymbolsResolvedCallback NotifyComplete, 2104 RegisterDependenciesFunction RegisterDependencies) { 2105 2106 LLVM_DEBUG({ 2107 runSessionLocked([&]() { 2108 dbgs() << "Looking up " << Symbols << " in " << SearchOrder 2109 << " (required state: " << RequiredState << ")\n"; 2110 }); 2111 }); 2112 2113 // lookup can be re-entered recursively if running on a single thread. Run any 2114 // outstanding MUs in case this query depends on them, otherwise this lookup 2115 // will starve waiting for a result from an MU that is stuck in the queue. 2116 dispatchOutstandingMUs(); 2117 2118 auto Unresolved = std::move(Symbols); 2119 auto Q = std::make_shared<AsynchronousSymbolQuery>(Unresolved, RequiredState, 2120 std::move(NotifyComplete)); 2121 2122 auto IPLS = std::make_unique<InProgressFullLookupState>( 2123 K, SearchOrder, std::move(Unresolved), RequiredState, std::move(Q), 2124 std::move(RegisterDependencies)); 2125 2126 OL_applyQueryPhase1(std::move(IPLS), Error::success()); 2127 } 2128 2129 Expected<SymbolMap> 2130 ExecutionSession::lookup(const JITDylibSearchOrder &SearchOrder, 2131 SymbolLookupSet Symbols, LookupKind K, 2132 SymbolState RequiredState, 2133 RegisterDependenciesFunction RegisterDependencies) { 2134 #if LLVM_ENABLE_THREADS 2135 // In the threaded case we use promises to return the results. 2136 std::promise<SymbolMap> PromisedResult; 2137 Error ResolutionError = Error::success(); 2138 2139 auto NotifyComplete = [&](Expected<SymbolMap> R) { 2140 if (R) 2141 PromisedResult.set_value(std::move(*R)); 2142 else { 2143 ErrorAsOutParameter _(&ResolutionError); 2144 ResolutionError = R.takeError(); 2145 PromisedResult.set_value(SymbolMap()); 2146 } 2147 }; 2148 2149 #else 2150 SymbolMap Result; 2151 Error ResolutionError = Error::success(); 2152 2153 auto NotifyComplete = [&](Expected<SymbolMap> R) { 2154 ErrorAsOutParameter _(&ResolutionError); 2155 if (R) 2156 Result = std::move(*R); 2157 else 2158 ResolutionError = R.takeError(); 2159 }; 2160 #endif 2161 2162 // Perform the asynchronous lookup. 2163 lookup(K, SearchOrder, std::move(Symbols), RequiredState, NotifyComplete, 2164 RegisterDependencies); 2165 2166 #if LLVM_ENABLE_THREADS 2167 auto ResultFuture = PromisedResult.get_future(); 2168 auto Result = ResultFuture.get(); 2169 2170 if (ResolutionError) 2171 return std::move(ResolutionError); 2172 2173 return std::move(Result); 2174 2175 #else 2176 if (ResolutionError) 2177 return std::move(ResolutionError); 2178 2179 return Result; 2180 #endif 2181 } 2182 2183 Expected<ExecutorSymbolDef> 2184 ExecutionSession::lookup(const JITDylibSearchOrder &SearchOrder, 2185 SymbolStringPtr Name, SymbolState RequiredState) { 2186 SymbolLookupSet Names({Name}); 2187 2188 if (auto ResultMap = lookup(SearchOrder, std::move(Names), LookupKind::Static, 2189 RequiredState, NoDependenciesToRegister)) { 2190 assert(ResultMap->size() == 1 && "Unexpected number of results"); 2191 assert(ResultMap->count(Name) && "Missing result for symbol"); 2192 return std::move(ResultMap->begin()->second); 2193 } else 2194 return ResultMap.takeError(); 2195 } 2196 2197 Expected<ExecutorSymbolDef> 2198 ExecutionSession::lookup(ArrayRef<JITDylib *> SearchOrder, SymbolStringPtr Name, 2199 SymbolState RequiredState) { 2200 return lookup(makeJITDylibSearchOrder(SearchOrder), Name, RequiredState); 2201 } 2202 2203 Expected<ExecutorSymbolDef> 2204 ExecutionSession::lookup(ArrayRef<JITDylib *> SearchOrder, StringRef Name, 2205 SymbolState RequiredState) { 2206 return lookup(SearchOrder, intern(Name), RequiredState); 2207 } 2208 2209 Error ExecutionSession::registerJITDispatchHandlers( 2210 JITDylib &JD, JITDispatchHandlerAssociationMap WFs) { 2211 2212 auto TagAddrs = lookup({{&JD, JITDylibLookupFlags::MatchAllSymbols}}, 2213 SymbolLookupSet::fromMapKeys( 2214 WFs, SymbolLookupFlags::WeaklyReferencedSymbol)); 2215 if (!TagAddrs) 2216 return TagAddrs.takeError(); 2217 2218 // Associate tag addresses with implementations. 2219 std::lock_guard<std::mutex> Lock(JITDispatchHandlersMutex); 2220 for (auto &KV : *TagAddrs) { 2221 auto TagAddr = KV.second.getAddress(); 2222 if (JITDispatchHandlers.count(TagAddr)) 2223 return make_error<StringError>("Tag " + formatv("{0:x16}", TagAddr) + 2224 " (for " + *KV.first + 2225 ") already registered", 2226 inconvertibleErrorCode()); 2227 auto I = WFs.find(KV.first); 2228 assert(I != WFs.end() && I->second && 2229 "JITDispatchHandler implementation missing"); 2230 JITDispatchHandlers[KV.second.getAddress()] = 2231 std::make_shared<JITDispatchHandlerFunction>(std::move(I->second)); 2232 LLVM_DEBUG({ 2233 dbgs() << "Associated function tag \"" << *KV.first << "\" (" 2234 << formatv("{0:x}", KV.second.getAddress()) << ") with handler\n"; 2235 }); 2236 } 2237 return Error::success(); 2238 } 2239 2240 void ExecutionSession::runJITDispatchHandler(SendResultFunction SendResult, 2241 ExecutorAddr HandlerFnTagAddr, 2242 ArrayRef<char> ArgBuffer) { 2243 2244 std::shared_ptr<JITDispatchHandlerFunction> F; 2245 { 2246 std::lock_guard<std::mutex> Lock(JITDispatchHandlersMutex); 2247 auto I = JITDispatchHandlers.find(HandlerFnTagAddr); 2248 if (I != JITDispatchHandlers.end()) 2249 F = I->second; 2250 } 2251 2252 if (F) 2253 (*F)(std::move(SendResult), ArgBuffer.data(), ArgBuffer.size()); 2254 else 2255 SendResult(shared::WrapperFunctionResult::createOutOfBandError( 2256 ("No function registered for tag " + 2257 formatv("{0:x16}", HandlerFnTagAddr)) 2258 .str())); 2259 } 2260 2261 void ExecutionSession::dump(raw_ostream &OS) { 2262 runSessionLocked([this, &OS]() { 2263 for (auto &JD : JDs) 2264 JD->dump(OS); 2265 }); 2266 } 2267 2268 void ExecutionSession::dispatchOutstandingMUs() { 2269 LLVM_DEBUG(dbgs() << "Dispatching MaterializationUnits...\n"); 2270 while (true) { 2271 std::optional<std::pair<std::unique_ptr<MaterializationUnit>, 2272 std::unique_ptr<MaterializationResponsibility>>> 2273 JMU; 2274 2275 { 2276 std::lock_guard<std::recursive_mutex> Lock(OutstandingMUsMutex); 2277 if (!OutstandingMUs.empty()) { 2278 JMU.emplace(std::move(OutstandingMUs.back())); 2279 OutstandingMUs.pop_back(); 2280 } 2281 } 2282 2283 if (!JMU) 2284 break; 2285 2286 assert(JMU->first && "No MU?"); 2287 LLVM_DEBUG(dbgs() << " Dispatching \"" << JMU->first->getName() << "\"\n"); 2288 dispatchTask(std::make_unique<MaterializationTask>(std::move(JMU->first), 2289 std::move(JMU->second))); 2290 } 2291 LLVM_DEBUG(dbgs() << "Done dispatching MaterializationUnits.\n"); 2292 } 2293 2294 Error ExecutionSession::removeResourceTracker(ResourceTracker &RT) { 2295 LLVM_DEBUG({ 2296 dbgs() << "In " << RT.getJITDylib().getName() << " removing tracker " 2297 << formatv("{0:x}", RT.getKeyUnsafe()) << "\n"; 2298 }); 2299 std::vector<ResourceManager *> CurrentResourceManagers; 2300 2301 JITDylib::AsynchronousSymbolQuerySet QueriesToFail; 2302 std::shared_ptr<SymbolDependenceMap> FailedSymbols; 2303 2304 runSessionLocked([&] { 2305 CurrentResourceManagers = ResourceManagers; 2306 RT.makeDefunct(); 2307 std::tie(QueriesToFail, FailedSymbols) = RT.getJITDylib().removeTracker(RT); 2308 }); 2309 2310 Error Err = Error::success(); 2311 2312 auto &JD = RT.getJITDylib(); 2313 for (auto *L : reverse(CurrentResourceManagers)) 2314 Err = joinErrors(std::move(Err), 2315 L->handleRemoveResources(JD, RT.getKeyUnsafe())); 2316 2317 for (auto &Q : QueriesToFail) 2318 Q->handleFailed( 2319 make_error<FailedToMaterialize>(getSymbolStringPool(), FailedSymbols)); 2320 2321 return Err; 2322 } 2323 2324 void ExecutionSession::transferResourceTracker(ResourceTracker &DstRT, 2325 ResourceTracker &SrcRT) { 2326 LLVM_DEBUG({ 2327 dbgs() << "In " << SrcRT.getJITDylib().getName() 2328 << " transfering resources from tracker " 2329 << formatv("{0:x}", SrcRT.getKeyUnsafe()) << " to tracker " 2330 << formatv("{0:x}", DstRT.getKeyUnsafe()) << "\n"; 2331 }); 2332 2333 // No-op transfers are allowed and do not invalidate the source. 2334 if (&DstRT == &SrcRT) 2335 return; 2336 2337 assert(&DstRT.getJITDylib() == &SrcRT.getJITDylib() && 2338 "Can't transfer resources between JITDylibs"); 2339 runSessionLocked([&]() { 2340 SrcRT.makeDefunct(); 2341 auto &JD = DstRT.getJITDylib(); 2342 JD.transferTracker(DstRT, SrcRT); 2343 for (auto *L : reverse(ResourceManagers)) 2344 L->handleTransferResources(JD, DstRT.getKeyUnsafe(), 2345 SrcRT.getKeyUnsafe()); 2346 }); 2347 } 2348 2349 void ExecutionSession::destroyResourceTracker(ResourceTracker &RT) { 2350 runSessionLocked([&]() { 2351 LLVM_DEBUG({ 2352 dbgs() << "In " << RT.getJITDylib().getName() << " destroying tracker " 2353 << formatv("{0:x}", RT.getKeyUnsafe()) << "\n"; 2354 }); 2355 if (!RT.isDefunct()) 2356 transferResourceTracker(*RT.getJITDylib().getDefaultResourceTracker(), 2357 RT); 2358 }); 2359 } 2360 2361 Error ExecutionSession::IL_updateCandidatesFor( 2362 JITDylib &JD, JITDylibLookupFlags JDLookupFlags, 2363 SymbolLookupSet &Candidates, SymbolLookupSet *NonCandidates) { 2364 return Candidates.forEachWithRemoval( 2365 [&](const SymbolStringPtr &Name, 2366 SymbolLookupFlags SymLookupFlags) -> Expected<bool> { 2367 /// Search for the symbol. If not found then continue without 2368 /// removal. 2369 auto SymI = JD.Symbols.find(Name); 2370 if (SymI == JD.Symbols.end()) 2371 return false; 2372 2373 // If this is a non-exported symbol and we're matching exported 2374 // symbols only then remove this symbol from the candidates list. 2375 // 2376 // If we're tracking non-candidates then add this to the non-candidate 2377 // list. 2378 if (!SymI->second.getFlags().isExported() && 2379 JDLookupFlags == JITDylibLookupFlags::MatchExportedSymbolsOnly) { 2380 if (NonCandidates) 2381 NonCandidates->add(Name, SymLookupFlags); 2382 return true; 2383 } 2384 2385 // If we match against a materialization-side-effects only symbol 2386 // then make sure it is weakly-referenced. Otherwise bail out with 2387 // an error. 2388 // FIXME: Use a "materialization-side-effects-only symbols must be 2389 // weakly referenced" specific error here to reduce confusion. 2390 if (SymI->second.getFlags().hasMaterializationSideEffectsOnly() && 2391 SymLookupFlags != SymbolLookupFlags::WeaklyReferencedSymbol) 2392 return make_error<SymbolsNotFound>(getSymbolStringPool(), 2393 SymbolNameVector({Name})); 2394 2395 // If we matched against this symbol but it is in the error state 2396 // then bail out and treat it as a failure to materialize. 2397 if (SymI->second.getFlags().hasError()) { 2398 auto FailedSymbolsMap = std::make_shared<SymbolDependenceMap>(); 2399 (*FailedSymbolsMap)[&JD] = {Name}; 2400 return make_error<FailedToMaterialize>(getSymbolStringPool(), 2401 std::move(FailedSymbolsMap)); 2402 } 2403 2404 // Otherwise this is a match. Remove it from the candidate set. 2405 return true; 2406 }); 2407 } 2408 2409 void ExecutionSession::OL_applyQueryPhase1( 2410 std::unique_ptr<InProgressLookupState> IPLS, Error Err) { 2411 2412 LLVM_DEBUG({ 2413 dbgs() << "Entering OL_applyQueryPhase1:\n" 2414 << " Lookup kind: " << IPLS->K << "\n" 2415 << " Search order: " << IPLS->SearchOrder 2416 << ", Current index = " << IPLS->CurSearchOrderIndex 2417 << (IPLS->NewJITDylib ? " (entering new JITDylib)" : "") << "\n" 2418 << " Lookup set: " << IPLS->LookupSet << "\n" 2419 << " Definition generator candidates: " 2420 << IPLS->DefGeneratorCandidates << "\n" 2421 << " Definition generator non-candidates: " 2422 << IPLS->DefGeneratorNonCandidates << "\n"; 2423 }); 2424 2425 // FIXME: We should attach the query as we go: This provides a result in a 2426 // single pass in the common case where all symbols have already reached the 2427 // required state. The query could be detached again in the 'fail' method on 2428 // IPLS. Phase 2 would be reduced to collecting and dispatching the MUs. 2429 2430 while (IPLS->CurSearchOrderIndex != IPLS->SearchOrder.size()) { 2431 2432 // If we've been handed an error or received one back from a generator then 2433 // fail the query. We don't need to unlink: At this stage the query hasn't 2434 // actually been lodged. 2435 if (Err) 2436 return IPLS->fail(std::move(Err)); 2437 2438 // Get the next JITDylib and lookup flags. 2439 auto &KV = IPLS->SearchOrder[IPLS->CurSearchOrderIndex]; 2440 auto &JD = *KV.first; 2441 auto JDLookupFlags = KV.second; 2442 2443 LLVM_DEBUG({ 2444 dbgs() << "Visiting \"" << JD.getName() << "\" (" << JDLookupFlags 2445 << ") with lookup set " << IPLS->LookupSet << ":\n"; 2446 }); 2447 2448 // If we've just reached a new JITDylib then perform some setup. 2449 if (IPLS->NewJITDylib) { 2450 2451 // Acquire the generator lock for this JITDylib. 2452 IPLS->GeneratorLock = std::unique_lock<std::mutex>(JD.GeneratorsMutex); 2453 2454 // Add any non-candidates from the last JITDylib (if any) back on to the 2455 // list of definition candidates for this JITDylib, reset definition 2456 // non-candidates to the empty set. 2457 SymbolLookupSet Tmp; 2458 std::swap(IPLS->DefGeneratorNonCandidates, Tmp); 2459 IPLS->DefGeneratorCandidates.append(std::move(Tmp)); 2460 2461 LLVM_DEBUG({ 2462 dbgs() << " First time visiting " << JD.getName() 2463 << ", resetting candidate sets and building generator stack\n"; 2464 }); 2465 2466 // Build the definition generator stack for this JITDylib. 2467 runSessionLocked([&] { 2468 IPLS->CurDefGeneratorStack.reserve(JD.DefGenerators.size()); 2469 for (auto &DG : reverse(JD.DefGenerators)) 2470 IPLS->CurDefGeneratorStack.push_back(DG); 2471 }); 2472 2473 // Flag that we've done our initialization. 2474 IPLS->NewJITDylib = false; 2475 } 2476 2477 // Remove any generation candidates that are already defined (and match) in 2478 // this JITDylib. 2479 runSessionLocked([&] { 2480 // Update the list of candidates (and non-candidates) for definition 2481 // generation. 2482 LLVM_DEBUG(dbgs() << " Updating candidate set...\n"); 2483 Err = IL_updateCandidatesFor( 2484 JD, JDLookupFlags, IPLS->DefGeneratorCandidates, 2485 JD.DefGenerators.empty() ? nullptr 2486 : &IPLS->DefGeneratorNonCandidates); 2487 LLVM_DEBUG({ 2488 dbgs() << " Remaining candidates = " << IPLS->DefGeneratorCandidates 2489 << "\n"; 2490 }); 2491 }); 2492 2493 // If we encountered an error while filtering generation candidates then 2494 // bail out. 2495 if (Err) 2496 return IPLS->fail(std::move(Err)); 2497 2498 /// Apply any definition generators on the stack. 2499 LLVM_DEBUG({ 2500 if (IPLS->CurDefGeneratorStack.empty()) 2501 LLVM_DEBUG(dbgs() << " No generators to run for this JITDylib.\n"); 2502 else if (IPLS->DefGeneratorCandidates.empty()) 2503 LLVM_DEBUG(dbgs() << " No candidates to generate.\n"); 2504 else 2505 dbgs() << " Running " << IPLS->CurDefGeneratorStack.size() 2506 << " remaining generators for " 2507 << IPLS->DefGeneratorCandidates.size() << " candidates\n"; 2508 }); 2509 while (!IPLS->CurDefGeneratorStack.empty() && 2510 !IPLS->DefGeneratorCandidates.empty()) { 2511 auto DG = IPLS->CurDefGeneratorStack.back().lock(); 2512 IPLS->CurDefGeneratorStack.pop_back(); 2513 2514 if (!DG) 2515 return IPLS->fail(make_error<StringError>( 2516 "DefinitionGenerator removed while lookup in progress", 2517 inconvertibleErrorCode())); 2518 2519 auto K = IPLS->K; 2520 auto &LookupSet = IPLS->DefGeneratorCandidates; 2521 2522 // Run the generator. If the generator takes ownership of QA then this 2523 // will break the loop. 2524 { 2525 LLVM_DEBUG(dbgs() << " Attempting to generate " << LookupSet << "\n"); 2526 LookupState LS(std::move(IPLS)); 2527 Err = DG->tryToGenerate(LS, K, JD, JDLookupFlags, LookupSet); 2528 IPLS = std::move(LS.IPLS); 2529 } 2530 2531 // If there was an error then fail the query. 2532 if (Err) { 2533 LLVM_DEBUG({ 2534 dbgs() << " Error attempting to generate " << LookupSet << "\n"; 2535 }); 2536 assert(IPLS && "LS cannot be retained if error is returned"); 2537 return IPLS->fail(std::move(Err)); 2538 } 2539 2540 // Otherwise if QA was captured then break the loop. 2541 if (!IPLS) { 2542 LLVM_DEBUG( 2543 { dbgs() << " LookupState captured. Exiting phase1 for now.\n"; }); 2544 return; 2545 } 2546 2547 // Otherwise if we're continuing around the loop then update candidates 2548 // for the next round. 2549 runSessionLocked([&] { 2550 LLVM_DEBUG(dbgs() << " Updating candidate set post-generation\n"); 2551 Err = IL_updateCandidatesFor( 2552 JD, JDLookupFlags, IPLS->DefGeneratorCandidates, 2553 JD.DefGenerators.empty() ? nullptr 2554 : &IPLS->DefGeneratorNonCandidates); 2555 }); 2556 2557 // If updating candidates failed then fail the query. 2558 if (Err) { 2559 LLVM_DEBUG(dbgs() << " Error encountered while updating candidates\n"); 2560 return IPLS->fail(std::move(Err)); 2561 } 2562 } 2563 2564 if (IPLS->DefGeneratorCandidates.empty() && 2565 IPLS->DefGeneratorNonCandidates.empty()) { 2566 // Early out if there are no remaining symbols. 2567 LLVM_DEBUG(dbgs() << "All symbols matched.\n"); 2568 IPLS->CurSearchOrderIndex = IPLS->SearchOrder.size(); 2569 break; 2570 } else { 2571 // If we get here then we've moved on to the next JITDylib with candidates 2572 // remaining. 2573 LLVM_DEBUG(dbgs() << "Phase 1 moving to next JITDylib.\n"); 2574 ++IPLS->CurSearchOrderIndex; 2575 IPLS->NewJITDylib = true; 2576 } 2577 } 2578 2579 // Remove any weakly referenced candidates that could not be found/generated. 2580 IPLS->DefGeneratorCandidates.remove_if( 2581 [](const SymbolStringPtr &Name, SymbolLookupFlags SymLookupFlags) { 2582 return SymLookupFlags == SymbolLookupFlags::WeaklyReferencedSymbol; 2583 }); 2584 2585 // If we get here then we've finished searching all JITDylibs. 2586 // If we matched all symbols then move to phase 2, otherwise fail the query 2587 // with a SymbolsNotFound error. 2588 if (IPLS->DefGeneratorCandidates.empty()) { 2589 LLVM_DEBUG(dbgs() << "Phase 1 succeeded.\n"); 2590 IPLS->complete(std::move(IPLS)); 2591 } else { 2592 LLVM_DEBUG(dbgs() << "Phase 1 failed with unresolved symbols.\n"); 2593 IPLS->fail(make_error<SymbolsNotFound>( 2594 getSymbolStringPool(), IPLS->DefGeneratorCandidates.getSymbolNames())); 2595 } 2596 } 2597 2598 void ExecutionSession::OL_completeLookup( 2599 std::unique_ptr<InProgressLookupState> IPLS, 2600 std::shared_ptr<AsynchronousSymbolQuery> Q, 2601 RegisterDependenciesFunction RegisterDependencies) { 2602 2603 LLVM_DEBUG({ 2604 dbgs() << "Entering OL_completeLookup:\n" 2605 << " Lookup kind: " << IPLS->K << "\n" 2606 << " Search order: " << IPLS->SearchOrder 2607 << ", Current index = " << IPLS->CurSearchOrderIndex 2608 << (IPLS->NewJITDylib ? " (entering new JITDylib)" : "") << "\n" 2609 << " Lookup set: " << IPLS->LookupSet << "\n" 2610 << " Definition generator candidates: " 2611 << IPLS->DefGeneratorCandidates << "\n" 2612 << " Definition generator non-candidates: " 2613 << IPLS->DefGeneratorNonCandidates << "\n"; 2614 }); 2615 2616 bool QueryComplete = false; 2617 DenseMap<JITDylib *, JITDylib::UnmaterializedInfosList> CollectedUMIs; 2618 2619 auto LodgingErr = runSessionLocked([&]() -> Error { 2620 for (auto &KV : IPLS->SearchOrder) { 2621 auto &JD = *KV.first; 2622 auto JDLookupFlags = KV.second; 2623 LLVM_DEBUG({ 2624 dbgs() << "Visiting \"" << JD.getName() << "\" (" << JDLookupFlags 2625 << ") with lookup set " << IPLS->LookupSet << ":\n"; 2626 }); 2627 2628 auto Err = IPLS->LookupSet.forEachWithRemoval( 2629 [&](const SymbolStringPtr &Name, 2630 SymbolLookupFlags SymLookupFlags) -> Expected<bool> { 2631 LLVM_DEBUG({ 2632 dbgs() << " Attempting to match \"" << Name << "\" (" 2633 << SymLookupFlags << ")... "; 2634 }); 2635 2636 /// Search for the symbol. If not found then continue without 2637 /// removal. 2638 auto SymI = JD.Symbols.find(Name); 2639 if (SymI == JD.Symbols.end()) { 2640 LLVM_DEBUG(dbgs() << "skipping: not present\n"); 2641 return false; 2642 } 2643 2644 // If this is a non-exported symbol and we're matching exported 2645 // symbols only then skip this symbol without removal. 2646 if (!SymI->second.getFlags().isExported() && 2647 JDLookupFlags == 2648 JITDylibLookupFlags::MatchExportedSymbolsOnly) { 2649 LLVM_DEBUG(dbgs() << "skipping: not exported\n"); 2650 return false; 2651 } 2652 2653 // If we match against a materialization-side-effects only symbol 2654 // then make sure it is weakly-referenced. Otherwise bail out with 2655 // an error. 2656 // FIXME: Use a "materialization-side-effects-only symbols must be 2657 // weakly referenced" specific error here to reduce confusion. 2658 if (SymI->second.getFlags().hasMaterializationSideEffectsOnly() && 2659 SymLookupFlags != SymbolLookupFlags::WeaklyReferencedSymbol) { 2660 LLVM_DEBUG({ 2661 dbgs() << "error: " 2662 "required, but symbol is has-side-effects-only\n"; 2663 }); 2664 return make_error<SymbolsNotFound>(getSymbolStringPool(), 2665 SymbolNameVector({Name})); 2666 } 2667 2668 // If we matched against this symbol but it is in the error state 2669 // then bail out and treat it as a failure to materialize. 2670 if (SymI->second.getFlags().hasError()) { 2671 LLVM_DEBUG(dbgs() << "error: symbol is in error state\n"); 2672 auto FailedSymbolsMap = std::make_shared<SymbolDependenceMap>(); 2673 (*FailedSymbolsMap)[&JD] = {Name}; 2674 return make_error<FailedToMaterialize>( 2675 getSymbolStringPool(), std::move(FailedSymbolsMap)); 2676 } 2677 2678 // Otherwise this is a match. 2679 2680 // If this symbol is already in the requried state then notify the 2681 // query, remove the symbol and continue. 2682 if (SymI->second.getState() >= Q->getRequiredState()) { 2683 LLVM_DEBUG(dbgs() 2684 << "matched, symbol already in required state\n"); 2685 Q->notifySymbolMetRequiredState(Name, SymI->second.getSymbol()); 2686 return true; 2687 } 2688 2689 // Otherwise this symbol does not yet meet the required state. Check 2690 // whether it has a materializer attached, and if so prepare to run 2691 // it. 2692 if (SymI->second.hasMaterializerAttached()) { 2693 assert(SymI->second.getAddress() == ExecutorAddr() && 2694 "Symbol not resolved but already has address?"); 2695 auto UMII = JD.UnmaterializedInfos.find(Name); 2696 assert(UMII != JD.UnmaterializedInfos.end() && 2697 "Lazy symbol should have UnmaterializedInfo"); 2698 2699 auto UMI = UMII->second; 2700 assert(UMI->MU && "Materializer should not be null"); 2701 assert(UMI->RT && "Tracker should not be null"); 2702 LLVM_DEBUG({ 2703 dbgs() << "matched, preparing to dispatch MU@" << UMI->MU.get() 2704 << " (" << UMI->MU->getName() << ")\n"; 2705 }); 2706 2707 // Move all symbols associated with this MaterializationUnit into 2708 // materializing state. 2709 for (auto &KV : UMI->MU->getSymbols()) { 2710 auto SymK = JD.Symbols.find(KV.first); 2711 assert(SymK != JD.Symbols.end() && 2712 "No entry for symbol covered by MaterializationUnit"); 2713 SymK->second.setMaterializerAttached(false); 2714 SymK->second.setState(SymbolState::Materializing); 2715 JD.UnmaterializedInfos.erase(KV.first); 2716 } 2717 2718 // Add MU to the list of MaterializationUnits to be materialized. 2719 CollectedUMIs[&JD].push_back(std::move(UMI)); 2720 } else 2721 LLVM_DEBUG(dbgs() << "matched, registering query"); 2722 2723 // Add the query to the PendingQueries list and continue, deleting 2724 // the element from the lookup set. 2725 assert(SymI->second.getState() != SymbolState::NeverSearched && 2726 SymI->second.getState() != SymbolState::Ready && 2727 "By this line the symbol should be materializing"); 2728 auto &MI = JD.MaterializingInfos[Name]; 2729 MI.addQuery(Q); 2730 Q->addQueryDependence(JD, Name); 2731 2732 return true; 2733 }); 2734 2735 // Handle failure. 2736 if (Err) { 2737 2738 LLVM_DEBUG({ 2739 dbgs() << "Lookup failed. Detaching query and replacing MUs.\n"; 2740 }); 2741 2742 // Detach the query. 2743 Q->detach(); 2744 2745 // Replace the MUs. 2746 for (auto &KV : CollectedUMIs) { 2747 auto &JD = *KV.first; 2748 for (auto &UMI : KV.second) 2749 for (auto &KV2 : UMI->MU->getSymbols()) { 2750 assert(!JD.UnmaterializedInfos.count(KV2.first) && 2751 "Unexpected materializer in map"); 2752 auto SymI = JD.Symbols.find(KV2.first); 2753 assert(SymI != JD.Symbols.end() && "Missing symbol entry"); 2754 assert(SymI->second.getState() == SymbolState::Materializing && 2755 "Can not replace symbol that is not materializing"); 2756 assert(!SymI->second.hasMaterializerAttached() && 2757 "MaterializerAttached flag should not be set"); 2758 SymI->second.setMaterializerAttached(true); 2759 JD.UnmaterializedInfos[KV2.first] = UMI; 2760 } 2761 } 2762 2763 return Err; 2764 } 2765 } 2766 2767 LLVM_DEBUG(dbgs() << "Stripping unmatched weakly-referenced symbols\n"); 2768 IPLS->LookupSet.forEachWithRemoval( 2769 [&](const SymbolStringPtr &Name, SymbolLookupFlags SymLookupFlags) { 2770 if (SymLookupFlags == SymbolLookupFlags::WeaklyReferencedSymbol) { 2771 Q->dropSymbol(Name); 2772 return true; 2773 } else 2774 return false; 2775 }); 2776 2777 if (!IPLS->LookupSet.empty()) { 2778 LLVM_DEBUG(dbgs() << "Failing due to unresolved symbols\n"); 2779 return make_error<SymbolsNotFound>(getSymbolStringPool(), 2780 IPLS->LookupSet.getSymbolNames()); 2781 } 2782 2783 // Record whether the query completed. 2784 QueryComplete = Q->isComplete(); 2785 2786 LLVM_DEBUG({ 2787 dbgs() << "Query successfully " 2788 << (QueryComplete ? "completed" : "lodged") << "\n"; 2789 }); 2790 2791 // Move the collected MUs to the OutstandingMUs list. 2792 if (!CollectedUMIs.empty()) { 2793 std::lock_guard<std::recursive_mutex> Lock(OutstandingMUsMutex); 2794 2795 LLVM_DEBUG(dbgs() << "Adding MUs to dispatch:\n"); 2796 for (auto &KV : CollectedUMIs) { 2797 LLVM_DEBUG({ 2798 auto &JD = *KV.first; 2799 dbgs() << " For " << JD.getName() << ": Adding " << KV.second.size() 2800 << " MUs.\n"; 2801 }); 2802 for (auto &UMI : KV.second) { 2803 auto MR = createMaterializationResponsibility( 2804 *UMI->RT, std::move(UMI->MU->SymbolFlags), 2805 std::move(UMI->MU->InitSymbol)); 2806 OutstandingMUs.push_back( 2807 std::make_pair(std::move(UMI->MU), std::move(MR))); 2808 } 2809 } 2810 } else 2811 LLVM_DEBUG(dbgs() << "No MUs to dispatch.\n"); 2812 2813 if (RegisterDependencies && !Q->QueryRegistrations.empty()) { 2814 LLVM_DEBUG(dbgs() << "Registering dependencies\n"); 2815 RegisterDependencies(Q->QueryRegistrations); 2816 } else 2817 LLVM_DEBUG(dbgs() << "No dependencies to register\n"); 2818 2819 return Error::success(); 2820 }); 2821 2822 if (LodgingErr) { 2823 LLVM_DEBUG(dbgs() << "Failing query\n"); 2824 Q->detach(); 2825 Q->handleFailed(std::move(LodgingErr)); 2826 return; 2827 } 2828 2829 if (QueryComplete) { 2830 LLVM_DEBUG(dbgs() << "Completing query\n"); 2831 Q->handleComplete(*this); 2832 } 2833 2834 dispatchOutstandingMUs(); 2835 } 2836 2837 void ExecutionSession::OL_completeLookupFlags( 2838 std::unique_ptr<InProgressLookupState> IPLS, 2839 unique_function<void(Expected<SymbolFlagsMap>)> OnComplete) { 2840 2841 auto Result = runSessionLocked([&]() -> Expected<SymbolFlagsMap> { 2842 LLVM_DEBUG({ 2843 dbgs() << "Entering OL_completeLookupFlags:\n" 2844 << " Lookup kind: " << IPLS->K << "\n" 2845 << " Search order: " << IPLS->SearchOrder 2846 << ", Current index = " << IPLS->CurSearchOrderIndex 2847 << (IPLS->NewJITDylib ? " (entering new JITDylib)" : "") << "\n" 2848 << " Lookup set: " << IPLS->LookupSet << "\n" 2849 << " Definition generator candidates: " 2850 << IPLS->DefGeneratorCandidates << "\n" 2851 << " Definition generator non-candidates: " 2852 << IPLS->DefGeneratorNonCandidates << "\n"; 2853 }); 2854 2855 SymbolFlagsMap Result; 2856 2857 // Attempt to find flags for each symbol. 2858 for (auto &KV : IPLS->SearchOrder) { 2859 auto &JD = *KV.first; 2860 auto JDLookupFlags = KV.second; 2861 LLVM_DEBUG({ 2862 dbgs() << "Visiting \"" << JD.getName() << "\" (" << JDLookupFlags 2863 << ") with lookup set " << IPLS->LookupSet << ":\n"; 2864 }); 2865 2866 IPLS->LookupSet.forEachWithRemoval([&](const SymbolStringPtr &Name, 2867 SymbolLookupFlags SymLookupFlags) { 2868 LLVM_DEBUG({ 2869 dbgs() << " Attempting to match \"" << Name << "\" (" 2870 << SymLookupFlags << ")... "; 2871 }); 2872 2873 // Search for the symbol. If not found then continue without removing 2874 // from the lookup set. 2875 auto SymI = JD.Symbols.find(Name); 2876 if (SymI == JD.Symbols.end()) { 2877 LLVM_DEBUG(dbgs() << "skipping: not present\n"); 2878 return false; 2879 } 2880 2881 // If this is a non-exported symbol then it doesn't match. Skip it. 2882 if (!SymI->second.getFlags().isExported() && 2883 JDLookupFlags == JITDylibLookupFlags::MatchExportedSymbolsOnly) { 2884 LLVM_DEBUG(dbgs() << "skipping: not exported\n"); 2885 return false; 2886 } 2887 2888 LLVM_DEBUG({ 2889 dbgs() << "matched, \"" << Name << "\" -> " << SymI->second.getFlags() 2890 << "\n"; 2891 }); 2892 Result[Name] = SymI->second.getFlags(); 2893 return true; 2894 }); 2895 } 2896 2897 // Remove any weakly referenced symbols that haven't been resolved. 2898 IPLS->LookupSet.remove_if( 2899 [](const SymbolStringPtr &Name, SymbolLookupFlags SymLookupFlags) { 2900 return SymLookupFlags == SymbolLookupFlags::WeaklyReferencedSymbol; 2901 }); 2902 2903 if (!IPLS->LookupSet.empty()) { 2904 LLVM_DEBUG(dbgs() << "Failing due to unresolved symbols\n"); 2905 return make_error<SymbolsNotFound>(getSymbolStringPool(), 2906 IPLS->LookupSet.getSymbolNames()); 2907 } 2908 2909 LLVM_DEBUG(dbgs() << "Succeded, result = " << Result << "\n"); 2910 return Result; 2911 }); 2912 2913 // Run the callback on the result. 2914 LLVM_DEBUG(dbgs() << "Sending result to handler.\n"); 2915 OnComplete(std::move(Result)); 2916 } 2917 2918 void ExecutionSession::OL_destroyMaterializationResponsibility( 2919 MaterializationResponsibility &MR) { 2920 2921 assert(MR.SymbolFlags.empty() && 2922 "All symbols should have been explicitly materialized or failed"); 2923 MR.JD.unlinkMaterializationResponsibility(MR); 2924 } 2925 2926 SymbolNameSet ExecutionSession::OL_getRequestedSymbols( 2927 const MaterializationResponsibility &MR) { 2928 return MR.JD.getRequestedSymbols(MR.SymbolFlags); 2929 } 2930 2931 Error ExecutionSession::OL_notifyResolved(MaterializationResponsibility &MR, 2932 const SymbolMap &Symbols) { 2933 LLVM_DEBUG({ 2934 dbgs() << "In " << MR.JD.getName() << " resolving " << Symbols << "\n"; 2935 }); 2936 #ifndef NDEBUG 2937 for (auto &KV : Symbols) { 2938 auto I = MR.SymbolFlags.find(KV.first); 2939 assert(I != MR.SymbolFlags.end() && 2940 "Resolving symbol outside this responsibility set"); 2941 assert(!I->second.hasMaterializationSideEffectsOnly() && 2942 "Can't resolve materialization-side-effects-only symbol"); 2943 assert((KV.second.getFlags() & ~JITSymbolFlags::Common) == 2944 (I->second & ~JITSymbolFlags::Common) && 2945 "Resolving symbol with incorrect flags"); 2946 } 2947 #endif 2948 2949 return MR.JD.resolve(MR, Symbols); 2950 } 2951 2952 Error ExecutionSession::OL_notifyEmitted(MaterializationResponsibility &MR) { 2953 LLVM_DEBUG({ 2954 dbgs() << "In " << MR.JD.getName() << " emitting " << MR.SymbolFlags 2955 << "\n"; 2956 }); 2957 2958 if (auto Err = MR.JD.emit(MR, MR.SymbolFlags)) 2959 return Err; 2960 2961 MR.SymbolFlags.clear(); 2962 return Error::success(); 2963 } 2964 2965 Error ExecutionSession::OL_defineMaterializing( 2966 MaterializationResponsibility &MR, SymbolFlagsMap NewSymbolFlags) { 2967 2968 LLVM_DEBUG({ 2969 dbgs() << "In " << MR.JD.getName() << " defining materializing symbols " 2970 << NewSymbolFlags << "\n"; 2971 }); 2972 if (auto AcceptedDefs = 2973 MR.JD.defineMaterializing(MR, std::move(NewSymbolFlags))) { 2974 // Add all newly accepted symbols to this responsibility object. 2975 for (auto &KV : *AcceptedDefs) 2976 MR.SymbolFlags.insert(KV); 2977 return Error::success(); 2978 } else 2979 return AcceptedDefs.takeError(); 2980 } 2981 2982 void ExecutionSession::OL_notifyFailed(MaterializationResponsibility &MR) { 2983 2984 LLVM_DEBUG({ 2985 dbgs() << "In " << MR.JD.getName() << " failing materialization for " 2986 << MR.SymbolFlags << "\n"; 2987 }); 2988 2989 JITDylib::FailedSymbolsWorklist Worklist; 2990 2991 for (auto &KV : MR.SymbolFlags) 2992 Worklist.push_back(std::make_pair(&MR.JD, KV.first)); 2993 MR.SymbolFlags.clear(); 2994 2995 if (Worklist.empty()) 2996 return; 2997 2998 JITDylib::AsynchronousSymbolQuerySet FailedQueries; 2999 std::shared_ptr<SymbolDependenceMap> FailedSymbols; 3000 3001 runSessionLocked([&]() { 3002 // If the tracker is defunct then there's nothing to do here. 3003 if (MR.RT->isDefunct()) 3004 return; 3005 3006 std::tie(FailedQueries, FailedSymbols) = 3007 JITDylib::failSymbols(std::move(Worklist)); 3008 }); 3009 3010 for (auto &Q : FailedQueries) 3011 Q->handleFailed( 3012 make_error<FailedToMaterialize>(getSymbolStringPool(), FailedSymbols)); 3013 } 3014 3015 Error ExecutionSession::OL_replace(MaterializationResponsibility &MR, 3016 std::unique_ptr<MaterializationUnit> MU) { 3017 for (auto &KV : MU->getSymbols()) { 3018 assert(MR.SymbolFlags.count(KV.first) && 3019 "Replacing definition outside this responsibility set"); 3020 MR.SymbolFlags.erase(KV.first); 3021 } 3022 3023 if (MU->getInitializerSymbol() == MR.InitSymbol) 3024 MR.InitSymbol = nullptr; 3025 3026 LLVM_DEBUG(MR.JD.getExecutionSession().runSessionLocked([&]() { 3027 dbgs() << "In " << MR.JD.getName() << " replacing symbols with " << *MU 3028 << "\n"; 3029 });); 3030 3031 return MR.JD.replace(MR, std::move(MU)); 3032 } 3033 3034 Expected<std::unique_ptr<MaterializationResponsibility>> 3035 ExecutionSession::OL_delegate(MaterializationResponsibility &MR, 3036 const SymbolNameSet &Symbols) { 3037 3038 SymbolStringPtr DelegatedInitSymbol; 3039 SymbolFlagsMap DelegatedFlags; 3040 3041 for (auto &Name : Symbols) { 3042 auto I = MR.SymbolFlags.find(Name); 3043 assert(I != MR.SymbolFlags.end() && 3044 "Symbol is not tracked by this MaterializationResponsibility " 3045 "instance"); 3046 3047 DelegatedFlags[Name] = std::move(I->second); 3048 if (Name == MR.InitSymbol) 3049 std::swap(MR.InitSymbol, DelegatedInitSymbol); 3050 3051 MR.SymbolFlags.erase(I); 3052 } 3053 3054 return MR.JD.delegate(MR, std::move(DelegatedFlags), 3055 std::move(DelegatedInitSymbol)); 3056 } 3057 3058 void ExecutionSession::OL_addDependencies( 3059 MaterializationResponsibility &MR, const SymbolStringPtr &Name, 3060 const SymbolDependenceMap &Dependencies) { 3061 LLVM_DEBUG({ 3062 dbgs() << "Adding dependencies for " << Name << ": " << Dependencies 3063 << "\n"; 3064 }); 3065 assert(MR.SymbolFlags.count(Name) && 3066 "Symbol not covered by this MaterializationResponsibility instance"); 3067 MR.JD.addDependencies(Name, Dependencies); 3068 } 3069 3070 void ExecutionSession::OL_addDependenciesForAll( 3071 MaterializationResponsibility &MR, 3072 const SymbolDependenceMap &Dependencies) { 3073 LLVM_DEBUG({ 3074 dbgs() << "Adding dependencies for all symbols in " << MR.SymbolFlags << ": " 3075 << Dependencies << "\n"; 3076 }); 3077 for (auto &KV : MR.SymbolFlags) 3078 MR.JD.addDependencies(KV.first, Dependencies); 3079 } 3080 3081 #ifndef NDEBUG 3082 void ExecutionSession::dumpDispatchInfo(Task &T) { 3083 runSessionLocked([&]() { 3084 dbgs() << "Dispatching: "; 3085 T.printDescription(dbgs()); 3086 dbgs() << "\n"; 3087 }); 3088 } 3089 #endif // NDEBUG 3090 3091 } // End namespace orc. 3092 } // End namespace llvm. 3093