1 //===----- Core.cpp - Core ORC APIs (MaterializationUnit, VSO, etc.) ------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "llvm/ExecutionEngine/Orc/Core.h" 11 #include "llvm/Config/llvm-config.h" 12 #include "llvm/ExecutionEngine/Orc/OrcError.h" 13 #include "llvm/IR/Mangler.h" 14 #include "llvm/Support/Format.h" 15 16 #if LLVM_ENABLE_THREADS 17 #include <future> 18 #endif 19 20 namespace llvm { 21 namespace orc { 22 23 char FailedToMaterialize::ID = 0; 24 char SymbolsNotFound::ID = 0; 25 26 void MaterializationUnit::anchor() {} 27 void SymbolResolver::anchor() {} 28 29 raw_ostream &operator<<(raw_ostream &OS, const JITSymbolFlags &Flags) { 30 if (Flags.isWeak()) 31 OS << 'W'; 32 else if (Flags.isCommon()) 33 OS << 'C'; 34 else 35 OS << 'S'; 36 37 if (Flags.isExported()) 38 OS << 'E'; 39 else 40 OS << 'H'; 41 42 return OS; 43 } 44 45 raw_ostream &operator<<(raw_ostream &OS, const JITEvaluatedSymbol &Sym) { 46 OS << format("0x%016x", Sym.getAddress()) << " " << Sym.getFlags(); 47 return OS; 48 } 49 50 raw_ostream &operator<<(raw_ostream &OS, const SymbolMap::value_type &KV) { 51 OS << "\"" << *KV.first << "\": " << KV.second; 52 return OS; 53 } 54 55 raw_ostream &operator<<(raw_ostream &OS, const SymbolNameSet &Symbols) { 56 OS << "{"; 57 if (!Symbols.empty()) { 58 OS << " \"" << **Symbols.begin() << "\""; 59 for (auto &Sym : make_range(std::next(Symbols.begin()), Symbols.end())) 60 OS << ", \"" << *Sym << "\""; 61 } 62 OS << " }"; 63 return OS; 64 } 65 66 raw_ostream &operator<<(raw_ostream &OS, const SymbolMap &Symbols) { 67 OS << "{"; 68 if (!Symbols.empty()) { 69 OS << " {" << *Symbols.begin() << "}"; 70 for (auto &Sym : make_range(std::next(Symbols.begin()), Symbols.end())) 71 OS << ", {" << Sym << "}"; 72 } 73 OS << " }"; 74 return OS; 75 } 76 77 raw_ostream &operator<<(raw_ostream &OS, const SymbolFlagsMap &SymbolFlags) { 78 OS << "{"; 79 if (!SymbolFlags.empty()) { 80 OS << " {\"" << *SymbolFlags.begin()->first 81 << "\": " << SymbolFlags.begin()->second << "}"; 82 for (auto &KV : 83 make_range(std::next(SymbolFlags.begin()), SymbolFlags.end())) 84 OS << ", {\"" << *KV.first << "\": " << KV.second << "}"; 85 } 86 OS << " }"; 87 return OS; 88 } 89 90 raw_ostream &operator<<(raw_ostream &OS, const SymbolDependenceMap &Deps) { 91 OS << "{"; 92 if (!Deps.empty()) { 93 OS << " { " << Deps.begin()->first->getName() << ": " 94 << Deps.begin()->second << " }"; 95 for (auto &KV : make_range(std::next(Deps.begin()), Deps.end())) 96 OS << ", { " << KV.first->getName() << ": " << KV.second << " }"; 97 } 98 OS << " }"; 99 return OS; 100 } 101 102 FailedToMaterialize::FailedToMaterialize(SymbolNameSet Symbols) 103 : Symbols(std::move(Symbols)) { 104 assert(!this->Symbols.empty() && "Can not fail to resolve an empty set"); 105 } 106 107 std::error_code FailedToMaterialize::convertToErrorCode() const { 108 return orcError(OrcErrorCode::UnknownORCError); 109 } 110 111 void FailedToMaterialize::log(raw_ostream &OS) const { 112 OS << "Failed to materialize symbols: " << Symbols; 113 } 114 115 SymbolsNotFound::SymbolsNotFound(SymbolNameSet Symbols) 116 : Symbols(std::move(Symbols)) { 117 assert(!this->Symbols.empty() && "Can not fail to resolve an empty set"); 118 } 119 120 std::error_code SymbolsNotFound::convertToErrorCode() const { 121 return orcError(OrcErrorCode::UnknownORCError); 122 } 123 124 void SymbolsNotFound::log(raw_ostream &OS) const { 125 OS << "Symbols not found: " << Symbols; 126 } 127 128 void ExecutionSessionBase::failQuery(AsynchronousSymbolQuery &Q, Error Err) { 129 bool DeliveredError = true; 130 runSessionLocked([&]() -> void { 131 Q.detach(); 132 if (Q.canStillFail()) 133 Q.handleFailed(std::move(Err)); 134 else 135 DeliveredError = false; 136 }); 137 138 if (!DeliveredError) 139 reportError(std::move(Err)); 140 } 141 142 AsynchronousSymbolQuery::AsynchronousSymbolQuery( 143 const SymbolNameSet &Symbols, SymbolsResolvedCallback NotifySymbolsResolved, 144 SymbolsReadyCallback NotifySymbolsReady) 145 : NotifySymbolsResolved(std::move(NotifySymbolsResolved)), 146 NotifySymbolsReady(std::move(NotifySymbolsReady)) { 147 NotYetResolvedCount = NotYetReadyCount = Symbols.size(); 148 149 for (auto &S : Symbols) 150 ResolvedSymbols[S] = nullptr; 151 152 // If the query is empty it is trivially resolved/ready. 153 if (Symbols.empty()) { 154 handleFullyResolved(); 155 handleFullyReady(); 156 } 157 } 158 159 void AsynchronousSymbolQuery::resolve(const SymbolStringPtr &Name, 160 JITEvaluatedSymbol Sym) { 161 auto I = ResolvedSymbols.find(Name); 162 assert(I != ResolvedSymbols.end() && 163 "Resolving symbol outside the requested set"); 164 assert(I->second.getAddress() == 0 && "Redundantly resolving symbol Name"); 165 I->second = std::move(Sym); 166 --NotYetResolvedCount; 167 } 168 169 void AsynchronousSymbolQuery::handleFullyResolved() { 170 assert(NotYetResolvedCount == 0 && "Not fully resolved?"); 171 assert(NotifySymbolsResolved && 172 "NotifySymbolsResolved already called or error occurred"); 173 NotifySymbolsResolved( 174 ResolutionResult(std::move(ResolvedSymbols), QueryRegistrations)); 175 NotifySymbolsResolved = SymbolsResolvedCallback(); 176 } 177 178 void AsynchronousSymbolQuery::notifySymbolReady() { 179 assert(NotYetReadyCount != 0 && "All symbols already finalized"); 180 --NotYetReadyCount; 181 } 182 183 void AsynchronousSymbolQuery::handleFullyReady() { 184 assert(QueryRegistrations.empty() && 185 "Query is still registered with some symbols"); 186 assert(!NotifySymbolsResolved && "Resolution not applied yet"); 187 NotifySymbolsReady(Error::success()); 188 NotifySymbolsReady = SymbolsReadyCallback(); 189 } 190 191 bool AsynchronousSymbolQuery::canStillFail() { 192 return (NotifySymbolsResolved || NotifySymbolsReady); 193 } 194 195 void AsynchronousSymbolQuery::handleFailed(Error Err) { 196 assert(QueryRegistrations.empty() && ResolvedSymbols.empty() && 197 NotYetResolvedCount == 0 && NotYetReadyCount == 0 && 198 "Query should already have been abandoned"); 199 if (NotifySymbolsResolved) { 200 NotifySymbolsResolved(std::move(Err)); 201 NotifySymbolsResolved = SymbolsResolvedCallback(); 202 } else { 203 assert(NotifySymbolsReady && "Failed after both callbacks issued?"); 204 NotifySymbolsReady(std::move(Err)); 205 } 206 NotifySymbolsReady = SymbolsReadyCallback(); 207 } 208 209 void AsynchronousSymbolQuery::addQueryDependence(VSO &V, SymbolStringPtr Name) { 210 bool Added = QueryRegistrations[&V].insert(std::move(Name)).second; 211 (void)Added; 212 assert(Added && "Duplicate dependence notification?"); 213 } 214 215 void AsynchronousSymbolQuery::removeQueryDependence( 216 VSO &V, const SymbolStringPtr &Name) { 217 auto QRI = QueryRegistrations.find(&V); 218 assert(QRI != QueryRegistrations.end() && "No dependencies registered for V"); 219 assert(QRI->second.count(Name) && "No dependency on Name in V"); 220 QRI->second.erase(Name); 221 if (QRI->second.empty()) 222 QueryRegistrations.erase(QRI); 223 } 224 225 void AsynchronousSymbolQuery::detach() { 226 ResolvedSymbols.clear(); 227 NotYetResolvedCount = 0; 228 NotYetReadyCount = 0; 229 for (auto &KV : QueryRegistrations) 230 KV.first->detachQueryHelper(*this, KV.second); 231 QueryRegistrations.clear(); 232 } 233 234 MaterializationResponsibility::MaterializationResponsibility( 235 VSO &V, SymbolFlagsMap SymbolFlags) 236 : V(V), SymbolFlags(std::move(SymbolFlags)) { 237 assert(!this->SymbolFlags.empty() && "Materializing nothing?"); 238 239 #ifndef NDEBUG 240 for (auto &KV : this->SymbolFlags) 241 KV.second |= JITSymbolFlags::Materializing; 242 #endif 243 } 244 245 MaterializationResponsibility::~MaterializationResponsibility() { 246 assert(SymbolFlags.empty() && 247 "All symbols should have been explicitly materialized or failed"); 248 } 249 250 SymbolNameSet MaterializationResponsibility::getRequestedSymbols() { 251 return V.getRequestedSymbols(SymbolFlags); 252 } 253 254 void MaterializationResponsibility::resolve(const SymbolMap &Symbols) { 255 #ifndef NDEBUG 256 for (auto &KV : Symbols) { 257 auto I = SymbolFlags.find(KV.first); 258 assert(I != SymbolFlags.end() && 259 "Resolving symbol outside this responsibility set"); 260 assert(I->second.isMaterializing() && "Duplicate resolution"); 261 I->second &= ~JITSymbolFlags::Materializing; 262 if (I->second.isWeak()) 263 assert(I->second == (KV.second.getFlags() | JITSymbolFlags::Weak) && 264 "Resolving symbol with incorrect flags"); 265 else 266 assert(I->second == KV.second.getFlags() && 267 "Resolving symbol with incorrect flags"); 268 } 269 #endif 270 271 V.resolve(Symbols); 272 } 273 274 void MaterializationResponsibility::finalize() { 275 #ifndef NDEBUG 276 for (auto &KV : SymbolFlags) 277 assert(!KV.second.isMaterializing() && 278 "Failed to resolve symbol before finalization"); 279 #endif // NDEBUG 280 281 V.finalize(SymbolFlags); 282 SymbolFlags.clear(); 283 } 284 285 Error MaterializationResponsibility::defineMaterializing( 286 const SymbolFlagsMap &NewSymbolFlags) { 287 // Add the given symbols to this responsibility object. 288 // It's ok if we hit a duplicate here: In that case the new version will be 289 // discarded, and the VSO::defineMaterializing method will return a duplicate 290 // symbol error. 291 for (auto &KV : NewSymbolFlags) { 292 auto I = SymbolFlags.insert(KV).first; 293 (void)I; 294 #ifndef NDEBUG 295 I->second |= JITSymbolFlags::Materializing; 296 #endif 297 } 298 299 return V.defineMaterializing(NewSymbolFlags); 300 } 301 302 void MaterializationResponsibility::failMaterialization() { 303 304 SymbolNameSet FailedSymbols; 305 for (auto &KV : SymbolFlags) 306 FailedSymbols.insert(KV.first); 307 308 V.notifyFailed(FailedSymbols); 309 SymbolFlags.clear(); 310 } 311 312 void MaterializationResponsibility::replace( 313 std::unique_ptr<MaterializationUnit> MU) { 314 for (auto &KV : MU->getSymbols()) 315 SymbolFlags.erase(KV.first); 316 317 V.replace(std::move(MU)); 318 } 319 320 MaterializationResponsibility 321 MaterializationResponsibility::delegate(const SymbolNameSet &Symbols) { 322 SymbolFlagsMap DelegatedFlags; 323 324 for (auto &Name : Symbols) { 325 auto I = SymbolFlags.find(Name); 326 assert(I != SymbolFlags.end() && 327 "Symbol is not tracked by this MaterializationResponsibility " 328 "instance"); 329 330 DelegatedFlags[Name] = std::move(I->second); 331 SymbolFlags.erase(I); 332 } 333 334 return MaterializationResponsibility(V, std::move(DelegatedFlags)); 335 } 336 337 void MaterializationResponsibility::addDependencies( 338 const SymbolDependenceMap &Dependencies) { 339 V.addDependencies(SymbolFlags, Dependencies); 340 } 341 342 AbsoluteSymbolsMaterializationUnit::AbsoluteSymbolsMaterializationUnit( 343 SymbolMap Symbols) 344 : MaterializationUnit(extractFlags(Symbols)), Symbols(std::move(Symbols)) {} 345 346 void AbsoluteSymbolsMaterializationUnit::materialize( 347 MaterializationResponsibility R) { 348 R.resolve(Symbols); 349 R.finalize(); 350 } 351 352 void AbsoluteSymbolsMaterializationUnit::discard(const VSO &V, 353 SymbolStringPtr Name) { 354 assert(Symbols.count(Name) && "Symbol is not part of this MU"); 355 Symbols.erase(Name); 356 } 357 358 SymbolFlagsMap 359 AbsoluteSymbolsMaterializationUnit::extractFlags(const SymbolMap &Symbols) { 360 SymbolFlagsMap Flags; 361 for (const auto &KV : Symbols) 362 Flags[KV.first] = KV.second.getFlags(); 363 return Flags; 364 } 365 366 ReExportsMaterializationUnit::ReExportsMaterializationUnit( 367 VSO *SourceVSO, SymbolAliasMap Aliases) 368 : MaterializationUnit(extractFlags(Aliases)), SourceVSO(SourceVSO), 369 Aliases(std::move(Aliases)) {} 370 371 void ReExportsMaterializationUnit::materialize( 372 MaterializationResponsibility R) { 373 374 VSO &SrcV = SourceVSO ? *SourceVSO : R.getTargetVSO(); 375 auto &ES = SrcV.getExecutionSession(); 376 377 // Find the set of requested aliases and aliasees. Return any unrequested 378 // aliases back to the VSO so as to not prematurely materialize any aliasees. 379 auto RequestedSymbols = R.getRequestedSymbols(); 380 SymbolAliasMap RequestedAliases; 381 382 for (auto &Name : RequestedSymbols) { 383 auto I = Aliases.find(Name); 384 assert(I != Aliases.end() && "Symbol not found in aliases map?"); 385 RequestedAliases[Name] = std::move(I->second); 386 Aliases.erase(I); 387 } 388 389 if (!Aliases.empty()) { 390 if (SourceVSO) 391 R.replace(reexports(*SourceVSO, std::move(Aliases))); 392 else 393 R.replace(symbolAliases(std::move(Aliases))); 394 } 395 396 // The OnResolveInfo struct will hold the aliases and responsibilty for each 397 // query in the list. 398 struct OnResolveInfo { 399 OnResolveInfo(MaterializationResponsibility R, SymbolAliasMap Aliases) 400 : R(std::move(R)), Aliases(std::move(Aliases)) {} 401 402 MaterializationResponsibility R; 403 SymbolAliasMap Aliases; 404 }; 405 406 // Build a list of queries to issue. In each round we build the largest set of 407 // aliases that we can resolve without encountering a chain definition of the 408 // form Foo -> Bar, Bar -> Baz. Such a form would deadlock as the query would 409 // be waitin on a symbol that it itself had to resolve. Usually this will just 410 // involve one round and a single query. 411 412 std::vector<std::pair<SymbolNameSet, std::shared_ptr<OnResolveInfo>>> 413 QueryInfos; 414 while (!RequestedAliases.empty()) { 415 SymbolNameSet ResponsibilitySymbols; 416 SymbolNameSet QuerySymbols; 417 SymbolAliasMap QueryAliases; 418 419 for (auto I = RequestedAliases.begin(), E = RequestedAliases.end(); 420 I != E;) { 421 auto Tmp = I++; 422 423 // Chain detected. Skip this symbol for this round. 424 if (&SrcV == &R.getTargetVSO() && 425 (QueryAliases.count(Tmp->second.Aliasee) || 426 RequestedAliases.count(Tmp->second.Aliasee))) 427 continue; 428 429 ResponsibilitySymbols.insert(Tmp->first); 430 QuerySymbols.insert(Tmp->second.Aliasee); 431 QueryAliases[Tmp->first] = std::move(Tmp->second); 432 RequestedAliases.erase(Tmp); 433 } 434 assert(!QuerySymbols.empty() && "Alias cycle detected!"); 435 436 auto QueryInfo = std::make_shared<OnResolveInfo>( 437 R.delegate(ResponsibilitySymbols), std::move(QueryAliases)); 438 QueryInfos.push_back( 439 make_pair(std::move(QuerySymbols), std::move(QueryInfo))); 440 } 441 442 // Issue the queries. 443 while (!QueryInfos.empty()) { 444 auto QuerySymbols = std::move(QueryInfos.back().first); 445 auto QueryInfo = std::move(QueryInfos.back().second); 446 447 QueryInfos.pop_back(); 448 449 auto OnResolve = 450 [QueryInfo, 451 &SrcV](Expected<AsynchronousSymbolQuery::ResolutionResult> RR) { 452 if (RR) { 453 SymbolMap ResolutionMap; 454 SymbolNameSet Resolved; 455 for (auto &KV : QueryInfo->Aliases) { 456 assert(RR->Symbols.count(KV.second.Aliasee) && 457 "Result map missing entry?"); 458 ResolutionMap[KV.first] = JITEvaluatedSymbol( 459 RR->Symbols[KV.second.Aliasee].getAddress(), 460 KV.second.AliasFlags); 461 462 // FIXME: We're creating a SymbolFlagsMap and a std::map of 463 // std::sets just to add one dependency here. This needs a 464 // re-think. 465 Resolved.insert(KV.first); 466 } 467 QueryInfo->R.resolve(ResolutionMap); 468 469 SymbolDependenceMap Deps; 470 Deps[&SrcV] = std::move(Resolved); 471 QueryInfo->R.addDependencies(Deps); 472 473 QueryInfo->R.finalize(); 474 } else { 475 auto &ES = QueryInfo->R.getTargetVSO().getExecutionSession(); 476 ES.reportError(RR.takeError()); 477 QueryInfo->R.failMaterialization(); 478 } 479 }; 480 481 auto OnReady = [&ES](Error Err) { ES.reportError(std::move(Err)); }; 482 483 auto Q = std::make_shared<AsynchronousSymbolQuery>( 484 QuerySymbols, std::move(OnResolve), std::move(OnReady)); 485 486 auto Unresolved = SrcV.lookup(Q, std::move(QuerySymbols)); 487 488 if (!Unresolved.empty()) { 489 ES.failQuery(*Q, make_error<SymbolsNotFound>(std::move(Unresolved))); 490 return; 491 } 492 } 493 } 494 495 void ReExportsMaterializationUnit::discard(const VSO &V, SymbolStringPtr Name) { 496 assert(Aliases.count(Name) && 497 "Symbol not covered by this MaterializationUnit"); 498 Aliases.erase(Name); 499 } 500 501 SymbolFlagsMap 502 ReExportsMaterializationUnit::extractFlags(const SymbolAliasMap &Aliases) { 503 SymbolFlagsMap SymbolFlags; 504 for (auto &KV : Aliases) 505 SymbolFlags[KV.first] = KV.second.AliasFlags; 506 507 return SymbolFlags; 508 } 509 510 Expected<SymbolAliasMap> 511 buildSimpleReexportsAliasMap(VSO &SourceV, const SymbolNameSet &Symbols) { 512 SymbolFlagsMap Flags; 513 auto Unresolved = SourceV.lookupFlags(Flags, Symbols); 514 515 if (!Unresolved.empty()) 516 return make_error<SymbolsNotFound>(std::move(Unresolved)); 517 518 SymbolAliasMap Result; 519 for (auto &Name : Symbols) { 520 assert(Flags.count(Name) && "Missing entry in flags map"); 521 Result[Name] = SymbolAliasMapEntry(Name, Flags[Name]); 522 } 523 524 return Result; 525 } 526 527 Error VSO::defineMaterializing(const SymbolFlagsMap &SymbolFlags) { 528 return ES.runSessionLocked([&]() -> Error { 529 std::vector<SymbolMap::iterator> AddedSyms; 530 531 for (auto &KV : SymbolFlags) { 532 SymbolMap::iterator EntryItr; 533 bool Added; 534 535 auto NewFlags = KV.second; 536 NewFlags |= JITSymbolFlags::Materializing; 537 538 std::tie(EntryItr, Added) = Symbols.insert( 539 std::make_pair(KV.first, JITEvaluatedSymbol(0, NewFlags))); 540 541 if (Added) 542 AddedSyms.push_back(EntryItr); 543 else { 544 // Remove any symbols already added. 545 for (auto &SI : AddedSyms) 546 Symbols.erase(SI); 547 548 // FIXME: Return all duplicates. 549 return make_error<DuplicateDefinition>(*KV.first); 550 } 551 } 552 553 return Error::success(); 554 }); 555 } 556 557 void VSO::replace(std::unique_ptr<MaterializationUnit> MU) { 558 assert(MU != nullptr && "Can not replace with a null MaterializationUnit"); 559 560 auto MustRunMU = 561 ES.runSessionLocked([&, this]() -> std::unique_ptr<MaterializationUnit> { 562 563 #ifndef NDEBUG 564 for (auto &KV : MU->getSymbols()) { 565 auto SymI = Symbols.find(KV.first); 566 assert(SymI != Symbols.end() && "Replacing unknown symbol"); 567 assert(!SymI->second.getFlags().isLazy() && 568 SymI->second.getFlags().isMaterializing() && 569 "Can not replace symbol that is not materializing"); 570 assert(UnmaterializedInfos.count(KV.first) == 0 && 571 "Symbol being replaced should have no UnmaterializedInfo"); 572 } 573 #endif // NDEBUG 574 575 // If any symbol has pending queries against it then we need to 576 // materialize MU immediately. 577 for (auto &KV : MU->getSymbols()) { 578 auto MII = MaterializingInfos.find(KV.first); 579 if (MII != MaterializingInfos.end()) { 580 if (!MII->second.PendingQueries.empty()) 581 return std::move(MU); 582 } 583 } 584 585 // Otherwise, make MU responsible for all the symbols. 586 auto UMI = std::make_shared<UnmaterializedInfo>(std::move(MU)); 587 for (auto &KV : UMI->MU->getSymbols()) { 588 assert(!KV.second.isLazy() && 589 "Lazy flag should be managed internally."); 590 assert(!KV.second.isMaterializing() && 591 "Materializing flags should be managed internally."); 592 593 auto SymI = Symbols.find(KV.first); 594 JITSymbolFlags ReplaceFlags = KV.second; 595 ReplaceFlags |= JITSymbolFlags::Lazy; 596 SymI->second = JITEvaluatedSymbol(SymI->second.getAddress(), 597 std::move(ReplaceFlags)); 598 UnmaterializedInfos[KV.first] = UMI; 599 } 600 601 return nullptr; 602 }); 603 604 if (MustRunMU) 605 ES.dispatchMaterialization(*this, std::move(MustRunMU)); 606 } 607 608 SymbolNameSet VSO::getRequestedSymbols(const SymbolFlagsMap &SymbolFlags) { 609 return ES.runSessionLocked([&]() { 610 SymbolNameSet RequestedSymbols; 611 612 for (auto &KV : SymbolFlags) { 613 assert(Symbols.count(KV.first) && "VSO does not cover this symbol?"); 614 assert(Symbols[KV.first].getFlags().isMaterializing() && 615 "getRequestedSymbols can only be called for materializing " 616 "symbols"); 617 auto I = MaterializingInfos.find(KV.first); 618 if (I == MaterializingInfos.end()) 619 continue; 620 621 if (!I->second.PendingQueries.empty()) 622 RequestedSymbols.insert(KV.first); 623 } 624 625 return RequestedSymbols; 626 }); 627 } 628 629 void VSO::addDependencies(const SymbolFlagsMap &Dependants, 630 const SymbolDependenceMap &Dependencies) { 631 ES.runSessionLocked([&, this]() { 632 for (auto &KV : Dependants) { 633 const auto &Name = KV.first; 634 assert(Symbols.count(Name) && "Name not in symbol table"); 635 assert((Symbols[Name].getFlags().isLazy() || 636 Symbols[Name].getFlags().isMaterializing()) && 637 "Symbol is not lazy or materializing"); 638 639 auto &MI = MaterializingInfos[Name]; 640 assert(!MI.IsFinalized && "Can not add dependencies to finalized symbol"); 641 642 for (auto &KV : Dependencies) { 643 assert(KV.first && "Null VSO in dependency?"); 644 auto &OtherVSO = *KV.first; 645 auto &DepsOnOtherVSO = MI.UnfinalizedDependencies[&OtherVSO]; 646 647 for (auto &OtherSymbol : KV.second) { 648 auto &OtherMI = OtherVSO.MaterializingInfos[OtherSymbol]; 649 650 if (OtherMI.IsFinalized) 651 transferFinalizedNodeDependencies(MI, Name, OtherMI); 652 else if (&OtherVSO != this || OtherSymbol != Name) { 653 OtherMI.Dependants[this].insert(Name); 654 DepsOnOtherVSO.insert(OtherSymbol); 655 } 656 } 657 658 if (DepsOnOtherVSO.empty()) 659 MI.UnfinalizedDependencies.erase(&OtherVSO); 660 } 661 } 662 }); 663 } 664 665 void VSO::resolve(const SymbolMap &Resolved) { 666 auto FullyResolvedQueries = ES.runSessionLocked([&, this]() { 667 AsynchronousSymbolQuerySet FullyResolvedQueries; 668 for (const auto &KV : Resolved) { 669 auto &Name = KV.first; 670 auto Sym = KV.second; 671 672 assert(!Sym.getFlags().isLazy() && !Sym.getFlags().isMaterializing() && 673 "Materializing flags should be managed internally"); 674 675 auto I = Symbols.find(Name); 676 677 assert(I != Symbols.end() && "Symbol not found"); 678 assert(!I->second.getFlags().isLazy() && 679 I->second.getFlags().isMaterializing() && 680 "Symbol should be materializing"); 681 assert(I->second.getAddress() == 0 && "Symbol has already been resolved"); 682 683 assert((Sym.getFlags() & ~JITSymbolFlags::Weak) == 684 (JITSymbolFlags::stripTransientFlags(I->second.getFlags()) & 685 ~JITSymbolFlags::Weak) && 686 "Resolved flags should match the declared flags"); 687 688 // Once resolved, symbols can never be weak. 689 JITSymbolFlags ResolvedFlags = Sym.getFlags(); 690 ResolvedFlags &= ~JITSymbolFlags::Weak; 691 ResolvedFlags |= JITSymbolFlags::Materializing; 692 I->second = JITEvaluatedSymbol(Sym.getAddress(), ResolvedFlags); 693 694 auto &MI = MaterializingInfos[Name]; 695 for (auto &Q : MI.PendingQueries) { 696 Q->resolve(Name, Sym); 697 if (Q->isFullyResolved()) 698 FullyResolvedQueries.insert(Q); 699 } 700 } 701 702 return FullyResolvedQueries; 703 }); 704 705 for (auto &Q : FullyResolvedQueries) { 706 assert(Q->isFullyResolved() && "Q not fully resolved"); 707 Q->handleFullyResolved(); 708 } 709 } 710 711 void VSO::finalize(const SymbolFlagsMap &Finalized) { 712 auto FullyReadyQueries = ES.runSessionLocked([&, this]() { 713 AsynchronousSymbolQuerySet ReadyQueries; 714 715 for (const auto &KV : Finalized) { 716 const auto &Name = KV.first; 717 718 auto MII = MaterializingInfos.find(Name); 719 assert(MII != MaterializingInfos.end() && 720 "Missing MaterializingInfo entry"); 721 722 auto &MI = MII->second; 723 724 // For each dependant, transfer this node's unfinalized dependencies to 725 // it. If the dependant node is fully finalized then notify any pending 726 // queries. 727 for (auto &KV : MI.Dependants) { 728 auto &DependantVSO = *KV.first; 729 for (auto &DependantName : KV.second) { 730 auto DependantMII = 731 DependantVSO.MaterializingInfos.find(DependantName); 732 assert(DependantMII != DependantVSO.MaterializingInfos.end() && 733 "Dependant should have MaterializingInfo"); 734 735 auto &DependantMI = DependantMII->second; 736 737 // Remove the dependant's dependency on this node. 738 assert(DependantMI.UnfinalizedDependencies[this].count(Name) && 739 "Dependant does not count this symbol as a dependency?"); 740 DependantMI.UnfinalizedDependencies[this].erase(Name); 741 if (DependantMI.UnfinalizedDependencies[this].empty()) 742 DependantMI.UnfinalizedDependencies.erase(this); 743 744 // Transfer unfinalized dependencies from this node to the dependant. 745 DependantVSO.transferFinalizedNodeDependencies(DependantMI, 746 DependantName, MI); 747 748 // If the dependant is finalized and this node was the last of its 749 // unfinalized dependencies then notify any pending queries on the 750 // dependant node. 751 if (DependantMI.IsFinalized && 752 DependantMI.UnfinalizedDependencies.empty()) { 753 assert(DependantMI.Dependants.empty() && 754 "Dependants should be empty by now"); 755 for (auto &Q : DependantMI.PendingQueries) { 756 Q->notifySymbolReady(); 757 if (Q->isFullyReady()) 758 ReadyQueries.insert(Q); 759 Q->removeQueryDependence(DependantVSO, DependantName); 760 } 761 762 // If this dependant node was fully finalized we can erase its 763 // MaterializingInfo and update its materializing state. 764 assert(DependantVSO.Symbols.count(DependantName) && 765 "Dependant has no entry in the Symbols table"); 766 auto &DependantSym = DependantVSO.Symbols[DependantName]; 767 DependantSym.setFlags(static_cast<JITSymbolFlags::FlagNames>( 768 DependantSym.getFlags() & ~JITSymbolFlags::Materializing)); 769 DependantVSO.MaterializingInfos.erase(DependantMII); 770 } 771 } 772 } 773 MI.Dependants.clear(); 774 MI.IsFinalized = true; 775 776 if (MI.UnfinalizedDependencies.empty()) { 777 for (auto &Q : MI.PendingQueries) { 778 Q->notifySymbolReady(); 779 if (Q->isFullyReady()) 780 ReadyQueries.insert(Q); 781 Q->removeQueryDependence(*this, Name); 782 } 783 assert(Symbols.count(Name) && 784 "Symbol has no entry in the Symbols table"); 785 auto &Sym = Symbols[Name]; 786 Sym.setFlags(static_cast<JITSymbolFlags::FlagNames>( 787 Sym.getFlags() & ~JITSymbolFlags::Materializing)); 788 MaterializingInfos.erase(MII); 789 } 790 } 791 792 return ReadyQueries; 793 }); 794 795 for (auto &Q : FullyReadyQueries) { 796 assert(Q->isFullyReady() && "Q is not fully ready"); 797 Q->handleFullyReady(); 798 } 799 } 800 801 void VSO::notifyFailed(const SymbolNameSet &FailedSymbols) { 802 803 // FIXME: This should fail any transitively dependant symbols too. 804 805 auto FailedQueriesToNotify = ES.runSessionLocked([&, this]() { 806 AsynchronousSymbolQuerySet FailedQueries; 807 808 for (auto &Name : FailedSymbols) { 809 auto I = Symbols.find(Name); 810 assert(I != Symbols.end() && "Symbol not present in this VSO"); 811 Symbols.erase(I); 812 813 auto MII = MaterializingInfos.find(Name); 814 815 // If we have not created a MaterializingInfo for this symbol yet then 816 // there is nobody to notify. 817 if (MII == MaterializingInfos.end()) 818 continue; 819 820 // Copy all the queries to the FailedQueries list, then abandon them. 821 // This has to be a copy, and the copy has to come before the abandon 822 // operation: Each Q.detach() call will reach back into this 823 // PendingQueries list to remove Q. 824 for (auto &Q : MII->second.PendingQueries) 825 FailedQueries.insert(Q); 826 827 for (auto &Q : FailedQueries) 828 Q->detach(); 829 830 assert(MII->second.PendingQueries.empty() && 831 "Queries remain after symbol was failed"); 832 833 MaterializingInfos.erase(MII); 834 } 835 836 return FailedQueries; 837 }); 838 839 for (auto &Q : FailedQueriesToNotify) 840 Q->handleFailed(make_error<FailedToMaterialize>(FailedSymbols)); 841 } 842 843 void VSO::runOutstandingMUs() { 844 while (1) { 845 std::unique_ptr<MaterializationUnit> MU; 846 847 { 848 std::lock_guard<std::recursive_mutex> Lock(OutstandingMUsMutex); 849 if (!OutstandingMUs.empty()) { 850 MU = std::move(OutstandingMUs.back()); 851 OutstandingMUs.pop_back(); 852 } 853 } 854 855 if (MU) 856 ES.dispatchMaterialization(*this, std::move(MU)); 857 else 858 break; 859 } 860 } 861 862 SymbolNameSet VSO::lookupFlags(SymbolFlagsMap &Flags, 863 const SymbolNameSet &Names) { 864 return ES.runSessionLocked([&, this]() { 865 auto Unresolved = lookupFlagsImpl(Flags, Names); 866 if (FallbackDefinitionGenerator && !Unresolved.empty()) { 867 auto FallbackDefs = FallbackDefinitionGenerator(*this, Unresolved); 868 if (!FallbackDefs.empty()) { 869 auto Unresolved2 = lookupFlagsImpl(Flags, FallbackDefs); 870 (void)Unresolved2; 871 assert(Unresolved2.empty() && 872 "All fallback defs should have been found by lookupFlagsImpl"); 873 for (auto &D : FallbackDefs) 874 Unresolved.erase(D); 875 } 876 }; 877 return Unresolved; 878 }); 879 } 880 881 SymbolNameSet VSO::lookupFlagsImpl(SymbolFlagsMap &Flags, 882 const SymbolNameSet &Names) { 883 SymbolNameSet Unresolved; 884 885 for (auto &Name : Names) { 886 auto I = Symbols.find(Name); 887 888 if (I == Symbols.end()) { 889 Unresolved.insert(Name); 890 continue; 891 } 892 893 assert(!Flags.count(Name) && "Symbol already present in Flags map"); 894 Flags[Name] = JITSymbolFlags::stripTransientFlags(I->second.getFlags()); 895 } 896 897 return Unresolved; 898 } 899 900 SymbolNameSet VSO::lookup(std::shared_ptr<AsynchronousSymbolQuery> Q, 901 SymbolNameSet Names) { 902 assert(Q && "Query can not be null"); 903 904 runOutstandingMUs(); 905 906 LookupImplActionFlags ActionFlags = None; 907 std::vector<std::unique_ptr<MaterializationUnit>> MUs; 908 909 SymbolNameSet Unresolved = std::move(Names); 910 ES.runSessionLocked([&, this]() { 911 ActionFlags = lookupImpl(Q, MUs, Unresolved); 912 if (FallbackDefinitionGenerator && !Unresolved.empty()) { 913 assert(ActionFlags == None && 914 "ActionFlags set but unresolved symbols remain?"); 915 auto FallbackDefs = FallbackDefinitionGenerator(*this, Unresolved); 916 if (!FallbackDefs.empty()) { 917 for (auto &D : FallbackDefs) 918 Unresolved.erase(D); 919 ActionFlags = lookupImpl(Q, MUs, FallbackDefs); 920 assert(FallbackDefs.empty() && 921 "All fallback defs should have been found by lookupImpl"); 922 } 923 } 924 }); 925 926 assert((MUs.empty() || ActionFlags == None) && 927 "If action flags are set, there should be no work to do (so no MUs)"); 928 929 if (ActionFlags & NotifyFullyResolved) 930 Q->handleFullyResolved(); 931 932 if (ActionFlags & NotifyFullyReady) 933 Q->handleFullyReady(); 934 935 // FIXME: Swap back to the old code below once RuntimeDyld works with 936 // callbacks from asynchronous queries. 937 // Add MUs to the OutstandingMUs list. 938 { 939 std::lock_guard<std::recursive_mutex> Lock(OutstandingMUsMutex); 940 for (auto &MU : MUs) 941 OutstandingMUs.push_back(std::move(MU)); 942 } 943 runOutstandingMUs(); 944 945 // Dispatch any required MaterializationUnits for materialization. 946 // for (auto &MU : MUs) 947 // ES.dispatchMaterialization(*this, std::move(MU)); 948 949 return Unresolved; 950 } 951 952 VSO::LookupImplActionFlags 953 VSO::lookupImpl(std::shared_ptr<AsynchronousSymbolQuery> &Q, 954 std::vector<std::unique_ptr<MaterializationUnit>> &MUs, 955 SymbolNameSet &Unresolved) { 956 LookupImplActionFlags ActionFlags = None; 957 958 for (auto I = Unresolved.begin(), E = Unresolved.end(); I != E;) { 959 auto TmpI = I++; 960 auto Name = *TmpI; 961 962 // Search for the name in Symbols. Skip it if not found. 963 auto SymI = Symbols.find(Name); 964 if (SymI == Symbols.end()) 965 continue; 966 967 // If we found Name in V, remove it frome the Unresolved set and add it 968 // to the dependencies set. 969 Unresolved.erase(TmpI); 970 971 // If the symbol has an address then resolve it. 972 if (SymI->second.getAddress() != 0) { 973 Q->resolve(Name, SymI->second); 974 if (Q->isFullyResolved()) 975 ActionFlags |= NotifyFullyResolved; 976 } 977 978 // If the symbol is lazy, get the MaterialiaztionUnit for it. 979 if (SymI->second.getFlags().isLazy()) { 980 assert(SymI->second.getAddress() == 0 && 981 "Lazy symbol should not have a resolved address"); 982 assert(!SymI->second.getFlags().isMaterializing() && 983 "Materializing and lazy should not both be set"); 984 auto UMII = UnmaterializedInfos.find(Name); 985 assert(UMII != UnmaterializedInfos.end() && 986 "Lazy symbol should have UnmaterializedInfo"); 987 auto MU = std::move(UMII->second->MU); 988 assert(MU != nullptr && "Materializer should not be null"); 989 990 // Kick all symbols associated with this MaterializationUnit into 991 // materializing state. 992 for (auto &KV : MU->getSymbols()) { 993 auto SymK = Symbols.find(KV.first); 994 auto Flags = SymK->second.getFlags(); 995 Flags &= ~JITSymbolFlags::Lazy; 996 Flags |= JITSymbolFlags::Materializing; 997 SymK->second.setFlags(Flags); 998 UnmaterializedInfos.erase(KV.first); 999 } 1000 1001 // Add MU to the list of MaterializationUnits to be materialized. 1002 MUs.push_back(std::move(MU)); 1003 } else if (!SymI->second.getFlags().isMaterializing()) { 1004 // The symbol is neither lazy nor materializing. Finalize it and 1005 // continue. 1006 Q->notifySymbolReady(); 1007 if (Q->isFullyReady()) 1008 ActionFlags |= NotifyFullyReady; 1009 continue; 1010 } 1011 1012 // Add the query to the PendingQueries list. 1013 assert(SymI->second.getFlags().isMaterializing() && 1014 "By this line the symbol should be materializing"); 1015 auto &MI = MaterializingInfos[Name]; 1016 MI.PendingQueries.push_back(Q); 1017 Q->addQueryDependence(*this, Name); 1018 } 1019 1020 return ActionFlags; 1021 } 1022 1023 void VSO::dump(raw_ostream &OS) { 1024 ES.runSessionLocked([&, this]() { 1025 OS << "VSO \"" << VSOName 1026 << "\" (ES: " << format("0x%016x", reinterpret_cast<uintptr_t>(&ES)) 1027 << "):\n" 1028 << "Symbol table:\n"; 1029 1030 for (auto &KV : Symbols) { 1031 OS << " \"" << *KV.first 1032 << "\": " << format("0x%016x", KV.second.getAddress()); 1033 if (KV.second.getFlags().isLazy() || 1034 KV.second.getFlags().isMaterializing()) { 1035 OS << " ("; 1036 if (KV.second.getFlags().isLazy()) { 1037 auto I = UnmaterializedInfos.find(KV.first); 1038 assert(I != UnmaterializedInfos.end() && 1039 "Lazy symbol should have UnmaterializedInfo"); 1040 OS << " Lazy (MU=" << I->second->MU.get() << ")"; 1041 } 1042 if (KV.second.getFlags().isMaterializing()) 1043 OS << " Materializing"; 1044 OS << " )\n"; 1045 } else 1046 OS << "\n"; 1047 } 1048 1049 if (!MaterializingInfos.empty()) 1050 OS << " MaterializingInfos entries:\n"; 1051 for (auto &KV : MaterializingInfos) { 1052 OS << " \"" << *KV.first << "\":\n" 1053 << " IsFinalized = " << (KV.second.IsFinalized ? "true" : "false") 1054 << "\n" 1055 << " " << KV.second.PendingQueries.size() 1056 << " pending queries: { "; 1057 for (auto &Q : KV.second.PendingQueries) 1058 OS << Q.get() << " "; 1059 OS << "}\n Dependants:\n"; 1060 for (auto &KV2 : KV.second.Dependants) 1061 OS << " " << KV2.first->getName() << ": " << KV2.second << "\n"; 1062 OS << " Unfinalized Dependencies:\n"; 1063 for (auto &KV2 : KV.second.UnfinalizedDependencies) 1064 OS << " " << KV2.first->getName() << ": " << KV2.second << "\n"; 1065 } 1066 }); 1067 } 1068 1069 Error VSO::defineImpl(MaterializationUnit &MU) { 1070 SymbolNameSet Duplicates; 1071 SymbolNameSet MUDefsOverridden; 1072 1073 struct ExistingDefOverriddenEntry { 1074 SymbolMap::iterator ExistingDefItr; 1075 JITSymbolFlags NewFlags; 1076 }; 1077 std::vector<ExistingDefOverriddenEntry> ExistingDefsOverridden; 1078 1079 for (auto &KV : MU.getSymbols()) { 1080 assert(!KV.second.isLazy() && "Lazy flag should be managed internally."); 1081 assert(!KV.second.isMaterializing() && 1082 "Materializing flags should be managed internally."); 1083 1084 SymbolMap::iterator EntryItr; 1085 bool Added; 1086 1087 auto NewFlags = KV.second; 1088 NewFlags |= JITSymbolFlags::Lazy; 1089 1090 std::tie(EntryItr, Added) = Symbols.insert( 1091 std::make_pair(KV.first, JITEvaluatedSymbol(0, NewFlags))); 1092 1093 if (!Added) { 1094 if (KV.second.isStrong()) { 1095 if (EntryItr->second.getFlags().isStrong() || 1096 (EntryItr->second.getFlags() & JITSymbolFlags::Materializing)) 1097 Duplicates.insert(KV.first); 1098 else 1099 ExistingDefsOverridden.push_back({EntryItr, NewFlags}); 1100 } else 1101 MUDefsOverridden.insert(KV.first); 1102 } 1103 } 1104 1105 if (!Duplicates.empty()) { 1106 // We need to remove the symbols we added. 1107 for (auto &KV : MU.getSymbols()) { 1108 if (Duplicates.count(KV.first)) 1109 continue; 1110 1111 bool Found = false; 1112 for (const auto &EDO : ExistingDefsOverridden) 1113 if (EDO.ExistingDefItr->first == KV.first) 1114 Found = true; 1115 1116 if (!Found) 1117 Symbols.erase(KV.first); 1118 } 1119 1120 // FIXME: Return all duplicates. 1121 return make_error<DuplicateDefinition>(**Duplicates.begin()); 1122 } 1123 1124 // Update flags on existing defs and call discard on their materializers. 1125 for (auto &EDO : ExistingDefsOverridden) { 1126 assert(EDO.ExistingDefItr->second.getFlags().isLazy() && 1127 !EDO.ExistingDefItr->second.getFlags().isMaterializing() && 1128 "Overridden existing def should be in the Lazy state"); 1129 1130 EDO.ExistingDefItr->second.setFlags(EDO.NewFlags); 1131 1132 auto UMII = UnmaterializedInfos.find(EDO.ExistingDefItr->first); 1133 assert(UMII != UnmaterializedInfos.end() && 1134 "Overridden existing def should have an UnmaterializedInfo"); 1135 1136 UMII->second->MU->doDiscard(*this, EDO.ExistingDefItr->first); 1137 } 1138 1139 // Discard overridden symbols povided by MU. 1140 for (auto &Sym : MUDefsOverridden) 1141 MU.doDiscard(*this, Sym); 1142 1143 return Error::success(); 1144 } 1145 1146 void VSO::detachQueryHelper(AsynchronousSymbolQuery &Q, 1147 const SymbolNameSet &QuerySymbols) { 1148 for (auto &QuerySymbol : QuerySymbols) { 1149 assert(MaterializingInfos.count(QuerySymbol) && 1150 "QuerySymbol does not have MaterializingInfo"); 1151 auto &MI = MaterializingInfos[QuerySymbol]; 1152 1153 auto IdenticalQuery = 1154 [&](const std::shared_ptr<AsynchronousSymbolQuery> &R) { 1155 return R.get() == &Q; 1156 }; 1157 1158 auto I = std::find_if(MI.PendingQueries.begin(), MI.PendingQueries.end(), 1159 IdenticalQuery); 1160 assert(I != MI.PendingQueries.end() && 1161 "Query Q should be in the PendingQueries list for QuerySymbol"); 1162 MI.PendingQueries.erase(I); 1163 } 1164 } 1165 1166 void VSO::transferFinalizedNodeDependencies( 1167 MaterializingInfo &DependantMI, const SymbolStringPtr &DependantName, 1168 MaterializingInfo &FinalizedMI) { 1169 for (auto &KV : FinalizedMI.UnfinalizedDependencies) { 1170 auto &DependencyVSO = *KV.first; 1171 SymbolNameSet *UnfinalizedDependenciesOnDependencyVSO = nullptr; 1172 1173 for (auto &DependencyName : KV.second) { 1174 auto &DependencyMI = DependencyVSO.MaterializingInfos[DependencyName]; 1175 1176 // Do not add self dependencies. 1177 if (&DependencyMI == &DependantMI) 1178 continue; 1179 1180 // If we haven't looked up the dependencies for DependencyVSO yet, do it 1181 // now and cache the result. 1182 if (!UnfinalizedDependenciesOnDependencyVSO) 1183 UnfinalizedDependenciesOnDependencyVSO = 1184 &DependantMI.UnfinalizedDependencies[&DependencyVSO]; 1185 1186 DependencyMI.Dependants[this].insert(DependantName); 1187 UnfinalizedDependenciesOnDependencyVSO->insert(DependencyName); 1188 } 1189 } 1190 } 1191 1192 VSO &ExecutionSession::createVSO(std::string Name) { 1193 return runSessionLocked([&, this]() -> VSO & { 1194 VSOs.push_back(std::unique_ptr<VSO>(new VSO(*this, std::move(Name)))); 1195 return *VSOs.back(); 1196 }); 1197 } 1198 1199 Expected<SymbolMap> blockingLookup(ExecutionSessionBase &ES, 1200 AsynchronousLookupFunction AsyncLookup, 1201 SymbolNameSet Names, bool WaitUntilReady, 1202 MaterializationResponsibility *MR) { 1203 1204 #if LLVM_ENABLE_THREADS 1205 // In the threaded case we use promises to return the results. 1206 std::promise<SymbolMap> PromisedResult; 1207 std::mutex ErrMutex; 1208 Error ResolutionError = Error::success(); 1209 std::promise<void> PromisedReady; 1210 Error ReadyError = Error::success(); 1211 auto OnResolve = 1212 [&](Expected<AsynchronousSymbolQuery::ResolutionResult> Result) { 1213 if (Result) { 1214 if (MR) 1215 MR->addDependencies(Result->Dependencies); 1216 PromisedResult.set_value(std::move(Result->Symbols)); 1217 } else { 1218 { 1219 ErrorAsOutParameter _(&ResolutionError); 1220 std::lock_guard<std::mutex> Lock(ErrMutex); 1221 ResolutionError = Result.takeError(); 1222 } 1223 PromisedResult.set_value(SymbolMap()); 1224 } 1225 }; 1226 1227 std::function<void(Error)> OnReady; 1228 if (WaitUntilReady) { 1229 OnReady = [&](Error Err) { 1230 if (Err) { 1231 ErrorAsOutParameter _(&ReadyError); 1232 std::lock_guard<std::mutex> Lock(ErrMutex); 1233 ReadyError = std::move(Err); 1234 } 1235 PromisedReady.set_value(); 1236 }; 1237 } else { 1238 OnReady = [&](Error Err) { 1239 if (Err) 1240 ES.reportError(std::move(Err)); 1241 }; 1242 } 1243 1244 #else 1245 SymbolMap Result; 1246 Error ResolutionError = Error::success(); 1247 Error ReadyError = Error::success(); 1248 1249 auto OnResolve = [&](Expected<AsynchronousSymbolQuery::ResolutionResult> R) { 1250 ErrorAsOutParameter _(&ResolutionError); 1251 if (R) { 1252 if (MR) 1253 MR->addDependencies(R->Dependencies); 1254 Result = std::move(R->Symbols); 1255 } else 1256 ResolutionError = R.takeError(); 1257 }; 1258 1259 std::function<void(Error)> OnReady; 1260 if (WaitUntilReady) { 1261 OnReady = [&](Error Err) { 1262 ErrorAsOutParameter _(&ReadyError); 1263 if (Err) 1264 ReadyError = std::move(Err); 1265 }; 1266 } else { 1267 OnReady = [&](Error Err) { 1268 if (Err) 1269 ES.reportError(std::move(Err)); 1270 }; 1271 } 1272 #endif 1273 1274 auto Query = std::make_shared<AsynchronousSymbolQuery>( 1275 Names, std::move(OnResolve), std::move(OnReady)); 1276 1277 SymbolNameSet UnresolvedSymbols = AsyncLookup(Query, std::move(Names)); 1278 1279 // If there are unresolved symbols then the query will never return. 1280 // Fail it with ES.failQuery. 1281 if (!UnresolvedSymbols.empty()) 1282 ES.failQuery(*Query, 1283 make_error<SymbolsNotFound>(std::move(UnresolvedSymbols))); 1284 1285 #if LLVM_ENABLE_THREADS 1286 auto ResultFuture = PromisedResult.get_future(); 1287 auto Result = ResultFuture.get(); 1288 1289 { 1290 std::lock_guard<std::mutex> Lock(ErrMutex); 1291 if (ResolutionError) { 1292 // ReadyError will never be assigned. Consume the success value. 1293 cantFail(std::move(ReadyError)); 1294 return std::move(ResolutionError); 1295 } 1296 } 1297 1298 if (WaitUntilReady) { 1299 auto ReadyFuture = PromisedReady.get_future(); 1300 ReadyFuture.get(); 1301 1302 { 1303 std::lock_guard<std::mutex> Lock(ErrMutex); 1304 if (ReadyError) 1305 return std::move(ReadyError); 1306 } 1307 } else 1308 cantFail(std::move(ReadyError)); 1309 1310 return std::move(Result); 1311 1312 #else 1313 if (ResolutionError) { 1314 // ReadyError will never be assigned. Consume the success value. 1315 cantFail(std::move(ReadyError)); 1316 return std::move(ResolutionError); 1317 } 1318 1319 if (ReadyError) 1320 return std::move(ReadyError); 1321 1322 return Result; 1323 #endif 1324 } 1325 1326 Expected<SymbolMap> lookup(const VSOList &VSOs, SymbolNameSet Names) { 1327 1328 if (VSOs.empty()) 1329 return SymbolMap(); 1330 1331 auto &ES = (*VSOs.begin())->getExecutionSession(); 1332 1333 auto LookupFn = [&](std::shared_ptr<AsynchronousSymbolQuery> Q, 1334 SymbolNameSet Unresolved) { 1335 for (auto *V : VSOs) { 1336 assert(V && "VSOs entries must not be null"); 1337 if (Unresolved.empty()) 1338 break; 1339 Unresolved = V->lookup(Q, std::move(Unresolved)); 1340 } 1341 return Unresolved; 1342 }; 1343 1344 return blockingLookup(ES, std::move(LookupFn), Names, true); 1345 } 1346 1347 /// Look up a symbol by searching a list of VSOs. 1348 Expected<JITEvaluatedSymbol> lookup(const VSOList &VSOs, SymbolStringPtr Name) { 1349 SymbolNameSet Names({Name}); 1350 if (auto ResultMap = lookup(VSOs, std::move(Names))) { 1351 assert(ResultMap->size() == 1 && "Unexpected number of results"); 1352 assert(ResultMap->count(Name) && "Missing result for symbol"); 1353 return std::move(ResultMap->begin()->second); 1354 } else 1355 return ResultMap.takeError(); 1356 } 1357 1358 MangleAndInterner::MangleAndInterner(ExecutionSessionBase &ES, 1359 const DataLayout &DL) 1360 : ES(ES), DL(DL) {} 1361 1362 SymbolStringPtr MangleAndInterner::operator()(StringRef Name) { 1363 std::string MangledName; 1364 { 1365 raw_string_ostream MangledNameStream(MangledName); 1366 Mangler::getNameWithPrefix(MangledNameStream, Name, DL); 1367 } 1368 return ES.getSymbolStringPool().intern(MangledName); 1369 } 1370 1371 } // End namespace orc. 1372 } // End namespace llvm. 1373