12#include "llvm/Config/llvm-config.h"
18#include <condition_variable>
22#define DEBUG_TYPE "orc"
38void MaterializationUnit::anchor() {}
41 assert((
reinterpret_cast<uintptr_t
>(JD.get()) & 0x1) == 0 &&
42 "JITDylib must be two byte aligned");
44 JDAndFlag.store(
reinterpret_cast<uintptr_t
>(JD.get()));
60void ResourceTracker::makeDefunct() {
61 uintptr_t Val = JDAndFlag.load();
76 OS <<
"Resource tracker " << (
void *)RT.
get() <<
" became defunct";
80 std::shared_ptr<SymbolStringPool> SSP,
81 std::shared_ptr<SymbolDependenceMap> Symbols)
83 assert(this->SSP &&
"String pool cannot be null");
84 assert(!this->Symbols->empty() &&
"Can not fail to resolve an empty set");
88 for (
auto &KV : *this->Symbols)
93 for (
auto &KV : *Symbols)
102 OS <<
"Failed to materialize symbols: " << *Symbols;
108 for (
auto &Sym : Symbols)
109 this->Symbols.push_back(Sym);
110 assert(!this->Symbols.
empty() &&
"Can not fail to resolve an empty set");
116 assert(!this->Symbols.empty() &&
"Can not fail to resolve an empty set");
124 OS <<
"Symbols not found: " << Symbols;
128 std::shared_ptr<SymbolStringPool> SSP,
SymbolNameSet Symbols)
130 assert(!this->Symbols.
empty() &&
"Can not fail to resolve an empty set");
138 OS <<
"Symbols could not be removed: " << Symbols;
146 OS <<
"Missing definitions in module " <<
ModuleName
155 OS <<
"Unexpected definitions in module " <<
ModuleName
162 : NotifyComplete(
std::
move(NotifyComplete)), RequiredState(RequiredState) {
164 "Cannot query for a symbols that have not reached the resolve state "
167 OutstandingSymbolsCount = Symbols.size();
169 for (
auto &KV : Symbols)
170 ResolvedSymbols[KV.first] =
nullptr;
177 "Resolving symbol outside the requested set");
178 assert(
I->second.getAddress() == 0 &&
"Redundantly resolving symbol Name");
185 I->second = std::move(Sym);
186 --OutstandingSymbolsCount;
190 assert(OutstandingSymbolsCount == 0 &&
191 "Symbols remain, handleComplete called prematurely");
193 class RunQueryCompleteTask :
public Task {
195 RunQueryCompleteTask(
SymbolMap ResolvedSymbols,
197 : ResolvedSymbols(
std::
move(ResolvedSymbols)),
198 NotifyComplete(
std::
move(NotifyComplete)) {}
200 OS <<
"Execute query complete callback for " << ResolvedSymbols;
202 void run()
override { NotifyComplete(std::move(ResolvedSymbols)); }
209 auto T = std::make_unique<RunQueryCompleteTask>(std::move(ResolvedSymbols),
210 std::move(NotifyComplete));
215void AsynchronousSymbolQuery::handleFailed(Error Err) {
217 OutstandingSymbolsCount == 0 &&
218 "Query should already have been abandoned");
219 NotifyComplete(std::move(Err));
223void AsynchronousSymbolQuery::addQueryDependence(JITDylib &JD,
224 SymbolStringPtr
Name) {
227 assert(Added &&
"Duplicate dependence notification?");
230void AsynchronousSymbolQuery::removeQueryDependence(
231 JITDylib &JD,
const SymbolStringPtr &
Name) {
232 auto QRI = QueryRegistrations.
find(&JD);
233 assert(QRI != QueryRegistrations.
end() &&
234 "No dependencies registered for JD");
235 assert(QRI->second.count(
Name) &&
"No dependency on Name in JD");
236 QRI->second.erase(
Name);
237 if (QRI->second.empty())
238 QueryRegistrations.
erase(QRI);
241void AsynchronousSymbolQuery::dropSymbol(
const SymbolStringPtr &
Name) {
244 "Redundant removal of weakly-referenced symbol");
246 --OutstandingSymbolsCount;
249void AsynchronousSymbolQuery::detach() {
250 ResolvedSymbols.
clear();
251 OutstandingSymbolsCount = 0;
252 for (
auto &KV : QueryRegistrations)
253 KV.first->detachQueryHelper(*
this, KV.second);
254 QueryRegistrations.clear();
262 return "<Absolute Symbols>";
265void AbsoluteSymbolsMaterializationUnit::materialize(
266 std::unique_ptr<MaterializationResponsibility> R) {
272 if (
auto Err = R->notifyResolved(Symbols)) {
273 R->getExecutionSession().reportError(std::move(Err));
274 R->failMaterialization();
277 if (
auto Err = R->notifyEmitted()) {
278 R->getExecutionSession().reportError(std::move(Err));
279 R->failMaterialization();
284void AbsoluteSymbolsMaterializationUnit::discard(
const JITDylib &JD,
285 const SymbolStringPtr &
Name) {
290MaterializationUnit::Interface
291AbsoluteSymbolsMaterializationUnit::extractFlags(
const SymbolMap &Symbols) {
293 for (
const auto &KV : Symbols)
294 Flags[KV.first] = KV.second.getFlags();
295 return MaterializationUnit::Interface(std::move(Flags),
nullptr);
302 SourceJDLookupFlags(SourceJDLookupFlags), Aliases(
std::
move(Aliases)) {}
305 return "<Reexports>";
308void ReExportsMaterializationUnit::materialize(
309 std::unique_ptr<MaterializationResponsibility> R) {
311 auto &ES = R->getTargetJITDylib().getExecutionSession();
312 JITDylib &TgtJD = R->getTargetJITDylib();
313 JITDylib &SrcJD = SourceJD ? *SourceJD : TgtJD;
318 auto RequestedSymbols = R->getRequestedSymbols();
321 for (
auto &
Name : RequestedSymbols) {
323 assert(
I != Aliases.
end() &&
"Symbol not found in aliases map?");
324 RequestedAliases[
Name] = std::move(
I->second);
330 dbgs() <<
"materializing reexports: target = " << TgtJD.
getName()
331 <<
", source = " << SrcJD.
getName() <<
" " << RequestedAliases
336 if (!Aliases.
empty()) {
337 auto Err = SourceJD ?
R->replace(
reexports(*SourceJD, std::move(Aliases),
338 SourceJDLookupFlags))
345 R->failMaterialization();
352 struct OnResolveInfo {
353 OnResolveInfo(std::unique_ptr<MaterializationResponsibility> R,
354 SymbolAliasMap Aliases)
357 std::unique_ptr<MaterializationResponsibility>
R;
369 std::vector<std::pair<SymbolLookupSet, std::shared_ptr<OnResolveInfo>>>
371 while (!RequestedAliases.
empty()) {
373 SymbolLookupSet QuerySymbols;
377 for (
auto &KV : RequestedAliases) {
379 if (&SrcJD == &TgtJD && (QueryAliases.count(KV.second.Aliasee) ||
380 RequestedAliases.count(KV.second.Aliasee)))
383 ResponsibilitySymbols.
insert(KV.first);
384 QuerySymbols.add(KV.second.Aliasee,
385 KV.second.AliasFlags.hasMaterializationSideEffectsOnly()
388 QueryAliases[KV.first] = std::move(KV.second);
392 for (
auto &KV : QueryAliases)
393 RequestedAliases.erase(KV.first);
395 assert(!QuerySymbols.empty() &&
"Alias cycle detected!");
397 auto NewR =
R->delegate(ResponsibilitySymbols);
400 R->failMaterialization();
404 auto QueryInfo = std::make_shared<OnResolveInfo>(std::move(*NewR),
405 std::move(QueryAliases));
406 QueryInfos.push_back(
407 make_pair(std::move(QuerySymbols), std::move(QueryInfo)));
411 while (!QueryInfos.empty()) {
412 auto QuerySymbols = std::move(QueryInfos.back().first);
413 auto QueryInfo = std::move(QueryInfos.back().second);
415 QueryInfos.pop_back();
417 auto RegisterDependencies = [QueryInfo,
424 assert(Deps.size() == 1 && Deps.count(&SrcJD) &&
425 "Unexpected dependencies for reexports");
427 auto &SrcJDDeps = Deps.find(&SrcJD)->second;
429 auto &PerAliasDeps = PerAliasDepsMap[&SrcJD];
431 for (
auto &KV : QueryInfo->Aliases)
432 if (SrcJDDeps.count(KV.second.Aliasee)) {
433 PerAliasDeps = {KV.second.Aliasee};
434 QueryInfo->R->addDependencies(KV.first, PerAliasDepsMap);
438 auto OnComplete = [QueryInfo](Expected<SymbolMap>
Result) {
439 auto &ES = QueryInfo->R->getTargetJITDylib().getExecutionSession();
442 for (
auto &KV : QueryInfo->Aliases) {
443 assert((KV.second.AliasFlags.hasMaterializationSideEffectsOnly() ||
444 Result->count(KV.second.Aliasee)) &&
445 "Result map missing entry?");
447 if (KV.second.AliasFlags.hasMaterializationSideEffectsOnly())
450 ResolutionMap[KV.first] = JITEvaluatedSymbol(
451 (*
Result)[KV.second.Aliasee].getAddress(), KV.second.AliasFlags);
453 if (
auto Err = QueryInfo->R->notifyResolved(ResolutionMap)) {
455 QueryInfo->R->failMaterialization();
458 if (
auto Err = QueryInfo->R->notifyEmitted()) {
460 QueryInfo->R->failMaterialization();
465 QueryInfo->R->failMaterialization();
472 std::move(RegisterDependencies));
476void ReExportsMaterializationUnit::discard(
const JITDylib &JD,
477 const SymbolStringPtr &
Name) {
479 "Symbol not covered by this MaterializationUnit");
483MaterializationUnit::Interface
484ReExportsMaterializationUnit::extractFlags(
const SymbolAliasMap &Aliases) {
486 for (
auto &KV : Aliases)
489 return MaterializationUnit::Interface(std::move(
SymbolFlags),
nullptr);
500 return Flags.takeError();
503 for (
auto &
Name : Symbols) {
504 assert(Flags->count(
Name) &&
"Missing entry in flags map");
523 virtual void complete(std::unique_ptr<InProgressLookupState> IPLS) = 0;
546 OnComplete(
std::
move(OnComplete)) {}
548 void complete(std::unique_ptr<InProgressLookupState> IPLS)
override {
550 auto &ES =
SearchOrder.front().first->getExecutionSession();
551 ES.OL_completeLookupFlags(std::move(IPLS), std::move(OnComplete));
556 OnComplete(std::move(Err));
568 std::shared_ptr<AsynchronousSymbolQuery> Q,
572 Q(
std::
move(Q)), RegisterDependencies(
std::
move(RegisterDependencies)) {
575 void complete(std::unique_ptr<InProgressLookupState> IPLS)
override {
577 auto &ES =
SearchOrder.front().first->getExecutionSession();
578 ES.OL_completeLookup(std::move(IPLS), std::move(Q),
579 std::move(RegisterDependencies));
585 Q->handleFailed(std::move(Err));
589 std::shared_ptr<AsynchronousSymbolQuery> Q;
596 : SourceJD(SourceJD), SourceJDLookupFlags(SourceJDLookupFlags),
603 assert(&JD != &SourceJD &&
"Cannot re-export from the same dylib");
607 K, {{&SourceJD, JDLookupFlags}}, LookupSet);
609 return Flags.takeError();
613 for (
auto &KV : *Flags)
614 if (!Allow || Allow(KV.first))
617 if (AliasMap.
empty())
627void LookupState::reset(InProgressLookupState *IPLS) { this->IPLS.reset(IPLS); }
635 assert(IPLS &&
"Cannot call continueLookup on empty LookupState");
636 auto &ES = IPLS->SearchOrder.begin()->first->getExecutionSession();
637 ES.OL_applyQueryPhase1(std::move(IPLS), std::move(Err));
647 std::vector<ResourceTrackerSP> TrackersToRemove;
649 assert(State != Closed &&
"JD is defunct");
650 for (
auto &KV : TrackerSymbols)
651 TrackersToRemove.push_back(KV.first);
656 for (
auto &RT : TrackersToRemove)
657 Err =
joinErrors(std::move(Err), RT->remove());
663 assert(State != Closed &&
"JD is defunct");
666 return DefaultTracker;
672 assert(State == Open &&
"JD is defunct");
680 assert(State == Open &&
"JD is defunct");
682 [&](
const std::shared_ptr<DefinitionGenerator> &
H) {
683 return H.get() == &
G;
685 assert(
I != DefGenerators.end() &&
"Generator not found");
686 DefGenerators.erase(
I);
695 std::vector<NonOwningSymbolStringPtr> AddedSyms;
696 std::vector<NonOwningSymbolStringPtr> RejectedWeakDefs;
698 for (
auto SFItr = SymbolFlags.begin(), SFEnd = SymbolFlags.end();
699 SFItr != SFEnd; ++SFItr) {
701 auto &Name = SFItr->first;
702 auto &Flags = SFItr->second;
704 auto EntryItr = Symbols.find(Name);
707 if (EntryItr != Symbols.end()) {
710 if (!Flags.isWeak()) {
712 for (auto &S : AddedSyms)
713 Symbols.erase(Symbols.find_as(S));
716 return make_error<DuplicateDefinition>(std::string(*Name));
720 RejectedWeakDefs.push_back(NonOwningSymbolStringPtr(Name));
731 while (!RejectedWeakDefs.empty()) {
732 SymbolFlags.erase(SymbolFlags.find_as(RejectedWeakDefs.back()));
733 RejectedWeakDefs.pop_back();
740Error JITDylib::replace(MaterializationResponsibility &FromMR,
741 std::unique_ptr<MaterializationUnit> MU) {
742 assert(MU !=
nullptr &&
"Can not replace with a null MaterializationUnit");
743 std::unique_ptr<MaterializationUnit> MustRunMU;
744 std::unique_ptr<MaterializationResponsibility> MustRunMR;
748 if (FromMR.RT->isDefunct())
749 return make_error<ResourceTrackerDefunct>(std::move(FromMR.RT));
752 for (
auto &KV : MU->getSymbols()) {
753 auto SymI = Symbols.find(KV.first);
754 assert(SymI != Symbols.end() &&
"Replacing unknown symbol");
755 assert(SymI->second.getState() == SymbolState::Materializing &&
756 "Can not replace a symbol that ha is not materializing");
757 assert(!SymI->second.hasMaterializerAttached() &&
758 "Symbol should not have materializer attached already");
759 assert(UnmaterializedInfos.count(KV.first) == 0 &&
760 "Symbol being replaced should have no UnmaterializedInfo");
768 for (
auto &KV : MU->getSymbols()) {
769 auto MII = MaterializingInfos.find(KV.first);
770 if (MII != MaterializingInfos.end()) {
771 if (MII->second.hasQueriesPending()) {
772 MustRunMR = ES.createMaterializationResponsibility(
773 *FromMR.RT, std::move(MU->SymbolFlags),
774 std::move(MU->InitSymbol));
775 MustRunMU = std::move(MU);
776 return Error::success();
782 auto UMI = std::make_shared<UnmaterializedInfo>(std::move(MU),
784 for (
auto &KV : UMI->MU->getSymbols()) {
785 auto SymI = Symbols.find(KV.first);
786 assert(SymI->second.getState() == SymbolState::Materializing &&
787 "Can not replace a symbol that is not materializing");
788 assert(!SymI->second.hasMaterializerAttached() &&
789 "Can not replace a symbol that has a materializer attached");
790 assert(UnmaterializedInfos.count(KV.first) == 0 &&
791 "Unexpected materializer entry in map");
792 SymI->second.setAddress(SymI->second.getAddress());
793 SymI->second.setMaterializerAttached(
true);
795 auto &UMIEntry = UnmaterializedInfos[KV.first];
796 assert((!UMIEntry || !UMIEntry->MU) &&
797 "Replacing symbol with materializer still attached");
808 assert(MustRunMR &&
"MustRunMU set implies MustRunMR set");
810 std::move(MustRunMU), std::move(MustRunMR)));
812 assert(!MustRunMR &&
"MustRunMU unset implies MustRunMR unset");
818Expected<std::unique_ptr<MaterializationResponsibility>>
819JITDylib::delegate(MaterializationResponsibility &FromMR,
820 SymbolFlagsMap SymbolFlags, SymbolStringPtr InitSymbol) {
823 [&]() -> Expected<std::unique_ptr<MaterializationResponsibility>> {
824 if (FromMR.RT->isDefunct())
825 return make_error<ResourceTrackerDefunct>(std::move(FromMR.RT));
827 return ES.createMaterializationResponsibility(
828 *FromMR.RT, std::move(SymbolFlags), std::move(InitSymbol));
833JITDylib::getRequestedSymbols(
const SymbolFlagsMap &SymbolFlags)
const {
837 for (
auto &KV : SymbolFlags) {
838 assert(Symbols.count(KV.first) &&
"JITDylib does not cover this symbol?");
839 assert(Symbols.find(KV.first)->second.getState() !=
840 SymbolState::NeverSearched &&
841 Symbols.find(KV.first)->second.getState() != SymbolState::Ready &&
842 "getRequestedSymbols can only be called for symbols that have "
843 "started materializing");
844 auto I = MaterializingInfos.find(KV.first);
845 if (
I == MaterializingInfos.end())
848 if (
I->second.hasQueriesPending())
849 RequestedSymbols.insert(KV.first);
852 return RequestedSymbols;
856void JITDylib::addDependencies(
const SymbolStringPtr &
Name,
857 const SymbolDependenceMap &Dependencies) {
859 assert(Symbols.count(
Name) &&
"Name not in symbol table");
860 assert(Symbols[
Name].getState() < SymbolState::Emitted &&
861 "Can not add dependencies for a symbol that is not materializing");
865 <<
": " << Dependencies <<
"\n";
872 auto &
MI = MaterializingInfos[
Name];
873 assert(Symbols[
Name].getState() != SymbolState::Emitted &&
874 "Can not add dependencies to an emitted symbol");
876 bool DependsOnSymbolInErrorState =
false;
880 for (
auto &KV : Dependencies) {
881 assert(KV.first &&
"Null JITDylib in dependency?");
882 auto &OtherJITDylib = *KV.first;
883 auto &DepsOnOtherJITDylib =
MI.UnemittedDependencies[&OtherJITDylib];
885 for (
auto &OtherSymbol : KV.second) {
888 auto OtherSymI = OtherJITDylib.Symbols.find(OtherSymbol);
892 assert(OtherSymI != OtherJITDylib.Symbols.end() &&
893 "Dependency on unknown symbol");
895 auto &OtherSymEntry = OtherSymI->second;
899 if (OtherSymEntry.getState() == SymbolState::Ready)
904 if (OtherSymEntry.getFlags().hasError()) {
905 DependsOnSymbolInErrorState =
true;
911 auto &OtherMI = OtherJITDylib.MaterializingInfos[OtherSymbol];
913 if (OtherSymEntry.getState() == SymbolState::Emitted)
914 transferEmittedNodeDependencies(
MI,
Name, OtherMI);
915 else if (&OtherJITDylib !=
this || OtherSymbol !=
Name) {
916 OtherMI.Dependants[
this].insert(
Name);
917 DepsOnOtherJITDylib.insert(OtherSymbol);
921 if (DepsOnOtherJITDylib.empty())
922 MI.UnemittedDependencies.erase(&OtherJITDylib);
927 if (DependsOnSymbolInErrorState)
929 JITSymbolFlags::HasError);
933Error JITDylib::resolve(MaterializationResponsibility &MR,
934 const SymbolMap &Resolved) {
935 AsynchronousSymbolQuerySet CompletedQueries;
938 if (MR.RT->isDefunct())
939 return make_error<ResourceTrackerDefunct>(MR.RT);
942 return make_error<StringError>(
"JITDylib " + getName() +
944 inconvertibleErrorCode());
946 struct WorklistEntry {
947 SymbolTable::iterator SymI;
948 JITEvaluatedSymbol ResolvedSym;
951 SymbolNameSet SymbolsInErrorState;
952 std::vector<WorklistEntry> Worklist;
956 for (
const auto &KV : Resolved) {
958 assert(!KV.second.getFlags().hasError() &&
959 "Resolution result can not have error flag set");
961 auto SymI = Symbols.find(KV.first);
963 assert(SymI != Symbols.end() &&
"Symbol not found");
964 assert(!SymI->second.hasMaterializerAttached() &&
965 "Resolving symbol with materializer attached?");
966 assert(SymI->second.getState() == SymbolState::Materializing &&
967 "Symbol should be materializing");
968 assert(SymI->second.getAddress() == 0 &&
969 "Symbol has already been resolved");
971 if (SymI->second.getFlags().hasError())
972 SymbolsInErrorState.insert(KV.first);
974 auto Flags = KV.second.getFlags();
975 Flags &= ~JITSymbolFlags::Common;
977 (SymI->second.getFlags() & ~JITSymbolFlags::Common) &&
978 "Resolved flags should match the declared flags");
981 {SymI, JITEvaluatedSymbol(KV.second.getAddress(), Flags)});
986 if (!SymbolsInErrorState.empty()) {
987 auto FailedSymbolsDepMap = std::make_shared<SymbolDependenceMap>();
988 (*FailedSymbolsDepMap)[
this] = std::move(SymbolsInErrorState);
989 return make_error<FailedToMaterialize>(
990 getExecutionSession().getSymbolStringPool(),
991 std::move(FailedSymbolsDepMap));
994 while (!Worklist.empty()) {
995 auto SymI = Worklist.back().SymI;
996 auto ResolvedSym = Worklist.back().ResolvedSym;
999 auto &
Name = SymI->first;
1002 JITSymbolFlags ResolvedFlags = ResolvedSym.getFlags();
1003 SymI->second.setAddress(ResolvedSym.getAddress());
1004 SymI->second.setFlags(ResolvedFlags);
1005 SymI->second.setState(SymbolState::Resolved);
1007 auto MII = MaterializingInfos.find(
Name);
1008 if (MII == MaterializingInfos.end())
1011 auto &
MI = MII->second;
1012 for (
auto &Q :
MI.takeQueriesMeeting(SymbolState::Resolved)) {
1013 Q->notifySymbolMetRequiredState(
Name, ResolvedSym);
1014 Q->removeQueryDependence(*
this,
Name);
1015 if (Q->isComplete())
1016 CompletedQueries.insert(std::move(Q));
1020 return Error::success();
1025 for (
auto &Q : CompletedQueries) {
1026 assert(Q->isComplete() &&
"Q not completed");
1027 Q->handleComplete(ES);
1030 return Error::success();
1033Error JITDylib::emit(MaterializationResponsibility &MR,
1034 const SymbolFlagsMap &Emitted) {
1035 AsynchronousSymbolQuerySet CompletedQueries;
1036 DenseMap<JITDylib *, SymbolNameVector> ReadySymbols;
1039 if (MR.RT->isDefunct())
1040 return make_error<ResourceTrackerDefunct>(MR.RT);
1043 return make_error<StringError>(
"JITDylib " + getName() +
1045 inconvertibleErrorCode());
1047 SymbolNameSet SymbolsInErrorState;
1048 std::vector<SymbolTable::iterator> Worklist;
1051 for (const auto &KV : Emitted) {
1052 auto &Name = KV.first;
1054 auto SymI = Symbols.find(Name);
1055 assert(SymI != Symbols.end() &&
"No symbol table entry for Name");
1057 if (SymI->second.getFlags().hasError())
1058 SymbolsInErrorState.insert(Name);
1060 Worklist.push_back(SymI);
1064 if (!SymbolsInErrorState.empty()) {
1065 auto FailedSymbolsDepMap = std::make_shared<SymbolDependenceMap>();
1066 (*FailedSymbolsDepMap)[this] = std::move(SymbolsInErrorState);
1067 return make_error<FailedToMaterialize>(
1068 getExecutionSession().getSymbolStringPool(),
1069 std::move(FailedSymbolsDepMap));
1073 while (!Worklist.empty()) {
1074 auto SymI = Worklist.back();
1075 Worklist.pop_back();
1077 auto &Name = SymI->first;
1078 auto &SymEntry = SymI->second;
1081 assert(((SymEntry.getFlags().hasMaterializationSideEffectsOnly() &&
1082 SymEntry.getState() == SymbolState::Materializing) ||
1083 SymEntry.getState() == SymbolState::Resolved) &&
1084 "Emitting from state other than Resolved");
1085 SymEntry.setState(SymbolState::Emitted);
1087 auto MII = MaterializingInfos.find(Name);
1091 if (MII == MaterializingInfos.end()) {
1092 SymEntry.setState(SymbolState::Ready);
1096 auto &
MI = MII->second;
1101 for (
auto &KV :
MI.Dependants) {
1102 auto &DependantJD = *KV.first;
1103 auto &DependantJDReadySymbols = ReadySymbols[&DependantJD];
1104 for (auto &DependantName : KV.second) {
1106 DependantJD.MaterializingInfos.find(DependantName);
1107 assert(DependantMII != DependantJD.MaterializingInfos.end() &&
1108 "Dependant should have MaterializingInfo");
1110 auto &DependantMI = DependantMII->second;
1113 assert(DependantMI.UnemittedDependencies.count(this) &&
1114 "Dependant does not have an unemitted dependencies record "
1117 assert(DependantMI.UnemittedDependencies[this].count(Name) &&
1118 "Dependant does not count this symbol as a dependency?");
1120 DependantMI.UnemittedDependencies[this].erase(Name);
1121 if (DependantMI.UnemittedDependencies[this].empty())
1122 DependantMI.UnemittedDependencies.erase(this);
1126 DependantJD.transferEmittedNodeDependencies(DependantMI,
1129 auto DependantSymI = DependantJD.Symbols.find(DependantName);
1130 assert(DependantSymI != DependantJD.Symbols.end() &&
1131 "Dependant has no entry in the Symbols table");
1132 auto &DependantSymEntry = DependantSymI->second;
1137 if (DependantSymEntry.getState() == SymbolState::Emitted &&
1138 DependantMI.UnemittedDependencies.empty()) {
1139 assert(DependantMI.Dependants.empty() &&
1140 "Dependants should be empty by now");
1144 DependantSymEntry.setState(SymbolState::Ready);
1145 DependantJDReadySymbols.push_back(DependantName);
1148 DependantMI.takeQueriesMeeting(SymbolState::Ready)) {
1149 Q->notifySymbolMetRequiredState(
1150 DependantName, DependantSymI->second.getSymbol());
1151 if (Q->isComplete())
1152 CompletedQueries.insert(Q);
1153 Q->removeQueryDependence(DependantJD, DependantName);
1155 DependantJD.MaterializingInfos.erase(DependantMII);
1160 auto &ThisJDReadySymbols = ReadySymbols[
this];
1161 MI.Dependants.clear();
1162 if (
MI.UnemittedDependencies.empty()) {
1163 SymI->second.setState(SymbolState::Ready);
1164 ThisJDReadySymbols.push_back(Name);
1165 for (auto &Q : MI.takeQueriesMeeting(SymbolState::Ready)) {
1166 Q->notifySymbolMetRequiredState(Name, SymI->second.getSymbol());
1167 if (Q->isComplete())
1168 CompletedQueries.insert(Q);
1169 Q->removeQueryDependence(*this, Name);
1171 MaterializingInfos.erase(MII);
1175 return Error::success();
1180 for (
auto &Q : CompletedQueries) {
1181 assert(Q->isComplete() &&
"Q is not complete");
1182 Q->handleComplete(ES);
1185 return Error::success();
1188void JITDylib::unlinkMaterializationResponsibility(
1189 MaterializationResponsibility &MR) {
1191 auto I = TrackerMRs.find(MR.RT.get());
1192 assert(
I != TrackerMRs.end() &&
"No MRs in TrackerMRs list for RT");
1193 assert(
I->second.count(&MR) &&
"MR not in TrackerMRs list for RT");
1194 I->second.erase(&MR);
1195 if (
I->second.empty())
1196 TrackerMRs.erase(MR.RT.get());
1200std::pair<JITDylib::AsynchronousSymbolQuerySet,
1201 std::shared_ptr<SymbolDependenceMap>>
1202JITDylib::failSymbols(FailedSymbolsWorklist Worklist) {
1203 AsynchronousSymbolQuerySet FailedQueries;
1204 auto FailedSymbolsMap = std::make_shared<SymbolDependenceMap>();
1206 while (!Worklist.empty()) {
1207 assert(Worklist.back().first &&
"Failed JITDylib can not be null");
1208 auto &JD = *Worklist.back().first;
1209 auto Name = std::move(Worklist.back().second);
1210 Worklist.pop_back();
1212 (*FailedSymbolsMap)[&JD].insert(
Name);
1215 auto SymI = JD.Symbols.find(
Name);
1221 if (SymI == JD.Symbols.end())
1223 auto &Sym = SymI->second;
1228 Sym.setFlags(Sym.getFlags() | JITSymbolFlags::HasError);
1233 auto MII = JD.MaterializingInfos.find(
Name);
1235 if (MII == JD.MaterializingInfos.end())
1238 auto &
MI = MII->second;
1241 for (
auto &KV :
MI.Dependants) {
1242 auto &DependantJD = *KV.first;
1243 for (
auto &DependantName : KV.second) {
1244 assert(DependantJD.Symbols.count(DependantName) &&
1245 "No symbol table entry for DependantName");
1246 auto &DependantSym = DependantJD.Symbols[DependantName];
1247 DependantSym.setFlags(DependantSym.getFlags() |
1248 JITSymbolFlags::HasError);
1250 assert(DependantJD.MaterializingInfos.count(DependantName) &&
1251 "No MaterializingInfo for dependant");
1252 auto &DependantMI = DependantJD.MaterializingInfos[DependantName];
1254 auto UnemittedDepI = DependantMI.UnemittedDependencies.find(&JD);
1255 assert(UnemittedDepI != DependantMI.UnemittedDependencies.end() &&
1256 "No UnemittedDependencies entry for this JITDylib");
1258 "No UnemittedDependencies entry for this symbol");
1259 UnemittedDepI->second.erase(
Name);
1260 if (UnemittedDepI->second.empty())
1261 DependantMI.UnemittedDependencies.erase(UnemittedDepI);
1266 if (DependantSym.getState() == SymbolState::Emitted) {
1267 assert(DependantMI.Dependants.empty() &&
1268 "Emitted symbol should not have dependants");
1269 Worklist.push_back(std::make_pair(&DependantJD, DependantName));
1273 MI.Dependants.clear();
1276 for (
auto &KV :
MI.UnemittedDependencies) {
1277 auto &UnemittedDepJD = *KV.first;
1278 for (
auto &UnemittedDepName : KV.second) {
1279 auto UnemittedDepMII =
1280 UnemittedDepJD.MaterializingInfos.find(UnemittedDepName);
1281 assert(UnemittedDepMII != UnemittedDepJD.MaterializingInfos.end() &&
1282 "Missing MII for unemitted dependency");
1283 assert(UnemittedDepMII->second.Dependants.count(&JD) &&
1284 "JD not listed as a dependant of unemitted dependency");
1285 assert(UnemittedDepMII->second.Dependants[&JD].count(
Name) &&
1286 "Name is not listed as a dependant of unemitted dependency");
1287 UnemittedDepMII->second.Dependants[&JD].erase(
Name);
1288 if (UnemittedDepMII->second.Dependants[&JD].empty())
1289 UnemittedDepMII->second.Dependants.erase(&JD);
1292 MI.UnemittedDependencies.clear();
1295 AsynchronousSymbolQueryList ToDetach;
1296 for (
auto &Q : MII->second.pendingQueries()) {
1298 FailedQueries.insert(Q);
1299 ToDetach.push_back(Q);
1301 for (
auto &Q : ToDetach)
1305 "Can not delete MaterializingInfo with dependants still attached");
1306 assert(
MI.UnemittedDependencies.empty() &&
1307 "Can not delete MaterializingInfo with unemitted dependencies "
1310 "Can not delete MaterializingInfo with queries pending");
1311 JD.MaterializingInfos.erase(MII);
1314 return std::make_pair(std::move(FailedQueries), std::move(FailedSymbolsMap));
1318 bool LinkAgainstThisJITDylibFirst) {
1320 assert(State == Open &&
"JD is defunct");
1321 if (LinkAgainstThisJITDylibFirst) {
1323 if (NewLinkOrder.empty() || NewLinkOrder.front().first !=
this)
1324 LinkOrder.push_back(
1325 std::make_pair(
this, JITDylibLookupFlags::MatchAllSymbols));
1328 LinkOrder = std::move(NewLinkOrder);
1339 assert(State == Open &&
"JD is defunct");
1340 for (
auto &KV : LinkOrder)
1341 if (KV.first == &OldJD) {
1342 KV = {&NewJD, JDLookupFlags};
1350 assert(State == Open &&
"JD is defunct");
1352 [&](
const JITDylibSearchOrder::value_type &KV) {
1353 return KV.first == &JD;
1355 if (
I != LinkOrder.end())
1362 assert(State == Open &&
"JD is defunct");
1363 using SymbolMaterializerItrPair =
1364 std::pair<SymbolTable::iterator, UnmaterializedInfosMap::iterator>;
1365 std::vector<SymbolMaterializerItrPair> SymbolsToRemove;
1369 for (
auto &
Name : Names) {
1370 auto I = Symbols.find(
Name);
1373 if (
I == Symbols.end()) {
1374 Missing.insert(
Name);
1379 if (
I->second.getState() != SymbolState::NeverSearched &&
1380 I->second.getState() != SymbolState::Ready) {
1385 auto UMII =
I->second.hasMaterializerAttached()
1386 ? UnmaterializedInfos.find(
Name)
1387 : UnmaterializedInfos.end();
1388 SymbolsToRemove.push_back(std::make_pair(
I, UMII));
1392 if (!Missing.empty())
1394 std::move(Missing));
1402 for (
auto &SymbolMaterializerItrPair : SymbolsToRemove) {
1403 auto UMII = SymbolMaterializerItrPair.second;
1406 if (UMII != UnmaterializedInfos.end()) {
1407 UMII->second->MU->doDiscard(*
this, UMII->first);
1408 UnmaterializedInfos.erase(UMII);
1411 auto SymI = SymbolMaterializerItrPair.first;
1412 Symbols.erase(SymI);
1415 return Error::success();
1421 OS <<
"JITDylib \"" <<
getName() <<
"\" (ES: "
1422 <<
format(
"0x%016" PRIx64,
reinterpret_cast<uintptr_t
>(&ES))
1436 if (State == Closed)
1438 OS <<
"Link order: " << LinkOrder <<
"\n"
1439 <<
"Symbol table:\n";
1441 for (
auto &KV : Symbols) {
1442 OS <<
" \"" << *KV.first <<
"\": ";
1443 if (
auto Addr = KV.second.getAddress())
1446 OS <<
"<not resolved> ";
1448 OS <<
" " << KV.second.getFlags() <<
" " << KV.second.getState();
1450 if (KV.second.hasMaterializerAttached()) {
1451 OS <<
" (Materializer ";
1452 auto I = UnmaterializedInfos.find(KV.first);
1453 assert(
I != UnmaterializedInfos.end() &&
1454 "Lazy symbol should have UnmaterializedInfo");
1455 OS <<
I->second->MU.get() <<
", " <<
I->second->MU->getName() <<
")\n";
1460 if (!MaterializingInfos.empty())
1461 OS <<
" MaterializingInfos entries:\n";
1462 for (
auto &KV : MaterializingInfos) {
1463 OS <<
" \"" << *KV.first <<
"\":\n"
1464 <<
" " << KV.second.pendingQueries().size()
1465 <<
" pending queries: { ";
1466 for (
const auto &Q : KV.second.pendingQueries())
1467 OS << Q.get() <<
" (" << Q->getRequiredState() <<
") ";
1468 OS <<
"}\n Dependants:\n";
1469 for (
auto &KV2 : KV.second.Dependants)
1470 OS <<
" " << KV2.first->getName() <<
": " << KV2.second <<
"\n";
1471 OS <<
" Unemitted Dependencies:\n";
1472 for (
auto &KV2 : KV.second.UnemittedDependencies)
1473 OS <<
" " << KV2.first->getName() <<
": " << KV2.second <<
"\n";
1474 assert((Symbols[KV.first].getState() != SymbolState::Ready ||
1475 !KV.second.pendingQueries().empty() ||
1476 !KV.second.Dependants.empty() ||
1477 !KV.second.UnemittedDependencies.empty()) &&
1478 "Stale materializing info entry");
1483void JITDylib::MaterializingInfo::addQuery(
1484 std::shared_ptr<AsynchronousSymbolQuery> Q) {
1488 [](
const std::shared_ptr<AsynchronousSymbolQuery> &V,
SymbolState S) {
1489 return V->getRequiredState() <= S;
1491 PendingQueries.insert(
I.base(), std::move(Q));
1494void JITDylib::MaterializingInfo::removeQuery(
1495 const AsynchronousSymbolQuery &Q) {
1498 PendingQueries, [&Q](
const std::shared_ptr<AsynchronousSymbolQuery> &V) {
1499 return V.get() == &Q;
1501 assert(
I != PendingQueries.end() &&
1502 "Query is not attached to this MaterializingInfo");
1503 PendingQueries.erase(
I);
1506JITDylib::AsynchronousSymbolQueryList
1507JITDylib::MaterializingInfo::takeQueriesMeeting(SymbolState RequiredState) {
1508 AsynchronousSymbolQueryList
Result;
1509 while (!PendingQueries.empty()) {
1510 if (PendingQueries.back()->getRequiredState() > RequiredState)
1513 Result.push_back(std::move(PendingQueries.back()));
1514 PendingQueries.pop_back();
1520JITDylib::JITDylib(ExecutionSession &ES, std::string
Name)
1525std::pair<JITDylib::AsynchronousSymbolQuerySet,
1526 std::shared_ptr<SymbolDependenceMap>>
1527JITDylib::removeTracker(ResourceTracker &RT) {
1529 assert(State != Closed &&
"JD is defunct");
1532 std::vector<std::pair<JITDylib *, SymbolStringPtr>> SymbolsToFail;
1534 if (&RT == DefaultTracker.
get()) {
1536 for (
auto &KV : TrackerSymbols)
1537 for (
auto &Sym : KV.second)
1538 TrackedSymbols.
insert(Sym);
1540 for (
auto &KV : Symbols) {
1541 auto &Sym = KV.first;
1542 if (!TrackedSymbols.count(Sym))
1543 SymbolsToRemove.push_back(Sym);
1546 DefaultTracker.
reset();
1549 auto I = TrackerSymbols.find(&RT);
1550 if (
I != TrackerSymbols.end()) {
1551 SymbolsToRemove = std::move(
I->second);
1552 TrackerSymbols.erase(
I);
1557 for (
auto &Sym : SymbolsToRemove) {
1558 assert(Symbols.count(Sym) &&
"Symbol not in symbol table");
1561 auto MII = MaterializingInfos.
find(Sym);
1562 if (MII != MaterializingInfos.
end())
1563 SymbolsToFail.push_back({
this, Sym});
1566 AsynchronousSymbolQuerySet QueriesToFail;
1567 auto Result = failSymbols(std::move(SymbolsToFail));
1570 for (
auto &Sym : SymbolsToRemove) {
1571 auto I = Symbols.find(Sym);
1572 assert(
I != Symbols.end() &&
"Symbol not present in table");
1575 if (
I->second.hasMaterializerAttached()) {
1577 UnmaterializedInfos.
erase(Sym);
1580 "Symbol has materializer attached");
1589void JITDylib::transferTracker(ResourceTracker &DstRT, ResourceTracker &SrcRT) {
1590 assert(State != Closed &&
"JD is defunct");
1591 assert(&DstRT != &SrcRT &&
"No-op transfers shouldn't call transferTracker");
1592 assert(&DstRT.getJITDylib() ==
this &&
"DstRT is not for this JITDylib");
1593 assert(&SrcRT.getJITDylib() ==
this &&
"SrcRT is not for this JITDylib");
1596 for (
auto &KV : UnmaterializedInfos) {
1597 if (KV.second->RT == &SrcRT)
1598 KV.second->RT = &DstRT;
1603 auto I = TrackerMRs.find(&SrcRT);
1604 if (
I != TrackerMRs.end()) {
1605 auto &SrcMRs =
I->second;
1606 auto &DstMRs = TrackerMRs[&DstRT];
1607 for (
auto *MR : SrcMRs)
1610 DstMRs = std::move(SrcMRs);
1612 for (
auto *MR : SrcMRs)
1616 TrackerMRs.erase(&SrcRT);
1622 if (&DstRT == DefaultTracker.
get()) {
1623 TrackerSymbols.erase(&SrcRT);
1629 if (&SrcRT == DefaultTracker.
get()) {
1630 assert(!TrackerSymbols.count(&SrcRT) &&
1631 "Default tracker should not appear in TrackerSymbols");
1636 for (
auto &KV : TrackerSymbols)
1637 for (
auto &Sym : KV.second)
1638 CurrentlyTrackedSymbols.
insert(Sym);
1640 for (
auto &KV : Symbols) {
1641 auto &Sym = KV.first;
1642 if (!CurrentlyTrackedSymbols.count(Sym))
1643 SymbolsToTrack.push_back(Sym);
1646 TrackerSymbols[&DstRT] = std::move(SymbolsToTrack);
1650 auto &DstTrackedSymbols = TrackerSymbols[&DstRT];
1654 auto SI = TrackerSymbols.find(&SrcRT);
1655 if (SI == TrackerSymbols.end())
1658 DstTrackedSymbols.reserve(DstTrackedSymbols.size() +
SI->second.size());
1659 for (
auto &Sym :
SI->second)
1660 DstTrackedSymbols.push_back(std::move(Sym));
1661 TrackerSymbols.erase(SI);
1664Error JITDylib::defineImpl(MaterializationUnit &MU) {
1669 std::vector<SymbolStringPtr> ExistingDefsOverridden;
1670 std::vector<SymbolStringPtr> MUDefsOverridden;
1672 for (
const auto &KV : MU.getSymbols()) {
1673 auto I = Symbols.find(KV.first);
1675 if (
I != Symbols.end()) {
1676 if (KV.second.isStrong()) {
1677 if (
I->second.getFlags().isStrong() ||
1679 Duplicates.insert(KV.first);
1682 "Overridden existing def should be in the never-searched "
1684 ExistingDefsOverridden.push_back(KV.first);
1687 MUDefsOverridden.push_back(KV.first);
1692 if (!Duplicates.empty()) {
1694 {
dbgs() <<
" Error: Duplicate symbols " << Duplicates <<
"\n"; });
1695 return make_error<DuplicateDefinition>(std::string(**Duplicates.begin()));
1700 if (!MUDefsOverridden.empty())
1701 dbgs() <<
" Defs in this MU overridden: " << MUDefsOverridden <<
"\n";
1703 for (
auto &S : MUDefsOverridden)
1704 MU.doDiscard(*
this, S);
1708 if (!ExistingDefsOverridden.empty())
1709 dbgs() <<
" Existing defs overridden by this MU: " << MUDefsOverridden
1712 for (
auto &S : ExistingDefsOverridden) {
1714 auto UMII = UnmaterializedInfos.find(S);
1715 assert(UMII != UnmaterializedInfos.end() &&
1716 "Overridden existing def should have an UnmaterializedInfo");
1717 UMII->second->MU->doDiscard(*
this, S);
1721 for (
auto &KV : MU.getSymbols()) {
1722 auto &SymEntry = Symbols[KV.first];
1723 SymEntry.setFlags(KV.second);
1725 SymEntry.setMaterializerAttached(
true);
1731void JITDylib::installMaterializationUnit(
1732 std::unique_ptr<MaterializationUnit> MU, ResourceTracker &RT) {
1735 if (&RT != DefaultTracker.
get()) {
1736 auto &TS = TrackerSymbols[&RT];
1737 TS.reserve(TS.size() + MU->getSymbols().size());
1738 for (
auto &KV : MU->getSymbols())
1739 TS.push_back(KV.first);
1742 auto UMI = std::make_shared<UnmaterializedInfo>(std::move(MU), &RT);
1743 for (
auto &KV : UMI->MU->getSymbols())
1744 UnmaterializedInfos[KV.first] = UMI;
1747void JITDylib::detachQueryHelper(AsynchronousSymbolQuery &Q,
1749 for (
auto &QuerySymbol : QuerySymbols) {
1751 "QuerySymbol does not have MaterializingInfo");
1752 auto &
MI = MaterializingInfos[QuerySymbol];
1757void JITDylib::transferEmittedNodeDependencies(
1758 MaterializingInfo &DependantMI,
const SymbolStringPtr &DependantName,
1759 MaterializingInfo &EmittedMI) {
1760 for (
auto &KV : EmittedMI.UnemittedDependencies) {
1761 auto &DependencyJD = *KV.first;
1762 SymbolNameSet *UnemittedDependenciesOnDependencyJD =
nullptr;
1764 for (
auto &DependencyName : KV.second) {
1765 auto &DependencyMI = DependencyJD.MaterializingInfos[DependencyName];
1768 if (&DependencyMI == &DependantMI)
1773 if (!UnemittedDependenciesOnDependencyJD)
1774 UnemittedDependenciesOnDependencyJD =
1775 &DependantMI.UnemittedDependencies[&DependencyJD];
1777 DependencyMI.Dependants[
this].
insert(DependantName);
1778 UnemittedDependenciesOnDependencyJD->insert(DependencyName);
1791 std::mutex LookupMutex;
1792 std::condition_variable CV;
1796 dbgs() <<
"Issuing init-symbol lookup:\n";
1797 for (
auto &KV : InitSyms)
1798 dbgs() <<
" " << KV.first->getName() <<
": " << KV.second <<
"\n";
1801 for (
auto &KV : InitSyms) {
1802 auto *JD = KV.first;
1803 auto Names = std::move(KV.second);
1810 std::lock_guard<std::mutex> Lock(LookupMutex);
1814 "Duplicate JITDylib in lookup?");
1815 CompoundResult[JD] = std::move(*
Result);
1825 std::unique_lock<std::mutex> Lock(LookupMutex);
1826 CV.wait(Lock, [&] {
return Count == 0 || CompoundErr; });
1829 return std::move(CompoundErr);
1831 return std::move(CompoundResult);
1838 class TriggerOnComplete {
1841 TriggerOnComplete(OnCompleteFn OnComplete)
1842 : OnComplete(std::move(OnComplete)) {}
1843 ~TriggerOnComplete() { OnComplete(std::move(LookupResult)); }
1844 void reportResult(
Error Err) {
1845 std::lock_guard<std::mutex> Lock(ResultMutex);
1846 LookupResult =
joinErrors(std::move(LookupResult), std::move(Err));
1850 std::mutex ResultMutex;
1851 Error LookupResult{Error::success()};
1852 OnCompleteFn OnComplete;
1856 dbgs() <<
"Issuing init-symbol lookup:\n";
1857 for (
auto &KV : InitSyms)
1858 dbgs() <<
" " << KV.first->getName() <<
": " << KV.second <<
"\n";
1861 auto TOC = std::make_shared<TriggerOnComplete>(std::move(OnComplete));
1863 for (
auto &KV : InitSyms) {
1864 auto *JD = KV.first;
1865 auto Names = std::move(KV.second);
1871 TOC->reportResult(
Result.takeError());
1878 OS <<
"Materialization task: " << MU->getName() <<
" in "
1879 << MR->getTargetJITDylib().getName();
1887 this->EPC->ES =
this;
1893 "Session still open. Did you forget to call endSession?");
1897 LLVM_DEBUG(
dbgs() <<
"Ending ExecutionSession " <<
this <<
"\n");
1900 SessionOpen =
false;
1901 return std::move(JDs);
1907 for (
auto &JD :
reverse(JITDylibsToClose))
1908 Err =
joinErrors(std::move(Err), JD->clear());
1910 Err =
joinErrors(std::move(Err), EPC->disconnect());
1921 assert(!ResourceManagers.empty() &&
"No managers registered");
1922 if (ResourceManagers.back() == &RM)
1923 ResourceManagers.pop_back();
1926 assert(
I != ResourceManagers.end() &&
"RM not registered");
1927 ResourceManagers.erase(
I);
1934 for (
auto &JD : JDs)
1935 if (JD->getName() ==
Name)
1952 if (
auto Err = P->setupJITDylib(JD))
1953 return std::move(Err);
1964 assert(JD.State == JITDylib::Open &&
"JD already closed");
1965 JD.State = JITDylib::Closing;
1967 assert(
I != JDs.end() &&
"JD does not appear in session JDs");
1973 auto Err = JD.
clear();
1977 Err =
joinErrors(std::move(Err), P->teardownJITDylib(JD));
1981 assert(JD.State == JITDylib::Closing &&
"JD should be closing");
1982 JD.State = JITDylib::Closed;
1983 assert(JD.Symbols.
empty() &&
"JD.Symbols is not empty after clear");
1985 "JD.UnmaterializedInfos is not empty after clear");
1987 "JD.MaterializingInfos is not empty after clear");
1988 assert(JD.TrackerSymbols.empty() &&
1989 "TrackerSymbols is not empty after clear");
1990 JD.DefGenerators.clear();
1991 JD.LinkOrder.clear();
1999 return std::vector<JITDylibSP>();
2001 auto &ES = JDs.
front()->getExecutionSession();
2002 return ES.runSessionLocked([&]() ->
Expected<std::vector<JITDylibSP>> {
2004 std::vector<JITDylibSP>
Result;
2006 for (
auto &JD : JDs) {
2008 if (JD->State != Open)
2009 return make_error<StringError>(
2010 "Error building link order: " + JD->getName() +
" is defunct",
2012 if (Visited.
count(JD.get()))
2017 Visited.
insert(JD.get());
2019 while (!WorkStack.empty()) {
2020 Result.push_back(std::move(WorkStack.back()));
2021 WorkStack.pop_back();
2023 for (auto &KV : llvm::reverse(Result.back()->LinkOrder)) {
2024 auto &JD = *KV.first;
2025 if (!Visited.insert(&JD).second)
2027 WorkStack.push_back(&JD);
2055 OL_applyQueryPhase1(std::make_unique<InProgressLookupFlagsState>(
2056 K, std::move(SearchOrder), std::move(LookupSet),
2057 std::move(OnComplete)),
2065 std::promise<MSVCPExpected<SymbolFlagsMap>> ResultP;
2066 OL_applyQueryPhase1(std::make_unique<InProgressLookupFlagsState>(
2067 K, std::move(SearchOrder), std::move(LookupSet),
2069 ResultP.set_value(std::move(
Result));
2073 auto ResultF = ResultP.get_future();
2074 return ResultF.get();
2085 dbgs() <<
"Looking up " << Symbols <<
" in " << SearchOrder
2086 <<
" (required state: " << RequiredState <<
")\n";
2093 dispatchOutstandingMUs();
2095 auto Unresolved = std::move(Symbols);
2096 auto Q = std::make_shared<AsynchronousSymbolQuery>(Unresolved, RequiredState,
2097 std::move(NotifyComplete));
2099 auto IPLS = std::make_unique<InProgressFullLookupState>(
2100 K, SearchOrder, std::move(Unresolved), RequiredState, std::move(Q),
2101 std::move(RegisterDependencies));
2111#if LLVM_ENABLE_THREADS
2113 std::promise<SymbolMap> PromisedResult;
2118 PromisedResult.set_value(std::move(*R));
2121 ResolutionError = R.takeError();
2135 ResolutionError = R.takeError();
2140 lookup(K, SearchOrder, std::move(Symbols), RequiredState, NotifyComplete,
2141 RegisterDependencies);
2143#if LLVM_ENABLE_THREADS
2144 auto ResultFuture = PromisedResult.get_future();
2145 auto Result = ResultFuture.get();
2147 if (ResolutionError)
2148 return std::move(ResolutionError);
2150 return std::move(
Result);
2153 if (ResolutionError)
2154 return std::move(ResolutionError);
2167 assert(ResultMap->size() == 1 &&
"Unexpected number of results");
2168 assert(ResultMap->count(
Name) &&
"Missing result for symbol");
2169 return std::move(ResultMap->begin()->second);
2171 return ResultMap.takeError();
2193 return TagAddrs.takeError();
2196 std::lock_guard<std::mutex> Lock(JITDispatchHandlersMutex);
2197 for (
auto &KV : *TagAddrs) {
2198 auto TagAddr = KV.second.getAddress();
2199 if (JITDispatchHandlers.count(TagAddr))
2200 return make_error<StringError>(
"Tag " +
formatv(
"{0:x16}", TagAddr) +
2201 " (for " + *KV.first +
2202 ") already registered",
2204 auto I = WFs.
find(KV.first);
2206 "JITDispatchHandler implementation missing");
2207 JITDispatchHandlers[KV.second.getAddress()] =
2208 std::make_shared<JITDispatchHandlerFunction>(std::move(
I->second));
2210 dbgs() <<
"Associated function tag \"" << *KV.first <<
"\" ("
2211 <<
formatv(
"{0:x}", KV.second.getAddress()) <<
") with handler\n";
2221 std::shared_ptr<JITDispatchHandlerFunction>
F;
2223 std::lock_guard<std::mutex> Lock(JITDispatchHandlersMutex);
2224 auto I = JITDispatchHandlers.find(HandlerFnTagAddr);
2225 if (
I != JITDispatchHandlers.end())
2230 (*F)(std::move(SendResult), ArgBuffer.
data(), ArgBuffer.
size());
2233 (
"No function registered for tag " +
2234 formatv(
"{0:x16}", HandlerFnTagAddr))
2240 for (
auto &JD : JDs)
2245void ExecutionSession::dispatchOutstandingMUs() {
2248 std::optional<std::pair<std::unique_ptr<MaterializationUnit>,
2249 std::unique_ptr<MaterializationResponsibility>>>
2253 std::lock_guard<std::recursive_mutex> Lock(OutstandingMUsMutex);
2254 if (!OutstandingMUs.empty()) {
2255 JMU.emplace(std::move(OutstandingMUs.back()));
2256 OutstandingMUs.pop_back();
2263 assert(JMU->first &&
"No MU?");
2264 LLVM_DEBUG(
dbgs() <<
" Dispatching \"" << JMU->first->getName() <<
"\"\n");
2265 dispatchTask(std::make_unique<MaterializationTask>(std::move(JMU->first),
2266 std::move(JMU->second)));
2268 LLVM_DEBUG(
dbgs() <<
"Done dispatching MaterializationUnits.\n");
2271Error ExecutionSession::removeResourceTracker(ResourceTracker &RT) {
2273 dbgs() <<
"In " << RT.getJITDylib().getName() <<
" removing tracker "
2274 <<
formatv(
"{0:x}", RT.getKeyUnsafe()) <<
"\n";
2276 std::vector<ResourceManager *> CurrentResourceManagers;
2278 JITDylib::AsynchronousSymbolQuerySet QueriesToFail;
2279 std::shared_ptr<SymbolDependenceMap> FailedSymbols;
2282 CurrentResourceManagers = ResourceManagers;
2284 std::tie(QueriesToFail, FailedSymbols) = RT.getJITDylib().removeTracker(RT);
2289 auto &JD = RT.getJITDylib();
2290 for (
auto *L :
reverse(CurrentResourceManagers))
2292 L->handleRemoveResources(JD, RT.getKeyUnsafe()));
2294 for (
auto &Q : QueriesToFail)
2301void ExecutionSession::transferResourceTracker(ResourceTracker &DstRT,
2302 ResourceTracker &SrcRT) {
2304 dbgs() <<
"In " << SrcRT.getJITDylib().getName()
2305 <<
" transfering resources from tracker "
2306 <<
formatv(
"{0:x}", SrcRT.getKeyUnsafe()) <<
" to tracker "
2307 <<
formatv(
"{0:x}", DstRT.getKeyUnsafe()) <<
"\n";
2311 if (&DstRT == &SrcRT)
2314 assert(&DstRT.getJITDylib() == &SrcRT.getJITDylib() &&
2315 "Can't transfer resources between JITDylibs");
2317 SrcRT.makeDefunct();
2318 auto &JD = DstRT.getJITDylib();
2319 JD.transferTracker(DstRT, SrcRT);
2320 for (
auto *L :
reverse(ResourceManagers))
2321 L->handleTransferResources(JD, DstRT.getKeyUnsafe(),
2322 SrcRT.getKeyUnsafe());
2326void ExecutionSession::destroyResourceTracker(ResourceTracker &RT) {
2329 dbgs() <<
"In " << RT.getJITDylib().getName() <<
" destroying tracker "
2330 <<
formatv(
"{0:x}", RT.getKeyUnsafe()) <<
"\n";
2332 if (!RT.isDefunct())
2333 transferResourceTracker(*RT.getJITDylib().getDefaultResourceTracker(),
2338Error ExecutionSession::IL_updateCandidatesFor(
2340 SymbolLookupSet &Candidates, SymbolLookupSet *NonCandidates) {
2341 return Candidates.forEachWithRemoval(
2342 [&](
const SymbolStringPtr &
Name,
2346 auto SymI = JD.Symbols.find(
Name);
2347 if (SymI == JD.Symbols.end())
2355 if (!SymI->second.getFlags().isExported() &&
2358 NonCandidates->add(Name, SymLookupFlags);
2367 if (SymI->second.getFlags().hasMaterializationSideEffectsOnly() &&
2374 if (SymI->second.getFlags().hasError()) {
2375 auto FailedSymbolsMap = std::make_shared<SymbolDependenceMap>();
2376 (*FailedSymbolsMap)[&JD] = {Name};
2378 std::move(FailedSymbolsMap));
2386void ExecutionSession::OL_applyQueryPhase1(
2387 std::unique_ptr<InProgressLookupState> IPLS, Error Err) {
2390 dbgs() <<
"Entering OL_applyQueryPhase1:\n"
2391 <<
" Lookup kind: " << IPLS->K <<
"\n"
2392 <<
" Search order: " << IPLS->SearchOrder
2393 <<
", Current index = " << IPLS->CurSearchOrderIndex
2394 << (IPLS->NewJITDylib ?
" (entering new JITDylib)" :
"") <<
"\n"
2395 <<
" Lookup set: " << IPLS->LookupSet <<
"\n"
2396 <<
" Definition generator candidates: "
2397 << IPLS->DefGeneratorCandidates <<
"\n"
2398 <<
" Definition generator non-candidates: "
2399 << IPLS->DefGeneratorNonCandidates <<
"\n";
2407 while (IPLS->CurSearchOrderIndex != IPLS->SearchOrder.size()) {
2413 return IPLS->fail(std::move(Err));
2416 auto &KV = IPLS->SearchOrder[IPLS->CurSearchOrderIndex];
2417 auto &JD = *KV.first;
2418 auto JDLookupFlags = KV.second;
2421 dbgs() <<
"Visiting \"" << JD.getName() <<
"\" (" << JDLookupFlags
2422 <<
") with lookup set " << IPLS->LookupSet <<
":\n";
2426 if (IPLS->NewJITDylib) {
2429 IPLS->GeneratorLock = std::unique_lock<std::mutex>(JD.GeneratorsMutex);
2434 SymbolLookupSet Tmp;
2435 std::swap(IPLS->DefGeneratorNonCandidates, Tmp);
2436 IPLS->DefGeneratorCandidates.append(std::move(Tmp));
2439 dbgs() <<
" First time visiting " << JD.getName()
2440 <<
", resetting candidate sets and building generator stack\n";
2445 IPLS->CurDefGeneratorStack.reserve(JD.DefGenerators.size());
2447 IPLS->CurDefGeneratorStack.push_back(DG);
2451 IPLS->NewJITDylib =
false;
2460 Err = IL_updateCandidatesFor(
2461 JD, JDLookupFlags, IPLS->DefGeneratorCandidates,
2462 JD.DefGenerators.empty() ?
nullptr
2463 : &IPLS->DefGeneratorNonCandidates);
2465 dbgs() <<
" Remaining candidates = " << IPLS->DefGeneratorCandidates
2473 return IPLS->fail(std::move(Err));
2477 if (IPLS->CurDefGeneratorStack.empty())
2478 LLVM_DEBUG(
dbgs() <<
" No generators to run for this JITDylib.\n");
2479 else if (IPLS->DefGeneratorCandidates.empty())
2482 dbgs() <<
" Running " << IPLS->CurDefGeneratorStack.size()
2483 <<
" remaining generators for "
2484 << IPLS->DefGeneratorCandidates.size() <<
" candidates\n";
2486 while (!IPLS->CurDefGeneratorStack.empty() &&
2487 !IPLS->DefGeneratorCandidates.empty()) {
2488 auto DG = IPLS->CurDefGeneratorStack.back().lock();
2489 IPLS->CurDefGeneratorStack.pop_back();
2492 return IPLS->fail(make_error<StringError>(
2493 "DefinitionGenerator removed while lookup in progress",
2497 auto &LookupSet = IPLS->DefGeneratorCandidates;
2502 LLVM_DEBUG(
dbgs() <<
" Attempting to generate " << LookupSet <<
"\n");
2504 Err = DG->tryToGenerate(LS, K, JD, JDLookupFlags, LookupSet);
2505 IPLS = std::move(
LS.IPLS);
2511 dbgs() <<
" Error attempting to generate " << LookupSet <<
"\n";
2513 assert(IPLS &&
"LS cannot be retained if error is returned");
2514 return IPLS->fail(std::move(Err));
2520 {
dbgs() <<
" LookupState captured. Exiting phase1 for now.\n"; });
2527 LLVM_DEBUG(
dbgs() <<
" Updating candidate set post-generation\n");
2528 Err = IL_updateCandidatesFor(
2529 JD, JDLookupFlags, IPLS->DefGeneratorCandidates,
2530 JD.DefGenerators.empty() ?
nullptr
2531 : &IPLS->DefGeneratorNonCandidates);
2536 LLVM_DEBUG(
dbgs() <<
" Error encountered while updating candidates\n");
2537 return IPLS->fail(std::move(Err));
2541 if (IPLS->DefGeneratorCandidates.empty() &&
2542 IPLS->DefGeneratorNonCandidates.empty()) {
2545 IPLS->CurSearchOrderIndex = IPLS->SearchOrder.size();
2551 ++IPLS->CurSearchOrderIndex;
2552 IPLS->NewJITDylib =
true;
2557 IPLS->DefGeneratorCandidates.remove_if(
2565 if (IPLS->DefGeneratorCandidates.empty()) {
2567 IPLS->complete(std::move(IPLS));
2569 LLVM_DEBUG(
dbgs() <<
"Phase 1 failed with unresolved symbols.\n");
2570 IPLS->fail(make_error<SymbolsNotFound>(
2575void ExecutionSession::OL_completeLookup(
2576 std::unique_ptr<InProgressLookupState> IPLS,
2577 std::shared_ptr<AsynchronousSymbolQuery> Q,
2581 dbgs() <<
"Entering OL_completeLookup:\n"
2582 <<
" Lookup kind: " << IPLS->K <<
"\n"
2583 <<
" Search order: " << IPLS->SearchOrder
2584 <<
", Current index = " << IPLS->CurSearchOrderIndex
2585 << (IPLS->NewJITDylib ?
" (entering new JITDylib)" :
"") <<
"\n"
2586 <<
" Lookup set: " << IPLS->LookupSet <<
"\n"
2587 <<
" Definition generator candidates: "
2588 << IPLS->DefGeneratorCandidates <<
"\n"
2589 <<
" Definition generator non-candidates: "
2590 << IPLS->DefGeneratorNonCandidates <<
"\n";
2593 bool QueryComplete =
false;
2594 DenseMap<JITDylib *, JITDylib::UnmaterializedInfosList> CollectedUMIs;
2597 for (
auto &KV : IPLS->SearchOrder) {
2598 auto &JD = *KV.first;
2599 auto JDLookupFlags = KV.second;
2601 dbgs() <<
"Visiting \"" << JD.getName() <<
"\" (" << JDLookupFlags
2602 <<
") with lookup set " << IPLS->LookupSet <<
":\n";
2605 auto Err = IPLS->LookupSet.forEachWithRemoval(
2606 [&](
const SymbolStringPtr &
Name,
2609 dbgs() <<
" Attempting to match \"" <<
Name <<
"\" ("
2610 << SymLookupFlags <<
")... ";
2615 auto SymI = JD.Symbols.find(
Name);
2616 if (SymI == JD.Symbols.end()) {
2623 if (!SymI->second.getFlags().isExported() &&
2635 if (SymI->second.getFlags().hasMaterializationSideEffectsOnly() &&
2639 "required, but symbol is has-side-effects-only\n";
2647 if (SymI->second.getFlags().hasError()) {
2649 auto FailedSymbolsMap = std::make_shared<SymbolDependenceMap>();
2650 (*FailedSymbolsMap)[&JD] = {
Name};
2651 return make_error<FailedToMaterialize>(
2659 if (SymI->second.getState() >= Q->getRequiredState()) {
2661 <<
"matched, symbol already in required state\n");
2662 Q->notifySymbolMetRequiredState(
Name, SymI->second.getSymbol());
2669 if (SymI->second.hasMaterializerAttached()) {
2670 assert(SymI->second.getAddress() == 0 &&
2671 "Symbol not resolved but already has address?");
2672 auto UMII = JD.UnmaterializedInfos.find(
Name);
2673 assert(UMII != JD.UnmaterializedInfos.end() &&
2674 "Lazy symbol should have UnmaterializedInfo");
2676 auto UMI = UMII->second;
2677 assert(UMI->MU &&
"Materializer should not be null");
2678 assert(UMI->RT &&
"Tracker should not be null");
2680 dbgs() <<
"matched, preparing to dispatch MU@" << UMI->MU.get()
2681 <<
" (" << UMI->MU->getName() <<
")\n";
2686 for (
auto &KV : UMI->MU->getSymbols()) {
2687 auto SymK = JD.Symbols.find(KV.first);
2688 assert(SymK != JD.Symbols.end() &&
2689 "No entry for symbol covered by MaterializationUnit");
2690 SymK->second.setMaterializerAttached(
false);
2692 JD.UnmaterializedInfos.erase(KV.first);
2696 CollectedUMIs[&JD].push_back(std::move(UMI));
2704 "By this line the symbol should be materializing");
2705 auto &
MI = JD.MaterializingInfos[
Name];
2707 Q->addQueryDependence(JD,
Name);
2716 dbgs() <<
"Lookup failed. Detaching query and replacing MUs.\n";
2723 for (
auto &KV : CollectedUMIs) {
2724 auto &JD = *KV.first;
2725 for (
auto &UMI : KV.second)
2726 for (
auto &KV2 : UMI->MU->getSymbols()) {
2727 assert(!JD.UnmaterializedInfos.count(KV2.first) &&
2728 "Unexpected materializer in map");
2729 auto SymI = JD.Symbols.find(KV2.first);
2730 assert(SymI != JD.Symbols.end() &&
"Missing symbol entry");
2732 "Can not replace symbol that is not materializing");
2733 assert(!SymI->second.hasMaterializerAttached() &&
2734 "MaterializerAttached flag should not be set");
2735 SymI->second.setMaterializerAttached(
true);
2736 JD.UnmaterializedInfos[KV2.first] = UMI;
2744 LLVM_DEBUG(
dbgs() <<
"Stripping unmatched weakly-referenced symbols\n");
2745 IPLS->LookupSet.forEachWithRemoval(
2748 Q->dropSymbol(
Name);
2754 if (!IPLS->LookupSet.empty()) {
2757 IPLS->LookupSet.getSymbolNames());
2761 QueryComplete = Q->isComplete();
2764 dbgs() <<
"Query successfully "
2765 << (QueryComplete ?
"completed" :
"lodged") <<
"\n";
2769 if (!CollectedUMIs.empty()) {
2770 std::lock_guard<std::recursive_mutex> Lock(OutstandingMUsMutex);
2773 for (
auto &KV : CollectedUMIs) {
2775 auto &JD = *KV.first;
2776 dbgs() <<
" For " << JD.getName() <<
": Adding " << KV.second.size()
2779 for (
auto &UMI : KV.second) {
2780 auto MR = createMaterializationResponsibility(
2781 *UMI->RT, std::move(UMI->MU->SymbolFlags),
2782 std::move(UMI->MU->InitSymbol));
2783 OutstandingMUs.push_back(
2784 std::make_pair(std::move(UMI->MU), std::move(MR)));
2790 if (RegisterDependencies && !Q->QueryRegistrations.empty()) {
2792 RegisterDependencies(Q->QueryRegistrations);
2802 Q->handleFailed(std::move(LodgingErr));
2806 if (QueryComplete) {
2808 Q->handleComplete(*
this);
2811 dispatchOutstandingMUs();
2814void ExecutionSession::OL_completeLookupFlags(
2815 std::unique_ptr<InProgressLookupState> IPLS,
2816 unique_function<
void(Expected<SymbolFlagsMap>)> OnComplete) {
2820 dbgs() <<
"Entering OL_completeLookupFlags:\n"
2821 <<
" Lookup kind: " << IPLS->K <<
"\n"
2822 <<
" Search order: " << IPLS->SearchOrder
2823 <<
", Current index = " << IPLS->CurSearchOrderIndex
2824 << (IPLS->NewJITDylib ?
" (entering new JITDylib)" :
"") <<
"\n"
2825 <<
" Lookup set: " << IPLS->LookupSet <<
"\n"
2826 <<
" Definition generator candidates: "
2827 << IPLS->DefGeneratorCandidates <<
"\n"
2828 <<
" Definition generator non-candidates: "
2829 << IPLS->DefGeneratorNonCandidates <<
"\n";
2835 for (
auto &KV : IPLS->SearchOrder) {
2836 auto &JD = *KV.first;
2837 auto JDLookupFlags = KV.second;
2839 dbgs() <<
"Visiting \"" << JD.getName() <<
"\" (" << JDLookupFlags
2840 <<
") with lookup set " << IPLS->LookupSet <<
":\n";
2843 IPLS->LookupSet.forEachWithRemoval([&](
const SymbolStringPtr &
Name,
2846 dbgs() <<
" Attempting to match \"" <<
Name <<
"\" ("
2847 << SymLookupFlags <<
")... ";
2852 auto SymI = JD.Symbols.find(
Name);
2853 if (SymI == JD.Symbols.end()) {
2859 if (!SymI->second.getFlags().isExported() &&
2866 dbgs() <<
"matched, \"" <<
Name <<
"\" -> " << SymI->second.getFlags()
2875 IPLS->LookupSet.remove_if(
2880 if (!IPLS->LookupSet.empty()) {
2883 IPLS->LookupSet.getSymbolNames());
2892 OnComplete(std::move(
Result));
2895void ExecutionSession::OL_destroyMaterializationResponsibility(
2896 MaterializationResponsibility &MR) {
2898 assert(MR.SymbolFlags.empty() &&
2899 "All symbols should have been explicitly materialized or failed");
2900 MR.JD.unlinkMaterializationResponsibility(MR);
2904 const MaterializationResponsibility &MR) {
2905 return MR.JD.getRequestedSymbols(MR.SymbolFlags);
2908Error ExecutionSession::OL_notifyResolved(MaterializationResponsibility &MR,
2911 dbgs() <<
"In " << MR.JD.getName() <<
" resolving " << Symbols <<
"\n";
2914 for (
auto &KV : Symbols) {
2915 auto I = MR.SymbolFlags.find(KV.first);
2916 assert(
I != MR.SymbolFlags.end() &&
2917 "Resolving symbol outside this responsibility set");
2918 assert(!
I->second.hasMaterializationSideEffectsOnly() &&
2919 "Can't resolve materialization-side-effects-only symbol");
2922 "Resolving symbol with incorrect flags");
2926 return MR.JD.resolve(MR, Symbols);
2929Error ExecutionSession::OL_notifyEmitted(MaterializationResponsibility &MR) {
2931 dbgs() <<
"In " << MR.JD.getName() <<
" emitting " << MR.SymbolFlags
2935 if (
auto Err = MR.JD.emit(MR, MR.SymbolFlags))
2938 MR.SymbolFlags.clear();
2942Error ExecutionSession::OL_defineMaterializing(
2943 MaterializationResponsibility &MR,
SymbolFlagsMap NewSymbolFlags) {
2946 dbgs() <<
"In " << MR.JD.getName() <<
" defining materializing symbols "
2947 << NewSymbolFlags <<
"\n";
2949 if (
auto AcceptedDefs =
2950 MR.JD.defineMaterializing(std::move(NewSymbolFlags))) {
2952 for (
auto &KV : *AcceptedDefs)
2953 MR.SymbolFlags.insert(KV);
2956 return AcceptedDefs.takeError();
2959void ExecutionSession::OL_notifyFailed(MaterializationResponsibility &MR) {
2962 dbgs() <<
"In " << MR.JD.getName() <<
" failing materialization for "
2963 << MR.SymbolFlags <<
"\n";
2966 JITDylib::FailedSymbolsWorklist Worklist;
2968 for (
auto &KV : MR.SymbolFlags)
2969 Worklist.push_back(std::make_pair(&MR.JD, KV.first));
2970 MR.SymbolFlags.clear();
2972 if (Worklist.empty())
2975 JITDylib::AsynchronousSymbolQuerySet FailedQueries;
2976 std::shared_ptr<SymbolDependenceMap> FailedSymbols;
2980 if (MR.RT->isDefunct())
2983 std::tie(FailedQueries, FailedSymbols) =
2984 JITDylib::failSymbols(std::move(Worklist));
2987 for (
auto &Q : FailedQueries)
2992Error ExecutionSession::OL_replace(MaterializationResponsibility &MR,
2993 std::unique_ptr<MaterializationUnit> MU) {
2994 for (
auto &KV : MU->getSymbols()) {
2995 assert(MR.SymbolFlags.count(KV.first) &&
2996 "Replacing definition outside this responsibility set");
2997 MR.SymbolFlags.erase(KV.first);
3000 if (MU->getInitializerSymbol() == MR.InitSymbol)
3001 MR.InitSymbol =
nullptr;
3003 LLVM_DEBUG(MR.JD.getExecutionSession().runSessionLocked([&]() {
3004 dbgs() <<
"In " << MR.JD.getName() <<
" replacing symbols with " << *MU
3008 return MR.JD.replace(MR, std::move(MU));
3011Expected<std::unique_ptr<MaterializationResponsibility>>
3012ExecutionSession::OL_delegate(MaterializationResponsibility &MR,
3015 SymbolStringPtr DelegatedInitSymbol;
3018 for (
auto &
Name : Symbols) {
3019 auto I = MR.SymbolFlags.find(
Name);
3020 assert(
I != MR.SymbolFlags.end() &&
3021 "Symbol is not tracked by this MaterializationResponsibility "
3024 DelegatedFlags[
Name] = std::move(
I->second);
3025 if (
Name == MR.InitSymbol)
3026 std::swap(MR.InitSymbol, DelegatedInitSymbol);
3028 MR.SymbolFlags.erase(
I);
3031 return MR.JD.delegate(MR, std::move(DelegatedFlags),
3032 std::move(DelegatedInitSymbol));
3035void ExecutionSession::OL_addDependencies(
3036 MaterializationResponsibility &MR,
const SymbolStringPtr &
Name,
3039 dbgs() <<
"Adding dependencies for " <<
Name <<
": " << Dependencies
3043 "Symbol not covered by this MaterializationResponsibility instance");
3044 MR.JD.addDependencies(
Name, Dependencies);
3047void ExecutionSession::OL_addDependenciesForAll(
3048 MaterializationResponsibility &MR,
3051 dbgs() <<
"Adding dependencies for all symbols in " << MR.SymbolFlags <<
": "
3052 << Dependencies <<
"\n";
3054 for (
auto &KV : MR.SymbolFlags)
3055 MR.JD.addDependencies(KV.first, Dependencies);
3059void ExecutionSession::dumpDispatchInfo(Task &
T) {
3061 dbgs() <<
"Dispatching: ";
3062 T.printDescription(
dbgs());
static StringRef getName(Value *V)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static uint32_t getFlags(const Symbol *Sym)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
const T & front() const
front - Get the first element.
size_t size() const
size - Get the array size.
bool empty() const
empty - Check if the array is empty.
iterator find(const_arg_type_t< KeyT > Val)
bool erase(const KeyT &Val)
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Helper for Errors used as out-parameters.
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
Represents a symbol that has been evaluated to an address already.
JITSymbolFlags getFlags() const
Return the flags for this symbol.
bool hasMaterializationSideEffectsOnly() const
Returns true if this symbol is a materialization-side-effects-only symbol.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
Symbol info for RuntimeDyld.
std::pair< iterator, bool > insert(const ValueT &V)
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
const std::string & getName() const
Get the name for this JITLinkDylib.
StringRef getName() const override
Return the name of this materialization unit.
AbsoluteSymbolsMaterializationUnit(SymbolMap Symbols)
AsynchronousSymbolQuery(const SymbolLookupSet &Symbols, SymbolState RequiredState, SymbolsResolvedCallback NotifyComplete)
Create a query for the given symbols.
void notifySymbolMetRequiredState(const SymbolStringPtr &Name, JITEvaluatedSymbol Sym)
Notify the query that a requested symbol has reached the required state.
Definition generators can be attached to JITDylibs to generate new definitions for otherwise unresolv...
virtual ~DefinitionGenerator()
An ExecutionSession represents a running JIT program.
Error endSession()
End the session.
void runJITDispatchHandler(SendResultFunction SendResult, JITTargetAddress HandlerFnTagAddr, ArrayRef< char > ArgBuffer)
Run a registered jit-side wrapper function.
void reportError(Error Err)
Report a error for this execution session.
void lookupFlags(LookupKind K, JITDylibSearchOrder SearchOrder, SymbolLookupSet Symbols, unique_function< void(Expected< SymbolFlagsMap >)> OnComplete)
Search the given JITDylibs to find the flags associated with each of the given symbols.
SymbolStringPtr intern(StringRef SymName)
Add a symbol name to the SymbolStringPool and return a pointer to it.
JITDylib * getJITDylibByName(StringRef Name)
Return a pointer to the "name" JITDylib.
JITDylib & createBareJITDylib(std::string Name)
Add a new bare JITDylib to this ExecutionSession.
std::shared_ptr< SymbolStringPool > getSymbolStringPool()
Get the SymbolStringPool for this instance.
void lookup(LookupKind K, const JITDylibSearchOrder &SearchOrder, SymbolLookupSet Symbols, SymbolState RequiredState, SymbolsResolvedCallback NotifyComplete, RegisterDependenciesFunction RegisterDependencies)
Search the given JITDylibs for the given symbols.
Error registerJITDispatchHandlers(JITDylib &JD, JITDispatchHandlerAssociationMap WFs)
For each tag symbol name, associate the corresponding AsyncHandlerWrapperFunction with the address of...
void registerResourceManager(ResourceManager &RM)
Register the given ResourceManager with this ExecutionSession.
~ExecutionSession()
Destroy an ExecutionSession.
void deregisterResourceManager(ResourceManager &RM)
Deregister the given ResourceManager with this ExecutionSession.
ExecutionSession(std::unique_ptr< ExecutorProcessControl > EPC)
Construct an ExecutionSession with the given ExecutorProcessControl object.
decltype(auto) runSessionLocked(Func &&F)
Run the given lambda with the session mutex locked.
void dump(raw_ostream &OS)
Dump the state of all the JITDylibs in this session.
Expected< JITDylib & > createJITDylib(std::string Name)
Add a new JITDylib to this ExecutionSession.
void dispatchTask(std::unique_ptr< Task > T)
Materialize the given unit.
Error removeJITDylib(JITDylib &JD)
Closes the given JITDylib.
FailedToMaterialize(std::shared_ptr< SymbolStringPool > SSP, std::shared_ptr< SymbolDependenceMap > Symbols)
std::error_code convertToErrorCode() const override
Convert this error to a std::error_code.
void log(raw_ostream &OS) const override
Print an error message to an output stream.
InProgressFullLookupState(LookupKind K, JITDylibSearchOrder SearchOrder, SymbolLookupSet LookupSet, SymbolState RequiredState, std::shared_ptr< AsynchronousSymbolQuery > Q, RegisterDependenciesFunction RegisterDependencies)
void complete(std::unique_ptr< InProgressLookupState > IPLS) override
void fail(Error Err) override
void complete(std::unique_ptr< InProgressLookupState > IPLS) override
void fail(Error Err) override
InProgressLookupFlagsState(LookupKind K, JITDylibSearchOrder SearchOrder, SymbolLookupSet LookupSet, unique_function< void(Expected< SymbolFlagsMap >)> OnComplete)
virtual ~InProgressLookupState()=default
SymbolLookupSet DefGeneratorCandidates
JITDylibSearchOrder SearchOrder
std::vector< std::weak_ptr< DefinitionGenerator > > CurDefGeneratorStack
size_t CurSearchOrderIndex
SymbolLookupSet LookupSet
virtual void complete(std::unique_ptr< InProgressLookupState > IPLS)=0
InProgressLookupState(LookupKind K, JITDylibSearchOrder SearchOrder, SymbolLookupSet LookupSet, SymbolState RequiredState)
SymbolState RequiredState
SymbolLookupSet DefGeneratorNonCandidates
virtual void fail(Error Err)=0
std::unique_lock< std::mutex > GeneratorLock
Represents a JIT'd dynamic library.
Error clear()
Calls remove on all trackers currently associated with this JITDylib.
Error define(std::unique_ptr< MaterializationUnitType > &&MU, ResourceTrackerSP RT=nullptr)
Define all symbols provided by the materialization unit to be part of this JITDylib.
ExecutionSession & getExecutionSession() const
Get a reference to the ExecutionSession for this JITDylib.
ResourceTrackerSP createResourceTracker()
Create a resource tracker for this JITDylib.
Expected< std::vector< JITDylibSP > > getReverseDFSLinkOrder()
Rteurn this JITDylib and its transitive dependencies in reverse DFS order based on linkage relationsh...
ResourceTrackerSP getDefaultResourceTracker()
Get the default resource tracker for this JITDylib.
void removeGenerator(DefinitionGenerator &G)
Remove a definition generator from this JITDylib.
Expected< std::vector< JITDylibSP > > getDFSLinkOrder()
Return this JITDylib and its transitive dependencies in DFS order based on linkage relationships.
Wraps state for a lookup-in-progress.
void continueLookup(Error Err)
Continue the lookup.
LookupState & operator=(LookupState &&)
void printDescription(raw_ostream &OS) override
A MaterializationUnit represents a set of symbol definitions that can be materialized as a group,...
SymbolFlagsMap SymbolFlags
std::error_code convertToErrorCode() const override
Convert this error to a std::error_code.
void log(raw_ostream &OS) const override
Print an error message to an output stream.
Non-owning SymbolStringPool entry pointer.
StringRef getName() const override
Return the name of this materialization unit.
ReExportsMaterializationUnit(JITDylib *SourceJD, JITDylibLookupFlags SourceJDLookupFlags, SymbolAliasMap Aliases)
SourceJD is allowed to be nullptr, in which case the source JITDylib is taken to be whatever JITDylib...
std::function< bool(SymbolStringPtr)> SymbolPredicate
Error tryToGenerate(LookupState &LS, LookupKind K, JITDylib &JD, JITDylibLookupFlags JDLookupFlags, const SymbolLookupSet &LookupSet) override
DefinitionGenerators should override this method to insert new definitions into the parent JITDylib.
ReexportsGenerator(JITDylib &SourceJD, JITDylibLookupFlags SourceJDLookupFlags, SymbolPredicate Allow=SymbolPredicate())
Create a reexports generator.
Listens for ResourceTracker operations.
virtual ~ResourceManager()
ResourceTrackerDefunct(ResourceTrackerSP RT)
void log(raw_ostream &OS) const override
Print an error message to an output stream.
std::error_code convertToErrorCode() const override
Convert this error to a std::error_code.
API to remove / transfer ownership of JIT resources.
JITDylib & getJITDylib() const
Return the JITDylib targeted by this tracker.
void transferTo(ResourceTracker &DstRT)
Transfer all resources associated with this key to the given tracker, which must target the same JITD...
ResourceTracker(const ResourceTracker &)=delete
Error remove()
Remove all resources associated with this key.
A set of symbols to look up, each associated with a SymbolLookupFlags value.
static SymbolLookupSet fromMapKeys(const DenseMap< SymbolStringPtr, KeyT > &M, SymbolLookupFlags Flags=SymbolLookupFlags::RequiredSymbol)
Construct a SymbolLookupSet from DenseMap keys.
Pointer to a pooled string representing a symbol name.
std::error_code convertToErrorCode() const override
Convert this error to a std::error_code.
void log(raw_ostream &OS) const override
Print an error message to an output stream.
SymbolsCouldNotBeRemoved(std::shared_ptr< SymbolStringPool > SSP, SymbolNameSet Symbols)
void log(raw_ostream &OS) const override
Print an error message to an output stream.
SymbolsNotFound(std::shared_ptr< SymbolStringPool > SSP, SymbolNameSet Symbols)
std::error_code convertToErrorCode() const override
Convert this error to a std::error_code.
Represents an abstract task for ORC to run.
std::error_code convertToErrorCode() const override
Convert this error to a std::error_code.
void log(raw_ostream &OS) const override
Print an error message to an output stream.
static WrapperFunctionResult createOutOfBandError(const char *Msg)
Create an out-of-band error by copying the given string.
This class implements an extremely fast bulk output stream that can only output to a stream.
IntrusiveRefCntPtr< JITDylib > JITDylibSP
JITDylibSearchOrder makeJITDylibSearchOrder(ArrayRef< JITDylib * > JDs, JITDylibLookupFlags Flags=JITDylibLookupFlags::MatchExportedSymbolsOnly)
Convenience function for creating a search order from an ArrayRef of JITDylib*, all with the same fla...
std::vector< std::pair< JITDylib *, JITDylibLookupFlags > > JITDylibSearchOrder
A list of (JITDylib*, JITDylibLookupFlags) pairs to be used as a search order during symbol lookup.
std::function< void(const SymbolDependenceMap &)> RegisterDependenciesFunction
Callback to register the dependencies for a given query.
@ MissingSymbolDefinitions
@ UnexpectedSymbolDefinitions
std::unique_ptr< ReExportsMaterializationUnit > symbolAliases(SymbolAliasMap Aliases)
Create a ReExportsMaterializationUnit with the given aliases.
DenseMap< SymbolStringPtr, JITEvaluatedSymbol > SymbolMap
A map from symbol names (as SymbolStringPtrs) to JITSymbols (address/flags pairs).
SymbolLookupFlags
Lookup flags that apply to each symbol in a lookup.
std::unique_ptr< ReExportsMaterializationUnit > reexports(JITDylib &SourceJD, SymbolAliasMap Aliases, JITDylibLookupFlags SourceJDLookupFlags=JITDylibLookupFlags::MatchExportedSymbolsOnly)
Create a materialization unit for re-exporting symbols from another JITDylib with alternative names/f...
DenseMap< SymbolStringPtr, SymbolAliasMapEntry > SymbolAliasMap
A map of Symbols to (Symbol, Flags) pairs.
JITDylibLookupFlags
Lookup flags that apply to each dylib in the search order for a lookup.
@ MatchExportedSymbolsOnly
DenseMap< SymbolStringPtr, JITSymbolFlags > SymbolFlagsMap
A map from symbol names (as SymbolStringPtrs) to JITSymbolFlags.
unique_function< void(Expected< SymbolMap >)> SymbolsResolvedCallback
Callback to notify client that symbols have been resolved.
DenseSet< SymbolStringPtr > SymbolNameSet
A set of symbol names (represented by SymbolStringPtrs for.
LookupKind
Describes the kind of lookup being performed.
RegisterDependenciesFunction NoDependenciesToRegister
This can be used as the value for a RegisterDependenciesFunction if there are no dependants to regist...
std::vector< SymbolStringPtr > SymbolNameVector
A vector of symbol names.
SymbolState
Represents the state that a symbol has reached during materialization.
@ Materializing
Added to the symbol table, never queried.
@ NeverSearched
No symbol should be in this state.
@ Ready
Emitted to memory, but waiting on transitive dependencies.
@ Resolved
Queried, materialization begun.
std::error_code orcError(OrcErrorCode ErrCode)
DenseMap< JITDylib *, SymbolNameSet > SymbolDependenceMap
A map from JITDylibs to sets of symbols.
Expected< SymbolAliasMap > buildSimpleReexportsAliasMap(JITDylib &SourceJD, const SymbolNameSet &Symbols)
Build a SymbolAliasMap for the common case where you want to re-export symbols from another JITDylib ...
This is an optimization pass for GlobalISel generic memory operations.
auto formatv(const char *Fmt, Ts &&... Vals) -> formatv_object< decltype(std::make_tuple(detail::build_format_adapter(std::forward< Ts >(Vals))...))>
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
void append_range(Container &C, Range &&R)
Wrapper function to append a range to a container.
auto reverse(ContainerTy &&C)
Error joinErrors(Error E1, Error E2)
Concatenate errors.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
auto lower_bound(R &&Range, T &&Value)
Provide wrappers to std::lower_bound which take ranges instead of having to pass begin/end explicitly...
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.