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/Support/Format.h" 14 15 #if LLVM_ENABLE_THREADS 16 #include <future> 17 #endif 18 19 namespace llvm { 20 namespace orc { 21 22 char FailedToMaterialize::ID = 0; 23 char FailedToResolve::ID = 0; 24 char FailedToFinalize::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 FailedToResolve::FailedToResolve(SymbolNameSet Symbols) 91 : Symbols(std::move(Symbols)) { 92 assert(!this->Symbols.empty() && "Can not fail to resolve an empty set"); 93 } 94 95 std::error_code FailedToResolve::convertToErrorCode() const { 96 return orcError(OrcErrorCode::UnknownORCError); 97 } 98 99 void FailedToResolve::log(raw_ostream &OS) const { 100 OS << "Failed to resolve symbols: " << Symbols; 101 } 102 103 FailedToFinalize::FailedToFinalize(SymbolNameSet Symbols) 104 : Symbols(std::move(Symbols)) { 105 assert(!this->Symbols.empty() && "Can not fail to finalize an empty set"); 106 } 107 108 std::error_code FailedToFinalize::convertToErrorCode() const { 109 return orcError(OrcErrorCode::UnknownORCError); 110 } 111 112 void FailedToFinalize::log(raw_ostream &OS) const { 113 OS << "Failed to finalize symbols: " << Symbols; 114 } 115 116 AsynchronousSymbolQuery::AsynchronousSymbolQuery( 117 const SymbolNameSet &Symbols, SymbolsResolvedCallback NotifySymbolsResolved, 118 SymbolsReadyCallback NotifySymbolsReady) 119 : NotifySymbolsResolved(std::move(NotifySymbolsResolved)), 120 NotifySymbolsReady(std::move(NotifySymbolsReady)) { 121 assert(this->NotifySymbolsResolved && 122 "Symbols resolved callback must be set"); 123 assert(this->NotifySymbolsReady && "Symbols ready callback must be set"); 124 OutstandingResolutions = OutstandingFinalizations = Symbols.size(); 125 } 126 127 void AsynchronousSymbolQuery::notifyMaterializationFailed(Error Err) { 128 if (OutstandingResolutions != 0) 129 NotifySymbolsResolved(std::move(Err)); 130 else if (OutstandingFinalizations != 0) 131 NotifySymbolsReady(std::move(Err)); 132 else 133 consumeError(std::move(Err)); 134 OutstandingResolutions = OutstandingFinalizations = 0; 135 } 136 137 void AsynchronousSymbolQuery::resolve(SymbolStringPtr Name, 138 JITEvaluatedSymbol Sym) { 139 // If OutstandingResolutions is zero we must have errored out already. Just 140 // ignore this. 141 if (OutstandingResolutions == 0) 142 return; 143 144 assert(!Symbols.count(Name) && "Symbol has already been assigned an address"); 145 Symbols.insert(std::make_pair(std::move(Name), std::move(Sym))); 146 --OutstandingResolutions; 147 if (OutstandingResolutions == 0) 148 NotifySymbolsResolved(std::move(Symbols)); 149 } 150 151 void AsynchronousSymbolQuery::finalizeSymbol() { 152 // If OutstandingFinalizations is zero we must have errored out already. Just 153 // ignore this. 154 if (OutstandingFinalizations == 0) 155 return; 156 157 assert(OutstandingFinalizations > 0 && "All symbols already finalized"); 158 --OutstandingFinalizations; 159 if (OutstandingFinalizations == 0) 160 NotifySymbolsReady(Error::success()); 161 } 162 163 MaterializationResponsibility::MaterializationResponsibility( 164 VSO &V, SymbolFlagsMap SymbolFlags) 165 : V(V), SymbolFlags(std::move(SymbolFlags)) { 166 assert(!this->SymbolFlags.empty() && "Materializing nothing?"); 167 } 168 169 MaterializationResponsibility::~MaterializationResponsibility() { 170 assert(SymbolFlags.empty() && 171 "All symbols should have been explicitly materialized or failed"); 172 } 173 174 void MaterializationResponsibility::resolve(const SymbolMap &Symbols) { 175 #ifndef NDEBUG 176 for (auto &KV : Symbols) { 177 auto I = SymbolFlags.find(KV.first); 178 assert(I != SymbolFlags.end() && 179 "Resolving symbol outside this responsibility set"); 180 assert(KV.second.getFlags() == I->second && 181 "Resolving symbol with incorrect flags"); 182 } 183 #endif 184 V.resolve(Symbols); 185 } 186 187 void MaterializationResponsibility::finalize() { 188 SymbolNameSet SymbolNames; 189 for (auto &KV : SymbolFlags) 190 SymbolNames.insert(KV.first); 191 SymbolFlags.clear(); 192 V.finalize(SymbolNames); 193 } 194 195 void MaterializationResponsibility::notifyMaterializationFailed() { 196 SymbolNameSet SymbolNames; 197 for (auto &KV : SymbolFlags) 198 SymbolNames.insert(KV.first); 199 SymbolFlags.clear(); 200 V.notifyMaterializationFailed(SymbolNames); 201 } 202 203 MaterializationResponsibility 204 MaterializationResponsibility::delegate(SymbolNameSet Symbols) { 205 SymbolFlagsMap ExtractedFlags; 206 207 for (auto &S : Symbols) { 208 auto I = SymbolFlags.find(S); 209 ExtractedFlags.insert(*I); 210 SymbolFlags.erase(I); 211 } 212 213 return MaterializationResponsibility(V, std::move(ExtractedFlags)); 214 } 215 216 VSO::Materializer::Materializer(std::unique_ptr<MaterializationUnit> MU, 217 MaterializationResponsibility R) 218 : MU(std::move(MU)), R(std::move(R)) {} 219 220 void VSO::Materializer::operator()() { MU->materialize(std::move(R)); } 221 222 VSO::UnmaterializedInfo::UnmaterializedInfo( 223 std::unique_ptr<MaterializationUnit> MU) 224 : MU(std::move(MU)), Symbols(this->MU->getSymbols()) {} 225 226 void VSO::UnmaterializedInfo::discard(VSO &V, SymbolStringPtr Name) { 227 assert(MU && "No materializer attached"); 228 MU->discard(V, Name); 229 auto I = Symbols.find(Name); 230 assert(I != Symbols.end() && "Symbol not found in this MU"); 231 Symbols.erase(I); 232 } 233 234 VSO::SymbolTableEntry::SymbolTableEntry(JITSymbolFlags Flags, 235 UnmaterializedInfoIterator UMII) 236 : Flags(Flags), UMII(std::move(UMII)) { 237 // We *don't* expect isLazy to be set here. That's for the VSO to do. 238 assert(!Flags.isLazy() && "Initial flags include lazy?"); 239 assert(!Flags.isMaterializing() && "Initial flags include materializing"); 240 this->Flags |= JITSymbolFlags::Lazy; 241 } 242 243 VSO::SymbolTableEntry::SymbolTableEntry(JITSymbolFlags Flags) 244 : Flags(Flags), Address(0) { 245 // We *don't* expect isMaterializing to be set here. That's for the VSO to do. 246 assert(!Flags.isLazy() && "Initial flags include lazy?"); 247 assert(!Flags.isMaterializing() && "Initial flags include materializing"); 248 this->Flags |= JITSymbolFlags::Materializing; 249 } 250 251 VSO::SymbolTableEntry::SymbolTableEntry(JITEvaluatedSymbol Sym) 252 : Flags(Sym.getFlags()), Address(Sym.getAddress()) { 253 assert(!Flags.isLazy() && !Flags.isMaterializing() && 254 "This constructor is for final symbols only"); 255 } 256 257 VSO::SymbolTableEntry::SymbolTableEntry(SymbolTableEntry &&Other) 258 : Flags(Other.Flags), Address(0) { 259 if (this->Flags.isLazy()) 260 UMII = std::move(Other.UMII); 261 else 262 Address = Other.Address; 263 } 264 265 VSO::SymbolTableEntry &VSO::SymbolTableEntry:: 266 operator=(SymbolTableEntry &&Other) { 267 destroy(); 268 Flags = std::move(Other.Flags); 269 if (Other.Flags.isLazy()) { 270 UMII = std::move(Other.UMII); 271 } else 272 Address = Other.Address; 273 return *this; 274 } 275 276 VSO::SymbolTableEntry::~SymbolTableEntry() { destroy(); } 277 278 void VSO::SymbolTableEntry::replaceWith(VSO &V, SymbolStringPtr Name, 279 JITEvaluatedSymbol Sym) { 280 assert(!Flags.isMaterializing() && 281 "Attempting to replace definition during materialization?"); 282 if (Flags.isLazy()) { 283 UMII->discard(V, Name); 284 if (UMII->Symbols.empty()) 285 V.UnmaterializedInfos.erase(UMII); 286 } 287 destroy(); 288 Flags = Sym.getFlags(); 289 Address = Sym.getAddress(); 290 } 291 292 void VSO::SymbolTableEntry::replaceWith(VSO &V, SymbolStringPtr Name, 293 JITSymbolFlags NewFlags, 294 UnmaterializedInfoIterator NewUMII) { 295 assert(!Flags.isMaterializing() && 296 "Attempting to replace definition during materialization?"); 297 if (Flags.isLazy()) { 298 UMII->discard(V, Name); 299 if (UMII->Symbols.empty()) 300 V.UnmaterializedInfos.erase(UMII); 301 } 302 destroy(); 303 Flags = NewFlags; 304 UMII = std::move(NewUMII); 305 } 306 307 void VSO::SymbolTableEntry::replaceMaterializing(VSO &V, SymbolStringPtr Name, 308 JITSymbolFlags NewFlags) { 309 assert(!NewFlags.isWeak() && 310 "Can't define a lazy symbol in materializing mode"); 311 assert(!NewFlags.isLazy() && !NewFlags.isMaterializing() && 312 "Flags should not be in lazy or materializing state"); 313 if (Flags.isLazy()) { 314 UMII->discard(V, Name); 315 if (UMII->Symbols.empty()) 316 V.UnmaterializedInfos.erase(UMII); 317 } 318 destroy(); 319 Flags = NewFlags; 320 Flags |= JITSymbolFlags::Materializing; 321 Address = 0; 322 } 323 324 void VSO::SymbolTableEntry::notifyMaterializing() { 325 assert(Flags.isLazy() && "Can only start materializing from lazy state"); 326 UMII.~UnmaterializedInfoIterator(); 327 Flags &= ~JITSymbolFlags::Lazy; 328 Flags |= JITSymbolFlags::Materializing; 329 Address = 0; 330 } 331 332 void VSO::SymbolTableEntry::resolve(VSO &V, JITEvaluatedSymbol Sym) { 333 assert(!Flags.isLazy() && Flags.isMaterializing() && 334 "Can only resolve in materializing state"); 335 Flags = Sym.getFlags(); 336 Flags |= JITSymbolFlags::Materializing; 337 Address = Sym.getAddress(); 338 assert(Address != 0 && "Can not resolve to null"); 339 } 340 341 void VSO::SymbolTableEntry::finalize() { 342 assert(Address != 0 && "Cannot finalize with null address"); 343 assert(Flags.isMaterializing() && !Flags.isLazy() && 344 "Symbol should be in materializing state"); 345 Flags &= ~JITSymbolFlags::Materializing; 346 } 347 348 void VSO::SymbolTableEntry::destroy() { 349 if (Flags.isLazy()) 350 UMII.~UnmaterializedInfoIterator(); 351 } 352 353 VSO::RelativeLinkageStrength VSO::compareLinkage(Optional<JITSymbolFlags> Old, 354 JITSymbolFlags New) { 355 if (Old == None) 356 return llvm::orc::VSO::NewDefinitionIsStronger; 357 358 if (Old->isStrong()) { 359 if (New.isStrong()) 360 return llvm::orc::VSO::DuplicateDefinition; 361 else 362 return llvm::orc::VSO::ExistingDefinitionIsStronger; 363 } else { 364 if (New.isStrong()) 365 return llvm::orc::VSO::NewDefinitionIsStronger; 366 else 367 return llvm::orc::VSO::ExistingDefinitionIsStronger; 368 } 369 } 370 371 VSO::RelativeLinkageStrength 372 VSO::compareLinkage(SymbolStringPtr Name, JITSymbolFlags NewFlags) const { 373 auto I = Symbols.find(Name); 374 return compareLinkage( 375 I == Symbols.end() ? None : Optional<JITSymbolFlags>(I->second.Flags), 376 NewFlags); 377 } 378 379 Error VSO::define(SymbolMap NewSymbols) { 380 Error Err = Error::success(); 381 for (auto &KV : NewSymbols) { 382 auto I = Symbols.find(KV.first); 383 auto LinkageResult = compareLinkage( 384 I == Symbols.end() ? None : Optional<JITSymbolFlags>(I->second.Flags), 385 KV.second.getFlags()); 386 387 // Silently discard weaker definitions. 388 if (LinkageResult == ExistingDefinitionIsStronger) 389 continue; 390 391 // Report duplicate definition errors. 392 if (LinkageResult == DuplicateDefinition) { 393 Err = joinErrors(std::move(Err), 394 make_error<orc::DuplicateDefinition>(*KV.first)); 395 continue; 396 } 397 398 if (I != Symbols.end()) 399 I->second.replaceWith(*this, I->first, KV.second); 400 else 401 Symbols.insert(std::make_pair(KV.first, std::move(KV.second))); 402 } 403 return Err; 404 } 405 406 Error VSO::defineLazy(std::unique_ptr<MaterializationUnit> MU) { 407 auto UMII = UnmaterializedInfos.insert(UnmaterializedInfos.end(), 408 UnmaterializedInfo(std::move(MU))); 409 410 Error Err = Error::success(); 411 for (auto &KV : UMII->Symbols) { 412 auto I = Symbols.find(KV.first); 413 414 assert((I == Symbols.end() || 415 !I->second.Flags.isMaterializing()) && 416 "Attempt to replace materializing symbol definition"); 417 418 auto LinkageResult = compareLinkage( 419 I == Symbols.end() ? None : Optional<JITSymbolFlags>(I->second.Flags), 420 KV.second); 421 422 // Discard weaker definitions. 423 if (LinkageResult == ExistingDefinitionIsStronger) { 424 UMII->discard(*this, KV.first); 425 continue; 426 } 427 428 // Report duplicate definition errors. 429 if (LinkageResult == DuplicateDefinition) { 430 Err = joinErrors(std::move(Err), 431 make_error<orc::DuplicateDefinition>(*KV.first)); 432 // Duplicate definitions are discarded, so remove the duplicates from 433 // materializer. 434 UMII->discard(*this, KV.first); 435 continue; 436 } 437 438 // Existing definition was weaker. Replace it. 439 if (I != Symbols.end()) 440 I->second.replaceWith(*this, KV.first, KV.second, UMII); 441 else 442 Symbols.insert( 443 std::make_pair(KV.first, SymbolTableEntry(KV.second, UMII))); 444 } 445 446 if (UMII->Symbols.empty()) 447 UnmaterializedInfos.erase(UMII); 448 449 return Err; 450 } 451 452 SymbolNameSet VSO::lookupFlags(SymbolFlagsMap &Flags, SymbolNameSet Names) { 453 454 for (SymbolNameSet::iterator I = Names.begin(), E = Names.end(); I != E;) { 455 auto Tmp = I++; 456 auto SymI = Symbols.find(*Tmp); 457 458 // If the symbol isn't in this dylib then just continue. 459 if (SymI == Symbols.end()) 460 continue; 461 462 Names.erase(Tmp); 463 464 Flags[SymI->first] = 465 JITSymbolFlags::stripTransientFlags(SymI->second.Flags); 466 } 467 468 return Names; 469 } 470 471 VSO::LookupResult VSO::lookup(std::shared_ptr<AsynchronousSymbolQuery> Query, 472 SymbolNameSet Names) { 473 MaterializerList Materializers; 474 475 for (SymbolNameSet::iterator I = Names.begin(), E = Names.end(); I != E;) { 476 auto Tmp = I++; 477 auto SymI = Symbols.find(*Tmp); 478 479 // If the symbol isn't in this dylib then just continue. 480 if (SymI == Symbols.end()) 481 continue; 482 483 // The symbol is in the VSO. Erase it from Names and proceed. 484 Names.erase(Tmp); 485 486 // If this symbol has not been materialized yet grab its materializer, 487 // move all of its sibling symbols to the materializing state, and 488 // delete its unmaterialized info. 489 if (SymI->second.Flags.isLazy()) { 490 assert(SymI->second.UMII->MU && 491 "Lazy symbol has no materializer attached"); 492 auto MU = std::move(SymI->second.UMII->MU); 493 auto SymbolFlags = std::move(SymI->second.UMII->Symbols); 494 UnmaterializedInfos.erase(SymI->second.UMII); 495 496 for (auto &KV : SymbolFlags) { 497 auto SiblingI = Symbols.find(KV.first); 498 MaterializingInfos.insert( 499 std::make_pair(SiblingI->first, MaterializingInfo())); 500 SiblingI->second.notifyMaterializing(); 501 } 502 503 Materializers.push_back(Materializer( 504 std::move(MU), 505 MaterializationResponsibility(*this, std::move(SymbolFlags)))); 506 } 507 508 // If this symbol already has a fully materialized value, just use it. 509 if (!SymI->second.Flags.isMaterializing()) { 510 Query->resolve(SymI->first, JITEvaluatedSymbol(SymI->second.Address, 511 SymI->second.Flags)); 512 Query->finalizeSymbol(); 513 continue; 514 } 515 516 // If this symbol is materializing, then get (or create) its 517 // MaterializingInfo struct and appaend the query. 518 auto J = MaterializingInfos.find(SymI->first); 519 assert(J != MaterializingInfos.end() && "Missing MaterializingInfo"); 520 521 if (SymI->second.Address) { 522 auto Sym = JITEvaluatedSymbol(SymI->second.Address, SymI->second.Flags); 523 Query->resolve(SymI->first, Sym); 524 assert(J->second.PendingResolution.empty() && 525 "Queries still pending resolution on resolved symbol?"); 526 J->second.PendingFinalization.push_back(Query); 527 } else { 528 assert(J->second.PendingFinalization.empty() && 529 "Queries pendiing finalization on unresolved symbol?"); 530 J->second.PendingResolution.push_back(Query); 531 } 532 } 533 534 return {std::move(Materializers), std::move(Names)}; 535 } 536 537 void VSO::resolve(const SymbolMap &SymbolValues) { 538 for (auto &KV : SymbolValues) { 539 auto I = Symbols.find(KV.first); 540 assert(I != Symbols.end() && "Resolving symbol not present in this dylib"); 541 I->second.resolve(*this, KV.second); 542 543 auto J = MaterializingInfos.find(KV.first); 544 if (J == MaterializingInfos.end()) 545 continue; 546 547 assert(J->second.PendingFinalization.empty() && 548 "Queries already pending finalization?"); 549 for (auto &Q : J->second.PendingResolution) 550 Q->resolve(KV.first, KV.second); 551 J->second.PendingFinalization = std::move(J->second.PendingResolution); 552 J->second.PendingResolution = MaterializingInfo::QueryList(); 553 } 554 } 555 556 void VSO::notifyMaterializationFailed(const SymbolNameSet &Names) { 557 assert(!Names.empty() && "Failed to materialize empty set?"); 558 559 std::map<std::shared_ptr<AsynchronousSymbolQuery>, SymbolNameSet> 560 ResolutionFailures; 561 std::map<std::shared_ptr<AsynchronousSymbolQuery>, SymbolNameSet> 562 FinalizationFailures; 563 564 for (auto &S : Names) { 565 auto I = Symbols.find(S); 566 assert(I != Symbols.end() && "Symbol not present in this VSO"); 567 568 auto J = MaterializingInfos.find(S); 569 if (J != MaterializingInfos.end()) { 570 if (J->second.PendingFinalization.empty()) { 571 for (auto &Q : J->second.PendingResolution) 572 ResolutionFailures[Q].insert(S); 573 } else { 574 for (auto &Q : J->second.PendingFinalization) 575 FinalizationFailures[Q].insert(S); 576 } 577 MaterializingInfos.erase(J); 578 } 579 Symbols.erase(I); 580 } 581 582 for (auto &KV : ResolutionFailures) 583 KV.first->notifyMaterializationFailed( 584 make_error<FailedToResolve>(std::move(KV.second))); 585 586 for (auto &KV : FinalizationFailures) 587 KV.first->notifyMaterializationFailed( 588 make_error<FailedToFinalize>(std::move(KV.second))); 589 } 590 591 void VSO::finalize(const SymbolNameSet &SymbolsToFinalize) { 592 for (auto &S : SymbolsToFinalize) { 593 auto I = Symbols.find(S); 594 assert(I != Symbols.end() && "Finalizing symbol not present in this dylib"); 595 596 auto J = MaterializingInfos.find(S); 597 if (J != MaterializingInfos.end()) { 598 assert(J->second.PendingResolution.empty() && 599 "Queries still pending resolution?"); 600 for (auto &Q : J->second.PendingFinalization) 601 Q->finalizeSymbol(); 602 MaterializingInfos.erase(J); 603 } 604 I->second.finalize(); 605 } 606 } 607 608 Expected<SymbolMap> lookup(const std::vector<VSO *> &VSOs, SymbolNameSet Names, 609 MaterializationDispatcher DispatchMaterialization) { 610 #if LLVM_ENABLE_THREADS 611 // In the threaded case we use promises to return the results. 612 std::promise<SymbolMap> PromisedResult; 613 std::mutex ErrMutex; 614 Error ResolutionError = Error::success(); 615 std::promise<void> PromisedReady; 616 Error ReadyError = Error::success(); 617 auto OnResolve = [&](Expected<SymbolMap> Result) { 618 if (Result) 619 PromisedResult.set_value(std::move(*Result)); 620 else { 621 { 622 ErrorAsOutParameter _(&ResolutionError); 623 std::lock_guard<std::mutex> Lock(ErrMutex); 624 ResolutionError = Result.takeError(); 625 } 626 PromisedResult.set_value(SymbolMap()); 627 } 628 }; 629 auto OnReady = [&](Error Err) { 630 if (Err) { 631 ErrorAsOutParameter _(&ReadyError); 632 std::lock_guard<std::mutex> Lock(ErrMutex); 633 ReadyError = std::move(Err); 634 } 635 PromisedReady.set_value(); 636 }; 637 #else 638 SymbolMap Result; 639 Error ResolutionError = Error::success(); 640 Error ReadyError = Error::success(); 641 642 auto OnResolve = [&](Expected<SymbolMap> R) { 643 ErrorAsOutParameter _(&ResolutionError); 644 if (R) 645 Result = std::move(*R); 646 else 647 ResolutionError = R.takeError(); 648 }; 649 auto OnReady = [&](Error Err) { 650 ErrorAsOutParameter _(&ReadyError); 651 if (Err) 652 ReadyError = std::move(Err); 653 }; 654 #endif 655 656 auto Query = std::make_shared<AsynchronousSymbolQuery>( 657 Names, std::move(OnResolve), std::move(OnReady)); 658 SymbolNameSet UnresolvedSymbols(std::move(Names)); 659 660 for (auto *V : VSOs) { 661 662 if (UnresolvedSymbols.empty()) 663 break; 664 665 assert(V && "VSO pointers in VSOs list should be non-null"); 666 auto LR = V->lookup(Query, UnresolvedSymbols); 667 UnresolvedSymbols = std::move(LR.UnresolvedSymbols); 668 669 for (auto &M : LR.Materializers) 670 DispatchMaterialization(std::move(M)); 671 } 672 673 #if LLVM_ENABLE_THREADS 674 auto ResultFuture = PromisedResult.get_future(); 675 auto Result = ResultFuture.get(); 676 677 { 678 std::lock_guard<std::mutex> Lock(ErrMutex); 679 if (ResolutionError) { 680 // ReadyError will never be assigned. Consume the success value. 681 cantFail(std::move(ReadyError)); 682 return std::move(ResolutionError); 683 } 684 } 685 686 auto ReadyFuture = PromisedReady.get_future(); 687 ReadyFuture.get(); 688 689 { 690 std::lock_guard<std::mutex> Lock(ErrMutex); 691 if (ReadyError) 692 return std::move(ReadyError); 693 } 694 695 return std::move(Result); 696 697 #else 698 if (ResolutionError) { 699 // ReadyError will never be assigned. Consume the success value. 700 cantFail(std::move(ReadyError)); 701 return std::move(ResolutionError); 702 } 703 704 if (ReadyError) 705 return std::move(ReadyError); 706 707 return Result; 708 #endif 709 } 710 711 /// Look up a symbol by searching a list of VSOs. 712 Expected<JITEvaluatedSymbol> 713 lookup(const std::vector<VSO *> VSOs, SymbolStringPtr Name, 714 MaterializationDispatcher DispatchMaterialization) { 715 SymbolNameSet Names({Name}); 716 if (auto ResultMap = 717 lookup(VSOs, std::move(Names), std::move(DispatchMaterialization))) { 718 assert(ResultMap->size() == 1 && "Unexpected number of results"); 719 assert(ResultMap->count(Name) && "Missing result for symbol"); 720 return ResultMap->begin()->second; 721 } else 722 return ResultMap.takeError(); 723 } 724 725 void ExecutionSession::logErrorsToStdErr(Error Err) { 726 logAllUnhandledErrors(std::move(Err), errs(), "JIT session error: "); 727 } 728 729 } // End namespace orc. 730 } // End namespace llvm. 731