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