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/OrcError.h" 14 #include "llvm/IR/Mangler.h" 15 #include "llvm/Support/CommandLine.h" 16 #include "llvm/Support/Debug.h" 17 #include "llvm/Support/Format.h" 18 19 #if LLVM_ENABLE_THREADS 20 #include <future> 21 #endif 22 23 #define DEBUG_TYPE "orc" 24 25 using namespace llvm; 26 27 namespace { 28 29 #ifndef NDEBUG 30 31 cl::opt<bool> PrintHidden("debug-orc-print-hidden", cl::init(true), 32 cl::desc("debug print hidden symbols defined by " 33 "materialization units"), 34 cl::Hidden); 35 36 cl::opt<bool> PrintCallable("debug-orc-print-callable", cl::init(true), 37 cl::desc("debug print callable symbols defined by " 38 "materialization units"), 39 cl::Hidden); 40 41 cl::opt<bool> PrintData("debug-orc-print-data", cl::init(true), 42 cl::desc("debug print data symbols defined by " 43 "materialization units"), 44 cl::Hidden); 45 46 #endif // NDEBUG 47 48 // SetPrinter predicate that prints every element. 49 template <typename T> struct PrintAll { 50 bool operator()(const T &E) { return true; } 51 }; 52 53 bool anyPrintSymbolOptionSet() { 54 #ifndef NDEBUG 55 return PrintHidden || PrintCallable || PrintData; 56 #else 57 return false; 58 #endif // NDEBUG 59 } 60 61 bool flagsMatchCLOpts(const JITSymbolFlags &Flags) { 62 #ifndef NDEBUG 63 // Bail out early if this is a hidden symbol and we're not printing hiddens. 64 if (!PrintHidden && !Flags.isExported()) 65 return false; 66 67 // Return true if this is callable and we're printing callables. 68 if (PrintCallable && Flags.isCallable()) 69 return true; 70 71 // Return true if this is data and we're printing data. 72 if (PrintData && !Flags.isCallable()) 73 return true; 74 75 // otherwise return false. 76 return false; 77 #else 78 return false; 79 #endif // NDEBUG 80 } 81 82 // Prints a sequence of items, filtered by an user-supplied predicate. 83 template <typename Sequence, 84 typename Pred = PrintAll<typename Sequence::value_type>> 85 class SequencePrinter { 86 public: 87 SequencePrinter(const Sequence &S, char OpenSeq, char CloseSeq, 88 Pred ShouldPrint = Pred()) 89 : S(S), OpenSeq(OpenSeq), CloseSeq(CloseSeq), 90 ShouldPrint(std::move(ShouldPrint)) {} 91 92 void printTo(llvm::raw_ostream &OS) const { 93 bool PrintComma = false; 94 OS << OpenSeq; 95 for (auto &E : S) { 96 if (ShouldPrint(E)) { 97 if (PrintComma) 98 OS << ','; 99 OS << ' ' << E; 100 PrintComma = true; 101 } 102 } 103 OS << ' ' << CloseSeq; 104 } 105 106 private: 107 const Sequence &S; 108 char OpenSeq; 109 char CloseSeq; 110 mutable Pred ShouldPrint; 111 }; 112 113 template <typename Sequence, typename Pred> 114 SequencePrinter<Sequence, Pred> printSequence(const Sequence &S, char OpenSeq, 115 char CloseSeq, Pred P = Pred()) { 116 return SequencePrinter<Sequence, Pred>(S, OpenSeq, CloseSeq, std::move(P)); 117 } 118 119 // Render a SequencePrinter by delegating to its printTo method. 120 template <typename Sequence, typename Pred> 121 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, 122 const SequencePrinter<Sequence, Pred> &Printer) { 123 Printer.printTo(OS); 124 return OS; 125 } 126 127 struct PrintSymbolFlagsMapElemsMatchingCLOpts { 128 bool operator()(const orc::SymbolFlagsMap::value_type &KV) { 129 return flagsMatchCLOpts(KV.second); 130 } 131 }; 132 133 struct PrintSymbolMapElemsMatchingCLOpts { 134 bool operator()(const orc::SymbolMap::value_type &KV) { 135 return flagsMatchCLOpts(KV.second.getFlags()); 136 } 137 }; 138 139 } // end anonymous namespace 140 141 namespace llvm { 142 namespace orc { 143 144 char FailedToMaterialize::ID = 0; 145 char SymbolsNotFound::ID = 0; 146 char SymbolsCouldNotBeRemoved::ID = 0; 147 148 RegisterDependenciesFunction NoDependenciesToRegister = 149 RegisterDependenciesFunction(); 150 151 void MaterializationUnit::anchor() {} 152 153 raw_ostream &operator<<(raw_ostream &OS, const SymbolStringPtr &Sym) { 154 return OS << *Sym; 155 } 156 157 raw_ostream &operator<<(raw_ostream &OS, const SymbolNameSet &Symbols) { 158 return OS << printSequence(Symbols, '{', '}', PrintAll<SymbolStringPtr>()); 159 } 160 161 raw_ostream &operator<<(raw_ostream &OS, const SymbolNameVector &Symbols) { 162 return OS << printSequence(Symbols, '[', ']', PrintAll<SymbolStringPtr>()); 163 } 164 165 raw_ostream &operator<<(raw_ostream &OS, const JITSymbolFlags &Flags) { 166 if (Flags.hasError()) 167 OS << "[*ERROR*]"; 168 if (Flags.isCallable()) 169 OS << "[Callable]"; 170 else 171 OS << "[Data]"; 172 if (Flags.isWeak()) 173 OS << "[Weak]"; 174 else if (Flags.isCommon()) 175 OS << "[Common]"; 176 177 if (!Flags.isExported()) 178 OS << "[Hidden]"; 179 180 return OS; 181 } 182 183 raw_ostream &operator<<(raw_ostream &OS, const JITEvaluatedSymbol &Sym) { 184 return OS << format("0x%016" PRIx64, Sym.getAddress()) << " " 185 << Sym.getFlags(); 186 } 187 188 raw_ostream &operator<<(raw_ostream &OS, const SymbolFlagsMap::value_type &KV) { 189 return OS << "(\"" << KV.first << "\", " << KV.second << ")"; 190 } 191 192 raw_ostream &operator<<(raw_ostream &OS, const SymbolMap::value_type &KV) { 193 return OS << "(\"" << KV.first << "\": " << KV.second << ")"; 194 } 195 196 raw_ostream &operator<<(raw_ostream &OS, const SymbolFlagsMap &SymbolFlags) { 197 return OS << printSequence(SymbolFlags, '{', '}', 198 PrintSymbolFlagsMapElemsMatchingCLOpts()); 199 } 200 201 raw_ostream &operator<<(raw_ostream &OS, const SymbolMap &Symbols) { 202 return OS << printSequence(Symbols, '{', '}', 203 PrintSymbolMapElemsMatchingCLOpts()); 204 } 205 206 raw_ostream &operator<<(raw_ostream &OS, 207 const SymbolDependenceMap::value_type &KV) { 208 return OS << "(" << KV.first->getName() << ", " << KV.second << ")"; 209 } 210 211 raw_ostream &operator<<(raw_ostream &OS, const SymbolDependenceMap &Deps) { 212 return OS << printSequence(Deps, '{', '}', 213 PrintAll<SymbolDependenceMap::value_type>()); 214 } 215 216 raw_ostream &operator<<(raw_ostream &OS, const MaterializationUnit &MU) { 217 OS << "MU@" << &MU << " (\"" << MU.getName() << "\""; 218 if (anyPrintSymbolOptionSet()) 219 OS << ", " << MU.getSymbols(); 220 return OS << ")"; 221 } 222 223 raw_ostream &operator<<(raw_ostream &OS, const LookupKind &K) { 224 switch (K) { 225 case LookupKind::Static: 226 return OS << "Static"; 227 case LookupKind::DLSym: 228 return OS << "DLSym"; 229 } 230 llvm_unreachable("Invalid lookup kind"); 231 } 232 233 raw_ostream &operator<<(raw_ostream &OS, 234 const JITDylibLookupFlags &JDLookupFlags) { 235 switch (JDLookupFlags) { 236 case JITDylibLookupFlags::MatchExportedSymbolsOnly: 237 return OS << "MatchExportedSymbolsOnly"; 238 case JITDylibLookupFlags::MatchAllSymbols: 239 return OS << "MatchAllSymbols"; 240 } 241 llvm_unreachable("Invalid JITDylib lookup flags"); 242 } 243 244 raw_ostream &operator<<(raw_ostream &OS, const SymbolLookupFlags &LookupFlags) { 245 switch (LookupFlags) { 246 case SymbolLookupFlags::RequiredSymbol: 247 return OS << "RequiredSymbol"; 248 case SymbolLookupFlags::WeaklyReferencedSymbol: 249 return OS << "WeaklyReferencedSymbol"; 250 } 251 llvm_unreachable("Invalid symbol lookup flags"); 252 } 253 254 raw_ostream &operator<<(raw_ostream &OS, 255 const SymbolLookupSet::value_type &KV) { 256 return OS << "(" << KV.first << ", " << KV.second << ")"; 257 } 258 259 raw_ostream &operator<<(raw_ostream &OS, const SymbolLookupSet &LookupSet) { 260 return OS << printSequence(LookupSet, '{', '}', 261 PrintAll<SymbolLookupSet::value_type>()); 262 } 263 264 raw_ostream &operator<<(raw_ostream &OS, 265 const JITDylibSearchOrder &SearchOrder) { 266 OS << "["; 267 if (!SearchOrder.empty()) { 268 assert(SearchOrder.front().first && 269 "JITDylibList entries must not be null"); 270 OS << " (\"" << SearchOrder.front().first->getName() << "\", " 271 << SearchOrder.begin()->second << ")"; 272 for (auto &KV : 273 make_range(std::next(SearchOrder.begin(), 1), SearchOrder.end())) { 274 assert(KV.first && "JITDylibList entries must not be null"); 275 OS << ", (\"" << KV.first->getName() << "\", " << KV.second << ")"; 276 } 277 } 278 OS << " ]"; 279 return OS; 280 } 281 282 raw_ostream &operator<<(raw_ostream &OS, const SymbolAliasMap &Aliases) { 283 OS << "{"; 284 for (auto &KV : Aliases) 285 OS << " " << *KV.first << ": " << KV.second.Aliasee << " " 286 << KV.second.AliasFlags; 287 OS << " }"; 288 return OS; 289 } 290 291 raw_ostream &operator<<(raw_ostream &OS, const SymbolState &S) { 292 switch (S) { 293 case SymbolState::Invalid: 294 return OS << "Invalid"; 295 case SymbolState::NeverSearched: 296 return OS << "Never-Searched"; 297 case SymbolState::Materializing: 298 return OS << "Materializing"; 299 case SymbolState::Resolved: 300 return OS << "Resolved"; 301 case SymbolState::Emitted: 302 return OS << "Emitted"; 303 case SymbolState::Ready: 304 return OS << "Ready"; 305 } 306 llvm_unreachable("Invalid state"); 307 } 308 309 FailedToMaterialize::FailedToMaterialize( 310 std::shared_ptr<SymbolDependenceMap> Symbols) 311 : Symbols(std::move(Symbols)) { 312 assert(!this->Symbols->empty() && "Can not fail to resolve an empty set"); 313 } 314 315 std::error_code FailedToMaterialize::convertToErrorCode() const { 316 return orcError(OrcErrorCode::UnknownORCError); 317 } 318 319 void FailedToMaterialize::log(raw_ostream &OS) const { 320 OS << "Failed to materialize symbols: " << *Symbols; 321 } 322 323 SymbolsNotFound::SymbolsNotFound(SymbolNameSet Symbols) { 324 for (auto &Sym : Symbols) 325 this->Symbols.push_back(Sym); 326 assert(!this->Symbols.empty() && "Can not fail to resolve an empty set"); 327 } 328 329 SymbolsNotFound::SymbolsNotFound(SymbolNameVector Symbols) 330 : Symbols(std::move(Symbols)) { 331 assert(!this->Symbols.empty() && "Can not fail to resolve an empty set"); 332 } 333 334 std::error_code SymbolsNotFound::convertToErrorCode() const { 335 return orcError(OrcErrorCode::UnknownORCError); 336 } 337 338 void SymbolsNotFound::log(raw_ostream &OS) const { 339 OS << "Symbols not found: " << Symbols; 340 } 341 342 SymbolsCouldNotBeRemoved::SymbolsCouldNotBeRemoved(SymbolNameSet Symbols) 343 : Symbols(std::move(Symbols)) { 344 assert(!this->Symbols.empty() && "Can not fail to resolve an empty set"); 345 } 346 347 std::error_code SymbolsCouldNotBeRemoved::convertToErrorCode() const { 348 return orcError(OrcErrorCode::UnknownORCError); 349 } 350 351 void SymbolsCouldNotBeRemoved::log(raw_ostream &OS) const { 352 OS << "Symbols could not be removed: " << Symbols; 353 } 354 355 AsynchronousSymbolQuery::AsynchronousSymbolQuery( 356 const SymbolLookupSet &Symbols, SymbolState RequiredState, 357 SymbolsResolvedCallback NotifyComplete) 358 : NotifyComplete(std::move(NotifyComplete)), RequiredState(RequiredState) { 359 assert(RequiredState >= SymbolState::Resolved && 360 "Cannot query for a symbols that have not reached the resolve state " 361 "yet"); 362 363 OutstandingSymbolsCount = Symbols.size(); 364 365 for (auto &KV : Symbols) 366 ResolvedSymbols[KV.first] = nullptr; 367 } 368 369 void AsynchronousSymbolQuery::notifySymbolMetRequiredState( 370 const SymbolStringPtr &Name, JITEvaluatedSymbol Sym) { 371 auto I = ResolvedSymbols.find(Name); 372 assert(I != ResolvedSymbols.end() && 373 "Resolving symbol outside the requested set"); 374 assert(I->second.getAddress() == 0 && "Redundantly resolving symbol Name"); 375 I->second = std::move(Sym); 376 --OutstandingSymbolsCount; 377 } 378 379 void AsynchronousSymbolQuery::handleComplete() { 380 assert(OutstandingSymbolsCount == 0 && 381 "Symbols remain, handleComplete called prematurely"); 382 383 auto TmpNotifyComplete = std::move(NotifyComplete); 384 NotifyComplete = SymbolsResolvedCallback(); 385 TmpNotifyComplete(std::move(ResolvedSymbols)); 386 } 387 388 bool AsynchronousSymbolQuery::canStillFail() { return !!NotifyComplete; } 389 390 void AsynchronousSymbolQuery::handleFailed(Error Err) { 391 assert(QueryRegistrations.empty() && ResolvedSymbols.empty() && 392 OutstandingSymbolsCount == 0 && 393 "Query should already have been abandoned"); 394 NotifyComplete(std::move(Err)); 395 NotifyComplete = SymbolsResolvedCallback(); 396 } 397 398 void AsynchronousSymbolQuery::addQueryDependence(JITDylib &JD, 399 SymbolStringPtr Name) { 400 bool Added = QueryRegistrations[&JD].insert(std::move(Name)).second; 401 (void)Added; 402 assert(Added && "Duplicate dependence notification?"); 403 } 404 405 void AsynchronousSymbolQuery::removeQueryDependence( 406 JITDylib &JD, const SymbolStringPtr &Name) { 407 auto QRI = QueryRegistrations.find(&JD); 408 assert(QRI != QueryRegistrations.end() && 409 "No dependencies registered for JD"); 410 assert(QRI->second.count(Name) && "No dependency on Name in JD"); 411 QRI->second.erase(Name); 412 if (QRI->second.empty()) 413 QueryRegistrations.erase(QRI); 414 } 415 416 void AsynchronousSymbolQuery::detach() { 417 ResolvedSymbols.clear(); 418 OutstandingSymbolsCount = 0; 419 for (auto &KV : QueryRegistrations) 420 KV.first->detachQueryHelper(*this, KV.second); 421 QueryRegistrations.clear(); 422 } 423 424 MaterializationResponsibility::MaterializationResponsibility( 425 JITDylib &JD, SymbolFlagsMap SymbolFlags, VModuleKey K) 426 : JD(JD), SymbolFlags(std::move(SymbolFlags)), K(std::move(K)) { 427 assert(!this->SymbolFlags.empty() && "Materializing nothing?"); 428 } 429 430 MaterializationResponsibility::~MaterializationResponsibility() { 431 assert(SymbolFlags.empty() && 432 "All symbols should have been explicitly materialized or failed"); 433 } 434 435 SymbolNameSet MaterializationResponsibility::getRequestedSymbols() const { 436 return JD.getRequestedSymbols(SymbolFlags); 437 } 438 439 Error MaterializationResponsibility::notifyResolved(const SymbolMap &Symbols) { 440 LLVM_DEBUG({ 441 dbgs() << "In " << JD.getName() << " resolving " << Symbols << "\n"; 442 }); 443 #ifndef NDEBUG 444 for (auto &KV : Symbols) { 445 auto WeakFlags = JITSymbolFlags::Weak | JITSymbolFlags::Common; 446 auto I = SymbolFlags.find(KV.first); 447 assert(I != SymbolFlags.end() && 448 "Resolving symbol outside this responsibility set"); 449 assert((KV.second.getFlags() & ~WeakFlags) == (I->second & ~WeakFlags) && 450 "Resolving symbol with incorrect flags"); 451 } 452 #endif 453 454 return JD.resolve(Symbols); 455 } 456 457 Error MaterializationResponsibility::notifyEmitted() { 458 459 LLVM_DEBUG({ 460 dbgs() << "In " << JD.getName() << " emitting " << SymbolFlags << "\n"; 461 }); 462 463 if (auto Err = JD.emit(SymbolFlags)) 464 return Err; 465 466 SymbolFlags.clear(); 467 return Error::success(); 468 } 469 470 Error MaterializationResponsibility::defineMaterializing( 471 SymbolFlagsMap NewSymbolFlags) { 472 473 LLVM_DEBUG({ 474 dbgs() << "In " << JD.getName() << " defining materializing symbols " 475 << NewSymbolFlags << "\n"; 476 }); 477 if (auto AcceptedDefs = JD.defineMaterializing(std::move(NewSymbolFlags))) { 478 // Add all newly accepted symbols to this responsibility object. 479 for (auto &KV : *AcceptedDefs) 480 SymbolFlags.insert(KV); 481 return Error::success(); 482 } else 483 return AcceptedDefs.takeError(); 484 } 485 486 void MaterializationResponsibility::failMaterialization() { 487 488 LLVM_DEBUG({ 489 dbgs() << "In " << JD.getName() << " failing materialization for " 490 << SymbolFlags << "\n"; 491 }); 492 493 JITDylib::FailedSymbolsWorklist Worklist; 494 495 for (auto &KV : SymbolFlags) 496 Worklist.push_back(std::make_pair(&JD, KV.first)); 497 SymbolFlags.clear(); 498 499 JD.notifyFailed(std::move(Worklist)); 500 } 501 502 void MaterializationResponsibility::replace( 503 std::unique_ptr<MaterializationUnit> MU) { 504 for (auto &KV : MU->getSymbols()) 505 SymbolFlags.erase(KV.first); 506 507 LLVM_DEBUG(JD.getExecutionSession().runSessionLocked([&]() { 508 dbgs() << "In " << JD.getName() << " replacing symbols with " << *MU 509 << "\n"; 510 });); 511 512 JD.replace(std::move(MU)); 513 } 514 515 MaterializationResponsibility 516 MaterializationResponsibility::delegate(const SymbolNameSet &Symbols, 517 VModuleKey NewKey) { 518 519 if (NewKey == VModuleKey()) 520 NewKey = K; 521 522 SymbolFlagsMap DelegatedFlags; 523 524 for (auto &Name : Symbols) { 525 auto I = SymbolFlags.find(Name); 526 assert(I != SymbolFlags.end() && 527 "Symbol is not tracked by this MaterializationResponsibility " 528 "instance"); 529 530 DelegatedFlags[Name] = std::move(I->second); 531 SymbolFlags.erase(I); 532 } 533 534 return MaterializationResponsibility(JD, std::move(DelegatedFlags), 535 std::move(NewKey)); 536 } 537 538 void MaterializationResponsibility::addDependencies( 539 const SymbolStringPtr &Name, const SymbolDependenceMap &Dependencies) { 540 assert(SymbolFlags.count(Name) && 541 "Symbol not covered by this MaterializationResponsibility instance"); 542 JD.addDependencies(Name, Dependencies); 543 } 544 545 void MaterializationResponsibility::addDependenciesForAll( 546 const SymbolDependenceMap &Dependencies) { 547 for (auto &KV : SymbolFlags) 548 JD.addDependencies(KV.first, Dependencies); 549 } 550 551 AbsoluteSymbolsMaterializationUnit::AbsoluteSymbolsMaterializationUnit( 552 SymbolMap Symbols, VModuleKey K) 553 : MaterializationUnit(extractFlags(Symbols), std::move(K)), 554 Symbols(std::move(Symbols)) {} 555 556 StringRef AbsoluteSymbolsMaterializationUnit::getName() const { 557 return "<Absolute Symbols>"; 558 } 559 560 void AbsoluteSymbolsMaterializationUnit::materialize( 561 MaterializationResponsibility R) { 562 // No dependencies, so these calls can't fail. 563 cantFail(R.notifyResolved(Symbols)); 564 cantFail(R.notifyEmitted()); 565 } 566 567 void AbsoluteSymbolsMaterializationUnit::discard(const JITDylib &JD, 568 const SymbolStringPtr &Name) { 569 assert(Symbols.count(Name) && "Symbol is not part of this MU"); 570 Symbols.erase(Name); 571 } 572 573 SymbolFlagsMap 574 AbsoluteSymbolsMaterializationUnit::extractFlags(const SymbolMap &Symbols) { 575 SymbolFlagsMap Flags; 576 for (const auto &KV : Symbols) 577 Flags[KV.first] = KV.second.getFlags(); 578 return Flags; 579 } 580 581 ReExportsMaterializationUnit::ReExportsMaterializationUnit( 582 JITDylib *SourceJD, JITDylibLookupFlags SourceJDLookupFlags, 583 SymbolAliasMap Aliases, VModuleKey K) 584 : MaterializationUnit(extractFlags(Aliases), std::move(K)), 585 SourceJD(SourceJD), SourceJDLookupFlags(SourceJDLookupFlags), 586 Aliases(std::move(Aliases)) {} 587 588 StringRef ReExportsMaterializationUnit::getName() const { 589 return "<Reexports>"; 590 } 591 592 void ReExportsMaterializationUnit::materialize( 593 MaterializationResponsibility R) { 594 595 auto &ES = R.getTargetJITDylib().getExecutionSession(); 596 JITDylib &TgtJD = R.getTargetJITDylib(); 597 JITDylib &SrcJD = SourceJD ? *SourceJD : TgtJD; 598 599 // Find the set of requested aliases and aliasees. Return any unrequested 600 // aliases back to the JITDylib so as to not prematurely materialize any 601 // aliasees. 602 auto RequestedSymbols = R.getRequestedSymbols(); 603 SymbolAliasMap RequestedAliases; 604 605 for (auto &Name : RequestedSymbols) { 606 auto I = Aliases.find(Name); 607 assert(I != Aliases.end() && "Symbol not found in aliases map?"); 608 RequestedAliases[Name] = std::move(I->second); 609 Aliases.erase(I); 610 } 611 612 LLVM_DEBUG({ 613 ES.runSessionLocked([&]() { 614 dbgs() << "materializing reexports: target = " << TgtJD.getName() 615 << ", source = " << SrcJD.getName() << " " << RequestedAliases 616 << "\n"; 617 }); 618 }); 619 620 if (!Aliases.empty()) { 621 if (SourceJD) 622 R.replace(reexports(*SourceJD, std::move(Aliases), SourceJDLookupFlags)); 623 else 624 R.replace(symbolAliases(std::move(Aliases))); 625 } 626 627 // The OnResolveInfo struct will hold the aliases and responsibilty for each 628 // query in the list. 629 struct OnResolveInfo { 630 OnResolveInfo(MaterializationResponsibility R, SymbolAliasMap Aliases) 631 : R(std::move(R)), Aliases(std::move(Aliases)) {} 632 633 MaterializationResponsibility R; 634 SymbolAliasMap Aliases; 635 }; 636 637 // Build a list of queries to issue. In each round we build the largest set of 638 // aliases that we can resolve without encountering a chain definition of the 639 // form Foo -> Bar, Bar -> Baz. Such a form would deadlock as the query would 640 // be waitin on a symbol that it itself had to resolve. Usually this will just 641 // involve one round and a single query. 642 643 std::vector<std::pair<SymbolLookupSet, std::shared_ptr<OnResolveInfo>>> 644 QueryInfos; 645 while (!RequestedAliases.empty()) { 646 SymbolNameSet ResponsibilitySymbols; 647 SymbolLookupSet QuerySymbols; 648 SymbolAliasMap QueryAliases; 649 650 // Collect as many aliases as we can without including a chain. 651 for (auto &KV : RequestedAliases) { 652 // Chain detected. Skip this symbol for this round. 653 if (&SrcJD == &TgtJD && (QueryAliases.count(KV.second.Aliasee) || 654 RequestedAliases.count(KV.second.Aliasee))) 655 continue; 656 657 ResponsibilitySymbols.insert(KV.first); 658 QuerySymbols.add(KV.second.Aliasee); 659 QueryAliases[KV.first] = std::move(KV.second); 660 } 661 662 // Remove the aliases collected this round from the RequestedAliases map. 663 for (auto &KV : QueryAliases) 664 RequestedAliases.erase(KV.first); 665 666 assert(!QuerySymbols.empty() && "Alias cycle detected!"); 667 668 auto QueryInfo = std::make_shared<OnResolveInfo>( 669 R.delegate(ResponsibilitySymbols), std::move(QueryAliases)); 670 QueryInfos.push_back( 671 make_pair(std::move(QuerySymbols), std::move(QueryInfo))); 672 } 673 674 // Issue the queries. 675 while (!QueryInfos.empty()) { 676 auto QuerySymbols = std::move(QueryInfos.back().first); 677 auto QueryInfo = std::move(QueryInfos.back().second); 678 679 QueryInfos.pop_back(); 680 681 auto RegisterDependencies = [QueryInfo, 682 &SrcJD](const SymbolDependenceMap &Deps) { 683 // If there were no materializing symbols, just bail out. 684 if (Deps.empty()) 685 return; 686 687 // Otherwise the only deps should be on SrcJD. 688 assert(Deps.size() == 1 && Deps.count(&SrcJD) && 689 "Unexpected dependencies for reexports"); 690 691 auto &SrcJDDeps = Deps.find(&SrcJD)->second; 692 SymbolDependenceMap PerAliasDepsMap; 693 auto &PerAliasDeps = PerAliasDepsMap[&SrcJD]; 694 695 for (auto &KV : QueryInfo->Aliases) 696 if (SrcJDDeps.count(KV.second.Aliasee)) { 697 PerAliasDeps = {KV.second.Aliasee}; 698 QueryInfo->R.addDependencies(KV.first, PerAliasDepsMap); 699 } 700 }; 701 702 auto OnComplete = [QueryInfo](Expected<SymbolMap> Result) { 703 auto &ES = QueryInfo->R.getTargetJITDylib().getExecutionSession(); 704 if (Result) { 705 SymbolMap ResolutionMap; 706 for (auto &KV : QueryInfo->Aliases) { 707 assert(Result->count(KV.second.Aliasee) && 708 "Result map missing entry?"); 709 ResolutionMap[KV.first] = JITEvaluatedSymbol( 710 (*Result)[KV.second.Aliasee].getAddress(), KV.second.AliasFlags); 711 } 712 if (auto Err = QueryInfo->R.notifyResolved(ResolutionMap)) { 713 ES.reportError(std::move(Err)); 714 QueryInfo->R.failMaterialization(); 715 return; 716 } 717 if (auto Err = QueryInfo->R.notifyEmitted()) { 718 ES.reportError(std::move(Err)); 719 QueryInfo->R.failMaterialization(); 720 return; 721 } 722 } else { 723 ES.reportError(Result.takeError()); 724 QueryInfo->R.failMaterialization(); 725 } 726 }; 727 728 ES.lookup(LookupKind::Static, 729 JITDylibSearchOrder({{&SrcJD, SourceJDLookupFlags}}), 730 QuerySymbols, SymbolState::Resolved, std::move(OnComplete), 731 std::move(RegisterDependencies)); 732 } 733 } 734 735 void ReExportsMaterializationUnit::discard(const JITDylib &JD, 736 const SymbolStringPtr &Name) { 737 assert(Aliases.count(Name) && 738 "Symbol not covered by this MaterializationUnit"); 739 Aliases.erase(Name); 740 } 741 742 SymbolFlagsMap 743 ReExportsMaterializationUnit::extractFlags(const SymbolAliasMap &Aliases) { 744 SymbolFlagsMap SymbolFlags; 745 for (auto &KV : Aliases) 746 SymbolFlags[KV.first] = KV.second.AliasFlags; 747 748 return SymbolFlags; 749 } 750 751 Expected<SymbolAliasMap> 752 buildSimpleReexportsAliasMap(JITDylib &SourceJD, const SymbolNameSet &Symbols) { 753 SymbolLookupSet LookupSet(Symbols); 754 auto Flags = SourceJD.lookupFlags( 755 LookupKind::Static, JITDylibLookupFlags::MatchAllSymbols, LookupSet); 756 757 if (!Flags) 758 return Flags.takeError(); 759 760 if (!LookupSet.empty()) { 761 LookupSet.sortByName(); 762 return make_error<SymbolsNotFound>(LookupSet.getSymbolNames()); 763 } 764 765 SymbolAliasMap Result; 766 for (auto &Name : Symbols) { 767 assert(Flags->count(Name) && "Missing entry in flags map"); 768 Result[Name] = SymbolAliasMapEntry(Name, (*Flags)[Name]); 769 } 770 771 return Result; 772 } 773 774 ReexportsGenerator::ReexportsGenerator(JITDylib &SourceJD, 775 JITDylibLookupFlags SourceJDLookupFlags, 776 SymbolPredicate Allow) 777 : SourceJD(SourceJD), SourceJDLookupFlags(SourceJDLookupFlags), 778 Allow(std::move(Allow)) {} 779 780 Error ReexportsGenerator::tryToGenerate(LookupKind K, JITDylib &JD, 781 JITDylibLookupFlags JDLookupFlags, 782 const SymbolLookupSet &LookupSet) { 783 assert(&JD != &SourceJD && "Cannot re-export from the same dylib"); 784 785 // Use lookupFlags to find the subset of symbols that match our lookup. 786 auto Flags = SourceJD.lookupFlags(K, JDLookupFlags, LookupSet); 787 if (!Flags) 788 return Flags.takeError(); 789 790 // Create an alias map. 791 orc::SymbolAliasMap AliasMap; 792 for (auto &KV : *Flags) 793 if (!Allow || Allow(KV.first)) 794 AliasMap[KV.first] = SymbolAliasMapEntry(KV.first, KV.second); 795 796 if (AliasMap.empty()) 797 return Error::success(); 798 799 // Define the re-exports. 800 return JD.define(reexports(SourceJD, AliasMap, SourceJDLookupFlags)); 801 } 802 803 JITDylib::DefinitionGenerator::~DefinitionGenerator() {} 804 805 void JITDylib::removeGenerator(DefinitionGenerator &G) { 806 ES.runSessionLocked([&]() { 807 auto I = std::find_if(DefGenerators.begin(), DefGenerators.end(), 808 [&](const std::unique_ptr<DefinitionGenerator> &H) { 809 return H.get() == &G; 810 }); 811 assert(I != DefGenerators.end() && "Generator not found"); 812 DefGenerators.erase(I); 813 }); 814 } 815 816 Expected<SymbolFlagsMap> 817 JITDylib::defineMaterializing(SymbolFlagsMap SymbolFlags) { 818 819 return ES.runSessionLocked([&]() -> Expected<SymbolFlagsMap> { 820 std::vector<SymbolTable::iterator> AddedSyms; 821 std::vector<SymbolFlagsMap::iterator> RejectedWeakDefs; 822 823 for (auto SFItr = SymbolFlags.begin(), SFEnd = SymbolFlags.end(); 824 SFItr != SFEnd; ++SFItr) { 825 826 auto &Name = SFItr->first; 827 auto &Flags = SFItr->second; 828 829 auto EntryItr = Symbols.find(Name); 830 831 // If the entry already exists... 832 if (EntryItr != Symbols.end()) { 833 834 // If this is a strong definition then error out. 835 if (!Flags.isWeak()) { 836 // Remove any symbols already added. 837 for (auto &SI : AddedSyms) 838 Symbols.erase(SI); 839 840 // FIXME: Return all duplicates. 841 return make_error<DuplicateDefinition>(std::string(*Name)); 842 } 843 844 // Otherwise just make a note to discard this symbol after the loop. 845 RejectedWeakDefs.push_back(SFItr); 846 continue; 847 } else 848 EntryItr = 849 Symbols.insert(std::make_pair(Name, SymbolTableEntry(Flags))).first; 850 851 AddedSyms.push_back(EntryItr); 852 EntryItr->second.setState(SymbolState::Materializing); 853 } 854 855 // Remove any rejected weak definitions from the SymbolFlags map. 856 while (!RejectedWeakDefs.empty()) { 857 SymbolFlags.erase(RejectedWeakDefs.back()); 858 RejectedWeakDefs.pop_back(); 859 } 860 861 return SymbolFlags; 862 }); 863 } 864 865 void JITDylib::replace(std::unique_ptr<MaterializationUnit> MU) { 866 assert(MU != nullptr && "Can not replace with a null MaterializationUnit"); 867 868 auto MustRunMU = 869 ES.runSessionLocked([&, this]() -> std::unique_ptr<MaterializationUnit> { 870 871 #ifndef NDEBUG 872 for (auto &KV : MU->getSymbols()) { 873 auto SymI = Symbols.find(KV.first); 874 assert(SymI != Symbols.end() && "Replacing unknown symbol"); 875 assert(SymI->second.isInMaterializationPhase() && 876 "Can not call replace on a symbol that is not materializing"); 877 assert(!SymI->second.hasMaterializerAttached() && 878 "Symbol should not have materializer attached already"); 879 assert(UnmaterializedInfos.count(KV.first) == 0 && 880 "Symbol being replaced should have no UnmaterializedInfo"); 881 } 882 #endif // NDEBUG 883 884 // If any symbol has pending queries against it then we need to 885 // materialize MU immediately. 886 for (auto &KV : MU->getSymbols()) { 887 auto MII = MaterializingInfos.find(KV.first); 888 if (MII != MaterializingInfos.end()) { 889 if (MII->second.hasQueriesPending()) 890 return std::move(MU); 891 } 892 } 893 894 // Otherwise, make MU responsible for all the symbols. 895 auto UMI = std::make_shared<UnmaterializedInfo>(std::move(MU)); 896 for (auto &KV : UMI->MU->getSymbols()) { 897 auto SymI = Symbols.find(KV.first); 898 assert(SymI->second.getState() == SymbolState::Materializing && 899 "Can not replace a symbol that is not materializing"); 900 assert(!SymI->second.hasMaterializerAttached() && 901 "Can not replace a symbol that has a materializer attached"); 902 assert(UnmaterializedInfos.count(KV.first) == 0 && 903 "Unexpected materializer entry in map"); 904 SymI->second.setAddress(SymI->second.getAddress()); 905 SymI->second.setMaterializerAttached(true); 906 UnmaterializedInfos[KV.first] = UMI; 907 } 908 909 return nullptr; 910 }); 911 912 if (MustRunMU) 913 ES.dispatchMaterialization(*this, std::move(MustRunMU)); 914 } 915 916 SymbolNameSet 917 JITDylib::getRequestedSymbols(const SymbolFlagsMap &SymbolFlags) const { 918 return ES.runSessionLocked([&]() { 919 SymbolNameSet RequestedSymbols; 920 921 for (auto &KV : SymbolFlags) { 922 assert(Symbols.count(KV.first) && "JITDylib does not cover this symbol?"); 923 assert(Symbols.find(KV.first)->second.isInMaterializationPhase() && 924 "getRequestedSymbols can only be called for symbols that have " 925 "started materializing"); 926 auto I = MaterializingInfos.find(KV.first); 927 if (I == MaterializingInfos.end()) 928 continue; 929 930 if (I->second.hasQueriesPending()) 931 RequestedSymbols.insert(KV.first); 932 } 933 934 return RequestedSymbols; 935 }); 936 } 937 938 void JITDylib::addDependencies(const SymbolStringPtr &Name, 939 const SymbolDependenceMap &Dependencies) { 940 assert(Symbols.count(Name) && "Name not in symbol table"); 941 assert(Symbols[Name].isInMaterializationPhase() && 942 "Can not add dependencies for a symbol that is not materializing"); 943 944 LLVM_DEBUG({ 945 dbgs() << "In " << getName() << " adding dependencies for " 946 << *Name << ": " << Dependencies << "\n"; 947 }); 948 949 // If Name is already in an error state then just bail out. 950 if (Symbols[Name].getFlags().hasError()) 951 return; 952 953 auto &MI = MaterializingInfos[Name]; 954 assert(Symbols[Name].getState() != SymbolState::Emitted && 955 "Can not add dependencies to an emitted symbol"); 956 957 bool DependsOnSymbolInErrorState = false; 958 959 // Register dependencies, record whether any depenendency is in the error 960 // state. 961 for (auto &KV : Dependencies) { 962 assert(KV.first && "Null JITDylib in dependency?"); 963 auto &OtherJITDylib = *KV.first; 964 auto &DepsOnOtherJITDylib = MI.UnemittedDependencies[&OtherJITDylib]; 965 966 for (auto &OtherSymbol : KV.second) { 967 968 // Check the sym entry for the dependency. 969 auto OtherSymI = OtherJITDylib.Symbols.find(OtherSymbol); 970 971 #ifndef NDEBUG 972 // Assert that this symbol exists and has not reached the ready state 973 // already. 974 assert(OtherSymI != OtherJITDylib.Symbols.end() && 975 (OtherSymI->second.getState() != SymbolState::Ready && 976 "Dependency on emitted/ready symbol")); 977 #endif 978 979 auto &OtherSymEntry = OtherSymI->second; 980 981 // If the dependency is in an error state then note this and continue, 982 // we will move this symbol to the error state below. 983 if (OtherSymEntry.getFlags().hasError()) { 984 DependsOnSymbolInErrorState = true; 985 continue; 986 } 987 988 // If the dependency was not in the error state then add it to 989 // our list of dependencies. 990 assert(OtherJITDylib.MaterializingInfos.count(OtherSymbol) && 991 "No MaterializingInfo for dependency"); 992 auto &OtherMI = OtherJITDylib.MaterializingInfos[OtherSymbol]; 993 994 if (OtherSymEntry.getState() == SymbolState::Emitted) 995 transferEmittedNodeDependencies(MI, Name, OtherMI); 996 else if (&OtherJITDylib != this || OtherSymbol != Name) { 997 OtherMI.Dependants[this].insert(Name); 998 DepsOnOtherJITDylib.insert(OtherSymbol); 999 } 1000 } 1001 1002 if (DepsOnOtherJITDylib.empty()) 1003 MI.UnemittedDependencies.erase(&OtherJITDylib); 1004 } 1005 1006 // If this symbol dependended on any symbols in the error state then move 1007 // this symbol to the error state too. 1008 if (DependsOnSymbolInErrorState) 1009 Symbols[Name].setFlags(Symbols[Name].getFlags() | JITSymbolFlags::HasError); 1010 } 1011 1012 Error JITDylib::resolve(const SymbolMap &Resolved) { 1013 SymbolNameSet SymbolsInErrorState; 1014 AsynchronousSymbolQuerySet CompletedQueries; 1015 1016 ES.runSessionLocked([&, this]() { 1017 struct WorklistEntry { 1018 SymbolTable::iterator SymI; 1019 JITEvaluatedSymbol ResolvedSym; 1020 }; 1021 1022 std::vector<WorklistEntry> Worklist; 1023 Worklist.reserve(Resolved.size()); 1024 1025 // Build worklist and check for any symbols in the error state. 1026 for (const auto &KV : Resolved) { 1027 1028 assert(!KV.second.getFlags().hasError() && 1029 "Resolution result can not have error flag set"); 1030 1031 auto SymI = Symbols.find(KV.first); 1032 1033 assert(SymI != Symbols.end() && "Symbol not found"); 1034 assert(!SymI->second.hasMaterializerAttached() && 1035 "Resolving symbol with materializer attached?"); 1036 assert(SymI->second.getState() == SymbolState::Materializing && 1037 "Symbol should be materializing"); 1038 assert(SymI->second.getAddress() == 0 && 1039 "Symbol has already been resolved"); 1040 1041 if (SymI->second.getFlags().hasError()) 1042 SymbolsInErrorState.insert(KV.first); 1043 else { 1044 auto Flags = KV.second.getFlags(); 1045 Flags &= ~(JITSymbolFlags::Weak | JITSymbolFlags::Common); 1046 assert(Flags == (SymI->second.getFlags() & 1047 ~(JITSymbolFlags::Weak | JITSymbolFlags::Common)) && 1048 "Resolved flags should match the declared flags"); 1049 1050 Worklist.push_back( 1051 {SymI, JITEvaluatedSymbol(KV.second.getAddress(), Flags)}); 1052 } 1053 } 1054 1055 // If any symbols were in the error state then bail out. 1056 if (!SymbolsInErrorState.empty()) 1057 return; 1058 1059 while (!Worklist.empty()) { 1060 auto SymI = Worklist.back().SymI; 1061 auto ResolvedSym = Worklist.back().ResolvedSym; 1062 Worklist.pop_back(); 1063 1064 auto &Name = SymI->first; 1065 1066 // Resolved symbols can not be weak: discard the weak flag. 1067 JITSymbolFlags ResolvedFlags = ResolvedSym.getFlags(); 1068 SymI->second.setAddress(ResolvedSym.getAddress()); 1069 SymI->second.setFlags(ResolvedFlags); 1070 SymI->second.setState(SymbolState::Resolved); 1071 1072 auto &MI = MaterializingInfos[Name]; 1073 for (auto &Q : MI.takeQueriesMeeting(SymbolState::Resolved)) { 1074 Q->notifySymbolMetRequiredState(Name, ResolvedSym); 1075 Q->removeQueryDependence(*this, Name); 1076 if (Q->isComplete()) 1077 CompletedQueries.insert(std::move(Q)); 1078 } 1079 } 1080 }); 1081 1082 assert((SymbolsInErrorState.empty() || CompletedQueries.empty()) && 1083 "Can't fail symbols and completed queries at the same time"); 1084 1085 // If we failed any symbols then return an error. 1086 if (!SymbolsInErrorState.empty()) { 1087 auto FailedSymbolsDepMap = std::make_shared<SymbolDependenceMap>(); 1088 (*FailedSymbolsDepMap)[this] = std::move(SymbolsInErrorState); 1089 return make_error<FailedToMaterialize>(std::move(FailedSymbolsDepMap)); 1090 } 1091 1092 // Otherwise notify all the completed queries. 1093 for (auto &Q : CompletedQueries) { 1094 assert(Q->isComplete() && "Q not completed"); 1095 Q->handleComplete(); 1096 } 1097 1098 return Error::success(); 1099 } 1100 1101 Error JITDylib::emit(const SymbolFlagsMap &Emitted) { 1102 AsynchronousSymbolQuerySet CompletedQueries; 1103 SymbolNameSet SymbolsInErrorState; 1104 1105 ES.runSessionLocked([&, this]() { 1106 std::vector<SymbolTable::iterator> Worklist; 1107 1108 // Scan to build worklist, record any symbols in the erorr state. 1109 for (const auto &KV : Emitted) { 1110 auto &Name = KV.first; 1111 1112 auto SymI = Symbols.find(Name); 1113 assert(SymI != Symbols.end() && "No symbol table entry for Name"); 1114 1115 if (SymI->second.getFlags().hasError()) 1116 SymbolsInErrorState.insert(Name); 1117 else 1118 Worklist.push_back(SymI); 1119 } 1120 1121 // If any symbols were in the error state then bail out. 1122 if (!SymbolsInErrorState.empty()) 1123 return; 1124 1125 // Otherwise update dependencies and move to the emitted state. 1126 while (!Worklist.empty()) { 1127 auto SymI = Worklist.back(); 1128 Worklist.pop_back(); 1129 1130 auto &Name = SymI->first; 1131 auto &SymEntry = SymI->second; 1132 1133 // Move symbol to the emitted state. 1134 assert(SymEntry.getState() == SymbolState::Resolved && 1135 "Emitting from state other than Resolved"); 1136 SymEntry.setState(SymbolState::Emitted); 1137 1138 auto MII = MaterializingInfos.find(Name); 1139 assert(MII != MaterializingInfos.end() && 1140 "Missing MaterializingInfo entry"); 1141 auto &MI = MII->second; 1142 1143 // For each dependant, transfer this node's emitted dependencies to 1144 // it. If the dependant node is ready (i.e. has no unemitted 1145 // dependencies) then notify any pending queries. 1146 for (auto &KV : MI.Dependants) { 1147 auto &DependantJD = *KV.first; 1148 for (auto &DependantName : KV.second) { 1149 auto DependantMII = 1150 DependantJD.MaterializingInfos.find(DependantName); 1151 assert(DependantMII != DependantJD.MaterializingInfos.end() && 1152 "Dependant should have MaterializingInfo"); 1153 1154 auto &DependantMI = DependantMII->second; 1155 1156 // Remove the dependant's dependency on this node. 1157 assert(DependantMI.UnemittedDependencies.count(this) && 1158 "Dependant does not have an unemitted dependencies record for " 1159 "this JITDylib"); 1160 assert(DependantMI.UnemittedDependencies[this].count(Name) && 1161 "Dependant does not count this symbol as a dependency?"); 1162 1163 DependantMI.UnemittedDependencies[this].erase(Name); 1164 if (DependantMI.UnemittedDependencies[this].empty()) 1165 DependantMI.UnemittedDependencies.erase(this); 1166 1167 // Transfer unemitted dependencies from this node to the dependant. 1168 DependantJD.transferEmittedNodeDependencies(DependantMI, 1169 DependantName, MI); 1170 1171 auto DependantSymI = DependantJD.Symbols.find(DependantName); 1172 assert(DependantSymI != DependantJD.Symbols.end() && 1173 "Dependant has no entry in the Symbols table"); 1174 auto &DependantSymEntry = DependantSymI->second; 1175 1176 // If the dependant is emitted and this node was the last of its 1177 // unemitted dependencies then the dependant node is now ready, so 1178 // notify any pending queries on the dependant node. 1179 if (DependantSymEntry.getState() == SymbolState::Emitted && 1180 DependantMI.UnemittedDependencies.empty()) { 1181 assert(DependantMI.Dependants.empty() && 1182 "Dependants should be empty by now"); 1183 1184 // Since this dependant is now ready, we erase its MaterializingInfo 1185 // and update its materializing state. 1186 DependantSymEntry.setState(SymbolState::Ready); 1187 1188 for (auto &Q : DependantMI.takeQueriesMeeting(SymbolState::Ready)) { 1189 Q->notifySymbolMetRequiredState( 1190 DependantName, DependantSymI->second.getSymbol()); 1191 if (Q->isComplete()) 1192 CompletedQueries.insert(Q); 1193 Q->removeQueryDependence(DependantJD, DependantName); 1194 } 1195 1196 DependantJD.MaterializingInfos.erase(DependantMII); 1197 } 1198 } 1199 } 1200 1201 MI.Dependants.clear(); 1202 if (MI.UnemittedDependencies.empty()) { 1203 SymI->second.setState(SymbolState::Ready); 1204 for (auto &Q : MI.takeQueriesMeeting(SymbolState::Ready)) { 1205 Q->notifySymbolMetRequiredState(Name, SymI->second.getSymbol()); 1206 if (Q->isComplete()) 1207 CompletedQueries.insert(Q); 1208 Q->removeQueryDependence(*this, Name); 1209 } 1210 MaterializingInfos.erase(MII); 1211 } 1212 } 1213 }); 1214 1215 assert((SymbolsInErrorState.empty() || CompletedQueries.empty()) && 1216 "Can't fail symbols and completed queries at the same time"); 1217 1218 // If we failed any symbols then return an error. 1219 if (!SymbolsInErrorState.empty()) { 1220 auto FailedSymbolsDepMap = std::make_shared<SymbolDependenceMap>(); 1221 (*FailedSymbolsDepMap)[this] = std::move(SymbolsInErrorState); 1222 return make_error<FailedToMaterialize>(std::move(FailedSymbolsDepMap)); 1223 } 1224 1225 // Otherwise notify all the completed queries. 1226 for (auto &Q : CompletedQueries) { 1227 assert(Q->isComplete() && "Q is not complete"); 1228 Q->handleComplete(); 1229 } 1230 1231 return Error::success(); 1232 } 1233 1234 void JITDylib::notifyFailed(FailedSymbolsWorklist Worklist) { 1235 AsynchronousSymbolQuerySet FailedQueries; 1236 auto FailedSymbolsMap = std::make_shared<SymbolDependenceMap>(); 1237 1238 // Failing no symbols is a no-op. 1239 if (Worklist.empty()) 1240 return; 1241 1242 auto &ES = Worklist.front().first->getExecutionSession(); 1243 1244 ES.runSessionLocked([&]() { 1245 while (!Worklist.empty()) { 1246 assert(Worklist.back().first && "Failed JITDylib can not be null"); 1247 auto &JD = *Worklist.back().first; 1248 auto Name = std::move(Worklist.back().second); 1249 Worklist.pop_back(); 1250 1251 (*FailedSymbolsMap)[&JD].insert(Name); 1252 1253 assert(JD.Symbols.count(Name) && "No symbol table entry for Name"); 1254 auto &Sym = JD.Symbols[Name]; 1255 1256 // Move the symbol into the error state. 1257 // Note that this may be redundant: The symbol might already have been 1258 // moved to this state in response to the failure of a dependence. 1259 Sym.setFlags(Sym.getFlags() | JITSymbolFlags::HasError); 1260 1261 // FIXME: Come up with a sane mapping of state to 1262 // presence-of-MaterializingInfo so that we can assert presence / absence 1263 // here, rather than testing it. 1264 auto MII = JD.MaterializingInfos.find(Name); 1265 1266 if (MII == JD.MaterializingInfos.end()) 1267 continue; 1268 1269 auto &MI = MII->second; 1270 1271 // Move all dependants to the error state and disconnect from them. 1272 for (auto &KV : MI.Dependants) { 1273 auto &DependantJD = *KV.first; 1274 for (auto &DependantName : KV.second) { 1275 assert(DependantJD.Symbols.count(DependantName) && 1276 "No symbol table entry for DependantName"); 1277 auto &DependantSym = DependantJD.Symbols[DependantName]; 1278 DependantSym.setFlags(DependantSym.getFlags() | 1279 JITSymbolFlags::HasError); 1280 1281 assert(DependantJD.MaterializingInfos.count(DependantName) && 1282 "No MaterializingInfo for dependant"); 1283 auto &DependantMI = DependantJD.MaterializingInfos[DependantName]; 1284 1285 auto UnemittedDepI = DependantMI.UnemittedDependencies.find(&JD); 1286 assert(UnemittedDepI != DependantMI.UnemittedDependencies.end() && 1287 "No UnemittedDependencies entry for this JITDylib"); 1288 assert(UnemittedDepI->second.count(Name) && 1289 "No UnemittedDependencies entry for this symbol"); 1290 UnemittedDepI->second.erase(Name); 1291 if (UnemittedDepI->second.empty()) 1292 DependantMI.UnemittedDependencies.erase(UnemittedDepI); 1293 1294 // If this symbol is already in the emitted state then we need to 1295 // take responsibility for failing its queries, so add it to the 1296 // worklist. 1297 if (DependantSym.getState() == SymbolState::Emitted) { 1298 assert(DependantMI.Dependants.empty() && 1299 "Emitted symbol should not have dependants"); 1300 Worklist.push_back(std::make_pair(&DependantJD, DependantName)); 1301 } 1302 } 1303 } 1304 MI.Dependants.clear(); 1305 1306 // Disconnect from all unemitted depenencies. 1307 for (auto &KV : MI.UnemittedDependencies) { 1308 auto &UnemittedDepJD = *KV.first; 1309 for (auto &UnemittedDepName : KV.second) { 1310 auto UnemittedDepMII = 1311 UnemittedDepJD.MaterializingInfos.find(UnemittedDepName); 1312 assert(UnemittedDepMII != UnemittedDepJD.MaterializingInfos.end() && 1313 "Missing MII for unemitted dependency"); 1314 assert(UnemittedDepMII->second.Dependants.count(&JD) && 1315 "JD not listed as a dependant of unemitted dependency"); 1316 assert(UnemittedDepMII->second.Dependants[&JD].count(Name) && 1317 "Name is not listed as a dependant of unemitted dependency"); 1318 UnemittedDepMII->second.Dependants[&JD].erase(Name); 1319 if (UnemittedDepMII->second.Dependants[&JD].empty()) 1320 UnemittedDepMII->second.Dependants.erase(&JD); 1321 } 1322 } 1323 MI.UnemittedDependencies.clear(); 1324 1325 // Collect queries to be failed for this MII. 1326 AsynchronousSymbolQueryList ToDetach; 1327 for (auto &Q : MII->second.pendingQueries()) { 1328 // Add the query to the list to be failed and detach it. 1329 FailedQueries.insert(Q); 1330 ToDetach.push_back(Q); 1331 } 1332 for (auto &Q : ToDetach) 1333 Q->detach(); 1334 1335 assert(MI.Dependants.empty() && 1336 "Can not delete MaterializingInfo with dependants still attached"); 1337 assert(MI.UnemittedDependencies.empty() && 1338 "Can not delete MaterializingInfo with unemitted dependencies " 1339 "still attached"); 1340 assert(!MI.hasQueriesPending() && 1341 "Can not delete MaterializingInfo with queries pending"); 1342 JD.MaterializingInfos.erase(MII); 1343 } 1344 }); 1345 1346 for (auto &Q : FailedQueries) 1347 Q->handleFailed(make_error<FailedToMaterialize>(FailedSymbolsMap)); 1348 } 1349 1350 void JITDylib::setSearchOrder(JITDylibSearchOrder NewSearchOrder, 1351 bool SearchThisJITDylibFirst) { 1352 ES.runSessionLocked([&]() { 1353 if (SearchThisJITDylibFirst) { 1354 SearchOrder.clear(); 1355 if (NewSearchOrder.empty() || NewSearchOrder.front().first != this) 1356 SearchOrder.push_back( 1357 std::make_pair(this, JITDylibLookupFlags::MatchAllSymbols)); 1358 SearchOrder.insert(SearchOrder.end(), NewSearchOrder.begin(), 1359 NewSearchOrder.end()); 1360 } else 1361 SearchOrder = std::move(NewSearchOrder); 1362 }); 1363 } 1364 1365 void JITDylib::addToSearchOrder(JITDylib &JD, 1366 JITDylibLookupFlags JDLookupFlags) { 1367 ES.runSessionLocked([&]() { SearchOrder.push_back({&JD, JDLookupFlags}); }); 1368 } 1369 1370 void JITDylib::replaceInSearchOrder(JITDylib &OldJD, JITDylib &NewJD, 1371 JITDylibLookupFlags JDLookupFlags) { 1372 ES.runSessionLocked([&]() { 1373 for (auto &KV : SearchOrder) 1374 if (KV.first == &OldJD) { 1375 KV = {&NewJD, JDLookupFlags}; 1376 break; 1377 } 1378 }); 1379 } 1380 1381 void JITDylib::removeFromSearchOrder(JITDylib &JD) { 1382 ES.runSessionLocked([&]() { 1383 auto I = std::find_if(SearchOrder.begin(), SearchOrder.end(), 1384 [&](const JITDylibSearchOrder::value_type &KV) { 1385 return KV.first == &JD; 1386 }); 1387 if (I != SearchOrder.end()) 1388 SearchOrder.erase(I); 1389 }); 1390 } 1391 1392 Error JITDylib::remove(const SymbolNameSet &Names) { 1393 return ES.runSessionLocked([&]() -> Error { 1394 using SymbolMaterializerItrPair = 1395 std::pair<SymbolTable::iterator, UnmaterializedInfosMap::iterator>; 1396 std::vector<SymbolMaterializerItrPair> SymbolsToRemove; 1397 SymbolNameSet Missing; 1398 SymbolNameSet Materializing; 1399 1400 for (auto &Name : Names) { 1401 auto I = Symbols.find(Name); 1402 1403 // Note symbol missing. 1404 if (I == Symbols.end()) { 1405 Missing.insert(Name); 1406 continue; 1407 } 1408 1409 // Note symbol materializing. 1410 if (I->second.isInMaterializationPhase()) { 1411 Materializing.insert(Name); 1412 continue; 1413 } 1414 1415 auto UMII = I->second.hasMaterializerAttached() 1416 ? UnmaterializedInfos.find(Name) 1417 : UnmaterializedInfos.end(); 1418 SymbolsToRemove.push_back(std::make_pair(I, UMII)); 1419 } 1420 1421 // If any of the symbols are not defined, return an error. 1422 if (!Missing.empty()) 1423 return make_error<SymbolsNotFound>(std::move(Missing)); 1424 1425 // If any of the symbols are currently materializing, return an error. 1426 if (!Materializing.empty()) 1427 return make_error<SymbolsCouldNotBeRemoved>(std::move(Materializing)); 1428 1429 // Remove the symbols. 1430 for (auto &SymbolMaterializerItrPair : SymbolsToRemove) { 1431 auto UMII = SymbolMaterializerItrPair.second; 1432 1433 // If there is a materializer attached, call discard. 1434 if (UMII != UnmaterializedInfos.end()) { 1435 UMII->second->MU->doDiscard(*this, UMII->first); 1436 UnmaterializedInfos.erase(UMII); 1437 } 1438 1439 auto SymI = SymbolMaterializerItrPair.first; 1440 Symbols.erase(SymI); 1441 } 1442 1443 return Error::success(); 1444 }); 1445 } 1446 1447 Expected<SymbolFlagsMap> 1448 JITDylib::lookupFlags(LookupKind K, JITDylibLookupFlags JDLookupFlags, 1449 SymbolLookupSet LookupSet) { 1450 return ES.runSessionLocked([&, this]() -> Expected<SymbolFlagsMap> { 1451 SymbolFlagsMap Result; 1452 lookupFlagsImpl(Result, K, JDLookupFlags, LookupSet); 1453 1454 // Run any definition generators. 1455 for (auto &DG : DefGenerators) { 1456 1457 // Bail out early if we found everything. 1458 if (LookupSet.empty()) 1459 break; 1460 1461 // Run this generator. 1462 if (auto Err = DG->tryToGenerate(K, *this, JDLookupFlags, LookupSet)) 1463 return std::move(Err); 1464 1465 // Re-try the search. 1466 lookupFlagsImpl(Result, K, JDLookupFlags, LookupSet); 1467 } 1468 1469 return Result; 1470 }); 1471 } 1472 1473 void JITDylib::lookupFlagsImpl(SymbolFlagsMap &Result, LookupKind K, 1474 JITDylibLookupFlags JDLookupFlags, 1475 SymbolLookupSet &LookupSet) { 1476 1477 LookupSet.forEachWithRemoval( 1478 [&](const SymbolStringPtr &Name, SymbolLookupFlags Flags) -> bool { 1479 auto I = Symbols.find(Name); 1480 if (I == Symbols.end()) 1481 return false; 1482 assert(!Result.count(Name) && "Symbol already present in Flags map"); 1483 Result[Name] = I->second.getFlags(); 1484 return true; 1485 }); 1486 } 1487 1488 Error JITDylib::lodgeQuery(MaterializationUnitList &MUs, 1489 std::shared_ptr<AsynchronousSymbolQuery> &Q, 1490 LookupKind K, JITDylibLookupFlags JDLookupFlags, 1491 SymbolLookupSet &Unresolved) { 1492 assert(Q && "Query can not be null"); 1493 1494 if (auto Err = lodgeQueryImpl(MUs, Q, K, JDLookupFlags, Unresolved)) 1495 return Err; 1496 1497 // Run any definition generators. 1498 for (auto &DG : DefGenerators) { 1499 1500 // Bail out early if we have resolved everything. 1501 if (Unresolved.empty()) 1502 break; 1503 1504 // Run the generator. 1505 if (auto Err = DG->tryToGenerate(K, *this, JDLookupFlags, Unresolved)) 1506 return Err; 1507 1508 // Lodge query. This can not fail as any new definitions were added 1509 // by the generator under the session locked. Since they can't have 1510 // started materializing yet they can not have failed. 1511 cantFail(lodgeQueryImpl(MUs, Q, K, JDLookupFlags, Unresolved)); 1512 } 1513 1514 return Error::success(); 1515 } 1516 1517 Error JITDylib::lodgeQueryImpl(MaterializationUnitList &MUs, 1518 std::shared_ptr<AsynchronousSymbolQuery> &Q, 1519 LookupKind K, JITDylibLookupFlags JDLookupFlags, 1520 SymbolLookupSet &Unresolved) { 1521 1522 return Unresolved.forEachWithRemoval( 1523 [&](const SymbolStringPtr &Name, 1524 SymbolLookupFlags SymLookupFlags) -> Expected<bool> { 1525 // Search for name in symbols. If not found then continue without 1526 // removal. 1527 auto SymI = Symbols.find(Name); 1528 if (SymI == Symbols.end()) 1529 return false; 1530 1531 // If this is a non exported symbol and we're matching exported symbols 1532 // only then skip this symbol without removal. 1533 if (!SymI->second.getFlags().isExported() && 1534 JDLookupFlags == JITDylibLookupFlags::MatchExportedSymbolsOnly) 1535 return false; 1536 1537 // If we matched against this symbol but it is in the error state then 1538 // bail out and treat it as a failure to materialize. 1539 if (SymI->second.getFlags().hasError()) { 1540 auto FailedSymbolsMap = std::make_shared<SymbolDependenceMap>(); 1541 (*FailedSymbolsMap)[this] = {Name}; 1542 return make_error<FailedToMaterialize>(std::move(FailedSymbolsMap)); 1543 } 1544 1545 // If this symbol already meets the required state for then notify the 1546 // query, then remove the symbol and continue. 1547 if (SymI->second.getState() >= Q->getRequiredState()) { 1548 Q->notifySymbolMetRequiredState(Name, SymI->second.getSymbol()); 1549 return true; 1550 } 1551 1552 // Otherwise this symbol does not yet meet the required state. Check 1553 // whether it has a materializer attached, and if so prepare to run it. 1554 if (SymI->second.hasMaterializerAttached()) { 1555 assert(SymI->second.getAddress() == 0 && 1556 "Symbol not resolved but already has address?"); 1557 auto UMII = UnmaterializedInfos.find(Name); 1558 assert(UMII != UnmaterializedInfos.end() && 1559 "Lazy symbol should have UnmaterializedInfo"); 1560 auto MU = std::move(UMII->second->MU); 1561 assert(MU != nullptr && "Materializer should not be null"); 1562 1563 // Move all symbols associated with this MaterializationUnit into 1564 // materializing state. 1565 for (auto &KV : MU->getSymbols()) { 1566 auto SymK = Symbols.find(KV.first); 1567 SymK->second.setMaterializerAttached(false); 1568 SymK->second.setState(SymbolState::Materializing); 1569 UnmaterializedInfos.erase(KV.first); 1570 } 1571 1572 // Add MU to the list of MaterializationUnits to be materialized. 1573 MUs.push_back(std::move(MU)); 1574 } 1575 1576 // Add the query to the PendingQueries list and continue, deleting the 1577 // element. 1578 assert(SymI->second.isInMaterializationPhase() && 1579 "By this line the symbol should be materializing"); 1580 auto &MI = MaterializingInfos[Name]; 1581 MI.addQuery(Q); 1582 Q->addQueryDependence(*this, Name); 1583 return true; 1584 }); 1585 } 1586 1587 Expected<SymbolNameSet> 1588 JITDylib::legacyLookup(std::shared_ptr<AsynchronousSymbolQuery> Q, 1589 SymbolNameSet Names) { 1590 assert(Q && "Query can not be null"); 1591 1592 ES.runOutstandingMUs(); 1593 1594 bool QueryComplete = false; 1595 std::vector<std::unique_ptr<MaterializationUnit>> MUs; 1596 1597 SymbolLookupSet Unresolved(Names); 1598 auto Err = ES.runSessionLocked([&, this]() -> Error { 1599 QueryComplete = lookupImpl(Q, MUs, Unresolved); 1600 1601 // Run any definition generators. 1602 for (auto &DG : DefGenerators) { 1603 1604 // Bail out early if we have resolved everything. 1605 if (Unresolved.empty()) 1606 break; 1607 1608 assert(!QueryComplete && "query complete but unresolved symbols remain?"); 1609 if (auto Err = DG->tryToGenerate(LookupKind::Static, *this, 1610 JITDylibLookupFlags::MatchAllSymbols, 1611 Unresolved)) 1612 return Err; 1613 1614 if (!Unresolved.empty()) 1615 QueryComplete = lookupImpl(Q, MUs, Unresolved); 1616 } 1617 return Error::success(); 1618 }); 1619 1620 if (Err) 1621 return std::move(Err); 1622 1623 assert((MUs.empty() || !QueryComplete) && 1624 "If action flags are set, there should be no work to do (so no MUs)"); 1625 1626 if (QueryComplete) 1627 Q->handleComplete(); 1628 1629 // FIXME: Swap back to the old code below once RuntimeDyld works with 1630 // callbacks from asynchronous queries. 1631 // Add MUs to the OutstandingMUs list. 1632 { 1633 std::lock_guard<std::recursive_mutex> Lock(ES.OutstandingMUsMutex); 1634 for (auto &MU : MUs) 1635 ES.OutstandingMUs.push_back(make_pair(this, std::move(MU))); 1636 } 1637 ES.runOutstandingMUs(); 1638 1639 // Dispatch any required MaterializationUnits for materialization. 1640 // for (auto &MU : MUs) 1641 // ES.dispatchMaterialization(*this, std::move(MU)); 1642 1643 SymbolNameSet RemainingSymbols; 1644 for (auto &KV : Unresolved) 1645 RemainingSymbols.insert(KV.first); 1646 1647 return RemainingSymbols; 1648 } 1649 1650 bool JITDylib::lookupImpl( 1651 std::shared_ptr<AsynchronousSymbolQuery> &Q, 1652 std::vector<std::unique_ptr<MaterializationUnit>> &MUs, 1653 SymbolLookupSet &Unresolved) { 1654 bool QueryComplete = false; 1655 1656 std::vector<SymbolStringPtr> ToRemove; 1657 Unresolved.forEachWithRemoval( 1658 [&](const SymbolStringPtr &Name, SymbolLookupFlags Flags) -> bool { 1659 // Search for the name in Symbols. Skip without removing if not found. 1660 auto SymI = Symbols.find(Name); 1661 if (SymI == Symbols.end()) 1662 return false; 1663 1664 // If the symbol is already in the required state then notify the query 1665 // and remove. 1666 if (SymI->second.getState() >= Q->getRequiredState()) { 1667 Q->notifySymbolMetRequiredState(Name, SymI->second.getSymbol()); 1668 if (Q->isComplete()) 1669 QueryComplete = true; 1670 return true; 1671 } 1672 1673 // If the symbol is lazy, get the MaterialiaztionUnit for it. 1674 if (SymI->second.hasMaterializerAttached()) { 1675 assert(SymI->second.getAddress() == 0 && 1676 "Lazy symbol should not have a resolved address"); 1677 auto UMII = UnmaterializedInfos.find(Name); 1678 assert(UMII != UnmaterializedInfos.end() && 1679 "Lazy symbol should have UnmaterializedInfo"); 1680 auto MU = std::move(UMII->second->MU); 1681 assert(MU != nullptr && "Materializer should not be null"); 1682 1683 // Kick all symbols associated with this MaterializationUnit into 1684 // materializing state. 1685 for (auto &KV : MU->getSymbols()) { 1686 auto SymK = Symbols.find(KV.first); 1687 assert(SymK != Symbols.end() && "Missing symbol table entry"); 1688 SymK->second.setState(SymbolState::Materializing); 1689 SymK->second.setMaterializerAttached(false); 1690 UnmaterializedInfos.erase(KV.first); 1691 } 1692 1693 // Add MU to the list of MaterializationUnits to be materialized. 1694 MUs.push_back(std::move(MU)); 1695 } 1696 1697 // Add the query to the PendingQueries list. 1698 assert(SymI->second.isInMaterializationPhase() && 1699 "By this line the symbol should be materializing"); 1700 auto &MI = MaterializingInfos[Name]; 1701 MI.addQuery(Q); 1702 Q->addQueryDependence(*this, Name); 1703 return true; 1704 }); 1705 1706 return QueryComplete; 1707 } 1708 1709 void JITDylib::dump(raw_ostream &OS) { 1710 ES.runSessionLocked([&, this]() { 1711 OS << "JITDylib \"" << JITDylibName << "\" (ES: " 1712 << format("0x%016" PRIx64, reinterpret_cast<uintptr_t>(&ES)) << "):\n" 1713 << "Search order: " << SearchOrder << "\n" 1714 << "Symbol table:\n"; 1715 1716 for (auto &KV : Symbols) { 1717 OS << " \"" << *KV.first << "\": "; 1718 if (auto Addr = KV.second.getAddress()) 1719 OS << format("0x%016" PRIx64, Addr) << ", " << KV.second.getFlags() 1720 << " "; 1721 else 1722 OS << "<not resolved> "; 1723 1724 OS << KV.second.getState(); 1725 1726 if (KV.second.hasMaterializerAttached()) { 1727 OS << " (Materializer "; 1728 auto I = UnmaterializedInfos.find(KV.first); 1729 assert(I != UnmaterializedInfos.end() && 1730 "Lazy symbol should have UnmaterializedInfo"); 1731 OS << I->second->MU.get() << ")\n"; 1732 } else 1733 OS << "\n"; 1734 } 1735 1736 if (!MaterializingInfos.empty()) 1737 OS << " MaterializingInfos entries:\n"; 1738 for (auto &KV : MaterializingInfos) { 1739 OS << " \"" << *KV.first << "\":\n" 1740 << " " << KV.second.pendingQueries().size() 1741 << " pending queries: { "; 1742 for (const auto &Q : KV.second.pendingQueries()) 1743 OS << Q.get() << " (" << Q->getRequiredState() << ") "; 1744 OS << "}\n Dependants:\n"; 1745 for (auto &KV2 : KV.second.Dependants) 1746 OS << " " << KV2.first->getName() << ": " << KV2.second << "\n"; 1747 OS << " Unemitted Dependencies:\n"; 1748 for (auto &KV2 : KV.second.UnemittedDependencies) 1749 OS << " " << KV2.first->getName() << ": " << KV2.second << "\n"; 1750 } 1751 }); 1752 } 1753 1754 void JITDylib::MaterializingInfo::addQuery( 1755 std::shared_ptr<AsynchronousSymbolQuery> Q) { 1756 1757 auto I = std::lower_bound( 1758 PendingQueries.rbegin(), PendingQueries.rend(), Q->getRequiredState(), 1759 [](const std::shared_ptr<AsynchronousSymbolQuery> &V, SymbolState S) { 1760 return V->getRequiredState() <= S; 1761 }); 1762 PendingQueries.insert(I.base(), std::move(Q)); 1763 } 1764 1765 void JITDylib::MaterializingInfo::removeQuery( 1766 const AsynchronousSymbolQuery &Q) { 1767 // FIXME: Implement 'find_as' for shared_ptr<T>/T*. 1768 auto I = 1769 std::find_if(PendingQueries.begin(), PendingQueries.end(), 1770 [&Q](const std::shared_ptr<AsynchronousSymbolQuery> &V) { 1771 return V.get() == &Q; 1772 }); 1773 assert(I != PendingQueries.end() && 1774 "Query is not attached to this MaterializingInfo"); 1775 PendingQueries.erase(I); 1776 } 1777 1778 JITDylib::AsynchronousSymbolQueryList 1779 JITDylib::MaterializingInfo::takeQueriesMeeting(SymbolState RequiredState) { 1780 AsynchronousSymbolQueryList Result; 1781 while (!PendingQueries.empty()) { 1782 if (PendingQueries.back()->getRequiredState() > RequiredState) 1783 break; 1784 1785 Result.push_back(std::move(PendingQueries.back())); 1786 PendingQueries.pop_back(); 1787 } 1788 1789 return Result; 1790 } 1791 1792 JITDylib::JITDylib(ExecutionSession &ES, std::string Name) 1793 : ES(ES), JITDylibName(std::move(Name)) { 1794 SearchOrder.push_back({this, JITDylibLookupFlags::MatchAllSymbols}); 1795 } 1796 1797 Error JITDylib::defineImpl(MaterializationUnit &MU) { 1798 SymbolNameSet Duplicates; 1799 std::vector<SymbolStringPtr> ExistingDefsOverridden; 1800 std::vector<SymbolStringPtr> MUDefsOverridden; 1801 1802 for (const auto &KV : MU.getSymbols()) { 1803 auto I = Symbols.find(KV.first); 1804 1805 if (I != Symbols.end()) { 1806 if (KV.second.isStrong()) { 1807 if (I->second.getFlags().isStrong() || 1808 I->second.getState() > SymbolState::NeverSearched) 1809 Duplicates.insert(KV.first); 1810 else { 1811 assert(I->second.getState() == SymbolState::NeverSearched && 1812 "Overridden existing def should be in the never-searched " 1813 "state"); 1814 ExistingDefsOverridden.push_back(KV.first); 1815 } 1816 } else 1817 MUDefsOverridden.push_back(KV.first); 1818 } 1819 } 1820 1821 // If there were any duplicate definitions then bail out. 1822 if (!Duplicates.empty()) 1823 return make_error<DuplicateDefinition>(std::string(**Duplicates.begin())); 1824 1825 // Discard any overridden defs in this MU. 1826 for (auto &S : MUDefsOverridden) 1827 MU.doDiscard(*this, S); 1828 1829 // Discard existing overridden defs. 1830 for (auto &S : ExistingDefsOverridden) { 1831 1832 auto UMII = UnmaterializedInfos.find(S); 1833 assert(UMII != UnmaterializedInfos.end() && 1834 "Overridden existing def should have an UnmaterializedInfo"); 1835 UMII->second->MU->doDiscard(*this, S); 1836 } 1837 1838 // Finally, add the defs from this MU. 1839 for (auto &KV : MU.getSymbols()) { 1840 auto &SymEntry = Symbols[KV.first]; 1841 SymEntry.setFlags(KV.second); 1842 SymEntry.setState(SymbolState::NeverSearched); 1843 SymEntry.setMaterializerAttached(true); 1844 } 1845 1846 return Error::success(); 1847 } 1848 1849 void JITDylib::detachQueryHelper(AsynchronousSymbolQuery &Q, 1850 const SymbolNameSet &QuerySymbols) { 1851 for (auto &QuerySymbol : QuerySymbols) { 1852 assert(MaterializingInfos.count(QuerySymbol) && 1853 "QuerySymbol does not have MaterializingInfo"); 1854 auto &MI = MaterializingInfos[QuerySymbol]; 1855 MI.removeQuery(Q); 1856 } 1857 } 1858 1859 void JITDylib::transferEmittedNodeDependencies( 1860 MaterializingInfo &DependantMI, const SymbolStringPtr &DependantName, 1861 MaterializingInfo &EmittedMI) { 1862 for (auto &KV : EmittedMI.UnemittedDependencies) { 1863 auto &DependencyJD = *KV.first; 1864 SymbolNameSet *UnemittedDependenciesOnDependencyJD = nullptr; 1865 1866 for (auto &DependencyName : KV.second) { 1867 auto &DependencyMI = DependencyJD.MaterializingInfos[DependencyName]; 1868 1869 // Do not add self dependencies. 1870 if (&DependencyMI == &DependantMI) 1871 continue; 1872 1873 // If we haven't looked up the dependencies for DependencyJD yet, do it 1874 // now and cache the result. 1875 if (!UnemittedDependenciesOnDependencyJD) 1876 UnemittedDependenciesOnDependencyJD = 1877 &DependantMI.UnemittedDependencies[&DependencyJD]; 1878 1879 DependencyMI.Dependants[this].insert(DependantName); 1880 UnemittedDependenciesOnDependencyJD->insert(DependencyName); 1881 } 1882 } 1883 } 1884 1885 ExecutionSession::ExecutionSession(std::shared_ptr<SymbolStringPool> SSP) 1886 : SSP(SSP ? std::move(SSP) : std::make_shared<SymbolStringPool>()) { 1887 } 1888 1889 JITDylib *ExecutionSession::getJITDylibByName(StringRef Name) { 1890 return runSessionLocked([&, this]() -> JITDylib * { 1891 for (auto &JD : JDs) 1892 if (JD->getName() == Name) 1893 return JD.get(); 1894 return nullptr; 1895 }); 1896 } 1897 1898 JITDylib &ExecutionSession::createJITDylib(std::string Name) { 1899 assert(!getJITDylibByName(Name) && "JITDylib with that name already exists"); 1900 return runSessionLocked([&, this]() -> JITDylib & { 1901 JDs.push_back( 1902 std::unique_ptr<JITDylib>(new JITDylib(*this, std::move(Name)))); 1903 return *JDs.back(); 1904 }); 1905 } 1906 1907 void ExecutionSession::legacyFailQuery(AsynchronousSymbolQuery &Q, Error Err) { 1908 assert(!!Err && "Error should be in failure state"); 1909 1910 bool SendErrorToQuery; 1911 runSessionLocked([&]() { 1912 Q.detach(); 1913 SendErrorToQuery = Q.canStillFail(); 1914 }); 1915 1916 if (SendErrorToQuery) 1917 Q.handleFailed(std::move(Err)); 1918 else 1919 reportError(std::move(Err)); 1920 } 1921 1922 Expected<SymbolMap> ExecutionSession::legacyLookup( 1923 LegacyAsyncLookupFunction AsyncLookup, SymbolNameSet Names, 1924 SymbolState RequiredState, 1925 RegisterDependenciesFunction RegisterDependencies) { 1926 #if LLVM_ENABLE_THREADS 1927 // In the threaded case we use promises to return the results. 1928 std::promise<SymbolMap> PromisedResult; 1929 Error ResolutionError = Error::success(); 1930 auto NotifyComplete = [&](Expected<SymbolMap> R) { 1931 if (R) 1932 PromisedResult.set_value(std::move(*R)); 1933 else { 1934 ErrorAsOutParameter _(&ResolutionError); 1935 ResolutionError = R.takeError(); 1936 PromisedResult.set_value(SymbolMap()); 1937 } 1938 }; 1939 #else 1940 SymbolMap Result; 1941 Error ResolutionError = Error::success(); 1942 1943 auto NotifyComplete = [&](Expected<SymbolMap> R) { 1944 ErrorAsOutParameter _(&ResolutionError); 1945 if (R) 1946 Result = std::move(*R); 1947 else 1948 ResolutionError = R.takeError(); 1949 }; 1950 #endif 1951 1952 auto Query = std::make_shared<AsynchronousSymbolQuery>( 1953 SymbolLookupSet(Names), RequiredState, std::move(NotifyComplete)); 1954 // FIXME: This should be run session locked along with the registration code 1955 // and error reporting below. 1956 SymbolNameSet UnresolvedSymbols = AsyncLookup(Query, std::move(Names)); 1957 1958 // If the query was lodged successfully then register the dependencies, 1959 // otherwise fail it with an error. 1960 if (UnresolvedSymbols.empty()) 1961 RegisterDependencies(Query->QueryRegistrations); 1962 else { 1963 bool DeliverError = runSessionLocked([&]() { 1964 Query->detach(); 1965 return Query->canStillFail(); 1966 }); 1967 auto Err = make_error<SymbolsNotFound>(std::move(UnresolvedSymbols)); 1968 if (DeliverError) 1969 Query->handleFailed(std::move(Err)); 1970 else 1971 reportError(std::move(Err)); 1972 } 1973 1974 #if LLVM_ENABLE_THREADS 1975 auto ResultFuture = PromisedResult.get_future(); 1976 auto Result = ResultFuture.get(); 1977 if (ResolutionError) 1978 return std::move(ResolutionError); 1979 return std::move(Result); 1980 1981 #else 1982 if (ResolutionError) 1983 return std::move(ResolutionError); 1984 1985 return Result; 1986 #endif 1987 } 1988 1989 void ExecutionSession::lookup( 1990 LookupKind K, const JITDylibSearchOrder &SearchOrder, 1991 SymbolLookupSet Symbols, SymbolState RequiredState, 1992 SymbolsResolvedCallback NotifyComplete, 1993 RegisterDependenciesFunction RegisterDependencies) { 1994 1995 LLVM_DEBUG({ 1996 runSessionLocked([&]() { 1997 dbgs() << "Looking up " << Symbols << " in " << SearchOrder 1998 << " (required state: " << RequiredState << ")\n"; 1999 }); 2000 }); 2001 2002 // lookup can be re-entered recursively if running on a single thread. Run any 2003 // outstanding MUs in case this query depends on them, otherwise this lookup 2004 // will starve waiting for a result from an MU that is stuck in the queue. 2005 runOutstandingMUs(); 2006 2007 auto Unresolved = std::move(Symbols); 2008 std::map<JITDylib *, MaterializationUnitList> CollectedMUsMap; 2009 auto Q = std::make_shared<AsynchronousSymbolQuery>(Unresolved, RequiredState, 2010 std::move(NotifyComplete)); 2011 bool QueryComplete = false; 2012 2013 auto LodgingErr = runSessionLocked([&]() -> Error { 2014 auto LodgeQuery = [&]() -> Error { 2015 for (auto &KV : SearchOrder) { 2016 assert(KV.first && "JITDylibList entries must not be null"); 2017 assert(!CollectedMUsMap.count(KV.first) && 2018 "JITDylibList should not contain duplicate entries"); 2019 2020 auto &JD = *KV.first; 2021 auto JDLookupFlags = KV.second; 2022 if (auto Err = JD.lodgeQuery(CollectedMUsMap[&JD], Q, K, JDLookupFlags, 2023 Unresolved)) 2024 return Err; 2025 } 2026 2027 // Strip any weakly referenced symbols that were not found. 2028 Unresolved.forEachWithRemoval( 2029 [&](const SymbolStringPtr &Name, SymbolLookupFlags Flags) { 2030 if (Flags == SymbolLookupFlags::WeaklyReferencedSymbol) { 2031 Q->dropSymbol(Name); 2032 return true; 2033 } 2034 return false; 2035 }); 2036 2037 if (!Unresolved.empty()) 2038 return make_error<SymbolsNotFound>(Unresolved.getSymbolNames()); 2039 2040 return Error::success(); 2041 }; 2042 2043 if (auto Err = LodgeQuery()) { 2044 // Query failed. 2045 2046 // Disconnect the query from its dependencies. 2047 Q->detach(); 2048 2049 // Replace the MUs. 2050 for (auto &KV : CollectedMUsMap) 2051 for (auto &MU : KV.second) 2052 KV.first->replace(std::move(MU)); 2053 2054 return Err; 2055 } 2056 2057 // Query lodged successfully. 2058 2059 // Record whether this query is fully ready / resolved. We will use 2060 // this to call handleFullyResolved/handleFullyReady outside the session 2061 // lock. 2062 QueryComplete = Q->isComplete(); 2063 2064 // Call the register dependencies function. 2065 if (RegisterDependencies && !Q->QueryRegistrations.empty()) 2066 RegisterDependencies(Q->QueryRegistrations); 2067 2068 return Error::success(); 2069 }); 2070 2071 if (LodgingErr) { 2072 Q->handleFailed(std::move(LodgingErr)); 2073 return; 2074 } 2075 2076 if (QueryComplete) 2077 Q->handleComplete(); 2078 2079 // Move the MUs to the OutstandingMUs list, then materialize. 2080 { 2081 std::lock_guard<std::recursive_mutex> Lock(OutstandingMUsMutex); 2082 2083 for (auto &KV : CollectedMUsMap) 2084 for (auto &MU : KV.second) 2085 OutstandingMUs.push_back(std::make_pair(KV.first, std::move(MU))); 2086 } 2087 2088 runOutstandingMUs(); 2089 } 2090 2091 Expected<SymbolMap> 2092 ExecutionSession::lookup(const JITDylibSearchOrder &SearchOrder, 2093 const SymbolLookupSet &Symbols, LookupKind K, 2094 SymbolState RequiredState, 2095 RegisterDependenciesFunction RegisterDependencies) { 2096 #if LLVM_ENABLE_THREADS 2097 // In the threaded case we use promises to return the results. 2098 std::promise<SymbolMap> PromisedResult; 2099 Error ResolutionError = Error::success(); 2100 2101 auto NotifyComplete = [&](Expected<SymbolMap> R) { 2102 if (R) 2103 PromisedResult.set_value(std::move(*R)); 2104 else { 2105 ErrorAsOutParameter _(&ResolutionError); 2106 ResolutionError = R.takeError(); 2107 PromisedResult.set_value(SymbolMap()); 2108 } 2109 }; 2110 2111 #else 2112 SymbolMap Result; 2113 Error ResolutionError = Error::success(); 2114 2115 auto NotifyComplete = [&](Expected<SymbolMap> R) { 2116 ErrorAsOutParameter _(&ResolutionError); 2117 if (R) 2118 Result = std::move(*R); 2119 else 2120 ResolutionError = R.takeError(); 2121 }; 2122 #endif 2123 2124 // Perform the asynchronous lookup. 2125 lookup(K, SearchOrder, Symbols, RequiredState, NotifyComplete, 2126 RegisterDependencies); 2127 2128 #if LLVM_ENABLE_THREADS 2129 auto ResultFuture = PromisedResult.get_future(); 2130 auto Result = ResultFuture.get(); 2131 2132 if (ResolutionError) 2133 return std::move(ResolutionError); 2134 2135 return std::move(Result); 2136 2137 #else 2138 if (ResolutionError) 2139 return std::move(ResolutionError); 2140 2141 return Result; 2142 #endif 2143 } 2144 2145 Expected<JITEvaluatedSymbol> 2146 ExecutionSession::lookup(const JITDylibSearchOrder &SearchOrder, 2147 SymbolStringPtr Name) { 2148 SymbolLookupSet Names({Name}); 2149 2150 if (auto ResultMap = lookup(SearchOrder, std::move(Names), LookupKind::Static, 2151 SymbolState::Ready, NoDependenciesToRegister)) { 2152 assert(ResultMap->size() == 1 && "Unexpected number of results"); 2153 assert(ResultMap->count(Name) && "Missing result for symbol"); 2154 return std::move(ResultMap->begin()->second); 2155 } else 2156 return ResultMap.takeError(); 2157 } 2158 2159 Expected<JITEvaluatedSymbol> 2160 ExecutionSession::lookup(ArrayRef<JITDylib *> SearchOrder, 2161 SymbolStringPtr Name) { 2162 return lookup(makeJITDylibSearchOrder(SearchOrder), Name); 2163 } 2164 2165 Expected<JITEvaluatedSymbol> 2166 ExecutionSession::lookup(ArrayRef<JITDylib *> SearchOrder, StringRef Name) { 2167 return lookup(SearchOrder, intern(Name)); 2168 } 2169 2170 void ExecutionSession::dump(raw_ostream &OS) { 2171 runSessionLocked([this, &OS]() { 2172 for (auto &JD : JDs) 2173 JD->dump(OS); 2174 }); 2175 } 2176 2177 void ExecutionSession::runOutstandingMUs() { 2178 while (1) { 2179 std::pair<JITDylib *, std::unique_ptr<MaterializationUnit>> JITDylibAndMU; 2180 2181 { 2182 std::lock_guard<std::recursive_mutex> Lock(OutstandingMUsMutex); 2183 if (!OutstandingMUs.empty()) { 2184 JITDylibAndMU = std::move(OutstandingMUs.back()); 2185 OutstandingMUs.pop_back(); 2186 } 2187 } 2188 2189 if (JITDylibAndMU.first) { 2190 assert(JITDylibAndMU.second && "JITDylib, but no MU?"); 2191 dispatchMaterialization(*JITDylibAndMU.first, 2192 std::move(JITDylibAndMU.second)); 2193 } else 2194 break; 2195 } 2196 } 2197 2198 MangleAndInterner::MangleAndInterner(ExecutionSession &ES, const DataLayout &DL) 2199 : ES(ES), DL(DL) {} 2200 2201 SymbolStringPtr MangleAndInterner::operator()(StringRef Name) { 2202 std::string MangledName; 2203 { 2204 raw_string_ostream MangledNameStream(MangledName); 2205 Mangler::getNameWithPrefix(MangledNameStream, Name, DL); 2206 } 2207 return ES.intern(MangledName); 2208 } 2209 2210 } // End namespace orc. 2211 } // End namespace llvm. 2212