1 //===----- Core.cpp - Core ORC APIs (MaterializationUnit, VSO, etc.) ------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
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/Debug.h"
15 #include "llvm/Support/Format.h"
17 #if LLVM_ENABLE_THREADS
24 char FailedToMaterialize::ID = 0;
25 char SymbolsNotFound::ID = 0;
27 RegisterDependenciesFunction NoDependenciesToRegister =
28 RegisterDependenciesFunction();
30 void MaterializationUnit::anchor() {}
32 raw_ostream &operator<<(raw_ostream &OS, const JITSymbolFlags &Flags) {
35 else if (Flags.isCommon())
40 if (Flags.isExported())
48 raw_ostream &operator<<(raw_ostream &OS, const JITEvaluatedSymbol &Sym) {
49 OS << format("0x%016x", Sym.getAddress()) << " " << Sym.getFlags();
53 raw_ostream &operator<<(raw_ostream &OS, const SymbolMap::value_type &KV) {
54 OS << "\"" << *KV.first << "\": " << KV.second;
58 raw_ostream &operator<<(raw_ostream &OS, const SymbolNameSet &Symbols) {
60 if (!Symbols.empty()) {
61 OS << " \"" << **Symbols.begin() << "\"";
62 for (auto &Sym : make_range(std::next(Symbols.begin()), Symbols.end()))
63 OS << ", \"" << *Sym << "\"";
69 raw_ostream &operator<<(raw_ostream &OS, const SymbolMap &Symbols) {
71 if (!Symbols.empty()) {
72 OS << " {" << *Symbols.begin() << "}";
73 for (auto &Sym : make_range(std::next(Symbols.begin()), Symbols.end()))
74 OS << ", {" << Sym << "}";
80 raw_ostream &operator<<(raw_ostream &OS, const SymbolFlagsMap &SymbolFlags) {
82 if (!SymbolFlags.empty()) {
83 OS << " {\"" << *SymbolFlags.begin()->first
84 << "\": " << SymbolFlags.begin()->second << "}";
86 make_range(std::next(SymbolFlags.begin()), SymbolFlags.end()))
87 OS << ", {\"" << *KV.first << "\": " << KV.second << "}";
93 raw_ostream &operator<<(raw_ostream &OS, const SymbolDependenceMap &Deps) {
96 OS << " { " << Deps.begin()->first->getName() << ": "
97 << Deps.begin()->second << " }";
98 for (auto &KV : make_range(std::next(Deps.begin()), Deps.end()))
99 OS << ", { " << KV.first->getName() << ": " << KV.second << " }";
105 raw_ostream &operator<<(raw_ostream &OS, const VSOList &VSOs) {
108 assert(VSOs.front() && "VSOList entries must not be null");
109 OS << " " << VSOs.front()->getName();
110 for (auto *V : make_range(std::next(VSOs.begin()), VSOs.end())) {
111 assert(V && "VSOList entries must not be null");
112 OS << ", " << V->getName();
119 FailedToMaterialize::FailedToMaterialize(SymbolNameSet Symbols)
120 : Symbols(std::move(Symbols)) {
121 assert(!this->Symbols.empty() && "Can not fail to resolve an empty set");
124 std::error_code FailedToMaterialize::convertToErrorCode() const {
125 return orcError(OrcErrorCode::UnknownORCError);
128 void FailedToMaterialize::log(raw_ostream &OS) const {
129 OS << "Failed to materialize symbols: " << Symbols;
132 SymbolsNotFound::SymbolsNotFound(SymbolNameSet Symbols)
133 : Symbols(std::move(Symbols)) {
134 assert(!this->Symbols.empty() && "Can not fail to resolve an empty set");
137 std::error_code SymbolsNotFound::convertToErrorCode() const {
138 return orcError(OrcErrorCode::UnknownORCError);
141 void SymbolsNotFound::log(raw_ostream &OS) const {
142 OS << "Symbols not found: " << Symbols;
145 void ExecutionSessionBase::legacyFailQuery(AsynchronousSymbolQuery &Q,
147 assert(!!Err && "Error should be in failure state");
149 bool SendErrorToQuery;
150 runSessionLocked([&]() {
152 SendErrorToQuery = Q.canStillFail();
155 if (SendErrorToQuery)
156 Q.handleFailed(std::move(Err));
158 reportError(std::move(Err));
161 Expected<SymbolMap> ExecutionSessionBase::legacyLookup(
162 ExecutionSessionBase &ES, LegacyAsyncLookupFunction AsyncLookup,
163 SymbolNameSet Names, bool WaitUntilReady,
164 RegisterDependenciesFunction RegisterDependencies) {
165 #if LLVM_ENABLE_THREADS
166 // In the threaded case we use promises to return the results.
167 std::promise<SymbolMap> PromisedResult;
169 Error ResolutionError = Error::success();
170 std::promise<void> PromisedReady;
171 Error ReadyError = Error::success();
172 auto OnResolve = [&](Expected<SymbolMap> R) {
174 PromisedResult.set_value(std::move(*R));
177 ErrorAsOutParameter _(&ResolutionError);
178 std::lock_guard<std::mutex> Lock(ErrMutex);
179 ResolutionError = R.takeError();
181 PromisedResult.set_value(SymbolMap());
185 std::function<void(Error)> OnReady;
186 if (WaitUntilReady) {
187 OnReady = [&](Error Err) {
189 ErrorAsOutParameter _(&ReadyError);
190 std::lock_guard<std::mutex> Lock(ErrMutex);
191 ReadyError = std::move(Err);
193 PromisedReady.set_value();
196 OnReady = [&](Error Err) {
198 ES.reportError(std::move(Err));
204 Error ResolutionError = Error::success();
205 Error ReadyError = Error::success();
207 auto OnResolve = [&](Expected<SymbolMap> R) {
208 ErrorAsOutParameter _(&ResolutionError);
210 Result = std::move(*R);
212 ResolutionError = R.takeError();
215 std::function<void(Error)> OnReady;
216 if (WaitUntilReady) {
217 OnReady = [&](Error Err) {
218 ErrorAsOutParameter _(&ReadyError);
220 ReadyError = std::move(Err);
223 OnReady = [&](Error Err) {
225 ES.reportError(std::move(Err));
230 auto Query = std::make_shared<AsynchronousSymbolQuery>(
231 Names, std::move(OnResolve), std::move(OnReady));
232 // FIXME: This should be run session locked along with the registration code
233 // and error reporting below.
234 SymbolNameSet UnresolvedSymbols = AsyncLookup(Query, std::move(Names));
236 // If the query was lodged successfully then register the dependencies,
237 // otherwise fail it with an error.
238 if (UnresolvedSymbols.empty())
239 RegisterDependencies(Query->QueryRegistrations);
241 bool DeliverError = runSessionLocked([&]() {
243 return Query->canStillFail();
245 auto Err = make_error<SymbolsNotFound>(std::move(UnresolvedSymbols));
247 Query->handleFailed(std::move(Err));
249 ES.reportError(std::move(Err));
252 #if LLVM_ENABLE_THREADS
253 auto ResultFuture = PromisedResult.get_future();
254 auto Result = ResultFuture.get();
257 std::lock_guard<std::mutex> Lock(ErrMutex);
258 if (ResolutionError) {
259 // ReadyError will never be assigned. Consume the success value.
260 cantFail(std::move(ReadyError));
261 return std::move(ResolutionError);
265 if (WaitUntilReady) {
266 auto ReadyFuture = PromisedReady.get_future();
270 std::lock_guard<std::mutex> Lock(ErrMutex);
272 return std::move(ReadyError);
275 cantFail(std::move(ReadyError));
277 return std::move(Result);
280 if (ResolutionError) {
281 // ReadyError will never be assigned. Consume the success value.
282 cantFail(std::move(ReadyError));
283 return std::move(ResolutionError);
287 return std::move(ReadyError);
293 void ExecutionSessionBase::lookup(
294 const VSOList &VSOs, const SymbolNameSet &Symbols,
295 SymbolsResolvedCallback OnResolve, SymbolsReadyCallback OnReady,
296 RegisterDependenciesFunction RegisterDependencies) {
298 // lookup can be re-entered recursively if running on a single thread. Run any
299 // outstanding MUs in case this query depends on them, otherwise the main
300 // thread will starve waiting for a result from an MU that it failed to run.
303 auto Unresolved = std::move(Symbols);
304 std::map<VSO *, MaterializationUnitList> MUsMap;
305 auto Q = std::make_shared<AsynchronousSymbolQuery>(
306 Symbols, std::move(OnResolve), std::move(OnReady));
307 bool QueryIsFullyResolved = false;
308 bool QueryIsFullyReady = false;
309 bool QueryFailed = false;
311 runSessionLocked([&]() {
312 for (auto *V : VSOs) {
313 assert(V && "VSOList entries must not be null");
314 assert(!MUsMap.count(V) &&
315 "VSOList should not contain duplicate entries");
316 V->lodgeQuery(Q, Unresolved, MUsMap[V]);
319 if (Unresolved.empty()) {
320 // Query lodged successfully.
322 // Record whether this query is fully ready / resolved. We will use
323 // this to call handleFullyResolved/handleFullyReady outside the session
325 QueryIsFullyResolved = Q->isFullyResolved();
326 QueryIsFullyReady = Q->isFullyReady();
328 // Call the register dependencies function.
329 if (RegisterDependencies && !Q->QueryRegistrations.empty())
330 RegisterDependencies(Q->QueryRegistrations);
332 // Query failed due to unresolved symbols.
335 // Disconnect the query from its dependencies.
339 for (auto &KV : MUsMap)
340 for (auto &MU : KV.second)
341 KV.first->replace(std::move(MU));
346 Q->handleFailed(make_error<SymbolsNotFound>(std::move(Unresolved)));
349 if (QueryIsFullyResolved)
350 Q->handleFullyResolved();
351 if (QueryIsFullyReady)
352 Q->handleFullyReady();
355 // Move the MUs to the OutstandingMUs list, then materialize.
357 std::lock_guard<std::recursive_mutex> Lock(OutstandingMUsMutex);
359 for (auto &KV : MUsMap)
360 for (auto &MU : KV.second)
361 OutstandingMUs.push_back(std::make_pair(KV.first, std::move(MU)));
368 ExecutionSessionBase::lookup(const VSOList &VSOs, const SymbolNameSet &Symbols,
369 RegisterDependenciesFunction RegisterDependencies,
370 bool WaitUntilReady) {
371 #if LLVM_ENABLE_THREADS
372 // In the threaded case we use promises to return the results.
373 std::promise<SymbolMap> PromisedResult;
375 Error ResolutionError = Error::success();
376 std::promise<void> PromisedReady;
377 Error ReadyError = Error::success();
378 auto OnResolve = [&](Expected<SymbolMap> R) {
380 PromisedResult.set_value(std::move(*R));
383 ErrorAsOutParameter _(&ResolutionError);
384 std::lock_guard<std::mutex> Lock(ErrMutex);
385 ResolutionError = R.takeError();
387 PromisedResult.set_value(SymbolMap());
391 std::function<void(Error)> OnReady;
392 if (WaitUntilReady) {
393 OnReady = [&](Error Err) {
395 ErrorAsOutParameter _(&ReadyError);
396 std::lock_guard<std::mutex> Lock(ErrMutex);
397 ReadyError = std::move(Err);
399 PromisedReady.set_value();
402 OnReady = [&](Error Err) {
404 reportError(std::move(Err));
410 Error ResolutionError = Error::success();
411 Error ReadyError = Error::success();
413 auto OnResolve = [&](Expected<SymbolMap> R) {
414 ErrorAsOutParameter _(&ResolutionError);
416 Result = std::move(*R);
418 ResolutionError = R.takeError();
421 std::function<void(Error)> OnReady;
422 if (WaitUntilReady) {
423 OnReady = [&](Error Err) {
424 ErrorAsOutParameter _(&ReadyError);
426 ReadyError = std::move(Err);
429 OnReady = [&](Error Err) {
431 reportError(std::move(Err));
436 // Perform the asynchronous lookup.
437 lookup(VSOs, Symbols, OnResolve, OnReady, RegisterDependencies);
439 #if LLVM_ENABLE_THREADS
440 auto ResultFuture = PromisedResult.get_future();
441 auto Result = ResultFuture.get();
444 std::lock_guard<std::mutex> Lock(ErrMutex);
445 if (ResolutionError) {
446 // ReadyError will never be assigned. Consume the success value.
447 cantFail(std::move(ReadyError));
448 return std::move(ResolutionError);
452 if (WaitUntilReady) {
453 auto ReadyFuture = PromisedReady.get_future();
457 std::lock_guard<std::mutex> Lock(ErrMutex);
459 return std::move(ReadyError);
462 cantFail(std::move(ReadyError));
464 return std::move(Result);
467 if (ResolutionError) {
468 // ReadyError will never be assigned. Consume the success value.
469 cantFail(std::move(ReadyError));
470 return std::move(ResolutionError);
474 return std::move(ReadyError);
480 void ExecutionSessionBase::runOutstandingMUs() {
482 std::pair<VSO *, std::unique_ptr<MaterializationUnit>> VSOAndMU;
485 std::lock_guard<std::recursive_mutex> Lock(OutstandingMUsMutex);
486 if (!OutstandingMUs.empty()) {
487 VSOAndMU = std::move(OutstandingMUs.back());
488 OutstandingMUs.pop_back();
492 if (VSOAndMU.first) {
493 assert(VSOAndMU.second && "VSO, but no MU?");
494 dispatchMaterialization(*VSOAndMU.first, std::move(VSOAndMU.second));
500 AsynchronousSymbolQuery::AsynchronousSymbolQuery(
501 const SymbolNameSet &Symbols, SymbolsResolvedCallback NotifySymbolsResolved,
502 SymbolsReadyCallback NotifySymbolsReady)
503 : NotifySymbolsResolved(std::move(NotifySymbolsResolved)),
504 NotifySymbolsReady(std::move(NotifySymbolsReady)) {
505 NotYetResolvedCount = NotYetReadyCount = Symbols.size();
507 for (auto &S : Symbols)
508 ResolvedSymbols[S] = nullptr;
511 void AsynchronousSymbolQuery::resolve(const SymbolStringPtr &Name,
512 JITEvaluatedSymbol Sym) {
513 auto I = ResolvedSymbols.find(Name);
514 assert(I != ResolvedSymbols.end() &&
515 "Resolving symbol outside the requested set");
516 assert(I->second.getAddress() == 0 && "Redundantly resolving symbol Name");
517 I->second = std::move(Sym);
518 --NotYetResolvedCount;
521 void AsynchronousSymbolQuery::handleFullyResolved() {
522 assert(NotYetResolvedCount == 0 && "Not fully resolved?");
523 assert(NotifySymbolsResolved &&
524 "NotifySymbolsResolved already called or error occurred");
525 NotifySymbolsResolved(std::move(ResolvedSymbols));
526 NotifySymbolsResolved = SymbolsResolvedCallback();
529 void AsynchronousSymbolQuery::notifySymbolReady() {
530 assert(NotYetReadyCount != 0 && "All symbols already finalized");
534 void AsynchronousSymbolQuery::handleFullyReady() {
535 assert(QueryRegistrations.empty() &&
536 "Query is still registered with some symbols");
537 assert(!NotifySymbolsResolved && "Resolution not applied yet");
538 NotifySymbolsReady(Error::success());
539 NotifySymbolsReady = SymbolsReadyCallback();
542 bool AsynchronousSymbolQuery::canStillFail() {
543 return (NotifySymbolsResolved || NotifySymbolsReady);
546 void AsynchronousSymbolQuery::handleFailed(Error Err) {
547 assert(QueryRegistrations.empty() && ResolvedSymbols.empty() &&
548 NotYetResolvedCount == 0 && NotYetReadyCount == 0 &&
549 "Query should already have been abandoned");
550 if (NotifySymbolsResolved) {
551 NotifySymbolsResolved(std::move(Err));
552 NotifySymbolsResolved = SymbolsResolvedCallback();
554 assert(NotifySymbolsReady && "Failed after both callbacks issued?");
555 NotifySymbolsReady(std::move(Err));
557 NotifySymbolsReady = SymbolsReadyCallback();
560 void AsynchronousSymbolQuery::addQueryDependence(VSO &V, SymbolStringPtr Name) {
561 bool Added = QueryRegistrations[&V].insert(std::move(Name)).second;
563 assert(Added && "Duplicate dependence notification?");
566 void AsynchronousSymbolQuery::removeQueryDependence(
567 VSO &V, const SymbolStringPtr &Name) {
568 auto QRI = QueryRegistrations.find(&V);
569 assert(QRI != QueryRegistrations.end() && "No dependencies registered for V");
570 assert(QRI->second.count(Name) && "No dependency on Name in V");
571 QRI->second.erase(Name);
572 if (QRI->second.empty())
573 QueryRegistrations.erase(QRI);
576 void AsynchronousSymbolQuery::detach() {
577 ResolvedSymbols.clear();
578 NotYetResolvedCount = 0;
579 NotYetReadyCount = 0;
580 for (auto &KV : QueryRegistrations)
581 KV.first->detachQueryHelper(*this, KV.second);
582 QueryRegistrations.clear();
585 MaterializationResponsibility::MaterializationResponsibility(
586 VSO &V, SymbolFlagsMap SymbolFlags)
587 : V(V), SymbolFlags(std::move(SymbolFlags)) {
588 assert(!this->SymbolFlags.empty() && "Materializing nothing?");
591 for (auto &KV : this->SymbolFlags)
592 KV.second |= JITSymbolFlags::Materializing;
596 MaterializationResponsibility::~MaterializationResponsibility() {
597 assert(SymbolFlags.empty() &&
598 "All symbols should have been explicitly materialized or failed");
601 SymbolNameSet MaterializationResponsibility::getRequestedSymbols() {
602 return V.getRequestedSymbols(SymbolFlags);
605 void MaterializationResponsibility::resolve(const SymbolMap &Symbols) {
607 for (auto &KV : Symbols) {
608 auto I = SymbolFlags.find(KV.first);
609 assert(I != SymbolFlags.end() &&
610 "Resolving symbol outside this responsibility set");
611 assert(I->second.isMaterializing() && "Duplicate resolution");
612 I->second &= ~JITSymbolFlags::Materializing;
613 if (I->second.isWeak())
614 assert(I->second == (KV.second.getFlags() | JITSymbolFlags::Weak) &&
615 "Resolving symbol with incorrect flags");
617 assert(I->second == KV.second.getFlags() &&
618 "Resolving symbol with incorrect flags");
625 void MaterializationResponsibility::finalize() {
627 for (auto &KV : SymbolFlags)
628 assert(!KV.second.isMaterializing() &&
629 "Failed to resolve symbol before finalization");
632 V.finalize(SymbolFlags);
636 Error MaterializationResponsibility::defineMaterializing(
637 const SymbolFlagsMap &NewSymbolFlags) {
638 // Add the given symbols to this responsibility object.
639 // It's ok if we hit a duplicate here: In that case the new version will be
640 // discarded, and the VSO::defineMaterializing method will return a duplicate
642 for (auto &KV : NewSymbolFlags) {
643 auto I = SymbolFlags.insert(KV).first;
646 I->second |= JITSymbolFlags::Materializing;
650 return V.defineMaterializing(NewSymbolFlags);
653 void MaterializationResponsibility::failMaterialization() {
655 SymbolNameSet FailedSymbols;
656 for (auto &KV : SymbolFlags)
657 FailedSymbols.insert(KV.first);
659 V.notifyFailed(FailedSymbols);
663 void MaterializationResponsibility::replace(
664 std::unique_ptr<MaterializationUnit> MU) {
665 for (auto &KV : MU->getSymbols())
666 SymbolFlags.erase(KV.first);
668 V.replace(std::move(MU));
671 MaterializationResponsibility
672 MaterializationResponsibility::delegate(const SymbolNameSet &Symbols) {
673 SymbolFlagsMap DelegatedFlags;
675 for (auto &Name : Symbols) {
676 auto I = SymbolFlags.find(Name);
677 assert(I != SymbolFlags.end() &&
678 "Symbol is not tracked by this MaterializationResponsibility "
681 DelegatedFlags[Name] = std::move(I->second);
682 SymbolFlags.erase(I);
685 return MaterializationResponsibility(V, std::move(DelegatedFlags));
688 void MaterializationResponsibility::addDependencies(
689 const SymbolStringPtr &Name, const SymbolDependenceMap &Dependencies) {
690 assert(SymbolFlags.count(Name) &&
691 "Symbol not covered by this MaterializationResponsibility instance");
692 V.addDependencies(Name, Dependencies);
695 void MaterializationResponsibility::addDependenciesForAll(
696 const SymbolDependenceMap &Dependencies) {
697 for (auto &KV : SymbolFlags)
698 V.addDependencies(KV.first, Dependencies);
701 AbsoluteSymbolsMaterializationUnit::AbsoluteSymbolsMaterializationUnit(
703 : MaterializationUnit(extractFlags(Symbols)), Symbols(std::move(Symbols)) {}
705 void AbsoluteSymbolsMaterializationUnit::materialize(
706 MaterializationResponsibility R) {
711 void AbsoluteSymbolsMaterializationUnit::discard(const VSO &V,
712 SymbolStringPtr Name) {
713 assert(Symbols.count(Name) && "Symbol is not part of this MU");
718 AbsoluteSymbolsMaterializationUnit::extractFlags(const SymbolMap &Symbols) {
719 SymbolFlagsMap Flags;
720 for (const auto &KV : Symbols)
721 Flags[KV.first] = KV.second.getFlags();
725 ReExportsMaterializationUnit::ReExportsMaterializationUnit(
726 VSO *SourceVSO, SymbolAliasMap Aliases)
727 : MaterializationUnit(extractFlags(Aliases)), SourceVSO(SourceVSO),
728 Aliases(std::move(Aliases)) {}
730 void ReExportsMaterializationUnit::materialize(
731 MaterializationResponsibility R) {
733 auto &ES = R.getTargetVSO().getExecutionSession();
734 VSO &TgtV = R.getTargetVSO();
735 VSO &SrcV = SourceVSO ? *SourceVSO : TgtV;
737 // Find the set of requested aliases and aliasees. Return any unrequested
738 // aliases back to the VSO so as to not prematurely materialize any aliasees.
739 auto RequestedSymbols = R.getRequestedSymbols();
740 SymbolAliasMap RequestedAliases;
742 for (auto &Name : RequestedSymbols) {
743 auto I = Aliases.find(Name);
744 assert(I != Aliases.end() && "Symbol not found in aliases map?");
745 RequestedAliases[Name] = std::move(I->second);
749 if (!Aliases.empty()) {
751 R.replace(reexports(*SourceVSO, std::move(Aliases)));
753 R.replace(symbolAliases(std::move(Aliases)));
756 // The OnResolveInfo struct will hold the aliases and responsibilty for each
757 // query in the list.
758 struct OnResolveInfo {
759 OnResolveInfo(MaterializationResponsibility R, SymbolAliasMap Aliases)
760 : R(std::move(R)), Aliases(std::move(Aliases)) {}
762 MaterializationResponsibility R;
763 SymbolAliasMap Aliases;
766 // Build a list of queries to issue. In each round we build the largest set of
767 // aliases that we can resolve without encountering a chain definition of the
768 // form Foo -> Bar, Bar -> Baz. Such a form would deadlock as the query would
769 // be waitin on a symbol that it itself had to resolve. Usually this will just
770 // involve one round and a single query.
772 std::vector<std::pair<SymbolNameSet, std::shared_ptr<OnResolveInfo>>>
774 while (!RequestedAliases.empty()) {
775 SymbolNameSet ResponsibilitySymbols;
776 SymbolNameSet QuerySymbols;
777 SymbolAliasMap QueryAliases;
779 for (auto I = RequestedAliases.begin(), E = RequestedAliases.end();
783 // Chain detected. Skip this symbol for this round.
784 if (&SrcV == &TgtV && (QueryAliases.count(Tmp->second.Aliasee) ||
785 RequestedAliases.count(Tmp->second.Aliasee)))
788 ResponsibilitySymbols.insert(Tmp->first);
789 QuerySymbols.insert(Tmp->second.Aliasee);
790 QueryAliases[Tmp->first] = std::move(Tmp->second);
791 RequestedAliases.erase(Tmp);
793 assert(!QuerySymbols.empty() && "Alias cycle detected!");
795 auto QueryInfo = std::make_shared<OnResolveInfo>(
796 R.delegate(ResponsibilitySymbols), std::move(QueryAliases));
797 QueryInfos.push_back(
798 make_pair(std::move(QuerySymbols), std::move(QueryInfo)));
801 // Issue the queries.
802 while (!QueryInfos.empty()) {
803 auto QuerySymbols = std::move(QueryInfos.back().first);
804 auto QueryInfo = std::move(QueryInfos.back().second);
806 QueryInfos.pop_back();
808 auto RegisterDependencies = [QueryInfo,
809 &SrcV](const SymbolDependenceMap &Deps) {
810 // If there were no materializing symbols, just bail out.
814 // Otherwise the only deps should be on SrcV.
815 assert(Deps.size() == 1 && Deps.count(&SrcV) &&
816 "Unexpected dependencies for reexports");
818 auto &SrcVDeps = Deps.find(&SrcV)->second;
819 SymbolDependenceMap PerAliasDepsMap;
820 auto &PerAliasDeps = PerAliasDepsMap[&SrcV];
822 for (auto &KV : QueryInfo->Aliases)
823 if (SrcVDeps.count(KV.second.Aliasee)) {
824 PerAliasDeps = {KV.second.Aliasee};
825 QueryInfo->R.addDependencies(KV.first, PerAliasDepsMap);
829 auto OnResolve = [QueryInfo](Expected<SymbolMap> Result) {
831 SymbolMap ResolutionMap;
832 for (auto &KV : QueryInfo->Aliases) {
833 assert(Result->count(KV.second.Aliasee) &&
834 "Result map missing entry?");
835 ResolutionMap[KV.first] = JITEvaluatedSymbol(
836 (*Result)[KV.second.Aliasee].getAddress(), KV.second.AliasFlags);
838 QueryInfo->R.resolve(ResolutionMap);
839 QueryInfo->R.finalize();
841 auto &ES = QueryInfo->R.getTargetVSO().getExecutionSession();
842 ES.reportError(Result.takeError());
843 QueryInfo->R.failMaterialization();
847 auto OnReady = [&ES](Error Err) { ES.reportError(std::move(Err)); };
849 ES.lookup({&SrcV}, QuerySymbols, std::move(OnResolve), std::move(OnReady),
850 std::move(RegisterDependencies));
854 void ReExportsMaterializationUnit::discard(const VSO &V, SymbolStringPtr Name) {
855 assert(Aliases.count(Name) &&
856 "Symbol not covered by this MaterializationUnit");
861 ReExportsMaterializationUnit::extractFlags(const SymbolAliasMap &Aliases) {
862 SymbolFlagsMap SymbolFlags;
863 for (auto &KV : Aliases)
864 SymbolFlags[KV.first] = KV.second.AliasFlags;
869 Expected<SymbolAliasMap>
870 buildSimpleReexportsAliasMap(VSO &SourceV, const SymbolNameSet &Symbols) {
871 auto Flags = SourceV.lookupFlags(Symbols);
873 if (Flags.size() != Symbols.size()) {
874 SymbolNameSet Unresolved = Symbols;
875 for (auto &KV : Flags)
876 Unresolved.erase(KV.first);
877 return make_error<SymbolsNotFound>(std::move(Unresolved));
880 SymbolAliasMap Result;
881 for (auto &Name : Symbols) {
882 assert(Flags.count(Name) && "Missing entry in flags map");
883 Result[Name] = SymbolAliasMapEntry(Name, Flags[Name]);
889 Error VSO::defineMaterializing(const SymbolFlagsMap &SymbolFlags) {
890 return ES.runSessionLocked([&]() -> Error {
891 std::vector<SymbolMap::iterator> AddedSyms;
893 for (auto &KV : SymbolFlags) {
894 SymbolMap::iterator EntryItr;
897 auto NewFlags = KV.second;
898 NewFlags |= JITSymbolFlags::Materializing;
900 std::tie(EntryItr, Added) = Symbols.insert(
901 std::make_pair(KV.first, JITEvaluatedSymbol(0, NewFlags)));
904 AddedSyms.push_back(EntryItr);
906 // Remove any symbols already added.
907 for (auto &SI : AddedSyms)
910 // FIXME: Return all duplicates.
911 return make_error<DuplicateDefinition>(*KV.first);
915 return Error::success();
919 void VSO::replace(std::unique_ptr<MaterializationUnit> MU) {
920 assert(MU != nullptr && "Can not replace with a null MaterializationUnit");
923 ES.runSessionLocked([&, this]() -> std::unique_ptr<MaterializationUnit> {
926 for (auto &KV : MU->getSymbols()) {
927 auto SymI = Symbols.find(KV.first);
928 assert(SymI != Symbols.end() && "Replacing unknown symbol");
929 assert(!SymI->second.getFlags().isLazy() &&
930 SymI->second.getFlags().isMaterializing() &&
931 "Can not replace symbol that is not materializing");
932 assert(UnmaterializedInfos.count(KV.first) == 0 &&
933 "Symbol being replaced should have no UnmaterializedInfo");
937 // If any symbol has pending queries against it then we need to
938 // materialize MU immediately.
939 for (auto &KV : MU->getSymbols()) {
940 auto MII = MaterializingInfos.find(KV.first);
941 if (MII != MaterializingInfos.end()) {
942 if (!MII->second.PendingQueries.empty())
943 return std::move(MU);
947 // Otherwise, make MU responsible for all the symbols.
948 auto UMI = std::make_shared<UnmaterializedInfo>(std::move(MU));
949 for (auto &KV : UMI->MU->getSymbols()) {
950 assert(!KV.second.isLazy() &&
951 "Lazy flag should be managed internally.");
952 assert(!KV.second.isMaterializing() &&
953 "Materializing flags should be managed internally.");
955 auto SymI = Symbols.find(KV.first);
956 JITSymbolFlags ReplaceFlags = KV.second;
957 ReplaceFlags |= JITSymbolFlags::Lazy;
958 SymI->second = JITEvaluatedSymbol(SymI->second.getAddress(),
959 std::move(ReplaceFlags));
960 UnmaterializedInfos[KV.first] = UMI;
967 ES.dispatchMaterialization(*this, std::move(MustRunMU));
970 SymbolNameSet VSO::getRequestedSymbols(const SymbolFlagsMap &SymbolFlags) {
971 return ES.runSessionLocked([&]() {
972 SymbolNameSet RequestedSymbols;
974 for (auto &KV : SymbolFlags) {
975 assert(Symbols.count(KV.first) && "VSO does not cover this symbol?");
976 assert(Symbols[KV.first].getFlags().isMaterializing() &&
977 "getRequestedSymbols can only be called for materializing "
979 auto I = MaterializingInfos.find(KV.first);
980 if (I == MaterializingInfos.end())
983 if (!I->second.PendingQueries.empty())
984 RequestedSymbols.insert(KV.first);
987 return RequestedSymbols;
991 void VSO::addDependencies(const SymbolStringPtr &Name,
992 const SymbolDependenceMap &Dependencies) {
993 assert(Symbols.count(Name) && "Name not in symbol table");
994 assert((Symbols[Name].getFlags().isLazy() ||
995 Symbols[Name].getFlags().isMaterializing()) &&
996 "Symbol is not lazy or materializing");
998 auto &MI = MaterializingInfos[Name];
999 assert(!MI.IsFinalized && "Can not add dependencies to finalized symbol");
1001 for (auto &KV : Dependencies) {
1002 assert(KV.first && "Null VSO in dependency?");
1003 auto &OtherVSO = *KV.first;
1004 auto &DepsOnOtherVSO = MI.UnfinalizedDependencies[&OtherVSO];
1006 for (auto &OtherSymbol : KV.second) {
1008 // Assert that this symbol exists and has not been finalized already.
1009 auto SymI = OtherVSO.Symbols.find(OtherSymbol);
1010 assert(SymI != OtherVSO.Symbols.end() &&
1011 (SymI->second.getFlags().isLazy() ||
1012 SymI->second.getFlags().isMaterializing()) &&
1013 "Dependency on finalized symbol");
1016 auto &OtherMI = OtherVSO.MaterializingInfos[OtherSymbol];
1018 if (OtherMI.IsFinalized)
1019 transferFinalizedNodeDependencies(MI, Name, OtherMI);
1020 else if (&OtherVSO != this || OtherSymbol != Name) {
1021 OtherMI.Dependants[this].insert(Name);
1022 DepsOnOtherVSO.insert(OtherSymbol);
1026 if (DepsOnOtherVSO.empty())
1027 MI.UnfinalizedDependencies.erase(&OtherVSO);
1031 void VSO::resolve(const SymbolMap &Resolved) {
1032 auto FullyResolvedQueries = ES.runSessionLocked([&, this]() {
1033 AsynchronousSymbolQuerySet FullyResolvedQueries;
1034 for (const auto &KV : Resolved) {
1035 auto &Name = KV.first;
1036 auto Sym = KV.second;
1038 assert(!Sym.getFlags().isLazy() && !Sym.getFlags().isMaterializing() &&
1039 "Materializing flags should be managed internally");
1041 auto I = Symbols.find(Name);
1043 assert(I != Symbols.end() && "Symbol not found");
1044 assert(!I->second.getFlags().isLazy() &&
1045 I->second.getFlags().isMaterializing() &&
1046 "Symbol should be materializing");
1047 assert(I->second.getAddress() == 0 && "Symbol has already been resolved");
1049 assert((Sym.getFlags() & ~JITSymbolFlags::Weak) ==
1050 (JITSymbolFlags::stripTransientFlags(I->second.getFlags()) &
1051 ~JITSymbolFlags::Weak) &&
1052 "Resolved flags should match the declared flags");
1054 // Once resolved, symbols can never be weak.
1055 JITSymbolFlags ResolvedFlags = Sym.getFlags();
1056 ResolvedFlags &= ~JITSymbolFlags::Weak;
1057 ResolvedFlags |= JITSymbolFlags::Materializing;
1058 I->second = JITEvaluatedSymbol(Sym.getAddress(), ResolvedFlags);
1060 auto &MI = MaterializingInfos[Name];
1061 for (auto &Q : MI.PendingQueries) {
1062 Q->resolve(Name, Sym);
1063 if (Q->isFullyResolved())
1064 FullyResolvedQueries.insert(Q);
1068 return FullyResolvedQueries;
1071 for (auto &Q : FullyResolvedQueries) {
1072 assert(Q->isFullyResolved() && "Q not fully resolved");
1073 Q->handleFullyResolved();
1077 void VSO::finalize(const SymbolFlagsMap &Finalized) {
1078 auto FullyReadyQueries = ES.runSessionLocked([&, this]() {
1079 AsynchronousSymbolQuerySet ReadyQueries;
1081 for (const auto &KV : Finalized) {
1082 const auto &Name = KV.first;
1084 auto MII = MaterializingInfos.find(Name);
1085 assert(MII != MaterializingInfos.end() &&
1086 "Missing MaterializingInfo entry");
1088 auto &MI = MII->second;
1090 // For each dependant, transfer this node's unfinalized dependencies to
1091 // it. If the dependant node is fully finalized then notify any pending
1093 for (auto &KV : MI.Dependants) {
1094 auto &DependantVSO = *KV.first;
1095 for (auto &DependantName : KV.second) {
1097 DependantVSO.MaterializingInfos.find(DependantName);
1098 assert(DependantMII != DependantVSO.MaterializingInfos.end() &&
1099 "Dependant should have MaterializingInfo");
1101 auto &DependantMI = DependantMII->second;
1103 // Remove the dependant's dependency on this node.
1104 assert(DependantMI.UnfinalizedDependencies[this].count(Name) &&
1105 "Dependant does not count this symbol as a dependency?");
1106 DependantMI.UnfinalizedDependencies[this].erase(Name);
1107 if (DependantMI.UnfinalizedDependencies[this].empty())
1108 DependantMI.UnfinalizedDependencies.erase(this);
1110 // Transfer unfinalized dependencies from this node to the dependant.
1111 DependantVSO.transferFinalizedNodeDependencies(DependantMI,
1114 // If the dependant is finalized and this node was the last of its
1115 // unfinalized dependencies then notify any pending queries on the
1117 if (DependantMI.IsFinalized &&
1118 DependantMI.UnfinalizedDependencies.empty()) {
1119 assert(DependantMI.Dependants.empty() &&
1120 "Dependants should be empty by now");
1121 for (auto &Q : DependantMI.PendingQueries) {
1122 Q->notifySymbolReady();
1123 if (Q->isFullyReady())
1124 ReadyQueries.insert(Q);
1125 Q->removeQueryDependence(DependantVSO, DependantName);
1128 // If this dependant node was fully finalized we can erase its
1129 // MaterializingInfo and update its materializing state.
1130 assert(DependantVSO.Symbols.count(DependantName) &&
1131 "Dependant has no entry in the Symbols table");
1132 auto &DependantSym = DependantVSO.Symbols[DependantName];
1133 DependantSym.setFlags(static_cast<JITSymbolFlags::FlagNames>(
1134 DependantSym.getFlags() & ~JITSymbolFlags::Materializing));
1135 DependantVSO.MaterializingInfos.erase(DependantMII);
1139 MI.Dependants.clear();
1140 MI.IsFinalized = true;
1142 if (MI.UnfinalizedDependencies.empty()) {
1143 for (auto &Q : MI.PendingQueries) {
1144 Q->notifySymbolReady();
1145 if (Q->isFullyReady())
1146 ReadyQueries.insert(Q);
1147 Q->removeQueryDependence(*this, Name);
1149 assert(Symbols.count(Name) &&
1150 "Symbol has no entry in the Symbols table");
1151 auto &Sym = Symbols[Name];
1152 Sym.setFlags(static_cast<JITSymbolFlags::FlagNames>(
1153 Sym.getFlags() & ~JITSymbolFlags::Materializing));
1154 MaterializingInfos.erase(MII);
1158 return ReadyQueries;
1161 for (auto &Q : FullyReadyQueries) {
1162 assert(Q->isFullyReady() && "Q is not fully ready");
1163 Q->handleFullyReady();
1167 void VSO::notifyFailed(const SymbolNameSet &FailedSymbols) {
1169 // FIXME: This should fail any transitively dependant symbols too.
1171 auto FailedQueriesToNotify = ES.runSessionLocked([&, this]() {
1172 AsynchronousSymbolQuerySet FailedQueries;
1174 for (auto &Name : FailedSymbols) {
1175 auto I = Symbols.find(Name);
1176 assert(I != Symbols.end() && "Symbol not present in this VSO");
1179 auto MII = MaterializingInfos.find(Name);
1181 // If we have not created a MaterializingInfo for this symbol yet then
1182 // there is nobody to notify.
1183 if (MII == MaterializingInfos.end())
1186 // Copy all the queries to the FailedQueries list, then abandon them.
1187 // This has to be a copy, and the copy has to come before the abandon
1188 // operation: Each Q.detach() call will reach back into this
1189 // PendingQueries list to remove Q.
1190 for (auto &Q : MII->second.PendingQueries)
1191 FailedQueries.insert(Q);
1193 for (auto &Q : FailedQueries)
1196 assert(MII->second.PendingQueries.empty() &&
1197 "Queries remain after symbol was failed");
1199 MaterializingInfos.erase(MII);
1202 return FailedQueries;
1205 for (auto &Q : FailedQueriesToNotify)
1206 Q->handleFailed(make_error<FailedToMaterialize>(FailedSymbols));
1209 void VSO::setSearchOrder(VSOList NewSearchOrder, bool SearchThisVSOFirst) {
1210 if (SearchThisVSOFirst && NewSearchOrder.front() != this)
1211 NewSearchOrder.insert(NewSearchOrder.begin(), this);
1213 ES.runSessionLocked([&]() { SearchOrder = std::move(NewSearchOrder); });
1216 void VSO::addToSearchOrder(VSO &V) {
1217 ES.runSessionLocked([&]() { SearchOrder.push_back(&V); });
1220 void VSO::replaceInSearchOrder(VSO &OldV, VSO &NewV) {
1221 ES.runSessionLocked([&]() {
1222 auto I = std::find(SearchOrder.begin(), SearchOrder.end(), &OldV);
1224 if (I != SearchOrder.end())
1229 void VSO::removeFromSearchOrder(VSO &V) {
1230 ES.runSessionLocked([&]() {
1231 auto I = std::find(SearchOrder.begin(), SearchOrder.end(), &V);
1232 if (I != SearchOrder.end())
1233 SearchOrder.erase(I);
1237 SymbolFlagsMap VSO::lookupFlags(const SymbolNameSet &Names) {
1238 return ES.runSessionLocked([&, this]() {
1239 SymbolFlagsMap Result;
1240 auto Unresolved = lookupFlagsImpl(Result, Names);
1241 if (FallbackDefinitionGenerator && !Unresolved.empty()) {
1242 auto FallbackDefs = FallbackDefinitionGenerator(*this, Unresolved);
1243 if (!FallbackDefs.empty()) {
1244 auto Unresolved2 = lookupFlagsImpl(Result, FallbackDefs);
1246 assert(Unresolved2.empty() &&
1247 "All fallback defs should have been found by lookupFlagsImpl");
1254 SymbolNameSet VSO::lookupFlagsImpl(SymbolFlagsMap &Flags,
1255 const SymbolNameSet &Names) {
1256 SymbolNameSet Unresolved;
1258 for (auto &Name : Names) {
1259 auto I = Symbols.find(Name);
1261 if (I == Symbols.end()) {
1262 Unresolved.insert(Name);
1266 assert(!Flags.count(Name) && "Symbol already present in Flags map");
1267 Flags[Name] = JITSymbolFlags::stripTransientFlags(I->second.getFlags());
1273 void VSO::lodgeQuery(std::shared_ptr<AsynchronousSymbolQuery> &Q,
1274 SymbolNameSet &Unresolved, MaterializationUnitList &MUs) {
1275 assert(Q && "Query can not be null");
1277 lodgeQueryImpl(Q, Unresolved, MUs);
1278 if (FallbackDefinitionGenerator && !Unresolved.empty()) {
1279 auto FallbackDefs = FallbackDefinitionGenerator(*this, Unresolved);
1280 if (!FallbackDefs.empty()) {
1281 for (auto &D : FallbackDefs)
1282 Unresolved.erase(D);
1283 lodgeQueryImpl(Q, FallbackDefs, MUs);
1284 assert(FallbackDefs.empty() &&
1285 "All fallback defs should have been found by lookupImpl");
1290 void VSO::lodgeQueryImpl(
1291 std::shared_ptr<AsynchronousSymbolQuery> &Q, SymbolNameSet &Unresolved,
1292 std::vector<std::unique_ptr<MaterializationUnit>> &MUs) {
1293 for (auto I = Unresolved.begin(), E = Unresolved.end(); I != E;) {
1297 // Search for the name in Symbols. Skip it if not found.
1298 auto SymI = Symbols.find(Name);
1299 if (SymI == Symbols.end())
1302 // If we found Name in V, remove it frome the Unresolved set and add it
1303 // to the added set.
1304 Unresolved.erase(TmpI);
1306 // If the symbol has an address then resolve it.
1307 if (SymI->second.getAddress() != 0)
1308 Q->resolve(Name, SymI->second);
1310 // If the symbol is lazy, get the MaterialiaztionUnit for it.
1311 if (SymI->second.getFlags().isLazy()) {
1312 assert(SymI->second.getAddress() == 0 &&
1313 "Lazy symbol should not have a resolved address");
1314 assert(!SymI->second.getFlags().isMaterializing() &&
1315 "Materializing and lazy should not both be set");
1316 auto UMII = UnmaterializedInfos.find(Name);
1317 assert(UMII != UnmaterializedInfos.end() &&
1318 "Lazy symbol should have UnmaterializedInfo");
1319 auto MU = std::move(UMII->second->MU);
1320 assert(MU != nullptr && "Materializer should not be null");
1322 // Move all symbols associated with this MaterializationUnit into
1323 // materializing state.
1324 for (auto &KV : MU->getSymbols()) {
1325 auto SymK = Symbols.find(KV.first);
1326 auto Flags = SymK->second.getFlags();
1327 Flags &= ~JITSymbolFlags::Lazy;
1328 Flags |= JITSymbolFlags::Materializing;
1329 SymK->second.setFlags(Flags);
1330 UnmaterializedInfos.erase(KV.first);
1333 // Add MU to the list of MaterializationUnits to be materialized.
1334 MUs.push_back(std::move(MU));
1335 } else if (!SymI->second.getFlags().isMaterializing()) {
1336 // The symbol is neither lazy nor materializing. Finalize it and
1338 Q->notifySymbolReady();
1342 // Add the query to the PendingQueries list.
1343 assert(SymI->second.getFlags().isMaterializing() &&
1344 "By this line the symbol should be materializing");
1345 auto &MI = MaterializingInfos[Name];
1346 MI.PendingQueries.push_back(Q);
1347 Q->addQueryDependence(*this, Name);
1351 SymbolNameSet VSO::legacyLookup(std::shared_ptr<AsynchronousSymbolQuery> Q,
1352 SymbolNameSet Names) {
1353 assert(Q && "Query can not be null");
1355 ES.runOutstandingMUs();
1357 LookupImplActionFlags ActionFlags = None;
1358 std::vector<std::unique_ptr<MaterializationUnit>> MUs;
1360 SymbolNameSet Unresolved = std::move(Names);
1361 ES.runSessionLocked([&, this]() {
1362 ActionFlags = lookupImpl(Q, MUs, Unresolved);
1363 if (FallbackDefinitionGenerator && !Unresolved.empty()) {
1364 assert(ActionFlags == None &&
1365 "ActionFlags set but unresolved symbols remain?");
1366 auto FallbackDefs = FallbackDefinitionGenerator(*this, Unresolved);
1367 if (!FallbackDefs.empty()) {
1368 for (auto &D : FallbackDefs)
1369 Unresolved.erase(D);
1370 ActionFlags = lookupImpl(Q, MUs, FallbackDefs);
1371 assert(FallbackDefs.empty() &&
1372 "All fallback defs should have been found by lookupImpl");
1377 assert((MUs.empty() || ActionFlags == None) &&
1378 "If action flags are set, there should be no work to do (so no MUs)");
1380 if (ActionFlags & NotifyFullyResolved)
1381 Q->handleFullyResolved();
1383 if (ActionFlags & NotifyFullyReady)
1384 Q->handleFullyReady();
1386 // FIXME: Swap back to the old code below once RuntimeDyld works with
1387 // callbacks from asynchronous queries.
1388 // Add MUs to the OutstandingMUs list.
1390 std::lock_guard<std::recursive_mutex> Lock(ES.OutstandingMUsMutex);
1391 for (auto &MU : MUs)
1392 ES.OutstandingMUs.push_back(make_pair(this, std::move(MU)));
1394 ES.runOutstandingMUs();
1396 // Dispatch any required MaterializationUnits for materialization.
1397 // for (auto &MU : MUs)
1398 // ES.dispatchMaterialization(*this, std::move(MU));
1403 VSO::LookupImplActionFlags
1404 VSO::lookupImpl(std::shared_ptr<AsynchronousSymbolQuery> &Q,
1405 std::vector<std::unique_ptr<MaterializationUnit>> &MUs,
1406 SymbolNameSet &Unresolved) {
1407 LookupImplActionFlags ActionFlags = None;
1409 for (auto I = Unresolved.begin(), E = Unresolved.end(); I != E;) {
1413 // Search for the name in Symbols. Skip it if not found.
1414 auto SymI = Symbols.find(Name);
1415 if (SymI == Symbols.end())
1418 // If we found Name in V, remove it frome the Unresolved set and add it
1419 // to the dependencies set.
1420 Unresolved.erase(TmpI);
1422 // If the symbol has an address then resolve it.
1423 if (SymI->second.getAddress() != 0) {
1424 Q->resolve(Name, SymI->second);
1425 if (Q->isFullyResolved())
1426 ActionFlags |= NotifyFullyResolved;
1429 // If the symbol is lazy, get the MaterialiaztionUnit for it.
1430 if (SymI->second.getFlags().isLazy()) {
1431 assert(SymI->second.getAddress() == 0 &&
1432 "Lazy symbol should not have a resolved address");
1433 assert(!SymI->second.getFlags().isMaterializing() &&
1434 "Materializing and lazy should not both be set");
1435 auto UMII = UnmaterializedInfos.find(Name);
1436 assert(UMII != UnmaterializedInfos.end() &&
1437 "Lazy symbol should have UnmaterializedInfo");
1438 auto MU = std::move(UMII->second->MU);
1439 assert(MU != nullptr && "Materializer should not be null");
1441 // Kick all symbols associated with this MaterializationUnit into
1442 // materializing state.
1443 for (auto &KV : MU->getSymbols()) {
1444 auto SymK = Symbols.find(KV.first);
1445 auto Flags = SymK->second.getFlags();
1446 Flags &= ~JITSymbolFlags::Lazy;
1447 Flags |= JITSymbolFlags::Materializing;
1448 SymK->second.setFlags(Flags);
1449 UnmaterializedInfos.erase(KV.first);
1452 // Add MU to the list of MaterializationUnits to be materialized.
1453 MUs.push_back(std::move(MU));
1454 } else if (!SymI->second.getFlags().isMaterializing()) {
1455 // The symbol is neither lazy nor materializing. Finalize it and
1457 Q->notifySymbolReady();
1458 if (Q->isFullyReady())
1459 ActionFlags |= NotifyFullyReady;
1463 // Add the query to the PendingQueries list.
1464 assert(SymI->second.getFlags().isMaterializing() &&
1465 "By this line the symbol should be materializing");
1466 auto &MI = MaterializingInfos[Name];
1467 MI.PendingQueries.push_back(Q);
1468 Q->addQueryDependence(*this, Name);
1474 void VSO::dump(raw_ostream &OS) {
1475 ES.runSessionLocked([&, this]() {
1476 OS << "VSO \"" << VSOName
1477 << "\" (ES: " << format("0x%016x", reinterpret_cast<uintptr_t>(&ES))
1479 << "Symbol table:\n";
1481 for (auto &KV : Symbols) {
1482 OS << " \"" << *KV.first
1483 << "\": " << format("0x%016x", KV.second.getAddress());
1484 if (KV.second.getFlags().isLazy() ||
1485 KV.second.getFlags().isMaterializing()) {
1487 if (KV.second.getFlags().isLazy()) {
1488 auto I = UnmaterializedInfos.find(KV.first);
1489 assert(I != UnmaterializedInfos.end() &&
1490 "Lazy symbol should have UnmaterializedInfo");
1491 OS << " Lazy (MU=" << I->second->MU.get() << ")";
1493 if (KV.second.getFlags().isMaterializing())
1494 OS << " Materializing";
1500 if (!MaterializingInfos.empty())
1501 OS << " MaterializingInfos entries:\n";
1502 for (auto &KV : MaterializingInfos) {
1503 OS << " \"" << *KV.first << "\":\n"
1504 << " IsFinalized = " << (KV.second.IsFinalized ? "true" : "false")
1506 << " " << KV.second.PendingQueries.size()
1507 << " pending queries: { ";
1508 for (auto &Q : KV.second.PendingQueries)
1509 OS << Q.get() << " ";
1510 OS << "}\n Dependants:\n";
1511 for (auto &KV2 : KV.second.Dependants)
1512 OS << " " << KV2.first->getName() << ": " << KV2.second << "\n";
1513 OS << " Unfinalized Dependencies:\n";
1514 for (auto &KV2 : KV.second.UnfinalizedDependencies)
1515 OS << " " << KV2.first->getName() << ": " << KV2.second << "\n";
1520 VSO::VSO(ExecutionSessionBase &ES, std::string Name)
1521 : ES(ES), VSOName(std::move(Name)) {
1522 SearchOrder.push_back(this);
1525 Error VSO::defineImpl(MaterializationUnit &MU) {
1526 SymbolNameSet Duplicates;
1527 SymbolNameSet MUDefsOverridden;
1529 struct ExistingDefOverriddenEntry {
1530 SymbolMap::iterator ExistingDefItr;
1531 JITSymbolFlags NewFlags;
1533 std::vector<ExistingDefOverriddenEntry> ExistingDefsOverridden;
1535 for (auto &KV : MU.getSymbols()) {
1536 assert(!KV.second.isLazy() && "Lazy flag should be managed internally.");
1537 assert(!KV.second.isMaterializing() &&
1538 "Materializing flags should be managed internally.");
1540 SymbolMap::iterator EntryItr;
1543 auto NewFlags = KV.second;
1544 NewFlags |= JITSymbolFlags::Lazy;
1546 std::tie(EntryItr, Added) = Symbols.insert(
1547 std::make_pair(KV.first, JITEvaluatedSymbol(0, NewFlags)));
1550 if (KV.second.isStrong()) {
1551 if (EntryItr->second.getFlags().isStrong() ||
1552 (EntryItr->second.getFlags() & JITSymbolFlags::Materializing))
1553 Duplicates.insert(KV.first);
1555 ExistingDefsOverridden.push_back({EntryItr, NewFlags});
1557 MUDefsOverridden.insert(KV.first);
1561 if (!Duplicates.empty()) {
1562 // We need to remove the symbols we added.
1563 for (auto &KV : MU.getSymbols()) {
1564 if (Duplicates.count(KV.first))
1568 for (const auto &EDO : ExistingDefsOverridden)
1569 if (EDO.ExistingDefItr->first == KV.first)
1573 Symbols.erase(KV.first);
1576 // FIXME: Return all duplicates.
1577 return make_error<DuplicateDefinition>(**Duplicates.begin());
1580 // Update flags on existing defs and call discard on their materializers.
1581 for (auto &EDO : ExistingDefsOverridden) {
1582 assert(EDO.ExistingDefItr->second.getFlags().isLazy() &&
1583 !EDO.ExistingDefItr->second.getFlags().isMaterializing() &&
1584 "Overridden existing def should be in the Lazy state");
1586 EDO.ExistingDefItr->second.setFlags(EDO.NewFlags);
1588 auto UMII = UnmaterializedInfos.find(EDO.ExistingDefItr->first);
1589 assert(UMII != UnmaterializedInfos.end() &&
1590 "Overridden existing def should have an UnmaterializedInfo");
1592 UMII->second->MU->doDiscard(*this, EDO.ExistingDefItr->first);
1595 // Discard overridden symbols povided by MU.
1596 for (auto &Sym : MUDefsOverridden)
1597 MU.doDiscard(*this, Sym);
1599 return Error::success();
1602 void VSO::detachQueryHelper(AsynchronousSymbolQuery &Q,
1603 const SymbolNameSet &QuerySymbols) {
1604 for (auto &QuerySymbol : QuerySymbols) {
1605 assert(MaterializingInfos.count(QuerySymbol) &&
1606 "QuerySymbol does not have MaterializingInfo");
1607 auto &MI = MaterializingInfos[QuerySymbol];
1609 auto IdenticalQuery =
1610 [&](const std::shared_ptr<AsynchronousSymbolQuery> &R) {
1611 return R.get() == &Q;
1614 auto I = std::find_if(MI.PendingQueries.begin(), MI.PendingQueries.end(),
1616 assert(I != MI.PendingQueries.end() &&
1617 "Query Q should be in the PendingQueries list for QuerySymbol");
1618 MI.PendingQueries.erase(I);
1622 void VSO::transferFinalizedNodeDependencies(
1623 MaterializingInfo &DependantMI, const SymbolStringPtr &DependantName,
1624 MaterializingInfo &FinalizedMI) {
1625 for (auto &KV : FinalizedMI.UnfinalizedDependencies) {
1626 auto &DependencyVSO = *KV.first;
1627 SymbolNameSet *UnfinalizedDependenciesOnDependencyVSO = nullptr;
1629 for (auto &DependencyName : KV.second) {
1630 auto &DependencyMI = DependencyVSO.MaterializingInfos[DependencyName];
1632 // Do not add self dependencies.
1633 if (&DependencyMI == &DependantMI)
1636 // If we haven't looked up the dependencies for DependencyVSO yet, do it
1637 // now and cache the result.
1638 if (!UnfinalizedDependenciesOnDependencyVSO)
1639 UnfinalizedDependenciesOnDependencyVSO =
1640 &DependantMI.UnfinalizedDependencies[&DependencyVSO];
1642 DependencyMI.Dependants[this].insert(DependantName);
1643 UnfinalizedDependenciesOnDependencyVSO->insert(DependencyName);
1648 VSO &ExecutionSession::createVSO(std::string Name) {
1649 return runSessionLocked([&, this]() -> VSO & {
1650 VSOs.push_back(std::unique_ptr<VSO>(new VSO(*this, std::move(Name))));
1651 return *VSOs.back();
1655 Expected<SymbolMap> lookup(const VSOList &VSOs, SymbolNameSet Names) {
1660 auto &ES = (*VSOs.begin())->getExecutionSession();
1662 return ES.lookup(VSOs, Names, NoDependenciesToRegister, true);
1665 /// Look up a symbol by searching a list of VSOs.
1666 Expected<JITEvaluatedSymbol> lookup(const VSOList &VSOs, SymbolStringPtr Name) {
1667 SymbolNameSet Names({Name});
1668 if (auto ResultMap = lookup(VSOs, std::move(Names))) {
1669 assert(ResultMap->size() == 1 && "Unexpected number of results");
1670 assert(ResultMap->count(Name) && "Missing result for symbol");
1671 return std::move(ResultMap->begin()->second);
1673 return ResultMap.takeError();
1676 MangleAndInterner::MangleAndInterner(ExecutionSessionBase &ES,
1677 const DataLayout &DL)
1680 SymbolStringPtr MangleAndInterner::operator()(StringRef Name) {
1681 std::string MangledName;
1683 raw_string_ostream MangledNameStream(MangledName);
1684 Mangler::getNameWithPrefix(MangledNameStream, Name, DL);
1686 return ES.getSymbolStringPool().intern(MangledName);
1689 } // End namespace orc.
1690 } // End namespace llvm.