llvm.org GIT mirror llvm / c0773a5
[ORC] Fix a FIXME: Propagate errors to dependencies. When symbols are failed (via MaterializationResponsibility::failMaterialization) any symbols depending on them will now be moved to an error state. Attempting to resolve or emit a symbol in the error state (via the notifyResolved or notifyEmitted methods on MaterializationResponsibility) will result in an error. If notifyResolved or notifyEmitted return an error due to failure of a dependence then the caller should log or discard the error and call failMaterialization to propagate the failure to any queries waiting on the symbols being resolved/emitted (plus their dependencies). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@369808 91177308-0d34-0410-b5e6-96231b3b80d8 Lang Hames 24 days ago
8 changed file(s) with 657 addition(s) and 192 deletion(s). Raw diff Collapse all Expand all
122122 public:
123123 static char ID;
124124
125 FailedToMaterialize(SymbolNameSet Symbols);
125 FailedToMaterialize(std::shared_ptr Symbols);
126126 std::error_code convertToErrorCode() const override;
127127 void log(raw_ostream &OS) const override;
128 const SymbolNameSet &getSymbols() const { return Symbols; }
129
130 private:
131 SymbolNameSet Symbols;
128 const SymbolDependenceMap &getSymbols() const { return *Symbols; }
129
130 private:
131 std::shared_ptr Symbols;
132132 };
133133
134134 /// Used to notify clients when symbols can not be found during a lookup.
203203 /// symbols must be ones covered by this MaterializationResponsibility
204204 /// instance. Individual calls to this method may resolve a subset of the
205205 /// symbols, but all symbols must have been resolved prior to calling emit.
206 void notifyResolved(const SymbolMap &Symbols);
206 ///
207 /// This method will return an error if any symbols being resolved have been
208 /// moved to the error state due to the failure of a dependency. If this
209 /// method returns an error then clients should log it and call
210 /// failMaterialize. If no dependencies have been registered for the
211 /// symbols covered by this MaterializationResponsibiility then this method
212 /// is guaranteed to return Error::success() and can be wrapped with cantFail.
213 Error notifyResolved(const SymbolMap &Symbols);
207214
208215 /// Notifies the target JITDylib (and any pending queries on that JITDylib)
209216 /// that all symbols covered by this MaterializationResponsibility instance
210217 /// have been emitted.
211 void notifyEmitted();
218 ///
219 /// This method will return an error if any symbols being resolved have been
220 /// moved to the error state due to the failure of a dependency. If this
221 /// method returns an error then clients should log it and call
222 /// failMaterialize. If no dependencies have been registered for the
223 /// symbols covered by this MaterializationResponsibiility then this method
224 /// is guaranteed to return Error::success() and can be wrapped with cantFail.
225 Error notifyEmitted();
212226
213227 /// Adds new symbols to the JITDylib and this responsibility instance.
214228 /// JITDylib entries start out in the materializing state.
627641 void addQuery(std::shared_ptr Q);
628642 void removeQuery(const AsynchronousSymbolQuery &Q);
629643 AsynchronousSymbolQueryList takeQueriesMeeting(SymbolState RequiredState);
644 AsynchronousSymbolQueryList takeAllPendingQueries() {
645 return std::move(PendingQueries);
646 }
630647 bool hasQueriesPending() const { return !PendingQueries.empty(); }
631648 const AsynchronousSymbolQueryList &pendingQueries() const {
632649 return PendingQueries;
633650 }
634
635651 private:
636652 AsynchronousSymbolQueryList PendingQueries;
637653 };
698714 SymbolNameSet &Unresolved, bool MatchNonExported,
699715 MaterializationUnitList &MUs);
700716
701 void lodgeQueryImpl(std::shared_ptr &Q,
702 SymbolNameSet &Unresolved, bool MatchNonExported,
703 MaterializationUnitList &MUs);
717 Error lodgeQueryImpl(std::shared_ptr &Q,
718 SymbolNameSet &Unresolved, bool MatchNonExported,
719 MaterializationUnitList &MUs);
704720
705721 bool lookupImpl(std::shared_ptr &Q,
706722 std::vector> &MUs,
719735
720736 SymbolNameSet getRequestedSymbols(const SymbolFlagsMap &SymbolFlags) const;
721737
738 // Move a symbol to the failure state.
739 // Detaches the symbol from all dependencies, moves all dependants to the
740 // error state (but does not fail them), deletes the MaterializingInfo for
741 // the symbol (if present) and returns the set of queries that need to be
742 // notified of the failure.
743 AsynchronousSymbolQuerySet failSymbol(const SymbolStringPtr &Name);
744
722745 void addDependencies(const SymbolStringPtr &Name,
723746 const SymbolDependenceMap &Dependants);
724747
725 void resolve(const SymbolMap &Resolved);
726
727 void emit(const SymbolFlagsMap &Emitted);
728
729 void notifyFailed(const SymbolNameSet &FailedSymbols);
748 Error resolve(const SymbolMap &Resolved);
749
750 Error emit(const SymbolFlagsMap &Emitted);
751
752 void notifyFailed(const SymbolFlagsMap &FailedSymbols);
730753
731754 ExecutionSession &ES;
732755 std::string JITDylibName;
150150 }
151151
152152 raw_ostream &operator<<(raw_ostream &OS, const JITSymbolFlags &Flags) {
153 if (Flags.hasError())
154 OS << "[*ERROR*]";
153155 if (Flags.isCallable())
154156 OS << "[Callable]";
155157 else
243245 llvm_unreachable("Invalid state");
244246 }
245247
246 FailedToMaterialize::FailedToMaterialize(SymbolNameSet Symbols)
248 FailedToMaterialize::FailedToMaterialize(
249 std::shared_ptr Symbols)
247250 : Symbols(std::move(Symbols)) {
248 assert(!this->Symbols.empty() && "Can not fail to resolve an empty set");
251 assert(!this->Symbols->empty() && "Can not fail to resolve an empty set");
249252 }
250253
251254 std::error_code FailedToMaterialize::convertToErrorCode() const {
253256 }
254257
255258 void FailedToMaterialize::log(raw_ostream &OS) const {
256 OS << "Failed to materialize symbols: " << Symbols;
259 OS << "Failed to materialize symbols: " << *Symbols;
257260 }
258261
259262 SymbolsNotFound::SymbolsNotFound(SymbolNameSet Symbols)
366369 return JD.getRequestedSymbols(SymbolFlags);
367370 }
368371
369 void MaterializationResponsibility::notifyResolved(const SymbolMap &Symbols) {
372 Error MaterializationResponsibility::notifyResolved(const SymbolMap &Symbols) {
370373 LLVM_DEBUG({
371374 dbgs() << "In " << JD.getName() << " resolving " << Symbols << "\n";
372375 });
384387 }
385388 #endif
386389
387 JD.resolve(Symbols);
388 }
389
390 void MaterializationResponsibility::notifyEmitted() {
390 return JD.resolve(Symbols);
391 }
392
393 Error MaterializationResponsibility::notifyEmitted() {
391394
392395 LLVM_DEBUG({
393396 dbgs() << "In " << JD.getName() << " emitting " << SymbolFlags << "\n";
394397 });
395398
396 JD.emit(SymbolFlags);
399 if (auto Err = JD.emit(SymbolFlags))
400 return Err;
401
397402 SymbolFlags.clear();
403 return Error::success();
398404 }
399405
400406 Error MaterializationResponsibility::defineMaterializing(
416422 << SymbolFlags << "\n";
417423 });
418424
419 SymbolNameSet FailedSymbols;
420 for (auto &KV : SymbolFlags)
421 FailedSymbols.insert(KV.first);
422
423 JD.notifyFailed(FailedSymbols);
425 JD.notifyFailed(SymbolFlags);
424426 SymbolFlags.clear();
425427 }
426428
484486
485487 void AbsoluteSymbolsMaterializationUnit::materialize(
486488 MaterializationResponsibility R) {
487 R.notifyResolved(Symbols);
488 R.notifyEmitted();
489 // No dependencies, so these calls can't fail.
490 cantFail(R.notifyResolved(Symbols));
491 cantFail(R.notifyEmitted());
489492 }
490493
491494 void AbsoluteSymbolsMaterializationUnit::discard(const JITDylib &JD,
624627 };
625628
626629 auto OnComplete = [QueryInfo](Expected Result) {
630 auto &ES = QueryInfo->R.getTargetJITDylib().getExecutionSession();
627631 if (Result) {
628632 SymbolMap ResolutionMap;
629633 for (auto &KV : QueryInfo->Aliases) {
632636 ResolutionMap[KV.first] = JITEvaluatedSymbol(
633637 (*Result)[KV.second.Aliasee].getAddress(), KV.second.AliasFlags);
634638 }
635 QueryInfo->R.notifyResolved(ResolutionMap);
636 QueryInfo->R.notifyEmitted();
639 if (auto Err = QueryInfo->R.notifyResolved(ResolutionMap)) {
640 ES.reportError(std::move(Err));
641 QueryInfo->R.failMaterialization();
642 return;
643 }
644 if (auto Err = QueryInfo->R.notifyEmitted()) {
645 ES.reportError(std::move(Err));
646 QueryInfo->R.failMaterialization();
647 return;
648 }
637649 } else {
638 auto &ES = QueryInfo->R.getTargetJITDylib().getExecutionSession();
639650 ES.reportError(Result.takeError());
640651 QueryInfo->R.failMaterialization();
641652 }
829840 });
830841 }
831842
843 JITDylib::AsynchronousSymbolQuerySet
844 JITDylib::failSymbol(const SymbolStringPtr &Name) {
845 assert(Symbols.count(Name) && "Name not in symbol table");
846 assert(Symbols[Name].getFlags().hasError() &&
847 "Failing symbol not in the error state");
848
849 auto MII = MaterializingInfos.find(Name);
850 if (MII == MaterializingInfos.end())
851 return AsynchronousSymbolQuerySet();
852
853 auto &MI = MII->second;
854
855 // Visit all dependants.
856 for (auto &KV : MI.Dependants) {
857 auto &DependantJD = *KV.first;
858 for (auto &DependantName : KV.second) {
859 assert(DependantJD.Symbols.count(DependantName) &&
860 "No symbol with DependantName in DependantJD");
861 auto &DependantSymTabEntry = DependantJD.Symbols[DependantName];
862 DependantSymTabEntry.setFlags(DependantSymTabEntry.getFlags() |
863 JITSymbolFlags::HasError);
864
865 assert(DependantJD.MaterializingInfos.count(DependantName) &&
866 "Dependant symbol does not have MaterializingInfo?");
867 auto &DependantMI = DependantJD.MaterializingInfos[DependantName];
868
869 assert(DependantMI.UnemittedDependencies.count(this) &&
870 "No unemitted dependency recorded for this JD?");
871 auto UnemittedDepsI = DependantMI.UnemittedDependencies.find(this);
872 assert(UnemittedDepsI != DependantMI.UnemittedDependencies.end() &&
873 "No unemitted dependency on this JD");
874 assert(UnemittedDepsI->second.count(Name) &&
875 "No unemitted dependency on symbol Name in this JD");
876
877 UnemittedDepsI->second.erase(Name);
878 if (UnemittedDepsI->second.empty())
879 DependantMI.UnemittedDependencies.erase(UnemittedDepsI);
880 }
881 }
882
883 // Visit all unemitted dependencies and disconnect from them.
884 for (auto &KV : MI.UnemittedDependencies) {
885 auto &DependencyJD = *KV.first;
886 for (auto &DependencyName : KV.second) {
887 assert(DependencyJD.MaterializingInfos.count(DependencyName) &&
888 "Dependency does not have MaterializingInfo");
889 auto &DependencyMI = DependencyJD.MaterializingInfos[DependencyName];
890 auto DependantsI = DependencyMI.Dependants.find(this);
891 assert(DependantsI != DependencyMI.Dependants.end() &&
892 "No dependnts entry recorded for this JD");
893 assert(DependantsI->second.count(Name) &&
894 "No dependants entry recorded for Name");
895 DependantsI->second.erase(Name);
896 if (DependantsI->second.empty())
897 DependencyMI.Dependants.erase(DependantsI);
898 }
899 }
900
901 AsynchronousSymbolQuerySet QueriesToFail;
902 for (auto &Q : MI.takeAllPendingQueries())
903 QueriesToFail.insert(std::move(Q));
904 return QueriesToFail;
905 }
906
832907 void JITDylib::addDependencies(const SymbolStringPtr &Name,
833908 const SymbolDependenceMap &Dependencies) {
834909 assert(Symbols.count(Name) && "Name not in symbol table");
835910 assert(Symbols[Name].isInMaterializationPhase() &&
836911 "Can not add dependencies for a symbol that is not materializing");
837912
913 // If Name is already in an error state then just bail out.
914 if (Symbols[Name].getFlags().hasError())
915 return;
916
838917 auto &MI = MaterializingInfos[Name];
839918 assert(!MI.IsEmitted && "Can not add dependencies to an emitted symbol");
840919
920 bool DependsOnSymbolInErrorState = false;
921
922 // Register dependencies, record whether any depenendency is in the error
923 // state.
841924 for (auto &KV : Dependencies) {
842925 assert(KV.first && "Null JITDylib in dependency?");
843926 auto &OtherJITDylib = *KV.first;
844927 auto &DepsOnOtherJITDylib = MI.UnemittedDependencies[&OtherJITDylib];
845928
846929 for (auto &OtherSymbol : KV.second) {
930
931 // Check the sym entry for the dependency.
932 auto SymI = OtherJITDylib.Symbols.find(OtherSymbol);
933
847934 #ifndef NDEBUG
848935 // Assert that this symbol exists and has not been emitted already.
849 auto SymI = OtherJITDylib.Symbols.find(OtherSymbol);
850936 assert(SymI != OtherJITDylib.Symbols.end() &&
851937 (SymI->second.getState() != SymbolState::Ready &&
852938 "Dependency on emitted symbol"));
853939 #endif
854940
941 // If the dependency is in an error state then note this and continue,
942 // we will move this symbol to the error state below.
943 if (SymI->second.getFlags().hasError()) {
944 DependsOnSymbolInErrorState = true;
945 continue;
946 }
947
948 // If the dependency was not in the error state then add it to
949 // our list of dependencies.
950 assert(OtherJITDylib.MaterializingInfos.count(OtherSymbol) &&
951 "No MaterializingInfo for dependency");
855952 auto &OtherMI = OtherJITDylib.MaterializingInfos[OtherSymbol];
856953
857954 if (OtherMI.IsEmitted)
865962 if (DepsOnOtherJITDylib.empty())
866963 MI.UnemittedDependencies.erase(&OtherJITDylib);
867964 }
868 }
869
870 void JITDylib::resolve(const SymbolMap &Resolved) {
871 auto CompletedQueries = ES.runSessionLocked([&, this]() {
872 AsynchronousSymbolQuerySet CompletedQueries;
965
966 // If this symbol dependended on any symbols in the error state then move
967 // this symbol to the error state too.
968 if (DependsOnSymbolInErrorState)
969 Symbols[Name].setFlags(Symbols[Name].getFlags() | JITSymbolFlags::HasError);
970 }
971
972 Error JITDylib::resolve(const SymbolMap &Resolved) {
973 SymbolNameSet SymbolsInErrorState;
974 AsynchronousSymbolQuerySet CompletedQueries;
975
976 ES.runSessionLocked([&, this]() {
977 struct WorklistEntry {
978 SymbolTable::iterator SymI;
979 JITEvaluatedSymbol ResolvedSym;
980 };
981
982 std::vector Worklist;
983 Worklist.reserve(Resolved.size());
984
985 // Build worklist and check for any symbols in the error state.
873986 for (const auto &KV : Resolved) {
874 auto &Name = KV.first;
875 auto Sym = KV.second;
876
877 auto I = Symbols.find(Name);
878
879 assert(I != Symbols.end() && "Symbol not found");
880 assert(!I->second.hasMaterializerAttached() &&
987
988 assert(!KV.second.getFlags().hasError() &&
989 "Resolution result can not have error flag set");
990
991 auto SymI = Symbols.find(KV.first);
992
993 assert(SymI != Symbols.end() && "Symbol not found");
994 assert(!SymI->second.hasMaterializerAttached() &&
881995 "Resolving symbol with materializer attached?");
882 assert(I->second.getState() == SymbolState::Materializing &&
996 assert(SymI->second.getState() == SymbolState::Materializing &&
883997 "Symbol should be materializing");
884 assert(I->second.getAddress() == 0 && "Symbol has already been resolved");
885
886 assert((Sym.getFlags() & ~JITSymbolFlags::Weak) ==
887 (I->second.getFlags() & ~JITSymbolFlags::Weak) &&
888 "Resolved flags should match the declared flags");
889
890 // Once resolved, symbols can never be weak.
891 JITSymbolFlags ResolvedFlags = Sym.getFlags();
998 assert(SymI->second.getAddress() == 0 &&
999 "Symbol has already been resolved");
1000
1001 if (SymI->second.getFlags().hasError())
1002 SymbolsInErrorState.insert(KV.first);
1003 else {
1004 assert((KV.second.getFlags() & ~JITSymbolFlags::Weak) ==
1005 (SymI->second.getFlags() & ~JITSymbolFlags::Weak) &&
1006 "Resolved flags should match the declared flags");
1007
1008 Worklist.push_back({SymI, KV.second});
1009 }
1010 }
1011
1012 // If any symbols were in the error state then bail out.
1013 if (!SymbolsInErrorState.empty())
1014 return;
1015
1016 while (!Worklist.empty()) {
1017 auto SymI = Worklist.back().SymI;
1018 auto ResolvedSym = Worklist.back().ResolvedSym;
1019 Worklist.pop_back();
1020
1021 auto &Name = SymI->first;
1022
1023 // Resolved symbols can not be weak: discard the weak flag.
1024 JITSymbolFlags ResolvedFlags = ResolvedSym.getFlags();
8921025 ResolvedFlags &= ~JITSymbolFlags::Weak;
893 I->second.setAddress(Sym.getAddress());
894 I->second.setFlags(ResolvedFlags);
895 I->second.setState(SymbolState::Resolved);
1026 SymI->second.setAddress(ResolvedSym.getAddress());
1027 SymI->second.setFlags(ResolvedFlags);
1028 SymI->second.setState(SymbolState::Resolved);
8961029
8971030 auto &MI = MaterializingInfos[Name];
8981031 for (auto &Q : MI.takeQueriesMeeting(SymbolState::Resolved)) {
899 Q->notifySymbolMetRequiredState(Name, Sym);
1032 Q->notifySymbolMetRequiredState(Name, ResolvedSym);
9001033 if (Q->isComplete())
9011034 CompletedQueries.insert(std::move(Q));
9021035 }
9031036 }
904
905 return CompletedQueries;
906 });
907
1037 });
1038
1039 assert((SymbolsInErrorState.empty() || CompletedQueries.empty()) &&
1040 "Can't fail symbols and completed queries at the same time");
1041
1042 // If we failed any symbols then return an error.
1043 if (!SymbolsInErrorState.empty()) {
1044 auto FailedSymbolsDepMap = std::make_shared();
1045 (*FailedSymbolsDepMap)[this] = std::move(SymbolsInErrorState);
1046 return make_error(std::move(FailedSymbolsDepMap));
1047 }
1048
1049 // Otherwise notify all the completed queries.
9081050 for (auto &Q : CompletedQueries) {
9091051 assert(Q->isComplete() && "Q not completed");
9101052 Q->handleComplete();
9111053 }
912 }
913
914 void JITDylib::emit(const SymbolFlagsMap &Emitted) {
915 auto CompletedQueries = ES.runSessionLocked([&, this]() {
916 AsynchronousSymbolQuerySet CompletedQueries;
917
1054
1055 return Error::success();
1056 }
1057
1058 Error JITDylib::emit(const SymbolFlagsMap &Emitted) {
1059 AsynchronousSymbolQuerySet CompletedQueries;
1060 SymbolNameSet SymbolsInErrorState;
1061
1062 ES.runSessionLocked([&, this]() {
1063 std::vector Worklist;
1064
1065 // Scan to build worklist, record any symbols in the erorr state.
9181066 for (const auto &KV : Emitted) {
919 const auto &Name = KV.first;
1067 auto &Name = KV.first;
1068
1069 auto SymI = Symbols.find(Name);
1070 assert(SymI != Symbols.end() && "No symbol table entry for Name");
1071
1072 if (SymI->second.getFlags().hasError())
1073 SymbolsInErrorState.insert(Name);
1074 else
1075 Worklist.push_back(SymI);
1076 }
1077
1078 // If any symbols were in the error state then bail out.
1079 if (!SymbolsInErrorState.empty())
1080 return;
1081
1082 // Otherwise update dependencies and move to the emitted state.
1083 while (!Worklist.empty()) {
1084 auto SymI = Worklist.back();
1085 Worklist.pop_back();
1086
1087 auto &Name = SymI->first;
9201088
9211089 auto MII = MaterializingInfos.find(Name);
9221090 assert(MII != MaterializingInfos.end() &&
9231091 "Missing MaterializingInfo entry");
924
9251092 auto &MI = MII->second;
9261093
9271094 // For each dependant, transfer this node's emitted dependencies to
9381105 auto &DependantMI = DependantMII->second;
9391106
9401107 // Remove the dependant's dependency on this node.
1108 assert(DependantMI.UnemittedDependencies.count(this) &&
1109 "Dependant does not have an unemitted dependencies record for "
1110 "this JITDylib");
9411111 assert(DependantMI.UnemittedDependencies[this].count(Name) &&
9421112 "Dependant does not count this symbol as a dependency?");
1113
9431114 DependantMI.UnemittedDependencies[this].erase(Name);
9441115 if (DependantMI.UnemittedDependencies[this].empty())
9451116 DependantMI.UnemittedDependencies.erase(this);
9791150 MI.IsEmitted = true;
9801151
9811152 if (MI.UnemittedDependencies.empty()) {
982 auto SymI = Symbols.find(Name);
983 assert(SymI != Symbols.end() && "Symbol has no entry in Symbols table");
9841153 SymI->second.setState(SymbolState::Ready);
9851154 for (auto &Q : MI.takeQueriesMeeting(SymbolState::Ready)) {
9861155 Q->notifySymbolMetRequiredState(Name, SymI->second.getSymbol());
9911160 MaterializingInfos.erase(MII);
9921161 }
9931162 }
994
995 return CompletedQueries;
996 });
997
1163 });
1164
1165 assert((SymbolsInErrorState.empty() || CompletedQueries.empty()) &&
1166 "Can't fail symbols and completed queries at the same time");
1167
1168 // If we failed any symbols then return an error.
1169 if (!SymbolsInErrorState.empty()) {
1170 auto FailedSymbolsDepMap = std::make_shared();
1171 (*FailedSymbolsDepMap)[this] = std::move(SymbolsInErrorState);
1172 return make_error(std::move(FailedSymbolsDepMap));
1173 }
1174
1175 // Otherwise notify all the completed queries.
9981176 for (auto &Q : CompletedQueries) {
9991177 assert(Q->isComplete() && "Q is not complete");
10001178 Q->handleComplete();
10011179 }
1002 }
1003
1004 void JITDylib::notifyFailed(const SymbolNameSet &FailedSymbols) {
1005
1006 // FIXME: This should fail any transitively dependant symbols too.
1007
1008 auto FailedQueriesToNotify = ES.runSessionLocked([&, this]() {
1009 AsynchronousSymbolQuerySet FailedQueries;
1010 std::vector MIIsToRemove;
1011
1012 for (auto &Name : FailedSymbols) {
1013 auto I = Symbols.find(Name);
1014 assert(I != Symbols.end() && "Symbol not present in this JITDylib");
1015 Symbols.erase(I);
1016
1180
1181 return Error::success();
1182 }
1183
1184 void JITDylib::notifyFailed(const SymbolFlagsMap &FailedSymbols) {
1185 AsynchronousSymbolQuerySet FailedQueries;
1186
1187 ES.runSessionLocked([&]() {
1188 for (auto &KV : FailedSymbols) {
1189 auto &Name = KV.first;
1190
1191 assert(Symbols.count(Name) && "No symbol table entry for Name");
1192 auto &Sym = Symbols[Name];
1193
1194 // Move the symbol into the error state.
1195 // Note that this may be redundant: The symbol might already have been
1196 // moved to this state in response to the failure of a dependence.
1197 Sym.setFlags(Sym.getFlags() | JITSymbolFlags::HasError);
1198
1199 // FIXME: Come up with a sane mapping of state to
1200 // presence-of-MaterializingInfo so that we can assert presence / absence
1201 // here, rather than testing it.
10171202 auto MII = MaterializingInfos.find(Name);
10181203
1019 // If we have not created a MaterializingInfo for this symbol yet then
1020 // there is nobody to notify.
10211204 if (MII == MaterializingInfos.end())
10221205 continue;
10231206
1024 // Remove this symbol from the dependants list of any dependencies.
1025 for (auto &KV : MII->second.UnemittedDependencies) {
1026 auto *DependencyJD = KV.first;
1027 auto &Dependencies = KV.second;
1028 for (auto &DependencyName : Dependencies) {
1029 auto DependencyMII =
1030 DependencyJD->MaterializingInfos.find(DependencyName);
1031 assert(DependencyMII != DependencyJD->MaterializingInfos.end() &&
1032 "Unemitted dependency must have a MaterializingInfo entry");
1033 assert(DependencyMII->second.Dependants.count(this) &&
1034 "Dependency's dependants list does not contain this JITDylib");
1035 assert(DependencyMII->second.Dependants[this].count(Name) &&
1036 "Dependency's dependants list does not contain dependant");
1037 DependencyMII->second.Dependants[this].erase(Name);
1207 auto &MI = MII->second;
1208
1209 // Move all dependants to the error state and disconnect from them.
1210 for (auto &KV : MI.Dependants) {
1211 auto &DependantJD = *KV.first;
1212 for (auto &DependantName : KV.second) {
1213 assert(DependantJD.Symbols.count(DependantName) &&
1214 "No symbol table entry for DependantName");
1215 auto &DependantSym = DependantJD.Symbols[DependantName];
1216 DependantSym.setFlags(DependantSym.getFlags() |
1217 JITSymbolFlags::HasError);
1218
1219 assert(DependantJD.MaterializingInfos.count(DependantName) &&
1220 "No MaterializingInfo for dependant");
1221 auto &DependantMI = DependantJD.MaterializingInfos[DependantName];
1222
1223 auto UnemittedDepI = DependantMI.UnemittedDependencies.find(this);
1224 assert(UnemittedDepI != DependantMI.UnemittedDependencies.end() &&
1225 "No UnemittedDependencies entry for this JITDylib");
1226 assert(UnemittedDepI->second.count(Name) &&
1227 "No UnemittedDependencies entry for this symbol");
1228 UnemittedDepI->second.erase(Name);
1229 if (UnemittedDepI->second.empty())
1230 DependantMI.UnemittedDependencies.erase(UnemittedDepI);
10381231 }
10391232 }
10401233
1041 // Copy all the queries to the FailedQueries list, then abandon them.
1042 // This has to be a copy, and the copy has to come before the abandon
1043 // operation: Each Q.detach() call will reach back into this
1044 // PendingQueries list to remove Q.
1234 // Disconnect from all unemitted depenencies.
1235 for (auto &KV : MI.UnemittedDependencies) {
1236 auto &UnemittedDepJD = *KV.first;
1237 for (auto &UnemittedDepName : KV.second) {
1238 auto UnemittedDepMII =
1239 UnemittedDepJD.MaterializingInfos.find(UnemittedDepName);
1240 assert(UnemittedDepMII != UnemittedDepJD.MaterializingInfos.end() &&
1241 "Missing MII for unemitted dependency");
1242 assert(UnemittedDepMII->second.Dependants.count(this) &&
1243 "JD not listed as a dependant of unemitted dependency");
1244 assert(UnemittedDepMII->second.Dependants[this].count(Name) &&
1245 "Name is not listed as a dependant of unemitted dependency");
1246 UnemittedDepMII->second.Dependants[this].erase(Name);
1247 if (UnemittedDepMII->second.Dependants[this].empty())
1248 UnemittedDepMII->second.Dependants.erase(this);
1249 }
1250 }
1251
1252 // Collect queries to be failed for this MII.
10451253 for (auto &Q : MII->second.pendingQueries())
10461254 FailedQueries.insert(Q);
1047
1048 MIIsToRemove.push_back(std::move(MII));
10491255 }
10501256
10511257 // Detach failed queries.
10531259 Q->detach();
10541260
10551261 // Remove the MaterializingInfos.
1056 for (auto &MII : MIIsToRemove) {
1057 assert(!MII->second.hasQueriesPending() &&
1058 "Queries remain after symbol was failed");
1059
1060 MaterializingInfos.erase(MII);
1061 }
1062
1063 return FailedQueries;
1064 });
1065
1066 for (auto &Q : FailedQueriesToNotify)
1067 Q->handleFailed(make_error(FailedSymbols));
1262 for (auto &KV : FailedSymbols) {
1263 assert(MaterializingInfos.count(KV.first) && "Expected MI for Name");
1264 MaterializingInfos.erase(KV.first);
1265 }
1266 });
1267
1268 auto FailedSymbolsMap = std::make_shared();
1269 for (auto &KV : FailedSymbols)
1270 (*FailedSymbolsMap)[this].insert(KV.first);
1271 for (auto &Q : FailedQueries)
1272 Q->handleFailed(make_error(FailedSymbolsMap));
10681273 }
10691274
10701275 void JITDylib::setSearchOrder(JITDylibSearchList NewSearchOrder,
12201425 MaterializationUnitList &MUs) {
12211426 assert(Q && "Query can not be null");
12221427
1223 lodgeQueryImpl(Q, Unresolved, MatchNonExported, MUs);
1428 if (auto Err = lodgeQueryImpl(Q, Unresolved, MatchNonExported, MUs))
1429 return Err;
12241430
12251431 // Run any definition generators.
12261432 for (auto &DG : DefGenerators) {
12321438 // Run the generator.
12331439 auto NewDefs = DG->tryToGenerate(*this, Unresolved);
12341440
1441 // If the generator returns an error then bail out.
12351442 if (!NewDefs)
12361443 return NewDefs.takeError();
12371444
1445 // If the generator was able to generate new definitions for any of the
1446 // unresolved symbols then lodge the query against them.
12381447 if (!NewDefs->empty()) {
12391448 for (auto &D : *NewDefs)
12401449 Unresolved.erase(D);
1241 lodgeQueryImpl(Q, *NewDefs, MatchNonExported, MUs);
1450
1451 // Lodge query. This can not fail as any new definitions were added
1452 // by the generator under the session locked. Since they can't have
1453 // started materializing yet the can not have failed.
1454 cantFail(lodgeQueryImpl(Q, *NewDefs, MatchNonExported, MUs));
1455
12421456 assert(NewDefs->empty() &&
12431457 "All fallback defs should have been found by lookupImpl");
12441458 }
12471461 return Error::success();
12481462 }
12491463
1250 void JITDylib::lodgeQueryImpl(
1464 Error JITDylib::lodgeQueryImpl(
12511465 std::shared_ptr &Q, SymbolNameSet &Unresolved,
12521466 bool MatchNonExported,
12531467 std::vector> &MUs) {
12671481 // If we matched against Name in JD, mark it to be removed from the
12681482 // Unresolved set.
12691483 ToRemove.push_back(Name);
1484
1485 // If we matched against this symbol but it is in the error state then
1486 // bail out and treat it as a failure to materialize.
1487 if (SymI->second.getFlags().hasError()) {
1488 auto FailedSymbolsMap = std::make_shared();
1489 (*FailedSymbolsMap)[this] = {Name};
1490 return make_error(std::move(FailedSymbolsMap));
1491 }
12701492
12711493 // If this symbol already meets the required state for then notify the
12721494 // query and continue.
13101532 // Remove any symbols that we found.
13111533 for (auto &Name : ToRemove)
13121534 Unresolved.erase(Name);
1535
1536 return Error::success();
13131537 }
13141538
13151539 Expected
3636 void materialize(MaterializationResponsibility R) override {
3737 SymbolMap Result;
3838 Result[Name] = JITEvaluatedSymbol(Compile(), JITSymbolFlags::Exported);
39 R.notifyResolved(Result);
40 R.notifyEmitted();
39 // No dependencies, so these calls cannot fail.
40 cantFail(R.notifyResolved(Result));
41 cantFail(R.notifyEmitted());
4142 }
4243
4344 void discard(const JITDylib &JD, const SymbolStringPtr &Name) override {
181181 for (auto &Alias : RequestedAliases)
182182 Stubs[Alias.first] = ISManager.findStub(*Alias.first, false);
183183
184 R.notifyResolved(Stubs);
185 R.notifyEmitted();
184 // No registered dependencies, so these calls cannot fail.
185 cantFail(R.notifyResolved(Stubs));
186 cantFail(R.notifyEmitted());
186187 }
187188
188189 void LazyReexportsMaterializationUnit::discard(const JITDylib &JD,
126126 if (auto Err = MR.defineMaterializing(ExtraSymbolsToClaim))
127127 return notifyFailed(std::move(Err));
128128
129 MR.notifyResolved(InternedResult);
129 if (auto Err = MR.notifyResolved(InternedResult)) {
130 Layer.getExecutionSession().reportError(std::move(Err));
131 MR.failMaterialization();
132 return;
133 }
130134
131135 Layer.notifyLoaded(MR);
132136 }
137141 if (auto Err = Layer.notifyEmitted(MR, std::move(A))) {
138142 Layer.getExecutionSession().reportError(std::move(Err));
139143 MR.failMaterialization();
140
141144 return;
142145 }
143 MR.notifyEmitted();
146 if (auto Err = MR.notifyEmitted()) {
147 Layer.getExecutionSession().reportError(std::move(Err));
148 MR.failMaterialization();
149 }
144150 }
145151
146152 AtomGraphPassFunction getMarkLivePass(const Triple &TT) const override {
183183 if (auto Err = R.defineMaterializing(ExtraSymbolsToClaim))
184184 return Err;
185185
186 R.notifyResolved(Symbols);
186 if (auto Err = R.notifyResolved(Symbols)) {
187 R.failMaterialization();
188 return Err;
189 }
187190
188191 if (NotifyLoaded)
189192 NotifyLoaded(K, Obj, *LoadedObjInfo);
200203 return;
201204 }
202205
203 R.notifyEmitted();
206 if (auto Err = R.notifyEmitted()) {
207 getExecutionSession().reportError(std::move(Err));
208 R.failMaterialization();
209 return;
210 }
204211
205212 if (NotifyEmitted)
206213 NotifyEmitted(K, std::move(ObjBuffer));
4747
4848 EXPECT_FALSE(OnCompletionRun) << "Should not have been resolved yet";
4949
50 FooMR->notifyResolved({{Foo, FooSym}});
50 cantFail(FooMR->notifyResolved({{Foo, FooSym}}));
5151
5252 EXPECT_FALSE(OnCompletionRun) << "Should not be ready yet";
5353
54 FooMR->notifyEmitted();
54 cantFail(FooMR->notifyEmitted());
5555
5656 EXPECT_TRUE(OnCompletionRun) << "Should have been marked ready";
5757 }
108108 SymbolFlagsMap({{Bar, BarSym.getFlags()}}),
109109 [this](MaterializationResponsibility R) {
110110 ADD_FAILURE() << "Unexpected materialization of \"Bar\"";
111 R.notifyResolved({{Bar, BarSym}});
112 R.notifyEmitted();
111 cantFail(R.notifyResolved({{Bar, BarSym}}));
112 cantFail(R.notifyEmitted());
113113 },
114114 [&](const JITDylib &JD, const SymbolStringPtr &Name) {
115115 EXPECT_EQ(Name, Bar) << "Expected \"Bar\" to be discarded";
155155 consumeError(std::move(Err));
156156 }
157157
158 BazR->notifyResolved({{Baz, BazSym}});
159 BazR->notifyEmitted();
158 cantFail(BazR->notifyResolved({{Baz, BazSym}}));
159 cantFail(BazR->notifyEmitted());
160160 {
161161 // Attempt 3: Search now that all symbols are fully materialized
162162 // (Foo, Baz), or not yet materialized (Bar).
317317 SymbolFlagsMap({{Bar, BarSym.getFlags()}}),
318318 [&](MaterializationResponsibility R) {
319319 BarMaterialized = true;
320 R.notifyResolved({{Bar, BarSym}});
321 R.notifyEmitted();
320 cantFail(R.notifyResolved({{Bar, BarSym}}));
321 cantFail(R.notifyEmitted());
322322 });
323323
324324 cantFail(JD.define(BarMU));
373373 OnCompletion, NoDependenciesToRegister);
374374
375375 FooR->addDependenciesForAll({{&JD, SymbolNameSet({Foo})}});
376 FooR->notifyResolved({{Foo, FooSym}});
377 FooR->notifyEmitted();
376 EXPECT_THAT_ERROR(FooR->notifyResolved({{Foo, FooSym}}), Succeeded())
377 << "No symbols marked failed, but Foo failed to resolve";
378 EXPECT_THAT_ERROR(FooR->notifyEmitted(), Succeeded())
379 << "No symbols marked failed, but Foo failed to emit";
378380
379381 EXPECT_TRUE(FooReady)
380382 << "Self-dependency prevented symbol from being marked ready";
487489 EXPECT_FALSE(BazResolved) << "\"Baz\" should not be resolved yet";
488490
489491 // Resolve the symbols (but do not emit them).
490 FooR->notifyResolved({{Foo, FooSym}});
491 BarR->notifyResolved({{Bar, BarSym}});
492 BazR->notifyResolved({{Baz, BazSym}});
492 EXPECT_THAT_ERROR(FooR->notifyResolved({{Foo, FooSym}}), Succeeded())
493 << "No symbols failed, but Foo failed to resolve";
494 EXPECT_THAT_ERROR(BarR->notifyResolved({{Bar, BarSym}}), Succeeded())
495 << "No symbols failed, but Bar failed to resolve";
496 EXPECT_THAT_ERROR(BazR->notifyResolved({{Baz, BazSym}}), Succeeded())
497 << "No symbols failed, but Baz failed to resolve";
493498
494499 // Verify that the symbols have been resolved, but are not ready yet.
495500 EXPECT_TRUE(FooResolved) << "\"Foo\" should be resolved now";
501506 EXPECT_FALSE(BazReady) << "\"Baz\" should not be ready yet";
502507
503508 // Emit two of the symbols.
504 FooR->notifyEmitted();
505 BarR->notifyEmitted();
509 EXPECT_THAT_ERROR(FooR->notifyEmitted(), Succeeded())
510 << "No symbols failed, but Foo failed to emit";
511 EXPECT_THAT_ERROR(BarR->notifyEmitted(), Succeeded())
512 << "No symbols failed, but Bar failed to emit";
506513
507514 // Verify that nothing is ready until the circular dependence is resolved.
508515 EXPECT_FALSE(FooReady) << "\"Foo\" still should not be ready";
510517 EXPECT_FALSE(BazReady) << "\"Baz\" still should not be ready";
511518
512519 // Emit the last symbol.
513 BazR->notifyEmitted();
520 EXPECT_THAT_ERROR(BazR->notifyEmitted(), Succeeded())
521 << "No symbols failed, but Baz failed to emit";
514522
515523 // Verify that everything becomes ready once the circular dependence resolved.
516524 EXPECT_TRUE(FooReady) << "\"Foo\" should be ready now";
517525 EXPECT_TRUE(BarReady) << "\"Bar\" should be ready now";
518526 EXPECT_TRUE(BazReady) << "\"Baz\" should be ready now";
527 }
528
529 TEST_F(CoreAPIsStandardTest, FailureInDependency) {
530 Optional FooR;
531 Optional BarR;
532
533 // Create a MaterializationUnit for each symbol that moves the
534 // MaterializationResponsibility into one of the locals above.
535 auto FooMU = std::make_unique(
536 SymbolFlagsMap({{Foo, FooSym.getFlags()}}),
537 [&](MaterializationResponsibility R) { FooR.emplace(std::move(R)); });
538
539 auto BarMU = std::make_unique(
540 SymbolFlagsMap({{Bar, BarSym.getFlags()}}),
541 [&](MaterializationResponsibility R) { BarR.emplace(std::move(R)); });
542
543 // Define the symbols.
544 cantFail(JD.define(FooMU));
545 cantFail(JD.define(BarMU));
546
547 bool OnFooReadyRun = false;
548 auto OnFooReady = [&](Expected Result) {
549 EXPECT_THAT_EXPECTED(std::move(Result), Failed());
550 OnFooReadyRun = true;
551 };
552
553 ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo}, SymbolState::Ready,
554 std::move(OnFooReady), NoDependenciesToRegister);
555
556 bool OnBarReadyRun = false;
557 auto OnBarReady = [&](Expected Result) {
558 EXPECT_THAT_EXPECTED(std::move(Result), Failed());
559 OnBarReadyRun = true;
560 };
561
562 ES.lookup(JITDylibSearchList({{&JD, false}}), {Bar}, SymbolState::Ready,
563 std::move(OnBarReady), NoDependenciesToRegister);
564
565 // Add a dependency by Foo on Bar.
566 FooR->addDependenciesForAll({{&JD, SymbolNameSet({Bar})}});
567
568 // Fail bar.
569 BarR->failMaterialization();
570
571 // Verify that queries on Bar failed, but queries on Foo have not yet.
572 EXPECT_TRUE(OnBarReadyRun) << "Query for \"Bar\" was not run";
573 EXPECT_FALSE(OnFooReadyRun) << "Query for \"Foo\" was run unexpectedly";
574
575 // Check that we can still resolve Foo (even though it has been failed).
576 EXPECT_THAT_ERROR(FooR->notifyResolved({{Foo, FooSym}}), Failed())
577 << "Expected resolution for \"Foo\" to fail.";
578
579 FooR->failMaterialization();
580
581 // Verify that queries on Foo have now failed.
582 EXPECT_TRUE(OnFooReadyRun) << "Query for \"Foo\" was not run";
583
584 // Verify that subsequent lookups on Bar and Foo fail.
585 EXPECT_THAT_EXPECTED(ES.lookup({&JD}, {Bar}), Failed())
586 << "Lookup on failed symbol should fail";
587
588 EXPECT_THAT_EXPECTED(ES.lookup({&JD}, {Foo}), Failed())
589 << "Lookup on failed symbol should fail";
590 }
591
592 TEST_F(CoreAPIsStandardTest, FailureInCircularDependency) {
593 Optional FooR;
594 Optional BarR;
595
596 // Create a MaterializationUnit for each symbol that moves the
597 // MaterializationResponsibility into one of the locals above.
598 auto FooMU = std::make_unique(
599 SymbolFlagsMap({{Foo, FooSym.getFlags()}}),
600 [&](MaterializationResponsibility R) { FooR.emplace(std::move(R)); });
601
602 auto BarMU = std::make_unique(
603 SymbolFlagsMap({{Bar, BarSym.getFlags()}}),
604 [&](MaterializationResponsibility R) { BarR.emplace(std::move(R)); });
605
606 // Define the symbols.
607 cantFail(JD.define(FooMU));
608 cantFail(JD.define(BarMU));
609
610 bool OnFooReadyRun = false;
611 auto OnFooReady = [&](Expected Result) {
612 EXPECT_THAT_EXPECTED(std::move(Result), Failed());
613 OnFooReadyRun = true;
614 };
615
616 ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo}, SymbolState::Ready,
617 std::move(OnFooReady), NoDependenciesToRegister);
618
619 bool OnBarReadyRun = false;
620 auto OnBarReady = [&](Expected Result) {
621 EXPECT_THAT_EXPECTED(std::move(Result), Failed());
622 OnBarReadyRun = true;
623 };
624
625 ES.lookup(JITDylibSearchList({{&JD, false}}), {Bar}, SymbolState::Ready,
626 std::move(OnBarReady), NoDependenciesToRegister);
627
628 // Add a dependency by Foo on Bar and vice-versa.
629 FooR->addDependenciesForAll({{&JD, SymbolNameSet({Bar})}});
630 BarR->addDependenciesForAll({{&JD, SymbolNameSet({Foo})}});
631
632 // Fail bar.
633 BarR->failMaterialization();
634
635 // Verify that queries on Bar failed, but queries on Foo have not yet.
636 EXPECT_TRUE(OnBarReadyRun) << "Query for \"Bar\" was not run";
637 EXPECT_FALSE(OnFooReadyRun) << "Query for \"Foo\" was run unexpectedly";
638
639 // Verify that trying to resolve Foo fails.
640 EXPECT_THAT_ERROR(FooR->notifyResolved({{Foo, FooSym}}), Failed())
641 << "Expected resolution for \"Foo\" to fail.";
642
643 FooR->failMaterialization();
644
645 // Verify that queries on Foo have now failed.
646 EXPECT_TRUE(OnFooReadyRun) << "Query for \"Foo\" was not run";
647
648 // Verify that subsequent lookups on Bar and Foo fail.
649 EXPECT_THAT_EXPECTED(ES.lookup({&JD}, {Bar}), Failed())
650 << "Lookup on failed symbol should fail";
651
652 EXPECT_THAT_EXPECTED(ES.lookup({&JD}, {Foo}), Failed())
653 << "Lookup on failed symbol should fail";
654 }
655
656 TEST_F(CoreAPIsStandardTest, AddDependencyOnFailedSymbol) {
657 Optional FooR;
658 Optional BarR;
659
660 // Create a MaterializationUnit for each symbol that moves the
661 // MaterializationResponsibility into one of the locals above.
662 auto FooMU = std::make_unique(
663 SymbolFlagsMap({{Foo, FooSym.getFlags()}}),
664 [&](MaterializationResponsibility R) { FooR.emplace(std::move(R)); });
665
666 auto BarMU = std::make_unique(
667 SymbolFlagsMap({{Bar, BarSym.getFlags()}}),
668 [&](MaterializationResponsibility R) { BarR.emplace(std::move(R)); });
669
670 // Define the symbols.
671 cantFail(JD.define(FooMU));
672 cantFail(JD.define(BarMU));
673
674 bool OnFooReadyRun = false;
675 auto OnFooReady = [&](Expected Result) {
676 EXPECT_THAT_EXPECTED(std::move(Result), Failed());
677 OnFooReadyRun = true;
678 };
679
680 ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo}, SymbolState::Ready,
681 std::move(OnFooReady), NoDependenciesToRegister);
682
683 bool OnBarReadyRun = false;
684 auto OnBarReady = [&](Expected Result) {
685 EXPECT_THAT_EXPECTED(std::move(Result), Failed());
686 OnBarReadyRun = true;
687 };
688
689 ES.lookup(JITDylibSearchList({{&JD, false}}), {Bar}, SymbolState::Ready,
690 std::move(OnBarReady), NoDependenciesToRegister);
691
692 // Fail bar.
693 BarR->failMaterialization();
694
695 // We expect Bar's query to fail immediately, but Foo's query not to have run
696 // yet.
697 EXPECT_TRUE(OnBarReadyRun) << "Query for \"Bar\" was not run";
698 EXPECT_FALSE(OnFooReadyRun) << "Query for \"Foo\" should not have run yet";
699
700 // Add dependency of Foo on Bar.
701 FooR->addDependenciesForAll({{&JD, SymbolNameSet({Bar})}});
702
703 // Check that we can still resolve Foo (even though it has been failed).
704 EXPECT_THAT_ERROR(FooR->notifyResolved({{Foo, FooSym}}), Failed())
705 << "Expected resolution for \"Foo\" to fail.";
706
707 FooR->failMaterialization();
708
709 // Foo's query should have failed before we return from addDependencies.
710 EXPECT_TRUE(OnFooReadyRun) << "Query for \"Foo\" was not run";
711
712 // Verify that subsequent lookups on Bar and Foo fail.
713 EXPECT_THAT_EXPECTED(ES.lookup({&JD}, {Bar}), Failed())
714 << "Lookup on failed symbol should fail";
715
716 EXPECT_THAT_EXPECTED(ES.lookup({&JD}, {Foo}), Failed())
717 << "Lookup on failed symbol should fail";
519718 }
520719
521720 TEST_F(CoreAPIsStandardTest, DropMaterializerWhenEmpty) {
559758 SymbolFlagsMap({{Foo, JITSymbolFlags::Exported}, {Bar, WeakExported}}),
560759 [&](MaterializationResponsibility R) {
561760 assert(BarDiscarded && "Bar should have been discarded by this point");
562 R.notifyResolved(SymbolMap({{Foo, FooSym}}));
563 R.notifyEmitted();
761 cantFail(R.notifyResolved(SymbolMap({{Foo, FooSym}})));
762 cantFail(R.notifyEmitted());
564763 FooMaterialized = true;
565764 },
566765 [&](const JITDylib &JD, SymbolStringPtr Name) {
600799 auto MU1 = std::make_unique(
601800 SymbolFlagsMap({{Foo, FooSym.getFlags()}, {Bar, BarSym.getFlags()}}),
602801 [&](MaterializationResponsibility R) {
603 R.notifyResolved(SymbolMap({{Foo, FooSym}, {Bar, BarSym}})), R.notifyEmitted();
802 cantFail(R.notifyResolved(SymbolMap({{Foo, FooSym}, {Bar, BarSym}})));
803 cantFail(R.notifyEmitted());
604804 BarMaterialized = true;
605805 });
606806
649849 [&](MaterializationResponsibility R) {
650850 cantFail(
651851 R.defineMaterializing(SymbolFlagsMap({{Bar, BarSym.getFlags()}})));
652 R.notifyResolved(SymbolMap({{Foo, FooSym}, {Bar, BarSym}}));
653 R.notifyEmitted();
852 cantFail(R.notifyResolved(SymbolMap({{Foo, FooSym}, {Bar, BarSym}})));
853 cantFail(R.notifyEmitted());
654854 });
655855
656856 cantFail(JD.define(MU));
715915
716916 EXPECT_FALSE(!!Result) << "Expected failure";
717917 if (!Result) {
718 handleAllErrors(Result.takeError(),
719 [&](FailedToMaterialize &F) {
720 EXPECT_EQ(F.getSymbols(), Names)
721 << "Expected to fail on symbols in Names";
722 },
723 [](ErrorInfoBase &EIB) {
724 std::string ErrMsg;
725 {
726 raw_string_ostream ErrOut(ErrMsg);
727 EIB.log(ErrOut);
728 }
729 ADD_FAILURE()
730 << "Expected a FailedToResolve error. Got:\n"
731 << ErrMsg;
732 });
918 handleAllErrors(
919 Result.takeError(),
920 [&](FailedToMaterialize &F) {
921 EXPECT_TRUE(F.getSymbols().count(&JD))
922 << "Expected to fail on JITDylib JD";
923 EXPECT_EQ(F.getSymbols().find(&JD)->second, Names)
924 << "Expected to fail on symbols in Names";
925 },
926 [](ErrorInfoBase &EIB) {
927 std::string ErrMsg;
928 {
929 raw_string_ostream ErrOut(ErrMsg);
930 EIB.log(ErrOut);
931 }
932 ADD_FAILURE() << "Expected a FailedToResolve error. Got:\n" << ErrMsg;
933 });
733934 }
734935 }
735936
740941 auto MU = std::make_unique(
741942 SymbolFlagsMap({{Foo, FooSym.getFlags()}, {Bar, BarSym.getFlags()}}),
742943 [&](MaterializationResponsibility R) {
743 R.notifyResolved(SymbolMap({{Foo, FooSym}, {Bar, BarSym}}));
944 cantFail(R.notifyResolved(SymbolMap({{Foo, FooSym}, {Bar, BarSym}})));
744945
745946 ES.lookup(
746947 JITDylibSearchList({{&JD, false}}), SymbolNameSet({Baz}),
772973 auto MU = std::make_unique(
773974 SymbolFlagsMap({{Foo, JITSymbolFlags::Exported}}),
774975 [&](MaterializationResponsibility R) {
775 R.notifyResolved({{Foo, FooSym}});
776 R.notifyEmitted();
976 cantFail(R.notifyResolved({{Foo, FooSym}}));
977 cantFail(R.notifyEmitted());
777978 });
778979
779980 cantFail(JD.define(MU));
8311032 auto NewMU = std::make_unique(
8321033 SymbolFlagsMap({{Bar, BarSym.getFlags()}}),
8331034 [&](MaterializationResponsibility R2) {
834 R2.notifyResolved(SymbolMap({{Bar, BarSym}}));
835 R2.notifyEmitted();
1035 cantFail(R2.notifyResolved(SymbolMap({{Bar, BarSym}})));
1036 cantFail(R2.notifyEmitted());
8361037 BarMaterialized = true;
8371038 });
8381039
8391040 R.replace(std::move(NewMU));
8401041
841 R.notifyResolved(SymbolMap({{Foo, FooSym}}));
842 R.notifyEmitted();
1042 cantFail(R.notifyResolved(SymbolMap({{Foo, FooSym}})));
1043 cantFail(R.notifyEmitted());
8431044
8441045 FooMaterialized = true;
8451046 });
8701071 [&](MaterializationResponsibility R) {
8711072 auto R2 = R.delegate({Bar});
8721073
873 R.notifyResolved({{Foo, FooSym}});
874 R.notifyEmitted();
875 R2.notifyResolved({{Bar, BarSym}});
876 R2.notifyEmitted();
1074 cantFail(R.notifyResolved({{Foo, FooSym}}));
1075 cantFail(R.notifyEmitted());
1076 cantFail(R2.notifyResolved({{Bar, BarSym}}));
1077 cantFail(R2.notifyEmitted());
8771078 });
8781079
8791080 cantFail(JD.define(MU));
9231124 << "Expected a duplicate definition error";
9241125 consumeError(std::move(Err));
9251126
926 FooResponsibility->notifyResolved(SymbolMap({{Foo, FooSym}}));
927 FooResponsibility->notifyEmitted();
1127 // No dependencies registered, can't fail:
1128 cantFail(FooResponsibility->notifyResolved(SymbolMap({{Foo, FooSym}})));
1129 cantFail(FooResponsibility->notifyEmitted());
9281130 }
9291131
9301132 } // namespace
4040 SymbolFlagsMap({{DummyTarget, JITSymbolFlags::Exported}}),
4141 [&](MaterializationResponsibility R) {
4242 DummyTargetMaterialized = true;
43 R.notifyResolved(
43 // No dependencies registered, can't fail.
44 cantFail(R.notifyResolved(
4445 {{DummyTarget,
4546 JITEvaluatedSymbol(static_cast(
4647 reinterpret_cast(&dummyTarget)),
47 JITSymbolFlags::Exported)}});
48 R.notifyEmitted();
48 JITSymbolFlags::Exported)}}));
49 cantFail(R.notifyEmitted());
4950 })));
5051
5152 unsigned NotifyResolvedCount = 0;