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