1 //===--- Core.cpp - Core ORC APIs (MaterializationUnit, JITDylib, etc.) ---===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "llvm/ExecutionEngine/Orc/Core.h"
10 #include "llvm/Config/llvm-config.h"
11 #include "llvm/ExecutionEngine/Orc/OrcError.h"
12 #include "llvm/IR/Mangler.h"
13 #include "llvm/Support/CommandLine.h"
14 #include "llvm/Support/Debug.h"
15 #include "llvm/Support/Format.h"
17 #if LLVM_ENABLE_THREADS
21 #define DEBUG_TYPE "orc"
29 cl::opt
<bool> PrintHidden("debug-orc-print-hidden", cl::init(true),
30 cl::desc("debug print hidden symbols defined by "
31 "materialization units"),
34 cl::opt
<bool> PrintCallable("debug-orc-print-callable", cl::init(true),
35 cl::desc("debug print callable symbols defined by "
36 "materialization units"),
39 cl::opt
<bool> PrintData("debug-orc-print-data", cl::init(true),
40 cl::desc("debug print data symbols defined by "
41 "materialization units"),
46 // SetPrinter predicate that prints every element.
47 template <typename T
> struct PrintAll
{
48 bool operator()(const T
&E
) { return true; }
51 bool anyPrintSymbolOptionSet() {
53 return PrintHidden
|| PrintCallable
|| PrintData
;
59 bool flagsMatchCLOpts(const JITSymbolFlags
&Flags
) {
61 // Bail out early if this is a hidden symbol and we're not printing hiddens.
62 if (!PrintHidden
&& !Flags
.isExported())
65 // Return true if this is callable and we're printing callables.
66 if (PrintCallable
&& Flags
.isCallable())
69 // Return true if this is data and we're printing data.
70 if (PrintData
&& !Flags
.isCallable())
73 // otherwise return false.
80 // Prints a set of items, filtered by an user-supplied predicate.
81 template <typename Set
, typename Pred
= PrintAll
<typename
Set::value_type
>>
84 SetPrinter(const Set
&S
, Pred ShouldPrint
= Pred())
85 : S(S
), ShouldPrint(std::move(ShouldPrint
)) {}
87 void printTo(llvm::raw_ostream
&OS
) const {
88 bool PrintComma
= false;
103 mutable Pred ShouldPrint
;
106 template <typename Set
, typename Pred
>
107 SetPrinter
<Set
, Pred
> printSet(const Set
&S
, Pred P
= Pred()) {
108 return SetPrinter
<Set
, Pred
>(S
, std::move(P
));
111 // Render a SetPrinter by delegating to its printTo method.
112 template <typename Set
, typename Pred
>
113 llvm::raw_ostream
&operator<<(llvm::raw_ostream
&OS
,
114 const SetPrinter
<Set
, Pred
> &Printer
) {
119 struct PrintSymbolFlagsMapElemsMatchingCLOpts
{
120 bool operator()(const orc::SymbolFlagsMap::value_type
&KV
) {
121 return flagsMatchCLOpts(KV
.second
);
125 struct PrintSymbolMapElemsMatchingCLOpts
{
126 bool operator()(const orc::SymbolMap::value_type
&KV
) {
127 return flagsMatchCLOpts(KV
.second
.getFlags());
131 } // end anonymous namespace
136 char FailedToMaterialize::ID
= 0;
137 char SymbolsNotFound::ID
= 0;
138 char SymbolsCouldNotBeRemoved::ID
= 0;
140 RegisterDependenciesFunction NoDependenciesToRegister
=
141 RegisterDependenciesFunction();
143 void MaterializationUnit::anchor() {}
145 raw_ostream
&operator<<(raw_ostream
&OS
, const SymbolStringPtr
&Sym
) {
149 raw_ostream
&operator<<(raw_ostream
&OS
, const SymbolNameSet
&Symbols
) {
150 return OS
<< printSet(Symbols
, PrintAll
<SymbolStringPtr
>());
153 raw_ostream
&operator<<(raw_ostream
&OS
, const JITSymbolFlags
&Flags
) {
154 if (Flags
.hasError())
156 if (Flags
.isCallable())
162 else if (Flags
.isCommon())
165 if (!Flags
.isExported())
171 raw_ostream
&operator<<(raw_ostream
&OS
, const JITEvaluatedSymbol
&Sym
) {
172 return OS
<< format("0x%016" PRIx64
, Sym
.getAddress()) << " "
176 raw_ostream
&operator<<(raw_ostream
&OS
, const SymbolFlagsMap::value_type
&KV
) {
177 return OS
<< "(\"" << KV
.first
<< "\", " << KV
.second
<< ")";
180 raw_ostream
&operator<<(raw_ostream
&OS
, const SymbolMap::value_type
&KV
) {
181 return OS
<< "(\"" << KV
.first
<< "\": " << KV
.second
<< ")";
184 raw_ostream
&operator<<(raw_ostream
&OS
, const SymbolFlagsMap
&SymbolFlags
) {
185 return OS
<< printSet(SymbolFlags
, PrintSymbolFlagsMapElemsMatchingCLOpts());
188 raw_ostream
&operator<<(raw_ostream
&OS
, const SymbolMap
&Symbols
) {
189 return OS
<< printSet(Symbols
, PrintSymbolMapElemsMatchingCLOpts());
192 raw_ostream
&operator<<(raw_ostream
&OS
,
193 const SymbolDependenceMap::value_type
&KV
) {
194 return OS
<< "(" << KV
.first
<< ", " << KV
.second
<< ")";
197 raw_ostream
&operator<<(raw_ostream
&OS
, const SymbolDependenceMap
&Deps
) {
198 return OS
<< printSet(Deps
, PrintAll
<SymbolDependenceMap::value_type
>());
201 raw_ostream
&operator<<(raw_ostream
&OS
, const MaterializationUnit
&MU
) {
202 OS
<< "MU@" << &MU
<< " (\"" << MU
.getName() << "\"";
203 if (anyPrintSymbolOptionSet())
204 OS
<< ", " << MU
.getSymbols();
208 raw_ostream
&operator<<(raw_ostream
&OS
, const JITDylibSearchList
&JDs
) {
211 assert(JDs
.front().first
&& "JITDylibList entries must not be null");
212 OS
<< " (\"" << JDs
.front().first
->getName() << "\", "
213 << (JDs
.front().second
? "true" : "false") << ")";
214 for (auto &KV
: make_range(std::next(JDs
.begin()), JDs
.end())) {
215 assert(KV
.first
&& "JITDylibList entries must not be null");
216 OS
<< ", (\"" << KV
.first
->getName() << "\", "
217 << (KV
.second
? "true" : "false") << ")";
224 raw_ostream
&operator<<(raw_ostream
&OS
, const SymbolAliasMap
&Aliases
) {
226 for (auto &KV
: Aliases
)
227 OS
<< " " << *KV
.first
<< ": " << KV
.second
.Aliasee
<< " "
228 << KV
.second
.AliasFlags
;
233 raw_ostream
&operator<<(raw_ostream
&OS
, const SymbolState
&S
) {
235 case SymbolState::Invalid
:
236 return OS
<< "Invalid";
237 case SymbolState::NeverSearched
:
238 return OS
<< "Never-Searched";
239 case SymbolState::Materializing
:
240 return OS
<< "Materializing";
241 case SymbolState::Resolved
:
242 return OS
<< "Resolved";
243 case SymbolState::Emitted
:
244 return OS
<< "Emitted";
245 case SymbolState::Ready
:
246 return OS
<< "Ready";
248 llvm_unreachable("Invalid state");
251 FailedToMaterialize::FailedToMaterialize(
252 std::shared_ptr
<SymbolDependenceMap
> Symbols
)
253 : Symbols(std::move(Symbols
)) {
254 assert(!this->Symbols
->empty() && "Can not fail to resolve an empty set");
257 std::error_code
FailedToMaterialize::convertToErrorCode() const {
258 return orcError(OrcErrorCode::UnknownORCError
);
261 void FailedToMaterialize::log(raw_ostream
&OS
) const {
262 OS
<< "Failed to materialize symbols: " << *Symbols
;
265 SymbolsNotFound::SymbolsNotFound(SymbolNameSet Symbols
)
266 : Symbols(std::move(Symbols
)) {
267 assert(!this->Symbols
.empty() && "Can not fail to resolve an empty set");
270 std::error_code
SymbolsNotFound::convertToErrorCode() const {
271 return orcError(OrcErrorCode::UnknownORCError
);
274 void SymbolsNotFound::log(raw_ostream
&OS
) const {
275 OS
<< "Symbols not found: " << Symbols
;
278 SymbolsCouldNotBeRemoved::SymbolsCouldNotBeRemoved(SymbolNameSet Symbols
)
279 : Symbols(std::move(Symbols
)) {
280 assert(!this->Symbols
.empty() && "Can not fail to resolve an empty set");
283 std::error_code
SymbolsCouldNotBeRemoved::convertToErrorCode() const {
284 return orcError(OrcErrorCode::UnknownORCError
);
287 void SymbolsCouldNotBeRemoved::log(raw_ostream
&OS
) const {
288 OS
<< "Symbols could not be removed: " << Symbols
;
291 AsynchronousSymbolQuery::AsynchronousSymbolQuery(
292 const SymbolNameSet
&Symbols
, SymbolState RequiredState
,
293 SymbolsResolvedCallback NotifyComplete
)
294 : NotifyComplete(std::move(NotifyComplete
)), RequiredState(RequiredState
) {
295 assert(RequiredState
>= SymbolState::Resolved
&&
296 "Cannot query for a symbols that have not reached the resolve state "
299 OutstandingSymbolsCount
= Symbols
.size();
301 for (auto &S
: Symbols
)
302 ResolvedSymbols
[S
] = nullptr;
305 void AsynchronousSymbolQuery::notifySymbolMetRequiredState(
306 const SymbolStringPtr
&Name
, JITEvaluatedSymbol Sym
) {
307 auto I
= ResolvedSymbols
.find(Name
);
308 assert(I
!= ResolvedSymbols
.end() &&
309 "Resolving symbol outside the requested set");
310 assert(I
->second
.getAddress() == 0 && "Redundantly resolving symbol Name");
311 I
->second
= std::move(Sym
);
312 --OutstandingSymbolsCount
;
315 void AsynchronousSymbolQuery::handleComplete() {
316 assert(OutstandingSymbolsCount
== 0 &&
317 "Symbols remain, handleComplete called prematurely");
319 auto TmpNotifyComplete
= std::move(NotifyComplete
);
320 NotifyComplete
= SymbolsResolvedCallback();
321 TmpNotifyComplete(std::move(ResolvedSymbols
));
324 bool AsynchronousSymbolQuery::canStillFail() { return !!NotifyComplete
; }
326 void AsynchronousSymbolQuery::handleFailed(Error Err
) {
327 assert(QueryRegistrations
.empty() && ResolvedSymbols
.empty() &&
328 OutstandingSymbolsCount
== 0 &&
329 "Query should already have been abandoned");
330 NotifyComplete(std::move(Err
));
331 NotifyComplete
= SymbolsResolvedCallback();
334 void AsynchronousSymbolQuery::addQueryDependence(JITDylib
&JD
,
335 SymbolStringPtr Name
) {
336 bool Added
= QueryRegistrations
[&JD
].insert(std::move(Name
)).second
;
338 assert(Added
&& "Duplicate dependence notification?");
341 void AsynchronousSymbolQuery::removeQueryDependence(
342 JITDylib
&JD
, const SymbolStringPtr
&Name
) {
343 auto QRI
= QueryRegistrations
.find(&JD
);
344 assert(QRI
!= QueryRegistrations
.end() &&
345 "No dependencies registered for JD");
346 assert(QRI
->second
.count(Name
) && "No dependency on Name in JD");
347 QRI
->second
.erase(Name
);
348 if (QRI
->second
.empty())
349 QueryRegistrations
.erase(QRI
);
352 void AsynchronousSymbolQuery::detach() {
353 ResolvedSymbols
.clear();
354 OutstandingSymbolsCount
= 0;
355 for (auto &KV
: QueryRegistrations
)
356 KV
.first
->detachQueryHelper(*this, KV
.second
);
357 QueryRegistrations
.clear();
360 MaterializationResponsibility::MaterializationResponsibility(
361 JITDylib
&JD
, SymbolFlagsMap SymbolFlags
, VModuleKey K
)
362 : JD(JD
), SymbolFlags(std::move(SymbolFlags
)), K(std::move(K
)) {
363 assert(!this->SymbolFlags
.empty() && "Materializing nothing?");
366 MaterializationResponsibility::~MaterializationResponsibility() {
367 assert(SymbolFlags
.empty() &&
368 "All symbols should have been explicitly materialized or failed");
371 SymbolNameSet
MaterializationResponsibility::getRequestedSymbols() const {
372 return JD
.getRequestedSymbols(SymbolFlags
);
375 Error
MaterializationResponsibility::notifyResolved(const SymbolMap
&Symbols
) {
377 dbgs() << "In " << JD
.getName() << " resolving " << Symbols
<< "\n";
380 for (auto &KV
: Symbols
) {
381 auto WeakFlags
= JITSymbolFlags::Weak
| JITSymbolFlags::Common
;
382 auto I
= SymbolFlags
.find(KV
.first
);
383 assert(I
!= SymbolFlags
.end() &&
384 "Resolving symbol outside this responsibility set");
385 assert((KV
.second
.getFlags() & ~WeakFlags
) == (I
->second
& ~WeakFlags
) &&
386 "Resolving symbol with incorrect flags");
390 return JD
.resolve(Symbols
);
393 Error
MaterializationResponsibility::notifyEmitted() {
396 dbgs() << "In " << JD
.getName() << " emitting " << SymbolFlags
<< "\n";
399 if (auto Err
= JD
.emit(SymbolFlags
))
403 return Error::success();
406 Error
MaterializationResponsibility::defineMaterializing(
407 const SymbolFlagsMap
&NewSymbolFlags
) {
408 // Add the given symbols to this responsibility object.
409 // It's ok if we hit a duplicate here: In that case the new version will be
410 // discarded, and the JITDylib::defineMaterializing method will return a
411 // duplicate symbol error.
412 for (auto &KV
: NewSymbolFlags
)
413 SymbolFlags
.insert(KV
);
415 return JD
.defineMaterializing(NewSymbolFlags
);
418 void MaterializationResponsibility::failMaterialization() {
421 dbgs() << "In " << JD
.getName() << " failing materialization for "
422 << SymbolFlags
<< "\n";
425 JITDylib::FailedSymbolsWorklist Worklist
;
427 for (auto &KV
: SymbolFlags
)
428 Worklist
.push_back(std::make_pair(&JD
, KV
.first
));
431 JD
.notifyFailed(std::move(Worklist
));
434 void MaterializationResponsibility::replace(
435 std::unique_ptr
<MaterializationUnit
> MU
) {
436 for (auto &KV
: MU
->getSymbols())
437 SymbolFlags
.erase(KV
.first
);
439 LLVM_DEBUG(JD
.getExecutionSession().runSessionLocked([&]() {
440 dbgs() << "In " << JD
.getName() << " replacing symbols with " << *MU
444 JD
.replace(std::move(MU
));
447 MaterializationResponsibility
448 MaterializationResponsibility::delegate(const SymbolNameSet
&Symbols
,
451 if (NewKey
== VModuleKey())
454 SymbolFlagsMap DelegatedFlags
;
456 for (auto &Name
: Symbols
) {
457 auto I
= SymbolFlags
.find(Name
);
458 assert(I
!= SymbolFlags
.end() &&
459 "Symbol is not tracked by this MaterializationResponsibility "
462 DelegatedFlags
[Name
] = std::move(I
->second
);
463 SymbolFlags
.erase(I
);
466 return MaterializationResponsibility(JD
, std::move(DelegatedFlags
),
470 void MaterializationResponsibility::addDependencies(
471 const SymbolStringPtr
&Name
, const SymbolDependenceMap
&Dependencies
) {
472 assert(SymbolFlags
.count(Name
) &&
473 "Symbol not covered by this MaterializationResponsibility instance");
474 JD
.addDependencies(Name
, Dependencies
);
477 void MaterializationResponsibility::addDependenciesForAll(
478 const SymbolDependenceMap
&Dependencies
) {
479 for (auto &KV
: SymbolFlags
)
480 JD
.addDependencies(KV
.first
, Dependencies
);
483 AbsoluteSymbolsMaterializationUnit::AbsoluteSymbolsMaterializationUnit(
484 SymbolMap Symbols
, VModuleKey K
)
485 : MaterializationUnit(extractFlags(Symbols
), std::move(K
)),
486 Symbols(std::move(Symbols
)) {}
488 StringRef
AbsoluteSymbolsMaterializationUnit::getName() const {
489 return "<Absolute Symbols>";
492 void AbsoluteSymbolsMaterializationUnit::materialize(
493 MaterializationResponsibility R
) {
494 // No dependencies, so these calls can't fail.
495 cantFail(R
.notifyResolved(Symbols
));
496 cantFail(R
.notifyEmitted());
499 void AbsoluteSymbolsMaterializationUnit::discard(const JITDylib
&JD
,
500 const SymbolStringPtr
&Name
) {
501 assert(Symbols
.count(Name
) && "Symbol is not part of this MU");
506 AbsoluteSymbolsMaterializationUnit::extractFlags(const SymbolMap
&Symbols
) {
507 SymbolFlagsMap Flags
;
508 for (const auto &KV
: Symbols
)
509 Flags
[KV
.first
] = KV
.second
.getFlags();
513 ReExportsMaterializationUnit::ReExportsMaterializationUnit(
514 JITDylib
*SourceJD
, bool MatchNonExported
, SymbolAliasMap Aliases
,
516 : MaterializationUnit(extractFlags(Aliases
), std::move(K
)),
517 SourceJD(SourceJD
), MatchNonExported(MatchNonExported
),
518 Aliases(std::move(Aliases
)) {}
520 StringRef
ReExportsMaterializationUnit::getName() const {
521 return "<Reexports>";
524 void ReExportsMaterializationUnit::materialize(
525 MaterializationResponsibility R
) {
527 auto &ES
= R
.getTargetJITDylib().getExecutionSession();
528 JITDylib
&TgtJD
= R
.getTargetJITDylib();
529 JITDylib
&SrcJD
= SourceJD
? *SourceJD
: TgtJD
;
531 // Find the set of requested aliases and aliasees. Return any unrequested
532 // aliases back to the JITDylib so as to not prematurely materialize any
534 auto RequestedSymbols
= R
.getRequestedSymbols();
535 SymbolAliasMap RequestedAliases
;
537 for (auto &Name
: RequestedSymbols
) {
538 auto I
= Aliases
.find(Name
);
539 assert(I
!= Aliases
.end() && "Symbol not found in aliases map?");
540 RequestedAliases
[Name
] = std::move(I
->second
);
545 ES
.runSessionLocked([&]() {
546 dbgs() << "materializing reexports: target = " << TgtJD
.getName()
547 << ", source = " << SrcJD
.getName() << " " << RequestedAliases
552 if (!Aliases
.empty()) {
554 R
.replace(reexports(*SourceJD
, std::move(Aliases
), MatchNonExported
));
556 R
.replace(symbolAliases(std::move(Aliases
)));
559 // The OnResolveInfo struct will hold the aliases and responsibilty for each
560 // query in the list.
561 struct OnResolveInfo
{
562 OnResolveInfo(MaterializationResponsibility R
, SymbolAliasMap Aliases
)
563 : R(std::move(R
)), Aliases(std::move(Aliases
)) {}
565 MaterializationResponsibility R
;
566 SymbolAliasMap Aliases
;
569 // Build a list of queries to issue. In each round we build the largest set of
570 // aliases that we can resolve without encountering a chain definition of the
571 // form Foo -> Bar, Bar -> Baz. Such a form would deadlock as the query would
572 // be waitin on a symbol that it itself had to resolve. Usually this will just
573 // involve one round and a single query.
575 std::vector
<std::pair
<SymbolNameSet
, std::shared_ptr
<OnResolveInfo
>>>
577 while (!RequestedAliases
.empty()) {
578 SymbolNameSet ResponsibilitySymbols
;
579 SymbolNameSet QuerySymbols
;
580 SymbolAliasMap QueryAliases
;
582 // Collect as many aliases as we can without including a chain.
583 for (auto &KV
: RequestedAliases
) {
584 // Chain detected. Skip this symbol for this round.
585 if (&SrcJD
== &TgtJD
&& (QueryAliases
.count(KV
.second
.Aliasee
) ||
586 RequestedAliases
.count(KV
.second
.Aliasee
)))
589 ResponsibilitySymbols
.insert(KV
.first
);
590 QuerySymbols
.insert(KV
.second
.Aliasee
);
591 QueryAliases
[KV
.first
] = std::move(KV
.second
);
594 // Remove the aliases collected this round from the RequestedAliases map.
595 for (auto &KV
: QueryAliases
)
596 RequestedAliases
.erase(KV
.first
);
598 assert(!QuerySymbols
.empty() && "Alias cycle detected!");
600 auto QueryInfo
= std::make_shared
<OnResolveInfo
>(
601 R
.delegate(ResponsibilitySymbols
), std::move(QueryAliases
));
602 QueryInfos
.push_back(
603 make_pair(std::move(QuerySymbols
), std::move(QueryInfo
)));
606 // Issue the queries.
607 while (!QueryInfos
.empty()) {
608 auto QuerySymbols
= std::move(QueryInfos
.back().first
);
609 auto QueryInfo
= std::move(QueryInfos
.back().second
);
611 QueryInfos
.pop_back();
613 auto RegisterDependencies
= [QueryInfo
,
614 &SrcJD
](const SymbolDependenceMap
&Deps
) {
615 // If there were no materializing symbols, just bail out.
619 // Otherwise the only deps should be on SrcJD.
620 assert(Deps
.size() == 1 && Deps
.count(&SrcJD
) &&
621 "Unexpected dependencies for reexports");
623 auto &SrcJDDeps
= Deps
.find(&SrcJD
)->second
;
624 SymbolDependenceMap PerAliasDepsMap
;
625 auto &PerAliasDeps
= PerAliasDepsMap
[&SrcJD
];
627 for (auto &KV
: QueryInfo
->Aliases
)
628 if (SrcJDDeps
.count(KV
.second
.Aliasee
)) {
629 PerAliasDeps
= {KV
.second
.Aliasee
};
630 QueryInfo
->R
.addDependencies(KV
.first
, PerAliasDepsMap
);
634 auto OnComplete
= [QueryInfo
](Expected
<SymbolMap
> Result
) {
635 auto &ES
= QueryInfo
->R
.getTargetJITDylib().getExecutionSession();
637 SymbolMap ResolutionMap
;
638 for (auto &KV
: QueryInfo
->Aliases
) {
639 assert(Result
->count(KV
.second
.Aliasee
) &&
640 "Result map missing entry?");
641 ResolutionMap
[KV
.first
] = JITEvaluatedSymbol(
642 (*Result
)[KV
.second
.Aliasee
].getAddress(), KV
.second
.AliasFlags
);
644 if (auto Err
= QueryInfo
->R
.notifyResolved(ResolutionMap
)) {
645 ES
.reportError(std::move(Err
));
646 QueryInfo
->R
.failMaterialization();
649 if (auto Err
= QueryInfo
->R
.notifyEmitted()) {
650 ES
.reportError(std::move(Err
));
651 QueryInfo
->R
.failMaterialization();
655 ES
.reportError(Result
.takeError());
656 QueryInfo
->R
.failMaterialization();
660 ES
.lookup(JITDylibSearchList({{&SrcJD
, MatchNonExported
}}), QuerySymbols
,
661 SymbolState::Resolved
, std::move(OnComplete
),
662 std::move(RegisterDependencies
));
666 void ReExportsMaterializationUnit::discard(const JITDylib
&JD
,
667 const SymbolStringPtr
&Name
) {
668 assert(Aliases
.count(Name
) &&
669 "Symbol not covered by this MaterializationUnit");
674 ReExportsMaterializationUnit::extractFlags(const SymbolAliasMap
&Aliases
) {
675 SymbolFlagsMap SymbolFlags
;
676 for (auto &KV
: Aliases
)
677 SymbolFlags
[KV
.first
] = KV
.second
.AliasFlags
;
682 Expected
<SymbolAliasMap
>
683 buildSimpleReexportsAliasMap(JITDylib
&SourceJD
, const SymbolNameSet
&Symbols
) {
684 auto Flags
= SourceJD
.lookupFlags(Symbols
);
687 return Flags
.takeError();
689 if (Flags
->size() != Symbols
.size()) {
690 SymbolNameSet Unresolved
= Symbols
;
691 for (auto &KV
: *Flags
)
692 Unresolved
.erase(KV
.first
);
693 return make_error
<SymbolsNotFound
>(std::move(Unresolved
));
696 SymbolAliasMap Result
;
697 for (auto &Name
: Symbols
) {
698 assert(Flags
->count(Name
) && "Missing entry in flags map");
699 Result
[Name
] = SymbolAliasMapEntry(Name
, (*Flags
)[Name
]);
705 ReexportsGenerator::ReexportsGenerator(JITDylib
&SourceJD
,
706 bool MatchNonExported
,
707 SymbolPredicate Allow
)
708 : SourceJD(SourceJD
), MatchNonExported(MatchNonExported
),
709 Allow(std::move(Allow
)) {}
711 Expected
<SymbolNameSet
>
712 ReexportsGenerator::tryToGenerate(JITDylib
&JD
, const SymbolNameSet
&Names
) {
713 orc::SymbolNameSet Added
;
714 orc::SymbolAliasMap AliasMap
;
716 auto Flags
= SourceJD
.lookupFlags(Names
);
719 return Flags
.takeError();
721 for (auto &KV
: *Flags
) {
722 if (Allow
&& !Allow(KV
.first
))
724 AliasMap
[KV
.first
] = SymbolAliasMapEntry(KV
.first
, KV
.second
);
725 Added
.insert(KV
.first
);
729 cantFail(JD
.define(reexports(SourceJD
, AliasMap
, MatchNonExported
)));
734 JITDylib::DefinitionGenerator::~DefinitionGenerator() {}
736 void JITDylib::removeGenerator(DefinitionGenerator
&G
) {
737 ES
.runSessionLocked([&]() {
738 auto I
= std::find_if(DefGenerators
.begin(), DefGenerators
.end(),
739 [&](const std::unique_ptr
<DefinitionGenerator
> &H
) {
740 return H
.get() == &G
;
742 assert(I
!= DefGenerators
.end() && "Generator not found");
743 DefGenerators
.erase(I
);
747 Error
JITDylib::defineMaterializing(const SymbolFlagsMap
&SymbolFlags
) {
748 return ES
.runSessionLocked([&]() -> Error
{
749 std::vector
<SymbolTable::iterator
> AddedSyms
;
751 for (auto &KV
: SymbolFlags
) {
752 SymbolTable::iterator EntryItr
;
755 std::tie(EntryItr
, Added
) =
756 Symbols
.insert(std::make_pair(KV
.first
, SymbolTableEntry(KV
.second
)));
759 AddedSyms
.push_back(EntryItr
);
760 EntryItr
->second
.setState(SymbolState::Materializing
);
762 // Remove any symbols already added.
763 for (auto &SI
: AddedSyms
)
766 // FIXME: Return all duplicates.
767 return make_error
<DuplicateDefinition
>(*KV
.first
);
771 return Error::success();
775 void JITDylib::replace(std::unique_ptr
<MaterializationUnit
> MU
) {
776 assert(MU
!= nullptr && "Can not replace with a null MaterializationUnit");
779 ES
.runSessionLocked([&, this]() -> std::unique_ptr
<MaterializationUnit
> {
782 for (auto &KV
: MU
->getSymbols()) {
783 auto SymI
= Symbols
.find(KV
.first
);
784 assert(SymI
!= Symbols
.end() && "Replacing unknown symbol");
785 assert(SymI
->second
.isInMaterializationPhase() &&
786 "Can not call replace on a symbol that is not materializing");
787 assert(!SymI
->second
.hasMaterializerAttached() &&
788 "Symbol should not have materializer attached already");
789 assert(UnmaterializedInfos
.count(KV
.first
) == 0 &&
790 "Symbol being replaced should have no UnmaterializedInfo");
794 // If any symbol has pending queries against it then we need to
795 // materialize MU immediately.
796 for (auto &KV
: MU
->getSymbols()) {
797 auto MII
= MaterializingInfos
.find(KV
.first
);
798 if (MII
!= MaterializingInfos
.end()) {
799 if (MII
->second
.hasQueriesPending())
800 return std::move(MU
);
804 // Otherwise, make MU responsible for all the symbols.
805 auto UMI
= std::make_shared
<UnmaterializedInfo
>(std::move(MU
));
806 for (auto &KV
: UMI
->MU
->getSymbols()) {
807 auto SymI
= Symbols
.find(KV
.first
);
808 assert(SymI
->second
.getState() == SymbolState::Materializing
&&
809 "Can not replace a symbol that is not materializing");
810 assert(!SymI
->second
.hasMaterializerAttached() &&
811 "Can not replace a symbol that has a materializer attached");
812 assert(UnmaterializedInfos
.count(KV
.first
) == 0 &&
813 "Unexpected materializer entry in map");
814 SymI
->second
.setAddress(SymI
->second
.getAddress());
815 SymI
->second
.setMaterializerAttached(true);
816 UnmaterializedInfos
[KV
.first
] = UMI
;
823 ES
.dispatchMaterialization(*this, std::move(MustRunMU
));
827 JITDylib::getRequestedSymbols(const SymbolFlagsMap
&SymbolFlags
) const {
828 return ES
.runSessionLocked([&]() {
829 SymbolNameSet RequestedSymbols
;
831 for (auto &KV
: SymbolFlags
) {
832 assert(Symbols
.count(KV
.first
) && "JITDylib does not cover this symbol?");
833 assert(Symbols
.find(KV
.first
)->second
.isInMaterializationPhase() &&
834 "getRequestedSymbols can only be called for symbols that have "
835 "started materializing");
836 auto I
= MaterializingInfos
.find(KV
.first
);
837 if (I
== MaterializingInfos
.end())
840 if (I
->second
.hasQueriesPending())
841 RequestedSymbols
.insert(KV
.first
);
844 return RequestedSymbols
;
848 void JITDylib::addDependencies(const SymbolStringPtr
&Name
,
849 const SymbolDependenceMap
&Dependencies
) {
850 assert(Symbols
.count(Name
) && "Name not in symbol table");
851 assert(Symbols
[Name
].isInMaterializationPhase() &&
852 "Can not add dependencies for a symbol that is not materializing");
854 // If Name is already in an error state then just bail out.
855 if (Symbols
[Name
].getFlags().hasError())
858 auto &MI
= MaterializingInfos
[Name
];
859 assert(Symbols
[Name
].getState() != SymbolState::Emitted
&&
860 "Can not add dependencies to an emitted symbol");
862 bool DependsOnSymbolInErrorState
= false;
864 // Register dependencies, record whether any depenendency is in the error
866 for (auto &KV
: Dependencies
) {
867 assert(KV
.first
&& "Null JITDylib in dependency?");
868 auto &OtherJITDylib
= *KV
.first
;
869 auto &DepsOnOtherJITDylib
= MI
.UnemittedDependencies
[&OtherJITDylib
];
871 for (auto &OtherSymbol
: KV
.second
) {
873 // Check the sym entry for the dependency.
874 auto OtherSymI
= OtherJITDylib
.Symbols
.find(OtherSymbol
);
877 // Assert that this symbol exists and has not reached the ready state
879 assert(OtherSymI
!= OtherJITDylib
.Symbols
.end() &&
880 (OtherSymI
->second
.getState() != SymbolState::Ready
&&
881 "Dependency on emitted/ready symbol"));
884 auto &OtherSymEntry
= OtherSymI
->second
;
886 // If the dependency is in an error state then note this and continue,
887 // we will move this symbol to the error state below.
888 if (OtherSymEntry
.getFlags().hasError()) {
889 DependsOnSymbolInErrorState
= true;
893 // If the dependency was not in the error state then add it to
894 // our list of dependencies.
895 assert(OtherJITDylib
.MaterializingInfos
.count(OtherSymbol
) &&
896 "No MaterializingInfo for dependency");
897 auto &OtherMI
= OtherJITDylib
.MaterializingInfos
[OtherSymbol
];
899 if (OtherSymEntry
.getState() == SymbolState::Emitted
)
900 transferEmittedNodeDependencies(MI
, Name
, OtherMI
);
901 else if (&OtherJITDylib
!= this || OtherSymbol
!= Name
) {
902 OtherMI
.Dependants
[this].insert(Name
);
903 DepsOnOtherJITDylib
.insert(OtherSymbol
);
907 if (DepsOnOtherJITDylib
.empty())
908 MI
.UnemittedDependencies
.erase(&OtherJITDylib
);
911 // If this symbol dependended on any symbols in the error state then move
912 // this symbol to the error state too.
913 if (DependsOnSymbolInErrorState
)
914 Symbols
[Name
].setFlags(Symbols
[Name
].getFlags() | JITSymbolFlags::HasError
);
917 Error
JITDylib::resolve(const SymbolMap
&Resolved
) {
918 SymbolNameSet SymbolsInErrorState
;
919 AsynchronousSymbolQuerySet CompletedQueries
;
921 ES
.runSessionLocked([&, this]() {
922 struct WorklistEntry
{
923 SymbolTable::iterator SymI
;
924 JITEvaluatedSymbol ResolvedSym
;
927 std::vector
<WorklistEntry
> Worklist
;
928 Worklist
.reserve(Resolved
.size());
930 // Build worklist and check for any symbols in the error state.
931 for (const auto &KV
: Resolved
) {
933 assert(!KV
.second
.getFlags().hasError() &&
934 "Resolution result can not have error flag set");
936 auto SymI
= Symbols
.find(KV
.first
);
938 assert(SymI
!= Symbols
.end() && "Symbol not found");
939 assert(!SymI
->second
.hasMaterializerAttached() &&
940 "Resolving symbol with materializer attached?");
941 assert(SymI
->second
.getState() == SymbolState::Materializing
&&
942 "Symbol should be materializing");
943 assert(SymI
->second
.getAddress() == 0 &&
944 "Symbol has already been resolved");
946 if (SymI
->second
.getFlags().hasError())
947 SymbolsInErrorState
.insert(KV
.first
);
949 auto Flags
= KV
.second
.getFlags();
950 Flags
&= ~(JITSymbolFlags::Weak
| JITSymbolFlags::Common
);
951 assert(Flags
== (SymI
->second
.getFlags() &
952 ~(JITSymbolFlags::Weak
| JITSymbolFlags::Common
)) &&
953 "Resolved flags should match the declared flags");
956 {SymI
, JITEvaluatedSymbol(KV
.second
.getAddress(), Flags
)});
960 // If any symbols were in the error state then bail out.
961 if (!SymbolsInErrorState
.empty())
964 while (!Worklist
.empty()) {
965 auto SymI
= Worklist
.back().SymI
;
966 auto ResolvedSym
= Worklist
.back().ResolvedSym
;
969 auto &Name
= SymI
->first
;
971 // Resolved symbols can not be weak: discard the weak flag.
972 JITSymbolFlags ResolvedFlags
= ResolvedSym
.getFlags();
973 SymI
->second
.setAddress(ResolvedSym
.getAddress());
974 SymI
->second
.setFlags(ResolvedFlags
);
975 SymI
->second
.setState(SymbolState::Resolved
);
977 auto &MI
= MaterializingInfos
[Name
];
978 for (auto &Q
: MI
.takeQueriesMeeting(SymbolState::Resolved
)) {
979 Q
->notifySymbolMetRequiredState(Name
, ResolvedSym
);
980 Q
->removeQueryDependence(*this, Name
);
982 CompletedQueries
.insert(std::move(Q
));
987 assert((SymbolsInErrorState
.empty() || CompletedQueries
.empty()) &&
988 "Can't fail symbols and completed queries at the same time");
990 // If we failed any symbols then return an error.
991 if (!SymbolsInErrorState
.empty()) {
992 auto FailedSymbolsDepMap
= std::make_shared
<SymbolDependenceMap
>();
993 (*FailedSymbolsDepMap
)[this] = std::move(SymbolsInErrorState
);
994 return make_error
<FailedToMaterialize
>(std::move(FailedSymbolsDepMap
));
997 // Otherwise notify all the completed queries.
998 for (auto &Q
: CompletedQueries
) {
999 assert(Q
->isComplete() && "Q not completed");
1000 Q
->handleComplete();
1003 return Error::success();
1006 Error
JITDylib::emit(const SymbolFlagsMap
&Emitted
) {
1007 AsynchronousSymbolQuerySet CompletedQueries
;
1008 SymbolNameSet SymbolsInErrorState
;
1010 ES
.runSessionLocked([&, this]() {
1011 std::vector
<SymbolTable::iterator
> Worklist
;
1013 // Scan to build worklist, record any symbols in the erorr state.
1014 for (const auto &KV
: Emitted
) {
1015 auto &Name
= KV
.first
;
1017 auto SymI
= Symbols
.find(Name
);
1018 assert(SymI
!= Symbols
.end() && "No symbol table entry for Name");
1020 if (SymI
->second
.getFlags().hasError())
1021 SymbolsInErrorState
.insert(Name
);
1023 Worklist
.push_back(SymI
);
1026 // If any symbols were in the error state then bail out.
1027 if (!SymbolsInErrorState
.empty())
1030 // Otherwise update dependencies and move to the emitted state.
1031 while (!Worklist
.empty()) {
1032 auto SymI
= Worklist
.back();
1033 Worklist
.pop_back();
1035 auto &Name
= SymI
->first
;
1036 auto &SymEntry
= SymI
->second
;
1038 // Move symbol to the emitted state.
1039 assert(SymEntry
.getState() == SymbolState::Resolved
&&
1040 "Emitting from state other than Resolved");
1041 SymEntry
.setState(SymbolState::Emitted
);
1043 auto MII
= MaterializingInfos
.find(Name
);
1044 assert(MII
!= MaterializingInfos
.end() &&
1045 "Missing MaterializingInfo entry");
1046 auto &MI
= MII
->second
;
1048 // For each dependant, transfer this node's emitted dependencies to
1049 // it. If the dependant node is ready (i.e. has no unemitted
1050 // dependencies) then notify any pending queries.
1051 for (auto &KV
: MI
.Dependants
) {
1052 auto &DependantJD
= *KV
.first
;
1053 for (auto &DependantName
: KV
.second
) {
1055 DependantJD
.MaterializingInfos
.find(DependantName
);
1056 assert(DependantMII
!= DependantJD
.MaterializingInfos
.end() &&
1057 "Dependant should have MaterializingInfo");
1059 auto &DependantMI
= DependantMII
->second
;
1061 // Remove the dependant's dependency on this node.
1062 assert(DependantMI
.UnemittedDependencies
.count(this) &&
1063 "Dependant does not have an unemitted dependencies record for "
1065 assert(DependantMI
.UnemittedDependencies
[this].count(Name
) &&
1066 "Dependant does not count this symbol as a dependency?");
1068 DependantMI
.UnemittedDependencies
[this].erase(Name
);
1069 if (DependantMI
.UnemittedDependencies
[this].empty())
1070 DependantMI
.UnemittedDependencies
.erase(this);
1072 // Transfer unemitted dependencies from this node to the dependant.
1073 DependantJD
.transferEmittedNodeDependencies(DependantMI
,
1076 auto DependantSymI
= DependantJD
.Symbols
.find(DependantName
);
1077 assert(DependantSymI
!= DependantJD
.Symbols
.end() &&
1078 "Dependant has no entry in the Symbols table");
1079 auto &DependantSymEntry
= DependantSymI
->second
;
1081 // If the dependant is emitted and this node was the last of its
1082 // unemitted dependencies then the dependant node is now ready, so
1083 // notify any pending queries on the dependant node.
1084 if (DependantSymEntry
.getState() == SymbolState::Emitted
&&
1085 DependantMI
.UnemittedDependencies
.empty()) {
1086 assert(DependantMI
.Dependants
.empty() &&
1087 "Dependants should be empty by now");
1089 // Since this dependant is now ready, we erase its MaterializingInfo
1090 // and update its materializing state.
1091 DependantSymEntry
.setState(SymbolState::Ready
);
1093 for (auto &Q
: DependantMI
.takeQueriesMeeting(SymbolState::Ready
)) {
1094 Q
->notifySymbolMetRequiredState(
1095 DependantName
, DependantSymI
->second
.getSymbol());
1096 if (Q
->isComplete())
1097 CompletedQueries
.insert(Q
);
1098 Q
->removeQueryDependence(DependantJD
, DependantName
);
1101 DependantJD
.MaterializingInfos
.erase(DependantMII
);
1106 MI
.Dependants
.clear();
1107 if (MI
.UnemittedDependencies
.empty()) {
1108 SymI
->second
.setState(SymbolState::Ready
);
1109 for (auto &Q
: MI
.takeQueriesMeeting(SymbolState::Ready
)) {
1110 Q
->notifySymbolMetRequiredState(Name
, SymI
->second
.getSymbol());
1111 if (Q
->isComplete())
1112 CompletedQueries
.insert(Q
);
1113 Q
->removeQueryDependence(*this, Name
);
1115 MaterializingInfos
.erase(MII
);
1120 assert((SymbolsInErrorState
.empty() || CompletedQueries
.empty()) &&
1121 "Can't fail symbols and completed queries at the same time");
1123 // If we failed any symbols then return an error.
1124 if (!SymbolsInErrorState
.empty()) {
1125 auto FailedSymbolsDepMap
= std::make_shared
<SymbolDependenceMap
>();
1126 (*FailedSymbolsDepMap
)[this] = std::move(SymbolsInErrorState
);
1127 return make_error
<FailedToMaterialize
>(std::move(FailedSymbolsDepMap
));
1130 // Otherwise notify all the completed queries.
1131 for (auto &Q
: CompletedQueries
) {
1132 assert(Q
->isComplete() && "Q is not complete");
1133 Q
->handleComplete();
1136 return Error::success();
1139 void JITDylib::notifyFailed(FailedSymbolsWorklist Worklist
) {
1140 AsynchronousSymbolQuerySet FailedQueries
;
1141 auto FailedSymbolsMap
= std::make_shared
<SymbolDependenceMap
>();
1143 // Failing no symbols is a no-op.
1144 if (Worklist
.empty())
1147 auto &ES
= Worklist
.front().first
->getExecutionSession();
1149 ES
.runSessionLocked([&]() {
1150 while (!Worklist
.empty()) {
1151 assert(Worklist
.back().first
&& "Failed JITDylib can not be null");
1152 auto &JD
= *Worklist
.back().first
;
1153 auto Name
= std::move(Worklist
.back().second
);
1154 Worklist
.pop_back();
1156 (*FailedSymbolsMap
)[&JD
].insert(Name
);
1158 assert(JD
.Symbols
.count(Name
) && "No symbol table entry for Name");
1159 auto &Sym
= JD
.Symbols
[Name
];
1161 // Move the symbol into the error state.
1162 // Note that this may be redundant: The symbol might already have been
1163 // moved to this state in response to the failure of a dependence.
1164 Sym
.setFlags(Sym
.getFlags() | JITSymbolFlags::HasError
);
1166 // FIXME: Come up with a sane mapping of state to
1167 // presence-of-MaterializingInfo so that we can assert presence / absence
1168 // here, rather than testing it.
1169 auto MII
= JD
.MaterializingInfos
.find(Name
);
1171 if (MII
== JD
.MaterializingInfos
.end())
1174 auto &MI
= MII
->second
;
1176 // Move all dependants to the error state and disconnect from them.
1177 for (auto &KV
: MI
.Dependants
) {
1178 auto &DependantJD
= *KV
.first
;
1179 for (auto &DependantName
: KV
.second
) {
1180 assert(DependantJD
.Symbols
.count(DependantName
) &&
1181 "No symbol table entry for DependantName");
1182 auto &DependantSym
= DependantJD
.Symbols
[DependantName
];
1183 DependantSym
.setFlags(DependantSym
.getFlags() |
1184 JITSymbolFlags::HasError
);
1186 assert(DependantJD
.MaterializingInfos
.count(DependantName
) &&
1187 "No MaterializingInfo for dependant");
1188 auto &DependantMI
= DependantJD
.MaterializingInfos
[DependantName
];
1190 auto UnemittedDepI
= DependantMI
.UnemittedDependencies
.find(&JD
);
1191 assert(UnemittedDepI
!= DependantMI
.UnemittedDependencies
.end() &&
1192 "No UnemittedDependencies entry for this JITDylib");
1193 assert(UnemittedDepI
->second
.count(Name
) &&
1194 "No UnemittedDependencies entry for this symbol");
1195 UnemittedDepI
->second
.erase(Name
);
1196 if (UnemittedDepI
->second
.empty())
1197 DependantMI
.UnemittedDependencies
.erase(UnemittedDepI
);
1199 // If this symbol is already in the emitted state then we need to
1200 // take responsibility for failing its queries, so add it to the
1202 if (DependantSym
.getState() == SymbolState::Emitted
) {
1203 assert(DependantMI
.Dependants
.empty() &&
1204 "Emitted symbol should not have dependants");
1205 Worklist
.push_back(std::make_pair(&DependantJD
, DependantName
));
1209 MI
.Dependants
.clear();
1211 // Disconnect from all unemitted depenencies.
1212 for (auto &KV
: MI
.UnemittedDependencies
) {
1213 auto &UnemittedDepJD
= *KV
.first
;
1214 for (auto &UnemittedDepName
: KV
.second
) {
1215 auto UnemittedDepMII
=
1216 UnemittedDepJD
.MaterializingInfos
.find(UnemittedDepName
);
1217 assert(UnemittedDepMII
!= UnemittedDepJD
.MaterializingInfos
.end() &&
1218 "Missing MII for unemitted dependency");
1219 assert(UnemittedDepMII
->second
.Dependants
.count(&JD
) &&
1220 "JD not listed as a dependant of unemitted dependency");
1221 assert(UnemittedDepMII
->second
.Dependants
[&JD
].count(Name
) &&
1222 "Name is not listed as a dependant of unemitted dependency");
1223 UnemittedDepMII
->second
.Dependants
[&JD
].erase(Name
);
1224 if (UnemittedDepMII
->second
.Dependants
[&JD
].empty())
1225 UnemittedDepMII
->second
.Dependants
.erase(&JD
);
1228 MI
.UnemittedDependencies
.clear();
1230 // Collect queries to be failed for this MII.
1231 for (auto &Q
: MII
->second
.pendingQueries()) {
1232 // Add the query to the list to be failed and detach it.
1233 FailedQueries
.insert(Q
);
1237 assert(MI
.Dependants
.empty() &&
1238 "Can not delete MaterializingInfo with dependants still attached");
1239 assert(MI
.UnemittedDependencies
.empty() &&
1240 "Can not delete MaterializingInfo with unemitted dependencies "
1242 assert(!MI
.hasQueriesPending() &&
1243 "Can not delete MaterializingInfo with queries pending");
1244 JD
.MaterializingInfos
.erase(MII
);
1248 for (auto &Q
: FailedQueries
)
1249 Q
->handleFailed(make_error
<FailedToMaterialize
>(FailedSymbolsMap
));
1252 void JITDylib::setSearchOrder(JITDylibSearchList NewSearchOrder
,
1253 bool SearchThisJITDylibFirst
,
1254 bool MatchNonExportedInThisDylib
) {
1255 if (SearchThisJITDylibFirst
) {
1256 if (NewSearchOrder
.empty() || NewSearchOrder
.front().first
!= this)
1257 NewSearchOrder
.insert(NewSearchOrder
.begin(),
1258 {this, MatchNonExportedInThisDylib
});
1261 ES
.runSessionLocked([&]() { SearchOrder
= std::move(NewSearchOrder
); });
1264 void JITDylib::addToSearchOrder(JITDylib
&JD
, bool MatchNonExported
) {
1265 ES
.runSessionLocked([&]() {
1266 SearchOrder
.push_back({&JD
, MatchNonExported
});
1270 void JITDylib::replaceInSearchOrder(JITDylib
&OldJD
, JITDylib
&NewJD
,
1271 bool MatchNonExported
) {
1272 ES
.runSessionLocked([&]() {
1273 auto I
= std::find_if(SearchOrder
.begin(), SearchOrder
.end(),
1274 [&](const JITDylibSearchList::value_type
&KV
) {
1275 return KV
.first
== &OldJD
;
1278 if (I
!= SearchOrder
.end())
1279 *I
= {&NewJD
, MatchNonExported
};
1283 void JITDylib::removeFromSearchOrder(JITDylib
&JD
) {
1284 ES
.runSessionLocked([&]() {
1285 auto I
= std::find_if(SearchOrder
.begin(), SearchOrder
.end(),
1286 [&](const JITDylibSearchList::value_type
&KV
) {
1287 return KV
.first
== &JD
;
1289 if (I
!= SearchOrder
.end())
1290 SearchOrder
.erase(I
);
1294 Error
JITDylib::remove(const SymbolNameSet
&Names
) {
1295 return ES
.runSessionLocked([&]() -> Error
{
1296 using SymbolMaterializerItrPair
=
1297 std::pair
<SymbolTable::iterator
, UnmaterializedInfosMap::iterator
>;
1298 std::vector
<SymbolMaterializerItrPair
> SymbolsToRemove
;
1299 SymbolNameSet Missing
;
1300 SymbolNameSet Materializing
;
1302 for (auto &Name
: Names
) {
1303 auto I
= Symbols
.find(Name
);
1305 // Note symbol missing.
1306 if (I
== Symbols
.end()) {
1307 Missing
.insert(Name
);
1311 // Note symbol materializing.
1312 if (I
->second
.isInMaterializationPhase()) {
1313 Materializing
.insert(Name
);
1317 auto UMII
= I
->second
.hasMaterializerAttached()
1318 ? UnmaterializedInfos
.find(Name
)
1319 : UnmaterializedInfos
.end();
1320 SymbolsToRemove
.push_back(std::make_pair(I
, UMII
));
1323 // If any of the symbols are not defined, return an error.
1324 if (!Missing
.empty())
1325 return make_error
<SymbolsNotFound
>(std::move(Missing
));
1327 // If any of the symbols are currently materializing, return an error.
1328 if (!Materializing
.empty())
1329 return make_error
<SymbolsCouldNotBeRemoved
>(std::move(Materializing
));
1331 // Remove the symbols.
1332 for (auto &SymbolMaterializerItrPair
: SymbolsToRemove
) {
1333 auto UMII
= SymbolMaterializerItrPair
.second
;
1335 // If there is a materializer attached, call discard.
1336 if (UMII
!= UnmaterializedInfos
.end()) {
1337 UMII
->second
->MU
->doDiscard(*this, UMII
->first
);
1338 UnmaterializedInfos
.erase(UMII
);
1341 auto SymI
= SymbolMaterializerItrPair
.first
;
1342 Symbols
.erase(SymI
);
1345 return Error::success();
1349 Expected
<SymbolFlagsMap
> JITDylib::lookupFlags(const SymbolNameSet
&Names
) {
1350 return ES
.runSessionLocked([&, this]() -> Expected
<SymbolFlagsMap
> {
1351 SymbolFlagsMap Result
;
1352 auto Unresolved
= lookupFlagsImpl(Result
, Names
);
1354 return Unresolved
.takeError();
1356 /// Run any definition generators.
1357 for (auto &DG
: DefGenerators
) {
1359 // Bail out early if we've resolved everything.
1360 if (Unresolved
->empty())
1363 // Run this generator.
1364 auto NewDefs
= DG
->tryToGenerate(*this, *Unresolved
);
1366 return NewDefs
.takeError();
1368 if (!NewDefs
->empty()) {
1369 auto Unresolved2
= lookupFlagsImpl(Result
, *NewDefs
);
1371 return Unresolved2
.takeError();
1373 assert(Unresolved2
->empty() &&
1374 "All fallback defs should have been found by lookupFlagsImpl");
1377 for (auto &Name
: *NewDefs
)
1378 Unresolved
->erase(Name
);
1384 Expected
<SymbolNameSet
> JITDylib::lookupFlagsImpl(SymbolFlagsMap
&Flags
,
1385 const SymbolNameSet
&Names
) {
1386 SymbolNameSet Unresolved
;
1388 for (auto &Name
: Names
) {
1389 auto I
= Symbols
.find(Name
);
1390 if (I
!= Symbols
.end()) {
1391 assert(!Flags
.count(Name
) && "Symbol already present in Flags map");
1392 Flags
[Name
] = I
->second
.getFlags();
1394 Unresolved
.insert(Name
);
1400 Error
JITDylib::lodgeQuery(std::shared_ptr
<AsynchronousSymbolQuery
> &Q
,
1401 SymbolNameSet
&Unresolved
, bool MatchNonExported
,
1402 MaterializationUnitList
&MUs
) {
1403 assert(Q
&& "Query can not be null");
1405 if (auto Err
= lodgeQueryImpl(Q
, Unresolved
, MatchNonExported
, MUs
))
1408 // Run any definition generators.
1409 for (auto &DG
: DefGenerators
) {
1411 // Bail out early if we have resolved everything.
1412 if (Unresolved
.empty())
1415 // Run the generator.
1416 auto NewDefs
= DG
->tryToGenerate(*this, Unresolved
);
1418 // If the generator returns an error then bail out.
1420 return NewDefs
.takeError();
1422 // If the generator was able to generate new definitions for any of the
1423 // unresolved symbols then lodge the query against them.
1424 if (!NewDefs
->empty()) {
1425 for (auto &D
: *NewDefs
)
1426 Unresolved
.erase(D
);
1428 // Lodge query. This can not fail as any new definitions were added
1429 // by the generator under the session locked. Since they can't have
1430 // started materializing yet the can not have failed.
1431 cantFail(lodgeQueryImpl(Q
, *NewDefs
, MatchNonExported
, MUs
));
1433 assert(NewDefs
->empty() &&
1434 "All fallback defs should have been found by lookupImpl");
1438 return Error::success();
1441 Error
JITDylib::lodgeQueryImpl(
1442 std::shared_ptr
<AsynchronousSymbolQuery
> &Q
, SymbolNameSet
&Unresolved
,
1443 bool MatchNonExported
,
1444 std::vector
<std::unique_ptr
<MaterializationUnit
>> &MUs
) {
1446 std::vector
<SymbolStringPtr
> ToRemove
;
1447 for (auto Name
: Unresolved
) {
1449 // Search for the name in Symbols. Skip it if not found.
1450 auto SymI
= Symbols
.find(Name
);
1451 if (SymI
== Symbols
.end())
1454 // If this is a non exported symbol and we're skipping those then skip it.
1455 if (!SymI
->second
.getFlags().isExported() && !MatchNonExported
)
1458 // If we matched against Name in JD, mark it to be removed from the
1460 ToRemove
.push_back(Name
);
1462 // If we matched against this symbol but it is in the error state then
1463 // bail out and treat it as a failure to materialize.
1464 if (SymI
->second
.getFlags().hasError()) {
1465 auto FailedSymbolsMap
= std::make_shared
<SymbolDependenceMap
>();
1466 (*FailedSymbolsMap
)[this] = {Name
};
1467 return make_error
<FailedToMaterialize
>(std::move(FailedSymbolsMap
));
1470 // If this symbol already meets the required state for then notify the
1471 // query and continue.
1472 if (SymI
->second
.getState() >= Q
->getRequiredState()) {
1473 Q
->notifySymbolMetRequiredState(Name
, SymI
->second
.getSymbol());
1477 // Otherwise this symbol does not yet meet the required state. Check whether
1478 // it has a materializer attached, and if so prepare to run it.
1479 if (SymI
->second
.hasMaterializerAttached()) {
1480 assert(SymI
->second
.getAddress() == 0 &&
1481 "Symbol not resolved but already has address?");
1482 auto UMII
= UnmaterializedInfos
.find(Name
);
1483 assert(UMII
!= UnmaterializedInfos
.end() &&
1484 "Lazy symbol should have UnmaterializedInfo");
1485 auto MU
= std::move(UMII
->second
->MU
);
1486 assert(MU
!= nullptr && "Materializer should not be null");
1488 // Move all symbols associated with this MaterializationUnit into
1489 // materializing state.
1490 for (auto &KV
: MU
->getSymbols()) {
1491 auto SymK
= Symbols
.find(KV
.first
);
1492 SymK
->second
.setMaterializerAttached(false);
1493 SymK
->second
.setState(SymbolState::Materializing
);
1494 UnmaterializedInfos
.erase(KV
.first
);
1497 // Add MU to the list of MaterializationUnits to be materialized.
1498 MUs
.push_back(std::move(MU
));
1501 // Add the query to the PendingQueries list.
1502 assert(SymI
->second
.isInMaterializationPhase() &&
1503 "By this line the symbol should be materializing");
1504 auto &MI
= MaterializingInfos
[Name
];
1506 Q
->addQueryDependence(*this, Name
);
1509 // Remove any symbols that we found.
1510 for (auto &Name
: ToRemove
)
1511 Unresolved
.erase(Name
);
1513 return Error::success();
1516 Expected
<SymbolNameSet
>
1517 JITDylib::legacyLookup(std::shared_ptr
<AsynchronousSymbolQuery
> Q
,
1518 SymbolNameSet Names
) {
1519 assert(Q
&& "Query can not be null");
1521 ES
.runOutstandingMUs();
1523 bool QueryComplete
= false;
1524 std::vector
<std::unique_ptr
<MaterializationUnit
>> MUs
;
1526 SymbolNameSet Unresolved
= std::move(Names
);
1527 auto Err
= ES
.runSessionLocked([&, this]() -> Error
{
1528 QueryComplete
= lookupImpl(Q
, MUs
, Unresolved
);
1530 // Run any definition generators.
1531 for (auto &DG
: DefGenerators
) {
1533 // Bail out early if we have resolved everything.
1534 if (Unresolved
.empty())
1537 assert(!QueryComplete
&& "query complete but unresolved symbols remain?");
1538 auto NewDefs
= DG
->tryToGenerate(*this, Unresolved
);
1540 return NewDefs
.takeError();
1541 if (!NewDefs
->empty()) {
1542 for (auto &D
: *NewDefs
)
1543 Unresolved
.erase(D
);
1544 QueryComplete
= lookupImpl(Q
, MUs
, *NewDefs
);
1545 assert(NewDefs
->empty() &&
1546 "All fallback defs should have been found by lookupImpl");
1549 return Error::success();
1553 return std::move(Err
);
1555 assert((MUs
.empty() || !QueryComplete
) &&
1556 "If action flags are set, there should be no work to do (so no MUs)");
1559 Q
->handleComplete();
1561 // FIXME: Swap back to the old code below once RuntimeDyld works with
1562 // callbacks from asynchronous queries.
1563 // Add MUs to the OutstandingMUs list.
1565 std::lock_guard
<std::recursive_mutex
> Lock(ES
.OutstandingMUsMutex
);
1566 for (auto &MU
: MUs
)
1567 ES
.OutstandingMUs
.push_back(make_pair(this, std::move(MU
)));
1569 ES
.runOutstandingMUs();
1571 // Dispatch any required MaterializationUnits for materialization.
1572 // for (auto &MU : MUs)
1573 // ES.dispatchMaterialization(*this, std::move(MU));
1578 bool JITDylib::lookupImpl(
1579 std::shared_ptr
<AsynchronousSymbolQuery
> &Q
,
1580 std::vector
<std::unique_ptr
<MaterializationUnit
>> &MUs
,
1581 SymbolNameSet
&Unresolved
) {
1582 bool QueryComplete
= false;
1584 std::vector
<SymbolStringPtr
> ToRemove
;
1585 for (auto Name
: Unresolved
) {
1587 // Search for the name in Symbols. Skip it if not found.
1588 auto SymI
= Symbols
.find(Name
);
1589 if (SymI
== Symbols
.end())
1592 // If we found Name, mark it to be removed from the Unresolved set.
1593 ToRemove
.push_back(Name
);
1595 if (SymI
->second
.getState() >= Q
->getRequiredState()) {
1596 Q
->notifySymbolMetRequiredState(Name
, SymI
->second
.getSymbol());
1597 if (Q
->isComplete())
1598 QueryComplete
= true;
1602 // If the symbol is lazy, get the MaterialiaztionUnit for it.
1603 if (SymI
->second
.hasMaterializerAttached()) {
1604 assert(SymI
->second
.getAddress() == 0 &&
1605 "Lazy symbol should not have a resolved address");
1606 auto UMII
= UnmaterializedInfos
.find(Name
);
1607 assert(UMII
!= UnmaterializedInfos
.end() &&
1608 "Lazy symbol should have UnmaterializedInfo");
1609 auto MU
= std::move(UMII
->second
->MU
);
1610 assert(MU
!= nullptr && "Materializer should not be null");
1612 // Kick all symbols associated with this MaterializationUnit into
1613 // materializing state.
1614 for (auto &KV
: MU
->getSymbols()) {
1615 auto SymK
= Symbols
.find(KV
.first
);
1616 assert(SymK
!= Symbols
.end() && "Missing symbol table entry");
1617 SymK
->second
.setState(SymbolState::Materializing
);
1618 SymK
->second
.setMaterializerAttached(false);
1619 UnmaterializedInfos
.erase(KV
.first
);
1622 // Add MU to the list of MaterializationUnits to be materialized.
1623 MUs
.push_back(std::move(MU
));
1626 // Add the query to the PendingQueries list.
1627 assert(SymI
->second
.isInMaterializationPhase() &&
1628 "By this line the symbol should be materializing");
1629 auto &MI
= MaterializingInfos
[Name
];
1631 Q
->addQueryDependence(*this, Name
);
1634 // Remove any marked symbols from the Unresolved set.
1635 for (auto &Name
: ToRemove
)
1636 Unresolved
.erase(Name
);
1638 return QueryComplete
;
1641 void JITDylib::dump(raw_ostream
&OS
) {
1642 ES
.runSessionLocked([&, this]() {
1643 OS
<< "JITDylib \"" << JITDylibName
<< "\" (ES: "
1644 << format("0x%016" PRIx64
, reinterpret_cast<uintptr_t>(&ES
)) << "):\n"
1645 << "Search order: [";
1646 for (auto &KV
: SearchOrder
)
1647 OS
<< " (\"" << KV
.first
->getName() << "\", "
1648 << (KV
.second
? "all" : "exported only") << ")";
1650 << "Symbol table:\n";
1652 for (auto &KV
: Symbols
) {
1653 OS
<< " \"" << *KV
.first
<< "\": ";
1654 if (auto Addr
= KV
.second
.getAddress())
1655 OS
<< format("0x%016" PRIx64
, Addr
) << ", " << KV
.second
.getFlags()
1658 OS
<< "<not resolved> ";
1660 OS
<< KV
.second
.getState();
1662 if (KV
.second
.hasMaterializerAttached()) {
1663 OS
<< " (Materializer ";
1664 auto I
= UnmaterializedInfos
.find(KV
.first
);
1665 assert(I
!= UnmaterializedInfos
.end() &&
1666 "Lazy symbol should have UnmaterializedInfo");
1667 OS
<< I
->second
->MU
.get() << ")\n";
1672 if (!MaterializingInfos
.empty())
1673 OS
<< " MaterializingInfos entries:\n";
1674 for (auto &KV
: MaterializingInfos
) {
1675 OS
<< " \"" << *KV
.first
<< "\":\n"
1676 << " " << KV
.second
.pendingQueries().size()
1677 << " pending queries: { ";
1678 for (const auto &Q
: KV
.second
.pendingQueries())
1679 OS
<< Q
.get() << " (" << Q
->getRequiredState() << ") ";
1680 OS
<< "}\n Dependants:\n";
1681 for (auto &KV2
: KV
.second
.Dependants
)
1682 OS
<< " " << KV2
.first
->getName() << ": " << KV2
.second
<< "\n";
1683 OS
<< " Unemitted Dependencies:\n";
1684 for (auto &KV2
: KV
.second
.UnemittedDependencies
)
1685 OS
<< " " << KV2
.first
->getName() << ": " << KV2
.second
<< "\n";
1690 void JITDylib::MaterializingInfo::addQuery(
1691 std::shared_ptr
<AsynchronousSymbolQuery
> Q
) {
1693 auto I
= std::lower_bound(
1694 PendingQueries
.rbegin(), PendingQueries
.rend(), Q
->getRequiredState(),
1695 [](const std::shared_ptr
<AsynchronousSymbolQuery
> &V
, SymbolState S
) {
1696 return V
->getRequiredState() <= S
;
1698 PendingQueries
.insert(I
.base(), std::move(Q
));
1701 void JITDylib::MaterializingInfo::removeQuery(
1702 const AsynchronousSymbolQuery
&Q
) {
1703 // FIXME: Implement 'find_as' for shared_ptr<T>/T*.
1705 std::find_if(PendingQueries
.begin(), PendingQueries
.end(),
1706 [&Q
](const std::shared_ptr
<AsynchronousSymbolQuery
> &V
) {
1707 return V
.get() == &Q
;
1709 assert(I
!= PendingQueries
.end() &&
1710 "Query is not attached to this MaterializingInfo");
1711 PendingQueries
.erase(I
);
1714 JITDylib::AsynchronousSymbolQueryList
1715 JITDylib::MaterializingInfo::takeQueriesMeeting(SymbolState RequiredState
) {
1716 AsynchronousSymbolQueryList Result
;
1717 while (!PendingQueries
.empty()) {
1718 if (PendingQueries
.back()->getRequiredState() > RequiredState
)
1721 Result
.push_back(std::move(PendingQueries
.back()));
1722 PendingQueries
.pop_back();
1728 JITDylib::JITDylib(ExecutionSession
&ES
, std::string Name
)
1729 : ES(ES
), JITDylibName(std::move(Name
)) {
1730 SearchOrder
.push_back({this, true});
1733 Error
JITDylib::defineImpl(MaterializationUnit
&MU
) {
1734 SymbolNameSet Duplicates
;
1735 std::vector
<SymbolStringPtr
> ExistingDefsOverridden
;
1736 std::vector
<SymbolStringPtr
> MUDefsOverridden
;
1738 for (const auto &KV
: MU
.getSymbols()) {
1739 auto I
= Symbols
.find(KV
.first
);
1741 if (I
!= Symbols
.end()) {
1742 if (KV
.second
.isStrong()) {
1743 if (I
->second
.getFlags().isStrong() ||
1744 I
->second
.getState() > SymbolState::NeverSearched
)
1745 Duplicates
.insert(KV
.first
);
1747 assert(I
->second
.getState() == SymbolState::NeverSearched
&&
1748 "Overridden existing def should be in the never-searched "
1750 ExistingDefsOverridden
.push_back(KV
.first
);
1753 MUDefsOverridden
.push_back(KV
.first
);
1757 // If there were any duplicate definitions then bail out.
1758 if (!Duplicates
.empty())
1759 return make_error
<DuplicateDefinition
>(**Duplicates
.begin());
1761 // Discard any overridden defs in this MU.
1762 for (auto &S
: MUDefsOverridden
)
1763 MU
.doDiscard(*this, S
);
1765 // Discard existing overridden defs.
1766 for (auto &S
: ExistingDefsOverridden
) {
1768 auto UMII
= UnmaterializedInfos
.find(S
);
1769 assert(UMII
!= UnmaterializedInfos
.end() &&
1770 "Overridden existing def should have an UnmaterializedInfo");
1771 UMII
->second
->MU
->doDiscard(*this, S
);
1774 // Finally, add the defs from this MU.
1775 for (auto &KV
: MU
.getSymbols()) {
1776 auto &SymEntry
= Symbols
[KV
.first
];
1777 SymEntry
.setFlags(KV
.second
);
1778 SymEntry
.setState(SymbolState::NeverSearched
);
1779 SymEntry
.setMaterializerAttached(true);
1782 return Error::success();
1785 void JITDylib::detachQueryHelper(AsynchronousSymbolQuery
&Q
,
1786 const SymbolNameSet
&QuerySymbols
) {
1787 for (auto &QuerySymbol
: QuerySymbols
) {
1788 assert(MaterializingInfos
.count(QuerySymbol
) &&
1789 "QuerySymbol does not have MaterializingInfo");
1790 auto &MI
= MaterializingInfos
[QuerySymbol
];
1795 void JITDylib::transferEmittedNodeDependencies(
1796 MaterializingInfo
&DependantMI
, const SymbolStringPtr
&DependantName
,
1797 MaterializingInfo
&EmittedMI
) {
1798 for (auto &KV
: EmittedMI
.UnemittedDependencies
) {
1799 auto &DependencyJD
= *KV
.first
;
1800 SymbolNameSet
*UnemittedDependenciesOnDependencyJD
= nullptr;
1802 for (auto &DependencyName
: KV
.second
) {
1803 auto &DependencyMI
= DependencyJD
.MaterializingInfos
[DependencyName
];
1805 // Do not add self dependencies.
1806 if (&DependencyMI
== &DependantMI
)
1809 // If we haven't looked up the dependencies for DependencyJD yet, do it
1810 // now and cache the result.
1811 if (!UnemittedDependenciesOnDependencyJD
)
1812 UnemittedDependenciesOnDependencyJD
=
1813 &DependantMI
.UnemittedDependencies
[&DependencyJD
];
1815 DependencyMI
.Dependants
[this].insert(DependantName
);
1816 UnemittedDependenciesOnDependencyJD
->insert(DependencyName
);
1821 ExecutionSession::ExecutionSession(std::shared_ptr
<SymbolStringPool
> SSP
)
1822 : SSP(SSP
? std::move(SSP
) : std::make_shared
<SymbolStringPool
>()) {
1823 // Construct the main dylib.
1824 JDs
.push_back(std::unique_ptr
<JITDylib
>(new JITDylib(*this, "<main>")));
1827 JITDylib
&ExecutionSession::getMainJITDylib() {
1828 return runSessionLocked([this]() -> JITDylib
& { return *JDs
.front(); });
1831 JITDylib
*ExecutionSession::getJITDylibByName(StringRef Name
) {
1832 return runSessionLocked([&, this]() -> JITDylib
* {
1833 for (auto &JD
: JDs
)
1834 if (JD
->getName() == Name
)
1840 JITDylib
&ExecutionSession::createJITDylib(std::string Name
,
1841 bool AddToMainDylibSearchOrder
) {
1842 assert(!getJITDylibByName(Name
) && "JITDylib with that name already exists");
1843 return runSessionLocked([&, this]() -> JITDylib
& {
1845 std::unique_ptr
<JITDylib
>(new JITDylib(*this, std::move(Name
))));
1846 if (AddToMainDylibSearchOrder
)
1847 JDs
.front()->addToSearchOrder(*JDs
.back());
1852 void ExecutionSession::legacyFailQuery(AsynchronousSymbolQuery
&Q
, Error Err
) {
1853 assert(!!Err
&& "Error should be in failure state");
1855 bool SendErrorToQuery
;
1856 runSessionLocked([&]() {
1858 SendErrorToQuery
= Q
.canStillFail();
1861 if (SendErrorToQuery
)
1862 Q
.handleFailed(std::move(Err
));
1864 reportError(std::move(Err
));
1867 Expected
<SymbolMap
> ExecutionSession::legacyLookup(
1868 LegacyAsyncLookupFunction AsyncLookup
, SymbolNameSet Names
,
1869 SymbolState RequiredState
,
1870 RegisterDependenciesFunction RegisterDependencies
) {
1871 #if LLVM_ENABLE_THREADS
1872 // In the threaded case we use promises to return the results.
1873 std::promise
<SymbolMap
> PromisedResult
;
1874 Error ResolutionError
= Error::success();
1875 auto NotifyComplete
= [&](Expected
<SymbolMap
> R
) {
1877 PromisedResult
.set_value(std::move(*R
));
1879 ErrorAsOutParameter
_(&ResolutionError
);
1880 ResolutionError
= R
.takeError();
1881 PromisedResult
.set_value(SymbolMap());
1886 Error ResolutionError
= Error::success();
1888 auto NotifyComplete
= [&](Expected
<SymbolMap
> R
) {
1889 ErrorAsOutParameter
_(&ResolutionError
);
1891 Result
= std::move(*R
);
1893 ResolutionError
= R
.takeError();
1897 auto Query
= std::make_shared
<AsynchronousSymbolQuery
>(
1898 Names
, RequiredState
, std::move(NotifyComplete
));
1899 // FIXME: This should be run session locked along with the registration code
1900 // and error reporting below.
1901 SymbolNameSet UnresolvedSymbols
= AsyncLookup(Query
, std::move(Names
));
1903 // If the query was lodged successfully then register the dependencies,
1904 // otherwise fail it with an error.
1905 if (UnresolvedSymbols
.empty())
1906 RegisterDependencies(Query
->QueryRegistrations
);
1908 bool DeliverError
= runSessionLocked([&]() {
1910 return Query
->canStillFail();
1912 auto Err
= make_error
<SymbolsNotFound
>(std::move(UnresolvedSymbols
));
1914 Query
->handleFailed(std::move(Err
));
1916 reportError(std::move(Err
));
1919 #if LLVM_ENABLE_THREADS
1920 auto ResultFuture
= PromisedResult
.get_future();
1921 auto Result
= ResultFuture
.get();
1922 if (ResolutionError
)
1923 return std::move(ResolutionError
);
1924 return std::move(Result
);
1927 if (ResolutionError
)
1928 return std::move(ResolutionError
);
1934 void ExecutionSession::lookup(
1935 const JITDylibSearchList
&SearchOrder
, SymbolNameSet Symbols
,
1936 SymbolState RequiredState
, SymbolsResolvedCallback NotifyComplete
,
1937 RegisterDependenciesFunction RegisterDependencies
) {
1940 runSessionLocked([&]() {
1941 dbgs() << "Looking up " << Symbols
<< " in " << SearchOrder
1942 << " (required state: " << RequiredState
<< ")\n";
1946 // lookup can be re-entered recursively if running on a single thread. Run any
1947 // outstanding MUs in case this query depends on them, otherwise this lookup
1948 // will starve waiting for a result from an MU that is stuck in the queue.
1949 runOutstandingMUs();
1951 auto Unresolved
= std::move(Symbols
);
1952 std::map
<JITDylib
*, MaterializationUnitList
> CollectedMUsMap
;
1953 auto Q
= std::make_shared
<AsynchronousSymbolQuery
>(Unresolved
, RequiredState
,
1954 std::move(NotifyComplete
));
1955 bool QueryComplete
= false;
1957 auto LodgingErr
= runSessionLocked([&]() -> Error
{
1958 auto LodgeQuery
= [&]() -> Error
{
1959 for (auto &KV
: SearchOrder
) {
1960 assert(KV
.first
&& "JITDylibList entries must not be null");
1961 assert(!CollectedMUsMap
.count(KV
.first
) &&
1962 "JITDylibList should not contain duplicate entries");
1964 auto &JD
= *KV
.first
;
1965 auto MatchNonExported
= KV
.second
;
1966 if (auto Err
= JD
.lodgeQuery(Q
, Unresolved
, MatchNonExported
,
1967 CollectedMUsMap
[&JD
]))
1971 if (!Unresolved
.empty())
1972 return make_error
<SymbolsNotFound
>(std::move(Unresolved
));
1974 return Error::success();
1977 if (auto Err
= LodgeQuery()) {
1980 // Disconnect the query from its dependencies.
1984 for (auto &KV
: CollectedMUsMap
)
1985 for (auto &MU
: KV
.second
)
1986 KV
.first
->replace(std::move(MU
));
1991 // Query lodged successfully.
1993 // Record whether this query is fully ready / resolved. We will use
1994 // this to call handleFullyResolved/handleFullyReady outside the session
1996 QueryComplete
= Q
->isComplete();
1998 // Call the register dependencies function.
1999 if (RegisterDependencies
&& !Q
->QueryRegistrations
.empty())
2000 RegisterDependencies(Q
->QueryRegistrations
);
2002 return Error::success();
2006 Q
->handleFailed(std::move(LodgingErr
));
2011 Q
->handleComplete();
2013 // Move the MUs to the OutstandingMUs list, then materialize.
2015 std::lock_guard
<std::recursive_mutex
> Lock(OutstandingMUsMutex
);
2017 for (auto &KV
: CollectedMUsMap
)
2018 for (auto &MU
: KV
.second
)
2019 OutstandingMUs
.push_back(std::make_pair(KV
.first
, std::move(MU
)));
2022 runOutstandingMUs();
2026 ExecutionSession::lookup(const JITDylibSearchList
&SearchOrder
,
2027 const SymbolNameSet
&Symbols
,
2028 SymbolState RequiredState
,
2029 RegisterDependenciesFunction RegisterDependencies
) {
2030 #if LLVM_ENABLE_THREADS
2031 // In the threaded case we use promises to return the results.
2032 std::promise
<SymbolMap
> PromisedResult
;
2033 Error ResolutionError
= Error::success();
2035 auto NotifyComplete
= [&](Expected
<SymbolMap
> R
) {
2037 PromisedResult
.set_value(std::move(*R
));
2039 ErrorAsOutParameter
_(&ResolutionError
);
2040 ResolutionError
= R
.takeError();
2041 PromisedResult
.set_value(SymbolMap());
2047 Error ResolutionError
= Error::success();
2049 auto NotifyComplete
= [&](Expected
<SymbolMap
> R
) {
2050 ErrorAsOutParameter
_(&ResolutionError
);
2052 Result
= std::move(*R
);
2054 ResolutionError
= R
.takeError();
2058 // Perform the asynchronous lookup.
2059 lookup(SearchOrder
, Symbols
, RequiredState
, NotifyComplete
,
2060 RegisterDependencies
);
2062 #if LLVM_ENABLE_THREADS
2063 auto ResultFuture
= PromisedResult
.get_future();
2064 auto Result
= ResultFuture
.get();
2066 if (ResolutionError
)
2067 return std::move(ResolutionError
);
2069 return std::move(Result
);
2072 if (ResolutionError
)
2073 return std::move(ResolutionError
);
2079 Expected
<JITEvaluatedSymbol
>
2080 ExecutionSession::lookup(const JITDylibSearchList
&SearchOrder
,
2081 SymbolStringPtr Name
) {
2082 SymbolNameSet
Names({Name
});
2084 if (auto ResultMap
= lookup(SearchOrder
, std::move(Names
), SymbolState::Ready
,
2085 NoDependenciesToRegister
)) {
2086 assert(ResultMap
->size() == 1 && "Unexpected number of results");
2087 assert(ResultMap
->count(Name
) && "Missing result for symbol");
2088 return std::move(ResultMap
->begin()->second
);
2090 return ResultMap
.takeError();
2093 Expected
<JITEvaluatedSymbol
>
2094 ExecutionSession::lookup(ArrayRef
<JITDylib
*> SearchOrder
,
2095 SymbolStringPtr Name
) {
2096 SymbolNameSet
Names({Name
});
2098 JITDylibSearchList FullSearchOrder
;
2099 FullSearchOrder
.reserve(SearchOrder
.size());
2100 for (auto *JD
: SearchOrder
)
2101 FullSearchOrder
.push_back({JD
, false});
2103 return lookup(FullSearchOrder
, Name
);
2106 Expected
<JITEvaluatedSymbol
>
2107 ExecutionSession::lookup(ArrayRef
<JITDylib
*> SearchOrder
, StringRef Name
) {
2108 return lookup(SearchOrder
, intern(Name
));
2111 void ExecutionSession::dump(raw_ostream
&OS
) {
2112 runSessionLocked([this, &OS
]() {
2113 for (auto &JD
: JDs
)
2118 void ExecutionSession::runOutstandingMUs() {
2120 std::pair
<JITDylib
*, std::unique_ptr
<MaterializationUnit
>> JITDylibAndMU
;
2123 std::lock_guard
<std::recursive_mutex
> Lock(OutstandingMUsMutex
);
2124 if (!OutstandingMUs
.empty()) {
2125 JITDylibAndMU
= std::move(OutstandingMUs
.back());
2126 OutstandingMUs
.pop_back();
2130 if (JITDylibAndMU
.first
) {
2131 assert(JITDylibAndMU
.second
&& "JITDylib, but no MU?");
2132 dispatchMaterialization(*JITDylibAndMU
.first
,
2133 std::move(JITDylibAndMU
.second
));
2139 MangleAndInterner::MangleAndInterner(ExecutionSession
&ES
, const DataLayout
&DL
)
2142 SymbolStringPtr
MangleAndInterner::operator()(StringRef Name
) {
2143 std::string MangledName
;
2145 raw_string_ostream
MangledNameStream(MangledName
);
2146 Mangler::getNameWithPrefix(MangledNameStream
, Name
, DL
);
2148 return ES
.intern(MangledName
);
2151 } // End namespace orc.
2152 } // End namespace llvm.