1 //===--- Core.cpp - Core ORC APIs (MaterializationUnit, JITDylib, etc.) ---===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "llvm/ExecutionEngine/Orc/Core.h"
10
11 #include "llvm/ADT/STLExtras.h"
12 #include "llvm/Config/llvm-config.h"
13 #include "llvm/ExecutionEngine/Orc/DebugUtils.h"
14 #include "llvm/ExecutionEngine/Orc/OrcError.h"
15 #include "llvm/Support/FormatVariadic.h"
16 #include "llvm/Support/MSVCErrorWorkarounds.h"
17
18 #include <condition_variable>
19 #include <future>
20
21 #define DEBUG_TYPE "orc"
22
23 namespace llvm {
24 namespace orc {
25
26 char ResourceTrackerDefunct::ID = 0;
27 char FailedToMaterialize::ID = 0;
28 char SymbolsNotFound::ID = 0;
29 char SymbolsCouldNotBeRemoved::ID = 0;
30 char MissingSymbolDefinitions::ID = 0;
31 char UnexpectedSymbolDefinitions::ID = 0;
32
33 RegisterDependenciesFunction NoDependenciesToRegister =
34 RegisterDependenciesFunction();
35
anchor()36 void MaterializationUnit::anchor() {}
37
ResourceTracker(JITDylibSP JD)38 ResourceTracker::ResourceTracker(JITDylibSP JD) {
39 assert((reinterpret_cast<uintptr_t>(JD.get()) & 0x1) == 0 &&
40 "JITDylib must be two byte aligned");
41 JD->Retain();
42 JDAndFlag.store(reinterpret_cast<uintptr_t>(JD.get()));
43 }
44
~ResourceTracker()45 ResourceTracker::~ResourceTracker() {
46 getJITDylib().getExecutionSession().destroyResourceTracker(*this);
47 getJITDylib().Release();
48 }
49
remove()50 Error ResourceTracker::remove() {
51 return getJITDylib().getExecutionSession().removeResourceTracker(*this);
52 }
53
transferTo(ResourceTracker & DstRT)54 void ResourceTracker::transferTo(ResourceTracker &DstRT) {
55 getJITDylib().getExecutionSession().transferResourceTracker(DstRT, *this);
56 }
57
makeDefunct()58 void ResourceTracker::makeDefunct() {
59 uintptr_t Val = JDAndFlag.load();
60 Val |= 0x1U;
61 JDAndFlag.store(Val);
62 }
63
~ResourceManager()64 ResourceManager::~ResourceManager() {}
65
ResourceTrackerDefunct(ResourceTrackerSP RT)66 ResourceTrackerDefunct::ResourceTrackerDefunct(ResourceTrackerSP RT)
67 : RT(std::move(RT)) {}
68
convertToErrorCode() const69 std::error_code ResourceTrackerDefunct::convertToErrorCode() const {
70 return orcError(OrcErrorCode::UnknownORCError);
71 }
72
log(raw_ostream & OS) const73 void ResourceTrackerDefunct::log(raw_ostream &OS) const {
74 OS << "Resource tracker " << (void *)RT.get() << " became defunct";
75 }
76
FailedToMaterialize(std::shared_ptr<SymbolDependenceMap> Symbols)77 FailedToMaterialize::FailedToMaterialize(
78 std::shared_ptr<SymbolDependenceMap> Symbols)
79 : Symbols(std::move(Symbols)) {
80 assert(!this->Symbols->empty() && "Can not fail to resolve an empty set");
81 }
82
convertToErrorCode() const83 std::error_code FailedToMaterialize::convertToErrorCode() const {
84 return orcError(OrcErrorCode::UnknownORCError);
85 }
86
log(raw_ostream & OS) const87 void FailedToMaterialize::log(raw_ostream &OS) const {
88 OS << "Failed to materialize symbols: " << *Symbols;
89 }
90
SymbolsNotFound(SymbolNameSet Symbols)91 SymbolsNotFound::SymbolsNotFound(SymbolNameSet Symbols) {
92 for (auto &Sym : Symbols)
93 this->Symbols.push_back(Sym);
94 assert(!this->Symbols.empty() && "Can not fail to resolve an empty set");
95 }
96
SymbolsNotFound(SymbolNameVector Symbols)97 SymbolsNotFound::SymbolsNotFound(SymbolNameVector Symbols)
98 : Symbols(std::move(Symbols)) {
99 assert(!this->Symbols.empty() && "Can not fail to resolve an empty set");
100 }
101
convertToErrorCode() const102 std::error_code SymbolsNotFound::convertToErrorCode() const {
103 return orcError(OrcErrorCode::UnknownORCError);
104 }
105
log(raw_ostream & OS) const106 void SymbolsNotFound::log(raw_ostream &OS) const {
107 OS << "Symbols not found: " << Symbols;
108 }
109
SymbolsCouldNotBeRemoved(SymbolNameSet Symbols)110 SymbolsCouldNotBeRemoved::SymbolsCouldNotBeRemoved(SymbolNameSet Symbols)
111 : Symbols(std::move(Symbols)) {
112 assert(!this->Symbols.empty() && "Can not fail to resolve an empty set");
113 }
114
convertToErrorCode() const115 std::error_code SymbolsCouldNotBeRemoved::convertToErrorCode() const {
116 return orcError(OrcErrorCode::UnknownORCError);
117 }
118
log(raw_ostream & OS) const119 void SymbolsCouldNotBeRemoved::log(raw_ostream &OS) const {
120 OS << "Symbols could not be removed: " << Symbols;
121 }
122
convertToErrorCode() const123 std::error_code MissingSymbolDefinitions::convertToErrorCode() const {
124 return orcError(OrcErrorCode::MissingSymbolDefinitions);
125 }
126
log(raw_ostream & OS) const127 void MissingSymbolDefinitions::log(raw_ostream &OS) const {
128 OS << "Missing definitions in module " << ModuleName
129 << ": " << Symbols;
130 }
131
convertToErrorCode() const132 std::error_code UnexpectedSymbolDefinitions::convertToErrorCode() const {
133 return orcError(OrcErrorCode::UnexpectedSymbolDefinitions);
134 }
135
log(raw_ostream & OS) const136 void UnexpectedSymbolDefinitions::log(raw_ostream &OS) const {
137 OS << "Unexpected definitions in module " << ModuleName
138 << ": " << Symbols;
139 }
140
AsynchronousSymbolQuery(const SymbolLookupSet & Symbols,SymbolState RequiredState,SymbolsResolvedCallback NotifyComplete)141 AsynchronousSymbolQuery::AsynchronousSymbolQuery(
142 const SymbolLookupSet &Symbols, SymbolState RequiredState,
143 SymbolsResolvedCallback NotifyComplete)
144 : NotifyComplete(std::move(NotifyComplete)), RequiredState(RequiredState) {
145 assert(RequiredState >= SymbolState::Resolved &&
146 "Cannot query for a symbols that have not reached the resolve state "
147 "yet");
148
149 OutstandingSymbolsCount = Symbols.size();
150
151 for (auto &KV : Symbols)
152 ResolvedSymbols[KV.first] = nullptr;
153 }
154
notifySymbolMetRequiredState(const SymbolStringPtr & Name,JITEvaluatedSymbol Sym)155 void AsynchronousSymbolQuery::notifySymbolMetRequiredState(
156 const SymbolStringPtr &Name, JITEvaluatedSymbol Sym) {
157 auto I = ResolvedSymbols.find(Name);
158 assert(I != ResolvedSymbols.end() &&
159 "Resolving symbol outside the requested set");
160 assert(I->second.getAddress() == 0 && "Redundantly resolving symbol Name");
161
162 // If this is a materialization-side-effects-only symbol then drop it,
163 // otherwise update its map entry with its resolved address.
164 if (Sym.getFlags().hasMaterializationSideEffectsOnly())
165 ResolvedSymbols.erase(I);
166 else
167 I->second = std::move(Sym);
168 --OutstandingSymbolsCount;
169 }
170
handleComplete()171 void AsynchronousSymbolQuery::handleComplete() {
172 assert(OutstandingSymbolsCount == 0 &&
173 "Symbols remain, handleComplete called prematurely");
174
175 auto TmpNotifyComplete = std::move(NotifyComplete);
176 NotifyComplete = SymbolsResolvedCallback();
177 TmpNotifyComplete(std::move(ResolvedSymbols));
178 }
179
handleFailed(Error Err)180 void AsynchronousSymbolQuery::handleFailed(Error Err) {
181 assert(QueryRegistrations.empty() && ResolvedSymbols.empty() &&
182 OutstandingSymbolsCount == 0 &&
183 "Query should already have been abandoned");
184 NotifyComplete(std::move(Err));
185 NotifyComplete = SymbolsResolvedCallback();
186 }
187
addQueryDependence(JITDylib & JD,SymbolStringPtr Name)188 void AsynchronousSymbolQuery::addQueryDependence(JITDylib &JD,
189 SymbolStringPtr Name) {
190 bool Added = QueryRegistrations[&JD].insert(std::move(Name)).second;
191 (void)Added;
192 assert(Added && "Duplicate dependence notification?");
193 }
194
removeQueryDependence(JITDylib & JD,const SymbolStringPtr & Name)195 void AsynchronousSymbolQuery::removeQueryDependence(
196 JITDylib &JD, const SymbolStringPtr &Name) {
197 auto QRI = QueryRegistrations.find(&JD);
198 assert(QRI != QueryRegistrations.end() &&
199 "No dependencies registered for JD");
200 assert(QRI->second.count(Name) && "No dependency on Name in JD");
201 QRI->second.erase(Name);
202 if (QRI->second.empty())
203 QueryRegistrations.erase(QRI);
204 }
205
dropSymbol(const SymbolStringPtr & Name)206 void AsynchronousSymbolQuery::dropSymbol(const SymbolStringPtr &Name) {
207 auto I = ResolvedSymbols.find(Name);
208 assert(I != ResolvedSymbols.end() &&
209 "Redundant removal of weakly-referenced symbol");
210 ResolvedSymbols.erase(I);
211 --OutstandingSymbolsCount;
212 }
213
detach()214 void AsynchronousSymbolQuery::detach() {
215 ResolvedSymbols.clear();
216 OutstandingSymbolsCount = 0;
217 for (auto &KV : QueryRegistrations)
218 KV.first->detachQueryHelper(*this, KV.second);
219 QueryRegistrations.clear();
220 }
221
AbsoluteSymbolsMaterializationUnit(SymbolMap Symbols)222 AbsoluteSymbolsMaterializationUnit::AbsoluteSymbolsMaterializationUnit(
223 SymbolMap Symbols)
224 : MaterializationUnit(extractFlags(Symbols), nullptr),
225 Symbols(std::move(Symbols)) {}
226
getName() const227 StringRef AbsoluteSymbolsMaterializationUnit::getName() const {
228 return "<Absolute Symbols>";
229 }
230
materialize(std::unique_ptr<MaterializationResponsibility> R)231 void AbsoluteSymbolsMaterializationUnit::materialize(
232 std::unique_ptr<MaterializationResponsibility> R) {
233 // No dependencies, so these calls can't fail.
234 cantFail(R->notifyResolved(Symbols));
235 cantFail(R->notifyEmitted());
236 }
237
discard(const JITDylib & JD,const SymbolStringPtr & Name)238 void AbsoluteSymbolsMaterializationUnit::discard(const JITDylib &JD,
239 const SymbolStringPtr &Name) {
240 assert(Symbols.count(Name) && "Symbol is not part of this MU");
241 Symbols.erase(Name);
242 }
243
244 SymbolFlagsMap
extractFlags(const SymbolMap & Symbols)245 AbsoluteSymbolsMaterializationUnit::extractFlags(const SymbolMap &Symbols) {
246 SymbolFlagsMap Flags;
247 for (const auto &KV : Symbols)
248 Flags[KV.first] = KV.second.getFlags();
249 return Flags;
250 }
251
ReExportsMaterializationUnit(JITDylib * SourceJD,JITDylibLookupFlags SourceJDLookupFlags,SymbolAliasMap Aliases)252 ReExportsMaterializationUnit::ReExportsMaterializationUnit(
253 JITDylib *SourceJD, JITDylibLookupFlags SourceJDLookupFlags,
254 SymbolAliasMap Aliases)
255 : MaterializationUnit(extractFlags(Aliases), nullptr), SourceJD(SourceJD),
256 SourceJDLookupFlags(SourceJDLookupFlags), Aliases(std::move(Aliases)) {}
257
getName() const258 StringRef ReExportsMaterializationUnit::getName() const {
259 return "<Reexports>";
260 }
261
materialize(std::unique_ptr<MaterializationResponsibility> R)262 void ReExportsMaterializationUnit::materialize(
263 std::unique_ptr<MaterializationResponsibility> R) {
264
265 auto &ES = R->getTargetJITDylib().getExecutionSession();
266 JITDylib &TgtJD = R->getTargetJITDylib();
267 JITDylib &SrcJD = SourceJD ? *SourceJD : TgtJD;
268
269 // Find the set of requested aliases and aliasees. Return any unrequested
270 // aliases back to the JITDylib so as to not prematurely materialize any
271 // aliasees.
272 auto RequestedSymbols = R->getRequestedSymbols();
273 SymbolAliasMap RequestedAliases;
274
275 for (auto &Name : RequestedSymbols) {
276 auto I = Aliases.find(Name);
277 assert(I != Aliases.end() && "Symbol not found in aliases map?");
278 RequestedAliases[Name] = std::move(I->second);
279 Aliases.erase(I);
280 }
281
282 LLVM_DEBUG({
283 ES.runSessionLocked([&]() {
284 dbgs() << "materializing reexports: target = " << TgtJD.getName()
285 << ", source = " << SrcJD.getName() << " " << RequestedAliases
286 << "\n";
287 });
288 });
289
290 if (!Aliases.empty()) {
291 auto Err = SourceJD ? R->replace(reexports(*SourceJD, std::move(Aliases),
292 SourceJDLookupFlags))
293 : R->replace(symbolAliases(std::move(Aliases)));
294
295 if (Err) {
296 // FIXME: Should this be reported / treated as failure to materialize?
297 // Or should this be treated as a sanctioned bailing-out?
298 ES.reportError(std::move(Err));
299 R->failMaterialization();
300 return;
301 }
302 }
303
304 // The OnResolveInfo struct will hold the aliases and responsibilty for each
305 // query in the list.
306 struct OnResolveInfo {
307 OnResolveInfo(std::unique_ptr<MaterializationResponsibility> R,
308 SymbolAliasMap Aliases)
309 : R(std::move(R)), Aliases(std::move(Aliases)) {}
310
311 std::unique_ptr<MaterializationResponsibility> R;
312 SymbolAliasMap Aliases;
313 };
314
315 // Build a list of queries to issue. In each round we build a query for the
316 // largest set of aliases that we can resolve without encountering a chain of
317 // aliases (e.g. Foo -> Bar, Bar -> Baz). Such a chain would deadlock as the
318 // query would be waiting on a symbol that it itself had to resolve. Creating
319 // a new query for each link in such a chain eliminates the possibility of
320 // deadlock. In practice chains are likely to be rare, and this algorithm will
321 // usually result in a single query to issue.
322
323 std::vector<std::pair<SymbolLookupSet, std::shared_ptr<OnResolveInfo>>>
324 QueryInfos;
325 while (!RequestedAliases.empty()) {
326 SymbolNameSet ResponsibilitySymbols;
327 SymbolLookupSet QuerySymbols;
328 SymbolAliasMap QueryAliases;
329
330 // Collect as many aliases as we can without including a chain.
331 for (auto &KV : RequestedAliases) {
332 // Chain detected. Skip this symbol for this round.
333 if (&SrcJD == &TgtJD && (QueryAliases.count(KV.second.Aliasee) ||
334 RequestedAliases.count(KV.second.Aliasee)))
335 continue;
336
337 ResponsibilitySymbols.insert(KV.first);
338 QuerySymbols.add(KV.second.Aliasee,
339 KV.second.AliasFlags.hasMaterializationSideEffectsOnly()
340 ? SymbolLookupFlags::WeaklyReferencedSymbol
341 : SymbolLookupFlags::RequiredSymbol);
342 QueryAliases[KV.first] = std::move(KV.second);
343 }
344
345 // Remove the aliases collected this round from the RequestedAliases map.
346 for (auto &KV : QueryAliases)
347 RequestedAliases.erase(KV.first);
348
349 assert(!QuerySymbols.empty() && "Alias cycle detected!");
350
351 auto NewR = R->delegate(ResponsibilitySymbols);
352 if (!NewR) {
353 ES.reportError(NewR.takeError());
354 R->failMaterialization();
355 return;
356 }
357
358 auto QueryInfo = std::make_shared<OnResolveInfo>(std::move(*NewR),
359 std::move(QueryAliases));
360 QueryInfos.push_back(
361 make_pair(std::move(QuerySymbols), std::move(QueryInfo)));
362 }
363
364 // Issue the queries.
365 while (!QueryInfos.empty()) {
366 auto QuerySymbols = std::move(QueryInfos.back().first);
367 auto QueryInfo = std::move(QueryInfos.back().second);
368
369 QueryInfos.pop_back();
370
371 auto RegisterDependencies = [QueryInfo,
372 &SrcJD](const SymbolDependenceMap &Deps) {
373 // If there were no materializing symbols, just bail out.
374 if (Deps.empty())
375 return;
376
377 // Otherwise the only deps should be on SrcJD.
378 assert(Deps.size() == 1 && Deps.count(&SrcJD) &&
379 "Unexpected dependencies for reexports");
380
381 auto &SrcJDDeps = Deps.find(&SrcJD)->second;
382 SymbolDependenceMap PerAliasDepsMap;
383 auto &PerAliasDeps = PerAliasDepsMap[&SrcJD];
384
385 for (auto &KV : QueryInfo->Aliases)
386 if (SrcJDDeps.count(KV.second.Aliasee)) {
387 PerAliasDeps = {KV.second.Aliasee};
388 QueryInfo->R->addDependencies(KV.first, PerAliasDepsMap);
389 }
390 };
391
392 auto OnComplete = [QueryInfo](Expected<SymbolMap> Result) {
393 auto &ES = QueryInfo->R->getTargetJITDylib().getExecutionSession();
394 if (Result) {
395 SymbolMap ResolutionMap;
396 for (auto &KV : QueryInfo->Aliases) {
397 assert((KV.second.AliasFlags.hasMaterializationSideEffectsOnly() ||
398 Result->count(KV.second.Aliasee)) &&
399 "Result map missing entry?");
400 // Don't try to resolve materialization-side-effects-only symbols.
401 if (KV.second.AliasFlags.hasMaterializationSideEffectsOnly())
402 continue;
403
404 ResolutionMap[KV.first] = JITEvaluatedSymbol(
405 (*Result)[KV.second.Aliasee].getAddress(), KV.second.AliasFlags);
406 }
407 if (auto Err = QueryInfo->R->notifyResolved(ResolutionMap)) {
408 ES.reportError(std::move(Err));
409 QueryInfo->R->failMaterialization();
410 return;
411 }
412 if (auto Err = QueryInfo->R->notifyEmitted()) {
413 ES.reportError(std::move(Err));
414 QueryInfo->R->failMaterialization();
415 return;
416 }
417 } else {
418 ES.reportError(Result.takeError());
419 QueryInfo->R->failMaterialization();
420 }
421 };
422
423 ES.lookup(LookupKind::Static,
424 JITDylibSearchOrder({{&SrcJD, SourceJDLookupFlags}}),
425 QuerySymbols, SymbolState::Resolved, std::move(OnComplete),
426 std::move(RegisterDependencies));
427 }
428 }
429
discard(const JITDylib & JD,const SymbolStringPtr & Name)430 void ReExportsMaterializationUnit::discard(const JITDylib &JD,
431 const SymbolStringPtr &Name) {
432 assert(Aliases.count(Name) &&
433 "Symbol not covered by this MaterializationUnit");
434 Aliases.erase(Name);
435 }
436
437 SymbolFlagsMap
extractFlags(const SymbolAliasMap & Aliases)438 ReExportsMaterializationUnit::extractFlags(const SymbolAliasMap &Aliases) {
439 SymbolFlagsMap SymbolFlags;
440 for (auto &KV : Aliases)
441 SymbolFlags[KV.first] = KV.second.AliasFlags;
442
443 return SymbolFlags;
444 }
445
buildSimpleReexportsAliasMap(JITDylib & SourceJD,SymbolNameSet Symbols)446 Expected<SymbolAliasMap> buildSimpleReexportsAliasMap(JITDylib &SourceJD,
447 SymbolNameSet Symbols) {
448 SymbolLookupSet LookupSet(Symbols);
449 auto Flags = SourceJD.getExecutionSession().lookupFlags(
450 LookupKind::Static, {{&SourceJD, JITDylibLookupFlags::MatchAllSymbols}},
451 SymbolLookupSet(std::move(Symbols)));
452
453 if (!Flags)
454 return Flags.takeError();
455
456 SymbolAliasMap Result;
457 for (auto &Name : Symbols) {
458 assert(Flags->count(Name) && "Missing entry in flags map");
459 Result[Name] = SymbolAliasMapEntry(Name, (*Flags)[Name]);
460 }
461
462 return Result;
463 }
464
465 class InProgressLookupState {
466 public:
InProgressLookupState(LookupKind K,JITDylibSearchOrder SearchOrder,SymbolLookupSet LookupSet,SymbolState RequiredState)467 InProgressLookupState(LookupKind K, JITDylibSearchOrder SearchOrder,
468 SymbolLookupSet LookupSet, SymbolState RequiredState)
469 : K(K), SearchOrder(std::move(SearchOrder)),
470 LookupSet(std::move(LookupSet)), RequiredState(RequiredState) {
471 DefGeneratorCandidates = this->LookupSet;
472 }
~InProgressLookupState()473 virtual ~InProgressLookupState() {}
474 virtual void complete(std::unique_ptr<InProgressLookupState> IPLS) = 0;
475 virtual void fail(Error Err) = 0;
476
477 LookupKind K;
478 JITDylibSearchOrder SearchOrder;
479 SymbolLookupSet LookupSet;
480 SymbolState RequiredState;
481
482 std::unique_lock<std::mutex> GeneratorLock;
483 size_t CurSearchOrderIndex = 0;
484 bool NewJITDylib = true;
485 SymbolLookupSet DefGeneratorCandidates;
486 SymbolLookupSet DefGeneratorNonCandidates;
487 std::vector<std::weak_ptr<DefinitionGenerator>> CurDefGeneratorStack;
488 };
489
490 class InProgressLookupFlagsState : public InProgressLookupState {
491 public:
InProgressLookupFlagsState(LookupKind K,JITDylibSearchOrder SearchOrder,SymbolLookupSet LookupSet,unique_function<void (Expected<SymbolFlagsMap>)> OnComplete)492 InProgressLookupFlagsState(
493 LookupKind K, JITDylibSearchOrder SearchOrder, SymbolLookupSet LookupSet,
494 unique_function<void(Expected<SymbolFlagsMap>)> OnComplete)
495 : InProgressLookupState(K, std::move(SearchOrder), std::move(LookupSet),
496 SymbolState::NeverSearched),
497 OnComplete(std::move(OnComplete)) {}
498
complete(std::unique_ptr<InProgressLookupState> IPLS)499 void complete(std::unique_ptr<InProgressLookupState> IPLS) override {
500 GeneratorLock = {}; // Unlock and release.
501 auto &ES = SearchOrder.front().first->getExecutionSession();
502 ES.OL_completeLookupFlags(std::move(IPLS), std::move(OnComplete));
503 }
504
fail(Error Err)505 void fail(Error Err) override {
506 GeneratorLock = {}; // Unlock and release.
507 OnComplete(std::move(Err));
508 }
509
510 private:
511 unique_function<void(Expected<SymbolFlagsMap>)> OnComplete;
512 };
513
514 class InProgressFullLookupState : public InProgressLookupState {
515 public:
InProgressFullLookupState(LookupKind K,JITDylibSearchOrder SearchOrder,SymbolLookupSet LookupSet,SymbolState RequiredState,std::shared_ptr<AsynchronousSymbolQuery> Q,RegisterDependenciesFunction RegisterDependencies)516 InProgressFullLookupState(LookupKind K, JITDylibSearchOrder SearchOrder,
517 SymbolLookupSet LookupSet,
518 SymbolState RequiredState,
519 std::shared_ptr<AsynchronousSymbolQuery> Q,
520 RegisterDependenciesFunction RegisterDependencies)
521 : InProgressLookupState(K, std::move(SearchOrder), std::move(LookupSet),
522 RequiredState),
523 Q(std::move(Q)), RegisterDependencies(std::move(RegisterDependencies)) {
524 }
525
complete(std::unique_ptr<InProgressLookupState> IPLS)526 void complete(std::unique_ptr<InProgressLookupState> IPLS) override {
527 GeneratorLock = {}; // Unlock and release.
528 auto &ES = SearchOrder.front().first->getExecutionSession();
529 ES.OL_completeLookup(std::move(IPLS), std::move(Q),
530 std::move(RegisterDependencies));
531 }
532
fail(Error Err)533 void fail(Error Err) override {
534 GeneratorLock = {};
535 Q->detach();
536 Q->handleFailed(std::move(Err));
537 }
538
539 private:
540 std::shared_ptr<AsynchronousSymbolQuery> Q;
541 RegisterDependenciesFunction RegisterDependencies;
542 };
543
ReexportsGenerator(JITDylib & SourceJD,JITDylibLookupFlags SourceJDLookupFlags,SymbolPredicate Allow)544 ReexportsGenerator::ReexportsGenerator(JITDylib &SourceJD,
545 JITDylibLookupFlags SourceJDLookupFlags,
546 SymbolPredicate Allow)
547 : SourceJD(SourceJD), SourceJDLookupFlags(SourceJDLookupFlags),
548 Allow(std::move(Allow)) {}
549
tryToGenerate(LookupState & LS,LookupKind K,JITDylib & JD,JITDylibLookupFlags JDLookupFlags,const SymbolLookupSet & LookupSet)550 Error ReexportsGenerator::tryToGenerate(LookupState &LS, LookupKind K,
551 JITDylib &JD,
552 JITDylibLookupFlags JDLookupFlags,
553 const SymbolLookupSet &LookupSet) {
554 assert(&JD != &SourceJD && "Cannot re-export from the same dylib");
555
556 // Use lookupFlags to find the subset of symbols that match our lookup.
557 auto Flags = JD.getExecutionSession().lookupFlags(
558 K, {{&SourceJD, JDLookupFlags}}, LookupSet);
559 if (!Flags)
560 return Flags.takeError();
561
562 // Create an alias map.
563 orc::SymbolAliasMap AliasMap;
564 for (auto &KV : *Flags)
565 if (!Allow || Allow(KV.first))
566 AliasMap[KV.first] = SymbolAliasMapEntry(KV.first, KV.second);
567
568 if (AliasMap.empty())
569 return Error::success();
570
571 // Define the re-exports.
572 return JD.define(reexports(SourceJD, AliasMap, SourceJDLookupFlags));
573 }
574
LookupState(std::unique_ptr<InProgressLookupState> IPLS)575 LookupState::LookupState(std::unique_ptr<InProgressLookupState> IPLS)
576 : IPLS(std::move(IPLS)) {}
577
reset(InProgressLookupState * IPLS)578 void LookupState::reset(InProgressLookupState *IPLS) { this->IPLS.reset(IPLS); }
579
~LookupState()580 LookupState::~LookupState() {}
581
continueLookup(Error Err)582 void LookupState::continueLookup(Error Err) {
583 assert(IPLS && "Cannot call continueLookup on empty LookupState");
584 auto &ES = IPLS->SearchOrder.begin()->first->getExecutionSession();
585 ES.OL_applyQueryPhase1(std::move(IPLS), std::move(Err));
586 }
587
~DefinitionGenerator()588 DefinitionGenerator::~DefinitionGenerator() {}
589
clear()590 Error JITDylib::clear() {
591 std::vector<ResourceTrackerSP> TrackersToRemove;
592 ES.runSessionLocked([&]() {
593 for (auto &KV : TrackerSymbols)
594 TrackersToRemove.push_back(KV.first);
595 TrackersToRemove.push_back(getDefaultResourceTracker());
596 });
597
598 Error Err = Error::success();
599 for (auto &RT : TrackersToRemove)
600 Err = joinErrors(std::move(Err), RT->remove());
601 return Err;
602 }
603
getDefaultResourceTracker()604 ResourceTrackerSP JITDylib::getDefaultResourceTracker() {
605 return ES.runSessionLocked([this] {
606 if (!DefaultTracker)
607 DefaultTracker = new ResourceTracker(this);
608 return DefaultTracker;
609 });
610 }
611
createResourceTracker()612 ResourceTrackerSP JITDylib::createResourceTracker() {
613 return ES.runSessionLocked([this] {
614 ResourceTrackerSP RT = new ResourceTracker(this);
615 return RT;
616 });
617 }
618
removeGenerator(DefinitionGenerator & G)619 void JITDylib::removeGenerator(DefinitionGenerator &G) {
620 std::lock_guard<std::mutex> Lock(GeneratorsMutex);
621 auto I = std::find_if(DefGenerators.begin(), DefGenerators.end(),
622 [&](const std::shared_ptr<DefinitionGenerator> &H) {
623 return H.get() == &G;
624 });
625 assert(I != DefGenerators.end() && "Generator not found");
626 DefGenerators.erase(I);
627 }
628
629 Expected<SymbolFlagsMap>
defineMaterializing(SymbolFlagsMap SymbolFlags)630 JITDylib::defineMaterializing(SymbolFlagsMap SymbolFlags) {
631
632 return ES.runSessionLocked([&]() -> Expected<SymbolFlagsMap> {
633 std::vector<SymbolTable::iterator> AddedSyms;
634 std::vector<SymbolFlagsMap::iterator> RejectedWeakDefs;
635
636 for (auto SFItr = SymbolFlags.begin(), SFEnd = SymbolFlags.end();
637 SFItr != SFEnd; ++SFItr) {
638
639 auto &Name = SFItr->first;
640 auto &Flags = SFItr->second;
641
642 auto EntryItr = Symbols.find(Name);
643
644 // If the entry already exists...
645 if (EntryItr != Symbols.end()) {
646
647 // If this is a strong definition then error out.
648 if (!Flags.isWeak()) {
649 // Remove any symbols already added.
650 for (auto &SI : AddedSyms)
651 Symbols.erase(SI);
652
653 // FIXME: Return all duplicates.
654 return make_error<DuplicateDefinition>(std::string(*Name));
655 }
656
657 // Otherwise just make a note to discard this symbol after the loop.
658 RejectedWeakDefs.push_back(SFItr);
659 continue;
660 } else
661 EntryItr =
662 Symbols.insert(std::make_pair(Name, SymbolTableEntry(Flags))).first;
663
664 AddedSyms.push_back(EntryItr);
665 EntryItr->second.setState(SymbolState::Materializing);
666 }
667
668 // Remove any rejected weak definitions from the SymbolFlags map.
669 while (!RejectedWeakDefs.empty()) {
670 SymbolFlags.erase(RejectedWeakDefs.back());
671 RejectedWeakDefs.pop_back();
672 }
673
674 return SymbolFlags;
675 });
676 }
677
replace(MaterializationResponsibility & FromMR,std::unique_ptr<MaterializationUnit> MU)678 Error JITDylib::replace(MaterializationResponsibility &FromMR,
679 std::unique_ptr<MaterializationUnit> MU) {
680 assert(MU != nullptr && "Can not replace with a null MaterializationUnit");
681 std::unique_ptr<MaterializationUnit> MustRunMU;
682 std::unique_ptr<MaterializationResponsibility> MustRunMR;
683
684 auto Err =
685 ES.runSessionLocked([&, this]() -> Error {
686 auto RT = getTracker(FromMR);
687
688 if (RT->isDefunct())
689 return make_error<ResourceTrackerDefunct>(std::move(RT));
690
691 #ifndef NDEBUG
692 for (auto &KV : MU->getSymbols()) {
693 auto SymI = Symbols.find(KV.first);
694 assert(SymI != Symbols.end() && "Replacing unknown symbol");
695 assert(SymI->second.getState() == SymbolState::Materializing &&
696 "Can not replace a symbol that ha is not materializing");
697 assert(!SymI->second.hasMaterializerAttached() &&
698 "Symbol should not have materializer attached already");
699 assert(UnmaterializedInfos.count(KV.first) == 0 &&
700 "Symbol being replaced should have no UnmaterializedInfo");
701 }
702 #endif // NDEBUG
703
704 // If the tracker is defunct we need to bail out immediately.
705
706 // If any symbol has pending queries against it then we need to
707 // materialize MU immediately.
708 for (auto &KV : MU->getSymbols()) {
709 auto MII = MaterializingInfos.find(KV.first);
710 if (MII != MaterializingInfos.end()) {
711 if (MII->second.hasQueriesPending()) {
712 MustRunMR = ES.createMaterializationResponsibility(
713 *RT, std::move(MU->SymbolFlags), std::move(MU->InitSymbol));
714 MustRunMU = std::move(MU);
715 return Error::success();
716 }
717 }
718 }
719
720 // Otherwise, make MU responsible for all the symbols.
721 auto RTI = MRTrackers.find(&FromMR);
722 assert(RTI != MRTrackers.end() && "No tracker for FromMR");
723 auto UMI =
724 std::make_shared<UnmaterializedInfo>(std::move(MU), RTI->second);
725 for (auto &KV : UMI->MU->getSymbols()) {
726 auto SymI = Symbols.find(KV.first);
727 assert(SymI->second.getState() == SymbolState::Materializing &&
728 "Can not replace a symbol that is not materializing");
729 assert(!SymI->second.hasMaterializerAttached() &&
730 "Can not replace a symbol that has a materializer attached");
731 assert(UnmaterializedInfos.count(KV.first) == 0 &&
732 "Unexpected materializer entry in map");
733 SymI->second.setAddress(SymI->second.getAddress());
734 SymI->second.setMaterializerAttached(true);
735
736 auto &UMIEntry = UnmaterializedInfos[KV.first];
737 assert((!UMIEntry || !UMIEntry->MU) &&
738 "Replacing symbol with materializer still attached");
739 UMIEntry = UMI;
740 }
741
742 return Error::success();
743 });
744
745 if (Err)
746 return Err;
747
748 if (MustRunMU) {
749 assert(MustRunMR && "MustRunMU set implies MustRunMR set");
750 ES.dispatchMaterialization(std::move(MustRunMU), std::move(MustRunMR));
751 } else {
752 assert(!MustRunMR && "MustRunMU unset implies MustRunMR unset");
753 }
754
755 return Error::success();
756 }
757
758 Expected<std::unique_ptr<MaterializationResponsibility>>
delegate(MaterializationResponsibility & FromMR,SymbolFlagsMap SymbolFlags,SymbolStringPtr InitSymbol)759 JITDylib::delegate(MaterializationResponsibility &FromMR,
760 SymbolFlagsMap SymbolFlags, SymbolStringPtr InitSymbol) {
761
762 return ES.runSessionLocked(
763 [&]() -> Expected<std::unique_ptr<MaterializationResponsibility>> {
764 auto RT = getTracker(FromMR);
765
766 if (RT->isDefunct())
767 return make_error<ResourceTrackerDefunct>(std::move(RT));
768
769 return ES.createMaterializationResponsibility(
770 *RT, std::move(SymbolFlags), std::move(InitSymbol));
771 });
772 }
773
774 SymbolNameSet
getRequestedSymbols(const SymbolFlagsMap & SymbolFlags) const775 JITDylib::getRequestedSymbols(const SymbolFlagsMap &SymbolFlags) const {
776 return ES.runSessionLocked([&]() {
777 SymbolNameSet RequestedSymbols;
778
779 for (auto &KV : SymbolFlags) {
780 assert(Symbols.count(KV.first) && "JITDylib does not cover this symbol?");
781 assert(Symbols.find(KV.first)->second.getState() !=
782 SymbolState::NeverSearched &&
783 Symbols.find(KV.first)->second.getState() != SymbolState::Ready &&
784 "getRequestedSymbols can only be called for symbols that have "
785 "started materializing");
786 auto I = MaterializingInfos.find(KV.first);
787 if (I == MaterializingInfos.end())
788 continue;
789
790 if (I->second.hasQueriesPending())
791 RequestedSymbols.insert(KV.first);
792 }
793
794 return RequestedSymbols;
795 });
796 }
797
addDependencies(const SymbolStringPtr & Name,const SymbolDependenceMap & Dependencies)798 void JITDylib::addDependencies(const SymbolStringPtr &Name,
799 const SymbolDependenceMap &Dependencies) {
800 assert(Symbols.count(Name) && "Name not in symbol table");
801 assert(Symbols[Name].getState() < SymbolState::Emitted &&
802 "Can not add dependencies for a symbol that is not materializing");
803
804 LLVM_DEBUG({
805 dbgs() << "In " << getName() << " adding dependencies for "
806 << *Name << ": " << Dependencies << "\n";
807 });
808
809 // If Name is already in an error state then just bail out.
810 if (Symbols[Name].getFlags().hasError())
811 return;
812
813 auto &MI = MaterializingInfos[Name];
814 assert(Symbols[Name].getState() != SymbolState::Emitted &&
815 "Can not add dependencies to an emitted symbol");
816
817 bool DependsOnSymbolInErrorState = false;
818
819 // Register dependencies, record whether any depenendency is in the error
820 // state.
821 for (auto &KV : Dependencies) {
822 assert(KV.first && "Null JITDylib in dependency?");
823 auto &OtherJITDylib = *KV.first;
824 auto &DepsOnOtherJITDylib = MI.UnemittedDependencies[&OtherJITDylib];
825
826 for (auto &OtherSymbol : KV.second) {
827
828 // Check the sym entry for the dependency.
829 auto OtherSymI = OtherJITDylib.Symbols.find(OtherSymbol);
830
831 // Assert that this symbol exists and has not reached the ready state
832 // already.
833 assert(OtherSymI != OtherJITDylib.Symbols.end() &&
834 "Dependency on unknown symbol");
835
836 auto &OtherSymEntry = OtherSymI->second;
837
838 // If the other symbol is already in the Ready state then there's no
839 // dependency to add.
840 if (OtherSymEntry.getState() == SymbolState::Ready)
841 continue;
842
843 // If the dependency is in an error state then note this and continue,
844 // we will move this symbol to the error state below.
845 if (OtherSymEntry.getFlags().hasError()) {
846 DependsOnSymbolInErrorState = true;
847 continue;
848 }
849
850 // If the dependency was not in the error state then add it to
851 // our list of dependencies.
852 auto &OtherMI = OtherJITDylib.MaterializingInfos[OtherSymbol];
853
854 if (OtherSymEntry.getState() == SymbolState::Emitted)
855 transferEmittedNodeDependencies(MI, Name, OtherMI);
856 else if (&OtherJITDylib != this || OtherSymbol != Name) {
857 OtherMI.Dependants[this].insert(Name);
858 DepsOnOtherJITDylib.insert(OtherSymbol);
859 }
860 }
861
862 if (DepsOnOtherJITDylib.empty())
863 MI.UnemittedDependencies.erase(&OtherJITDylib);
864 }
865
866 // If this symbol dependended on any symbols in the error state then move
867 // this symbol to the error state too.
868 if (DependsOnSymbolInErrorState)
869 Symbols[Name].setFlags(Symbols[Name].getFlags() | JITSymbolFlags::HasError);
870 }
871
resolve(MaterializationResponsibility & MR,const SymbolMap & Resolved)872 Error JITDylib::resolve(MaterializationResponsibility &MR,
873 const SymbolMap &Resolved) {
874 AsynchronousSymbolQuerySet CompletedQueries;
875
876 if (auto Err = ES.runSessionLocked([&, this]() -> Error {
877 auto RTI = MRTrackers.find(&MR);
878 assert(RTI != MRTrackers.end() && "No resource tracker for MR?");
879 if (RTI->second->isDefunct())
880 return make_error<ResourceTrackerDefunct>(RTI->second);
881
882 struct WorklistEntry {
883 SymbolTable::iterator SymI;
884 JITEvaluatedSymbol ResolvedSym;
885 };
886
887 SymbolNameSet SymbolsInErrorState;
888 std::vector<WorklistEntry> Worklist;
889 Worklist.reserve(Resolved.size());
890
891 // Build worklist and check for any symbols in the error state.
892 for (const auto &KV : Resolved) {
893
894 assert(!KV.second.getFlags().hasError() &&
895 "Resolution result can not have error flag set");
896
897 auto SymI = Symbols.find(KV.first);
898
899 assert(SymI != Symbols.end() && "Symbol not found");
900 assert(!SymI->second.hasMaterializerAttached() &&
901 "Resolving symbol with materializer attached?");
902 assert(SymI->second.getState() == SymbolState::Materializing &&
903 "Symbol should be materializing");
904 assert(SymI->second.getAddress() == 0 &&
905 "Symbol has already been resolved");
906
907 if (SymI->second.getFlags().hasError())
908 SymbolsInErrorState.insert(KV.first);
909 else {
910 auto Flags = KV.second.getFlags();
911 Flags &= ~(JITSymbolFlags::Weak | JITSymbolFlags::Common);
912 assert(Flags ==
913 (SymI->second.getFlags() &
914 ~(JITSymbolFlags::Weak | JITSymbolFlags::Common)) &&
915 "Resolved flags should match the declared flags");
916
917 Worklist.push_back(
918 {SymI, JITEvaluatedSymbol(KV.second.getAddress(), Flags)});
919 }
920 }
921
922 // If any symbols were in the error state then bail out.
923 if (!SymbolsInErrorState.empty()) {
924 auto FailedSymbolsDepMap = std::make_shared<SymbolDependenceMap>();
925 (*FailedSymbolsDepMap)[this] = std::move(SymbolsInErrorState);
926 return make_error<FailedToMaterialize>(
927 std::move(FailedSymbolsDepMap));
928 }
929
930 while (!Worklist.empty()) {
931 auto SymI = Worklist.back().SymI;
932 auto ResolvedSym = Worklist.back().ResolvedSym;
933 Worklist.pop_back();
934
935 auto &Name = SymI->first;
936
937 // Resolved symbols can not be weak: discard the weak flag.
938 JITSymbolFlags ResolvedFlags = ResolvedSym.getFlags();
939 SymI->second.setAddress(ResolvedSym.getAddress());
940 SymI->second.setFlags(ResolvedFlags);
941 SymI->second.setState(SymbolState::Resolved);
942
943 auto MII = MaterializingInfos.find(Name);
944 if (MII == MaterializingInfos.end())
945 continue;
946
947 auto &MI = MII->second;
948 for (auto &Q : MI.takeQueriesMeeting(SymbolState::Resolved)) {
949 Q->notifySymbolMetRequiredState(Name, ResolvedSym);
950 Q->removeQueryDependence(*this, Name);
951 if (Q->isComplete())
952 CompletedQueries.insert(std::move(Q));
953 }
954 }
955
956 return Error::success();
957 }))
958 return Err;
959
960 // Otherwise notify all the completed queries.
961 for (auto &Q : CompletedQueries) {
962 assert(Q->isComplete() && "Q not completed");
963 Q->handleComplete();
964 }
965
966 return Error::success();
967 }
968
emit(MaterializationResponsibility & MR,const SymbolFlagsMap & Emitted)969 Error JITDylib::emit(MaterializationResponsibility &MR,
970 const SymbolFlagsMap &Emitted) {
971 AsynchronousSymbolQuerySet CompletedQueries;
972 DenseMap<JITDylib *, SymbolNameVector> ReadySymbols;
973
974 if (auto Err = ES.runSessionLocked([&, this]() -> Error {
975 auto RTI = MRTrackers.find(&MR);
976 assert(RTI != MRTrackers.end() && "No resource tracker for MR?");
977 if (RTI->second->isDefunct())
978 return make_error<ResourceTrackerDefunct>(RTI->second);
979
980 SymbolNameSet SymbolsInErrorState;
981 std::vector<SymbolTable::iterator> Worklist;
982
983 // Scan to build worklist, record any symbols in the erorr state.
984 for (const auto &KV : Emitted) {
985 auto &Name = KV.first;
986
987 auto SymI = Symbols.find(Name);
988 assert(SymI != Symbols.end() && "No symbol table entry for Name");
989
990 if (SymI->second.getFlags().hasError())
991 SymbolsInErrorState.insert(Name);
992 else
993 Worklist.push_back(SymI);
994 }
995
996 // If any symbols were in the error state then bail out.
997 if (!SymbolsInErrorState.empty()) {
998 auto FailedSymbolsDepMap = std::make_shared<SymbolDependenceMap>();
999 (*FailedSymbolsDepMap)[this] = std::move(SymbolsInErrorState);
1000 return make_error<FailedToMaterialize>(
1001 std::move(FailedSymbolsDepMap));
1002 }
1003
1004 // Otherwise update dependencies and move to the emitted state.
1005 while (!Worklist.empty()) {
1006 auto SymI = Worklist.back();
1007 Worklist.pop_back();
1008
1009 auto &Name = SymI->first;
1010 auto &SymEntry = SymI->second;
1011
1012 // Move symbol to the emitted state.
1013 assert(((SymEntry.getFlags().hasMaterializationSideEffectsOnly() &&
1014 SymEntry.getState() == SymbolState::Materializing) ||
1015 SymEntry.getState() == SymbolState::Resolved) &&
1016 "Emitting from state other than Resolved");
1017 SymEntry.setState(SymbolState::Emitted);
1018
1019 auto MII = MaterializingInfos.find(Name);
1020
1021 // If this symbol has no MaterializingInfo then it's trivially ready.
1022 // Update its state and continue.
1023 if (MII == MaterializingInfos.end()) {
1024 SymEntry.setState(SymbolState::Ready);
1025 continue;
1026 }
1027
1028 auto &MI = MII->second;
1029
1030 // For each dependant, transfer this node's emitted dependencies to
1031 // it. If the dependant node is ready (i.e. has no unemitted
1032 // dependencies) then notify any pending queries.
1033 for (auto &KV : MI.Dependants) {
1034 auto &DependantJD = *KV.first;
1035 auto &DependantJDReadySymbols = ReadySymbols[&DependantJD];
1036 for (auto &DependantName : KV.second) {
1037 auto DependantMII =
1038 DependantJD.MaterializingInfos.find(DependantName);
1039 assert(DependantMII != DependantJD.MaterializingInfos.end() &&
1040 "Dependant should have MaterializingInfo");
1041
1042 auto &DependantMI = DependantMII->second;
1043
1044 // Remove the dependant's dependency on this node.
1045 assert(DependantMI.UnemittedDependencies.count(this) &&
1046 "Dependant does not have an unemitted dependencies record "
1047 "for "
1048 "this JITDylib");
1049 assert(DependantMI.UnemittedDependencies[this].count(Name) &&
1050 "Dependant does not count this symbol as a dependency?");
1051
1052 DependantMI.UnemittedDependencies[this].erase(Name);
1053 if (DependantMI.UnemittedDependencies[this].empty())
1054 DependantMI.UnemittedDependencies.erase(this);
1055
1056 // Transfer unemitted dependencies from this node to the
1057 // dependant.
1058 DependantJD.transferEmittedNodeDependencies(DependantMI,
1059 DependantName, MI);
1060
1061 auto DependantSymI = DependantJD.Symbols.find(DependantName);
1062 assert(DependantSymI != DependantJD.Symbols.end() &&
1063 "Dependant has no entry in the Symbols table");
1064 auto &DependantSymEntry = DependantSymI->second;
1065
1066 // If the dependant is emitted and this node was the last of its
1067 // unemitted dependencies then the dependant node is now ready, so
1068 // notify any pending queries on the dependant node.
1069 if (DependantSymEntry.getState() == SymbolState::Emitted &&
1070 DependantMI.UnemittedDependencies.empty()) {
1071 assert(DependantMI.Dependants.empty() &&
1072 "Dependants should be empty by now");
1073
1074 // Since this dependant is now ready, we erase its
1075 // MaterializingInfo and update its materializing state.
1076 DependantSymEntry.setState(SymbolState::Ready);
1077 DependantJDReadySymbols.push_back(DependantName);
1078
1079 for (auto &Q :
1080 DependantMI.takeQueriesMeeting(SymbolState::Ready)) {
1081 Q->notifySymbolMetRequiredState(
1082 DependantName, DependantSymI->second.getSymbol());
1083 if (Q->isComplete())
1084 CompletedQueries.insert(Q);
1085 Q->removeQueryDependence(DependantJD, DependantName);
1086 }
1087 }
1088 }
1089 }
1090
1091 auto &ThisJDReadySymbols = ReadySymbols[this];
1092 MI.Dependants.clear();
1093 if (MI.UnemittedDependencies.empty()) {
1094 SymI->second.setState(SymbolState::Ready);
1095 ThisJDReadySymbols.push_back(Name);
1096 for (auto &Q : MI.takeQueriesMeeting(SymbolState::Ready)) {
1097 Q->notifySymbolMetRequiredState(Name, SymI->second.getSymbol());
1098 if (Q->isComplete())
1099 CompletedQueries.insert(Q);
1100 Q->removeQueryDependence(*this, Name);
1101 }
1102 }
1103 }
1104
1105 return Error::success();
1106 }))
1107 return Err;
1108
1109 // Otherwise notify all the completed queries.
1110 for (auto &Q : CompletedQueries) {
1111 assert(Q->isComplete() && "Q is not complete");
1112 Q->handleComplete();
1113 }
1114
1115 return Error::success();
1116 }
1117
unlinkMaterializationResponsibility(MaterializationResponsibility & MR)1118 void JITDylib::unlinkMaterializationResponsibility(
1119 MaterializationResponsibility &MR) {
1120 ES.runSessionLocked([&]() {
1121 auto I = MRTrackers.find(&MR);
1122 assert(I != MRTrackers.end() && "MaterializationResponsibility not linked");
1123 MRTrackers.erase(I);
1124 });
1125 }
1126
1127 std::pair<JITDylib::AsynchronousSymbolQuerySet,
1128 std::shared_ptr<SymbolDependenceMap>>
failSymbols(FailedSymbolsWorklist Worklist)1129 JITDylib::failSymbols(FailedSymbolsWorklist Worklist) {
1130 AsynchronousSymbolQuerySet FailedQueries;
1131 auto FailedSymbolsMap = std::make_shared<SymbolDependenceMap>();
1132
1133 while (!Worklist.empty()) {
1134 assert(Worklist.back().first && "Failed JITDylib can not be null");
1135 auto &JD = *Worklist.back().first;
1136 auto Name = std::move(Worklist.back().second);
1137 Worklist.pop_back();
1138
1139 (*FailedSymbolsMap)[&JD].insert(Name);
1140
1141 assert(JD.Symbols.count(Name) && "No symbol table entry for Name");
1142 auto &Sym = JD.Symbols[Name];
1143
1144 // Move the symbol into the error state.
1145 // Note that this may be redundant: The symbol might already have been
1146 // moved to this state in response to the failure of a dependence.
1147 Sym.setFlags(Sym.getFlags() | JITSymbolFlags::HasError);
1148
1149 // FIXME: Come up with a sane mapping of state to
1150 // presence-of-MaterializingInfo so that we can assert presence / absence
1151 // here, rather than testing it.
1152 auto MII = JD.MaterializingInfos.find(Name);
1153
1154 if (MII == JD.MaterializingInfos.end())
1155 continue;
1156
1157 auto &MI = MII->second;
1158
1159 // Move all dependants to the error state and disconnect from them.
1160 for (auto &KV : MI.Dependants) {
1161 auto &DependantJD = *KV.first;
1162 for (auto &DependantName : KV.second) {
1163 assert(DependantJD.Symbols.count(DependantName) &&
1164 "No symbol table entry for DependantName");
1165 auto &DependantSym = DependantJD.Symbols[DependantName];
1166 DependantSym.setFlags(DependantSym.getFlags() |
1167 JITSymbolFlags::HasError);
1168
1169 assert(DependantJD.MaterializingInfos.count(DependantName) &&
1170 "No MaterializingInfo for dependant");
1171 auto &DependantMI = DependantJD.MaterializingInfos[DependantName];
1172
1173 auto UnemittedDepI = DependantMI.UnemittedDependencies.find(&JD);
1174 assert(UnemittedDepI != DependantMI.UnemittedDependencies.end() &&
1175 "No UnemittedDependencies entry for this JITDylib");
1176 assert(UnemittedDepI->second.count(Name) &&
1177 "No UnemittedDependencies entry for this symbol");
1178 UnemittedDepI->second.erase(Name);
1179 if (UnemittedDepI->second.empty())
1180 DependantMI.UnemittedDependencies.erase(UnemittedDepI);
1181
1182 // If this symbol is already in the emitted state then we need to
1183 // take responsibility for failing its queries, so add it to the
1184 // worklist.
1185 if (DependantSym.getState() == SymbolState::Emitted) {
1186 assert(DependantMI.Dependants.empty() &&
1187 "Emitted symbol should not have dependants");
1188 Worklist.push_back(std::make_pair(&DependantJD, DependantName));
1189 }
1190 }
1191 }
1192 MI.Dependants.clear();
1193
1194 // Disconnect from all unemitted depenencies.
1195 for (auto &KV : MI.UnemittedDependencies) {
1196 auto &UnemittedDepJD = *KV.first;
1197 for (auto &UnemittedDepName : KV.second) {
1198 auto UnemittedDepMII =
1199 UnemittedDepJD.MaterializingInfos.find(UnemittedDepName);
1200 assert(UnemittedDepMII != UnemittedDepJD.MaterializingInfos.end() &&
1201 "Missing MII for unemitted dependency");
1202 assert(UnemittedDepMII->second.Dependants.count(&JD) &&
1203 "JD not listed as a dependant of unemitted dependency");
1204 assert(UnemittedDepMII->second.Dependants[&JD].count(Name) &&
1205 "Name is not listed as a dependant of unemitted dependency");
1206 UnemittedDepMII->second.Dependants[&JD].erase(Name);
1207 if (UnemittedDepMII->second.Dependants[&JD].empty())
1208 UnemittedDepMII->second.Dependants.erase(&JD);
1209 }
1210 }
1211 MI.UnemittedDependencies.clear();
1212
1213 // Collect queries to be failed for this MII.
1214 AsynchronousSymbolQueryList ToDetach;
1215 for (auto &Q : MII->second.pendingQueries()) {
1216 // Add the query to the list to be failed and detach it.
1217 FailedQueries.insert(Q);
1218 ToDetach.push_back(Q);
1219 }
1220 for (auto &Q : ToDetach)
1221 Q->detach();
1222
1223 assert(MI.Dependants.empty() &&
1224 "Can not delete MaterializingInfo with dependants still attached");
1225 assert(MI.UnemittedDependencies.empty() &&
1226 "Can not delete MaterializingInfo with unemitted dependencies "
1227 "still attached");
1228 assert(!MI.hasQueriesPending() &&
1229 "Can not delete MaterializingInfo with queries pending");
1230 JD.MaterializingInfos.erase(MII);
1231 }
1232
1233 return std::make_pair(std::move(FailedQueries), std::move(FailedSymbolsMap));
1234 }
1235
setLinkOrder(JITDylibSearchOrder NewLinkOrder,bool LinkAgainstThisJITDylibFirst)1236 void JITDylib::setLinkOrder(JITDylibSearchOrder NewLinkOrder,
1237 bool LinkAgainstThisJITDylibFirst) {
1238 ES.runSessionLocked([&]() {
1239 if (LinkAgainstThisJITDylibFirst) {
1240 LinkOrder.clear();
1241 if (NewLinkOrder.empty() || NewLinkOrder.front().first != this)
1242 LinkOrder.push_back(
1243 std::make_pair(this, JITDylibLookupFlags::MatchAllSymbols));
1244 LinkOrder.insert(LinkOrder.end(), NewLinkOrder.begin(),
1245 NewLinkOrder.end());
1246 } else
1247 LinkOrder = std::move(NewLinkOrder);
1248 });
1249 }
1250
addToLinkOrder(JITDylib & JD,JITDylibLookupFlags JDLookupFlags)1251 void JITDylib::addToLinkOrder(JITDylib &JD, JITDylibLookupFlags JDLookupFlags) {
1252 ES.runSessionLocked([&]() { LinkOrder.push_back({&JD, JDLookupFlags}); });
1253 }
1254
replaceInLinkOrder(JITDylib & OldJD,JITDylib & NewJD,JITDylibLookupFlags JDLookupFlags)1255 void JITDylib::replaceInLinkOrder(JITDylib &OldJD, JITDylib &NewJD,
1256 JITDylibLookupFlags JDLookupFlags) {
1257 ES.runSessionLocked([&]() {
1258 for (auto &KV : LinkOrder)
1259 if (KV.first == &OldJD) {
1260 KV = {&NewJD, JDLookupFlags};
1261 break;
1262 }
1263 });
1264 }
1265
removeFromLinkOrder(JITDylib & JD)1266 void JITDylib::removeFromLinkOrder(JITDylib &JD) {
1267 ES.runSessionLocked([&]() {
1268 auto I = std::find_if(LinkOrder.begin(), LinkOrder.end(),
1269 [&](const JITDylibSearchOrder::value_type &KV) {
1270 return KV.first == &JD;
1271 });
1272 if (I != LinkOrder.end())
1273 LinkOrder.erase(I);
1274 });
1275 }
1276
remove(const SymbolNameSet & Names)1277 Error JITDylib::remove(const SymbolNameSet &Names) {
1278 return ES.runSessionLocked([&]() -> Error {
1279 using SymbolMaterializerItrPair =
1280 std::pair<SymbolTable::iterator, UnmaterializedInfosMap::iterator>;
1281 std::vector<SymbolMaterializerItrPair> SymbolsToRemove;
1282 SymbolNameSet Missing;
1283 SymbolNameSet Materializing;
1284
1285 for (auto &Name : Names) {
1286 auto I = Symbols.find(Name);
1287
1288 // Note symbol missing.
1289 if (I == Symbols.end()) {
1290 Missing.insert(Name);
1291 continue;
1292 }
1293
1294 // Note symbol materializing.
1295 if (I->second.getState() != SymbolState::NeverSearched &&
1296 I->second.getState() != SymbolState::Ready) {
1297 Materializing.insert(Name);
1298 continue;
1299 }
1300
1301 auto UMII = I->second.hasMaterializerAttached()
1302 ? UnmaterializedInfos.find(Name)
1303 : UnmaterializedInfos.end();
1304 SymbolsToRemove.push_back(std::make_pair(I, UMII));
1305 }
1306
1307 // If any of the symbols are not defined, return an error.
1308 if (!Missing.empty())
1309 return make_error<SymbolsNotFound>(std::move(Missing));
1310
1311 // If any of the symbols are currently materializing, return an error.
1312 if (!Materializing.empty())
1313 return make_error<SymbolsCouldNotBeRemoved>(std::move(Materializing));
1314
1315 // Remove the symbols.
1316 for (auto &SymbolMaterializerItrPair : SymbolsToRemove) {
1317 auto UMII = SymbolMaterializerItrPair.second;
1318
1319 // If there is a materializer attached, call discard.
1320 if (UMII != UnmaterializedInfos.end()) {
1321 UMII->second->MU->doDiscard(*this, UMII->first);
1322 UnmaterializedInfos.erase(UMII);
1323 }
1324
1325 auto SymI = SymbolMaterializerItrPair.first;
1326 Symbols.erase(SymI);
1327 }
1328
1329 return Error::success();
1330 });
1331 }
1332
dump(raw_ostream & OS)1333 void JITDylib::dump(raw_ostream &OS) {
1334 ES.runSessionLocked([&, this]() {
1335 OS << "JITDylib \"" << JITDylibName << "\" (ES: "
1336 << format("0x%016" PRIx64, reinterpret_cast<uintptr_t>(&ES)) << "):\n"
1337 << "Link order: " << LinkOrder << "\n"
1338 << "Symbol table:\n";
1339
1340 for (auto &KV : Symbols) {
1341 OS << " \"" << *KV.first << "\": ";
1342 if (auto Addr = KV.second.getAddress())
1343 OS << format("0x%016" PRIx64, Addr) << ", " << KV.second.getFlags()
1344 << " ";
1345 else
1346 OS << "<not resolved> ";
1347
1348 OS << KV.second.getFlags() << " " << KV.second.getState();
1349
1350 if (KV.second.hasMaterializerAttached()) {
1351 OS << " (Materializer ";
1352 auto I = UnmaterializedInfos.find(KV.first);
1353 assert(I != UnmaterializedInfos.end() &&
1354 "Lazy symbol should have UnmaterializedInfo");
1355 OS << I->second->MU.get() << ", " << I->second->MU->getName() << ")\n";
1356 } else
1357 OS << "\n";
1358 }
1359
1360 if (!MaterializingInfos.empty())
1361 OS << " MaterializingInfos entries:\n";
1362 for (auto &KV : MaterializingInfos) {
1363 OS << " \"" << *KV.first << "\":\n"
1364 << " " << KV.second.pendingQueries().size()
1365 << " pending queries: { ";
1366 for (const auto &Q : KV.second.pendingQueries())
1367 OS << Q.get() << " (" << Q->getRequiredState() << ") ";
1368 OS << "}\n Dependants:\n";
1369 for (auto &KV2 : KV.second.Dependants)
1370 OS << " " << KV2.first->getName() << ": " << KV2.second << "\n";
1371 OS << " Unemitted Dependencies:\n";
1372 for (auto &KV2 : KV.second.UnemittedDependencies)
1373 OS << " " << KV2.first->getName() << ": " << KV2.second << "\n";
1374 }
1375 });
1376 }
1377
addQuery(std::shared_ptr<AsynchronousSymbolQuery> Q)1378 void JITDylib::MaterializingInfo::addQuery(
1379 std::shared_ptr<AsynchronousSymbolQuery> Q) {
1380
1381 auto I = std::lower_bound(
1382 PendingQueries.rbegin(), PendingQueries.rend(), Q->getRequiredState(),
1383 [](const std::shared_ptr<AsynchronousSymbolQuery> &V, SymbolState S) {
1384 return V->getRequiredState() <= S;
1385 });
1386 PendingQueries.insert(I.base(), std::move(Q));
1387 }
1388
removeQuery(const AsynchronousSymbolQuery & Q)1389 void JITDylib::MaterializingInfo::removeQuery(
1390 const AsynchronousSymbolQuery &Q) {
1391 // FIXME: Implement 'find_as' for shared_ptr<T>/T*.
1392 auto I =
1393 std::find_if(PendingQueries.begin(), PendingQueries.end(),
1394 [&Q](const std::shared_ptr<AsynchronousSymbolQuery> &V) {
1395 return V.get() == &Q;
1396 });
1397 assert(I != PendingQueries.end() &&
1398 "Query is not attached to this MaterializingInfo");
1399 PendingQueries.erase(I);
1400 }
1401
1402 JITDylib::AsynchronousSymbolQueryList
takeQueriesMeeting(SymbolState RequiredState)1403 JITDylib::MaterializingInfo::takeQueriesMeeting(SymbolState RequiredState) {
1404 AsynchronousSymbolQueryList Result;
1405 while (!PendingQueries.empty()) {
1406 if (PendingQueries.back()->getRequiredState() > RequiredState)
1407 break;
1408
1409 Result.push_back(std::move(PendingQueries.back()));
1410 PendingQueries.pop_back();
1411 }
1412
1413 return Result;
1414 }
1415
JITDylib(ExecutionSession & ES,std::string Name)1416 JITDylib::JITDylib(ExecutionSession &ES, std::string Name)
1417 : ES(ES), JITDylibName(std::move(Name)) {
1418 LinkOrder.push_back({this, JITDylibLookupFlags::MatchAllSymbols});
1419 }
1420
getTracker(MaterializationResponsibility & MR)1421 ResourceTrackerSP JITDylib::getTracker(MaterializationResponsibility &MR) {
1422 auto I = MRTrackers.find(&MR);
1423 assert(I != MRTrackers.end() && "MR is not linked");
1424 assert(I->second && "Linked tracker is null");
1425 return I->second;
1426 }
1427
1428 std::pair<JITDylib::AsynchronousSymbolQuerySet,
1429 std::shared_ptr<SymbolDependenceMap>>
removeTracker(ResourceTracker & RT)1430 JITDylib::removeTracker(ResourceTracker &RT) {
1431 // Note: Should be called under the session lock.
1432
1433 SymbolNameVector SymbolsToRemove;
1434 std::vector<std::pair<JITDylib *, SymbolStringPtr>> SymbolsToFail;
1435
1436 if (&RT == DefaultTracker.get()) {
1437 SymbolNameSet TrackedSymbols;
1438 for (auto &KV : TrackerSymbols)
1439 for (auto &Sym : KV.second)
1440 TrackedSymbols.insert(Sym);
1441
1442 for (auto &KV : Symbols) {
1443 auto &Sym = KV.first;
1444 if (!TrackedSymbols.count(Sym))
1445 SymbolsToRemove.push_back(Sym);
1446 }
1447
1448 DefaultTracker.reset();
1449 } else {
1450 /// Check for a non-default tracker.
1451 auto I = TrackerSymbols.find(&RT);
1452 if (I != TrackerSymbols.end()) {
1453 SymbolsToRemove = std::move(I->second);
1454 TrackerSymbols.erase(I);
1455 }
1456 // ... if not found this tracker was already defunct. Nothing to do.
1457 }
1458
1459 for (auto &Sym : SymbolsToRemove) {
1460 assert(Symbols.count(Sym) && "Symbol not in symbol table");
1461
1462 // If there is a MaterializingInfo then collect any queries to fail.
1463 auto MII = MaterializingInfos.find(Sym);
1464 if (MII != MaterializingInfos.end())
1465 SymbolsToFail.push_back({this, Sym});
1466 }
1467
1468 AsynchronousSymbolQuerySet QueriesToFail;
1469 auto Result = failSymbols(std::move(SymbolsToFail));
1470
1471 // Removed symbols should be taken out of the table altogether.
1472 for (auto &Sym : SymbolsToRemove) {
1473 auto I = Symbols.find(Sym);
1474 assert(I != Symbols.end() && "Symbol not present in table");
1475
1476 // Remove Materializer if present.
1477 if (I->second.hasMaterializerAttached()) {
1478 // FIXME: Should this discard the symbols?
1479 UnmaterializedInfos.erase(Sym);
1480 } else {
1481 assert(!UnmaterializedInfos.count(Sym) &&
1482 "Symbol has materializer attached");
1483 }
1484
1485 Symbols.erase(I);
1486 }
1487
1488 return Result;
1489 }
1490
transferTracker(ResourceTracker & DstRT,ResourceTracker & SrcRT)1491 void JITDylib::transferTracker(ResourceTracker &DstRT, ResourceTracker &SrcRT) {
1492 assert(&DstRT != &SrcRT && "No-op transfers shouldn't call transferTracker");
1493 assert(&DstRT.getJITDylib() == this && "DstRT is not for this JITDylib");
1494 assert(&SrcRT.getJITDylib() == this && "SrcRT is not for this JITDylib");
1495
1496 // Update trackers for any not-yet materialized units.
1497 for (auto &KV : UnmaterializedInfos) {
1498 if (KV.second->RT == &SrcRT)
1499 KV.second->RT = &DstRT;
1500 }
1501
1502 // Update trackers for any active materialization responsibilities.
1503 for (auto &KV : MRTrackers) {
1504 if (KV.second == &SrcRT)
1505 KV.second = &DstRT;
1506 }
1507
1508 // If we're transfering to the default tracker we just need to delete the
1509 // tracked symbols for the source tracker.
1510 if (&DstRT == DefaultTracker.get()) {
1511 TrackerSymbols.erase(&SrcRT);
1512 return;
1513 }
1514
1515 // If we're transferring from the default tracker we need to find all
1516 // currently untracked symbols.
1517 if (&SrcRT == DefaultTracker.get()) {
1518 assert(!TrackerSymbols.count(&SrcRT) &&
1519 "Default tracker should not appear in TrackerSymbols");
1520
1521 SymbolNameVector SymbolsToTrack;
1522
1523 SymbolNameSet CurrentlyTrackedSymbols;
1524 for (auto &KV : TrackerSymbols)
1525 for (auto &Sym : KV.second)
1526 CurrentlyTrackedSymbols.insert(Sym);
1527
1528 for (auto &KV : Symbols) {
1529 auto &Sym = KV.first;
1530 if (!CurrentlyTrackedSymbols.count(Sym))
1531 SymbolsToTrack.push_back(Sym);
1532 }
1533
1534 TrackerSymbols[&DstRT] = std::move(SymbolsToTrack);
1535 return;
1536 }
1537
1538 auto &DstTrackedSymbols = TrackerSymbols[&DstRT];
1539
1540 // Finally if neither SrtRT or DstRT are the default tracker then
1541 // just append DstRT's tracked symbols to SrtRT's.
1542 auto SI = TrackerSymbols.find(&SrcRT);
1543 if (SI == TrackerSymbols.end())
1544 return;
1545
1546 DstTrackedSymbols.reserve(DstTrackedSymbols.size() + SI->second.size());
1547 for (auto &Sym : SI->second)
1548 DstTrackedSymbols.push_back(std::move(Sym));
1549 TrackerSymbols.erase(SI);
1550 }
1551
defineImpl(MaterializationUnit & MU)1552 Error JITDylib::defineImpl(MaterializationUnit &MU) {
1553
1554 LLVM_DEBUG({ dbgs() << " " << MU.getSymbols() << "\n"; });
1555
1556 SymbolNameSet Duplicates;
1557 std::vector<SymbolStringPtr> ExistingDefsOverridden;
1558 std::vector<SymbolStringPtr> MUDefsOverridden;
1559
1560 for (const auto &KV : MU.getSymbols()) {
1561 auto I = Symbols.find(KV.first);
1562
1563 if (I != Symbols.end()) {
1564 if (KV.second.isStrong()) {
1565 if (I->second.getFlags().isStrong() ||
1566 I->second.getState() > SymbolState::NeverSearched)
1567 Duplicates.insert(KV.first);
1568 else {
1569 assert(I->second.getState() == SymbolState::NeverSearched &&
1570 "Overridden existing def should be in the never-searched "
1571 "state");
1572 ExistingDefsOverridden.push_back(KV.first);
1573 }
1574 } else
1575 MUDefsOverridden.push_back(KV.first);
1576 }
1577 }
1578
1579 // If there were any duplicate definitions then bail out.
1580 if (!Duplicates.empty()) {
1581 LLVM_DEBUG(
1582 { dbgs() << " Error: Duplicate symbols " << Duplicates << "\n"; });
1583 return make_error<DuplicateDefinition>(std::string(**Duplicates.begin()));
1584 }
1585
1586 // Discard any overridden defs in this MU.
1587 LLVM_DEBUG({
1588 if (!MUDefsOverridden.empty())
1589 dbgs() << " Defs in this MU overridden: " << MUDefsOverridden << "\n";
1590 });
1591 for (auto &S : MUDefsOverridden)
1592 MU.doDiscard(*this, S);
1593
1594 // Discard existing overridden defs.
1595 LLVM_DEBUG({
1596 if (!ExistingDefsOverridden.empty())
1597 dbgs() << " Existing defs overridden by this MU: " << MUDefsOverridden
1598 << "\n";
1599 });
1600 for (auto &S : ExistingDefsOverridden) {
1601
1602 auto UMII = UnmaterializedInfos.find(S);
1603 assert(UMII != UnmaterializedInfos.end() &&
1604 "Overridden existing def should have an UnmaterializedInfo");
1605 UMII->second->MU->doDiscard(*this, S);
1606 }
1607
1608 // Finally, add the defs from this MU.
1609 for (auto &KV : MU.getSymbols()) {
1610 auto &SymEntry = Symbols[KV.first];
1611 SymEntry.setFlags(KV.second);
1612 SymEntry.setState(SymbolState::NeverSearched);
1613 SymEntry.setMaterializerAttached(true);
1614 }
1615
1616 return Error::success();
1617 }
1618
installMaterializationUnit(std::unique_ptr<MaterializationUnit> MU,ResourceTracker & RT)1619 void JITDylib::installMaterializationUnit(
1620 std::unique_ptr<MaterializationUnit> MU, ResourceTracker &RT) {
1621
1622 /// defineImpl succeeded.
1623 if (&RT != DefaultTracker.get()) {
1624 auto &TS = TrackerSymbols[&RT];
1625 TS.reserve(TS.size() + MU->getSymbols().size());
1626 for (auto &KV : MU->getSymbols())
1627 TS.push_back(KV.first);
1628 }
1629
1630 auto UMI = std::make_shared<UnmaterializedInfo>(std::move(MU), &RT);
1631 for (auto &KV : UMI->MU->getSymbols())
1632 UnmaterializedInfos[KV.first] = UMI;
1633 }
1634
detachQueryHelper(AsynchronousSymbolQuery & Q,const SymbolNameSet & QuerySymbols)1635 void JITDylib::detachQueryHelper(AsynchronousSymbolQuery &Q,
1636 const SymbolNameSet &QuerySymbols) {
1637 for (auto &QuerySymbol : QuerySymbols) {
1638 assert(MaterializingInfos.count(QuerySymbol) &&
1639 "QuerySymbol does not have MaterializingInfo");
1640 auto &MI = MaterializingInfos[QuerySymbol];
1641 MI.removeQuery(Q);
1642 }
1643 }
1644
transferEmittedNodeDependencies(MaterializingInfo & DependantMI,const SymbolStringPtr & DependantName,MaterializingInfo & EmittedMI)1645 void JITDylib::transferEmittedNodeDependencies(
1646 MaterializingInfo &DependantMI, const SymbolStringPtr &DependantName,
1647 MaterializingInfo &EmittedMI) {
1648 for (auto &KV : EmittedMI.UnemittedDependencies) {
1649 auto &DependencyJD = *KV.first;
1650 SymbolNameSet *UnemittedDependenciesOnDependencyJD = nullptr;
1651
1652 for (auto &DependencyName : KV.second) {
1653 auto &DependencyMI = DependencyJD.MaterializingInfos[DependencyName];
1654
1655 // Do not add self dependencies.
1656 if (&DependencyMI == &DependantMI)
1657 continue;
1658
1659 // If we haven't looked up the dependencies for DependencyJD yet, do it
1660 // now and cache the result.
1661 if (!UnemittedDependenciesOnDependencyJD)
1662 UnemittedDependenciesOnDependencyJD =
1663 &DependantMI.UnemittedDependencies[&DependencyJD];
1664
1665 DependencyMI.Dependants[this].insert(DependantName);
1666 UnemittedDependenciesOnDependencyJD->insert(DependencyName);
1667 }
1668 }
1669 }
1670
~Platform()1671 Platform::~Platform() {}
1672
lookupInitSymbols(ExecutionSession & ES,const DenseMap<JITDylib *,SymbolLookupSet> & InitSyms)1673 Expected<DenseMap<JITDylib *, SymbolMap>> Platform::lookupInitSymbols(
1674 ExecutionSession &ES,
1675 const DenseMap<JITDylib *, SymbolLookupSet> &InitSyms) {
1676
1677 DenseMap<JITDylib *, SymbolMap> CompoundResult;
1678 Error CompoundErr = Error::success();
1679 std::mutex LookupMutex;
1680 std::condition_variable CV;
1681 uint64_t Count = InitSyms.size();
1682
1683 LLVM_DEBUG({
1684 dbgs() << "Issuing init-symbol lookup:\n";
1685 for (auto &KV : InitSyms)
1686 dbgs() << " " << KV.first->getName() << ": " << KV.second << "\n";
1687 });
1688
1689 for (auto &KV : InitSyms) {
1690 auto *JD = KV.first;
1691 auto Names = std::move(KV.second);
1692 ES.lookup(
1693 LookupKind::Static,
1694 JITDylibSearchOrder({{JD, JITDylibLookupFlags::MatchAllSymbols}}),
1695 std::move(Names), SymbolState::Ready,
1696 [&, JD](Expected<SymbolMap> Result) {
1697 {
1698 std::lock_guard<std::mutex> Lock(LookupMutex);
1699 --Count;
1700 if (Result) {
1701 assert(!CompoundResult.count(JD) &&
1702 "Duplicate JITDylib in lookup?");
1703 CompoundResult[JD] = std::move(*Result);
1704 } else
1705 CompoundErr =
1706 joinErrors(std::move(CompoundErr), Result.takeError());
1707 }
1708 CV.notify_one();
1709 },
1710 NoDependenciesToRegister);
1711 }
1712
1713 std::unique_lock<std::mutex> Lock(LookupMutex);
1714 CV.wait(Lock, [&] { return Count == 0 || CompoundErr; });
1715
1716 if (CompoundErr)
1717 return std::move(CompoundErr);
1718
1719 return std::move(CompoundResult);
1720 }
1721
ExecutionSession(std::shared_ptr<SymbolStringPool> SSP)1722 ExecutionSession::ExecutionSession(std::shared_ptr<SymbolStringPool> SSP)
1723 : SSP(SSP ? std::move(SSP) : std::make_shared<SymbolStringPool>()) {}
1724
endSession()1725 Error ExecutionSession::endSession() {
1726 LLVM_DEBUG(dbgs() << "Ending ExecutionSession " << this << "\n");
1727
1728 std::vector<JITDylibSP> JITDylibsToClose = runSessionLocked([&] {
1729 SessionOpen = false;
1730 return std::move(JDs);
1731 });
1732
1733 // TODO: notifiy platform? run static deinits?
1734
1735 Error Err = Error::success();
1736 for (auto &JD : JITDylibsToClose)
1737 Err = joinErrors(std::move(Err), JD->clear());
1738 return Err;
1739 }
1740
registerResourceManager(ResourceManager & RM)1741 void ExecutionSession::registerResourceManager(ResourceManager &RM) {
1742 runSessionLocked([&] { ResourceManagers.push_back(&RM); });
1743 }
1744
deregisterResourceManager(ResourceManager & RM)1745 void ExecutionSession::deregisterResourceManager(ResourceManager &RM) {
1746 runSessionLocked([&] {
1747 assert(!ResourceManagers.empty() && "No managers registered");
1748 if (ResourceManagers.back() == &RM)
1749 ResourceManagers.pop_back();
1750 else {
1751 auto I = llvm::find(ResourceManagers, &RM);
1752 assert(I != ResourceManagers.end() && "RM not registered");
1753 ResourceManagers.erase(I);
1754 }
1755 });
1756 }
1757
getJITDylibByName(StringRef Name)1758 JITDylib *ExecutionSession::getJITDylibByName(StringRef Name) {
1759 return runSessionLocked([&, this]() -> JITDylib * {
1760 for (auto &JD : JDs)
1761 if (JD->getName() == Name)
1762 return JD.get();
1763 return nullptr;
1764 });
1765 }
1766
createBareJITDylib(std::string Name)1767 JITDylib &ExecutionSession::createBareJITDylib(std::string Name) {
1768 assert(!getJITDylibByName(Name) && "JITDylib with that name already exists");
1769 return runSessionLocked([&, this]() -> JITDylib & {
1770 JDs.push_back(new JITDylib(*this, std::move(Name)));
1771 return *JDs.back();
1772 });
1773 }
1774
createJITDylib(std::string Name)1775 Expected<JITDylib &> ExecutionSession::createJITDylib(std::string Name) {
1776 auto &JD = createBareJITDylib(Name);
1777 if (P)
1778 if (auto Err = P->setupJITDylib(JD))
1779 return std::move(Err);
1780 return JD;
1781 }
1782
getDFSLinkOrder(ArrayRef<JITDylibSP> JDs)1783 std::vector<JITDylibSP> JITDylib::getDFSLinkOrder(ArrayRef<JITDylibSP> JDs) {
1784 if (JDs.empty())
1785 return {};
1786
1787 auto &ES = JDs.front()->getExecutionSession();
1788 return ES.runSessionLocked([&]() {
1789 DenseSet<JITDylib *> Visited;
1790 std::vector<JITDylibSP> Result;
1791
1792 for (auto &JD : JDs) {
1793
1794 if (Visited.count(JD.get()))
1795 continue;
1796
1797 SmallVector<JITDylibSP, 64> WorkStack;
1798 WorkStack.push_back(JD);
1799 Visited.insert(JD.get());
1800
1801 while (!WorkStack.empty()) {
1802 Result.push_back(std::move(WorkStack.back()));
1803 WorkStack.pop_back();
1804
1805 for (auto &KV : llvm::reverse(Result.back()->LinkOrder)) {
1806 auto &JD = *KV.first;
1807 if (Visited.count(&JD))
1808 continue;
1809 Visited.insert(&JD);
1810 WorkStack.push_back(&JD);
1811 }
1812 }
1813 }
1814 return Result;
1815 });
1816 }
1817
1818 std::vector<JITDylibSP>
getReverseDFSLinkOrder(ArrayRef<JITDylibSP> JDs)1819 JITDylib::getReverseDFSLinkOrder(ArrayRef<JITDylibSP> JDs) {
1820 auto Tmp = getDFSLinkOrder(JDs);
1821 std::reverse(Tmp.begin(), Tmp.end());
1822 return Tmp;
1823 }
1824
getDFSLinkOrder()1825 std::vector<JITDylibSP> JITDylib::getDFSLinkOrder() {
1826 return getDFSLinkOrder({this});
1827 }
1828
getReverseDFSLinkOrder()1829 std::vector<JITDylibSP> JITDylib::getReverseDFSLinkOrder() {
1830 return getReverseDFSLinkOrder({this});
1831 }
1832
lookupFlags(LookupKind K,JITDylibSearchOrder SearchOrder,SymbolLookupSet LookupSet,unique_function<void (Expected<SymbolFlagsMap>)> OnComplete)1833 void ExecutionSession::lookupFlags(
1834 LookupKind K, JITDylibSearchOrder SearchOrder, SymbolLookupSet LookupSet,
1835 unique_function<void(Expected<SymbolFlagsMap>)> OnComplete) {
1836
1837 OL_applyQueryPhase1(std::make_unique<InProgressLookupFlagsState>(
1838 K, std::move(SearchOrder), std::move(LookupSet),
1839 std::move(OnComplete)),
1840 Error::success());
1841 }
1842
1843 Expected<SymbolFlagsMap>
lookupFlags(LookupKind K,JITDylibSearchOrder SearchOrder,SymbolLookupSet LookupSet)1844 ExecutionSession::lookupFlags(LookupKind K, JITDylibSearchOrder SearchOrder,
1845 SymbolLookupSet LookupSet) {
1846
1847 std::promise<MSVCPExpected<SymbolFlagsMap>> ResultP;
1848 OL_applyQueryPhase1(std::make_unique<InProgressLookupFlagsState>(
1849 K, std::move(SearchOrder), std::move(LookupSet),
1850 [&ResultP](Expected<SymbolFlagsMap> Result) {
1851 ResultP.set_value(std::move(Result));
1852 }),
1853 Error::success());
1854
1855 auto ResultF = ResultP.get_future();
1856 return ResultF.get();
1857 }
1858
lookup(LookupKind K,const JITDylibSearchOrder & SearchOrder,SymbolLookupSet Symbols,SymbolState RequiredState,SymbolsResolvedCallback NotifyComplete,RegisterDependenciesFunction RegisterDependencies)1859 void ExecutionSession::lookup(
1860 LookupKind K, const JITDylibSearchOrder &SearchOrder,
1861 SymbolLookupSet Symbols, SymbolState RequiredState,
1862 SymbolsResolvedCallback NotifyComplete,
1863 RegisterDependenciesFunction RegisterDependencies) {
1864
1865 LLVM_DEBUG({
1866 runSessionLocked([&]() {
1867 dbgs() << "Looking up " << Symbols << " in " << SearchOrder
1868 << " (required state: " << RequiredState << ")\n";
1869 });
1870 });
1871
1872 // lookup can be re-entered recursively if running on a single thread. Run any
1873 // outstanding MUs in case this query depends on them, otherwise this lookup
1874 // will starve waiting for a result from an MU that is stuck in the queue.
1875 dispatchOutstandingMUs();
1876
1877 auto Unresolved = std::move(Symbols);
1878 auto Q = std::make_shared<AsynchronousSymbolQuery>(Unresolved, RequiredState,
1879 std::move(NotifyComplete));
1880
1881 auto IPLS = std::make_unique<InProgressFullLookupState>(
1882 K, SearchOrder, std::move(Unresolved), RequiredState, std::move(Q),
1883 std::move(RegisterDependencies));
1884
1885 OL_applyQueryPhase1(std::move(IPLS), Error::success());
1886 }
1887
1888 Expected<SymbolMap>
lookup(const JITDylibSearchOrder & SearchOrder,const SymbolLookupSet & Symbols,LookupKind K,SymbolState RequiredState,RegisterDependenciesFunction RegisterDependencies)1889 ExecutionSession::lookup(const JITDylibSearchOrder &SearchOrder,
1890 const SymbolLookupSet &Symbols, LookupKind K,
1891 SymbolState RequiredState,
1892 RegisterDependenciesFunction RegisterDependencies) {
1893 #if LLVM_ENABLE_THREADS
1894 // In the threaded case we use promises to return the results.
1895 std::promise<SymbolMap> PromisedResult;
1896 Error ResolutionError = Error::success();
1897
1898 auto NotifyComplete = [&](Expected<SymbolMap> R) {
1899 if (R)
1900 PromisedResult.set_value(std::move(*R));
1901 else {
1902 ErrorAsOutParameter _(&ResolutionError);
1903 ResolutionError = R.takeError();
1904 PromisedResult.set_value(SymbolMap());
1905 }
1906 };
1907
1908 #else
1909 SymbolMap Result;
1910 Error ResolutionError = Error::success();
1911
1912 auto NotifyComplete = [&](Expected<SymbolMap> R) {
1913 ErrorAsOutParameter _(&ResolutionError);
1914 if (R)
1915 Result = std::move(*R);
1916 else
1917 ResolutionError = R.takeError();
1918 };
1919 #endif
1920
1921 // Perform the asynchronous lookup.
1922 lookup(K, SearchOrder, Symbols, RequiredState, NotifyComplete,
1923 RegisterDependencies);
1924
1925 #if LLVM_ENABLE_THREADS
1926 auto ResultFuture = PromisedResult.get_future();
1927 auto Result = ResultFuture.get();
1928
1929 if (ResolutionError)
1930 return std::move(ResolutionError);
1931
1932 return std::move(Result);
1933
1934 #else
1935 if (ResolutionError)
1936 return std::move(ResolutionError);
1937
1938 return Result;
1939 #endif
1940 }
1941
1942 Expected<JITEvaluatedSymbol>
lookup(const JITDylibSearchOrder & SearchOrder,SymbolStringPtr Name,SymbolState RequiredState)1943 ExecutionSession::lookup(const JITDylibSearchOrder &SearchOrder,
1944 SymbolStringPtr Name, SymbolState RequiredState) {
1945 SymbolLookupSet Names({Name});
1946
1947 if (auto ResultMap = lookup(SearchOrder, std::move(Names), LookupKind::Static,
1948 RequiredState, NoDependenciesToRegister)) {
1949 assert(ResultMap->size() == 1 && "Unexpected number of results");
1950 assert(ResultMap->count(Name) && "Missing result for symbol");
1951 return std::move(ResultMap->begin()->second);
1952 } else
1953 return ResultMap.takeError();
1954 }
1955
1956 Expected<JITEvaluatedSymbol>
lookup(ArrayRef<JITDylib * > SearchOrder,SymbolStringPtr Name,SymbolState RequiredState)1957 ExecutionSession::lookup(ArrayRef<JITDylib *> SearchOrder, SymbolStringPtr Name,
1958 SymbolState RequiredState) {
1959 return lookup(makeJITDylibSearchOrder(SearchOrder), Name, RequiredState);
1960 }
1961
1962 Expected<JITEvaluatedSymbol>
lookup(ArrayRef<JITDylib * > SearchOrder,StringRef Name,SymbolState RequiredState)1963 ExecutionSession::lookup(ArrayRef<JITDylib *> SearchOrder, StringRef Name,
1964 SymbolState RequiredState) {
1965 return lookup(SearchOrder, intern(Name), RequiredState);
1966 }
1967
dump(raw_ostream & OS)1968 void ExecutionSession::dump(raw_ostream &OS) {
1969 runSessionLocked([this, &OS]() {
1970 for (auto &JD : JDs)
1971 JD->dump(OS);
1972 });
1973 }
1974
dispatchOutstandingMUs()1975 void ExecutionSession::dispatchOutstandingMUs() {
1976 LLVM_DEBUG(dbgs() << "Dispatching MaterializationUnits...\n");
1977 while (1) {
1978 Optional<std::pair<std::unique_ptr<MaterializationUnit>,
1979 std::unique_ptr<MaterializationResponsibility>>>
1980 JMU;
1981
1982 {
1983 std::lock_guard<std::recursive_mutex> Lock(OutstandingMUsMutex);
1984 if (!OutstandingMUs.empty()) {
1985 JMU.emplace(std::move(OutstandingMUs.back()));
1986 OutstandingMUs.pop_back();
1987 }
1988 }
1989
1990 if (!JMU)
1991 break;
1992
1993 assert(JMU->first && "No MU?");
1994 LLVM_DEBUG(dbgs() << " Dispatching \"" << JMU->first->getName() << "\"\n");
1995 dispatchMaterialization(std::move(JMU->first), std::move(JMU->second));
1996 }
1997 LLVM_DEBUG(dbgs() << "Done dispatching MaterializationUnits.\n");
1998 }
1999
removeResourceTracker(ResourceTracker & RT)2000 Error ExecutionSession::removeResourceTracker(ResourceTracker &RT) {
2001 LLVM_DEBUG({
2002 dbgs() << "In " << RT.getJITDylib().getName() << " removing tracker "
2003 << formatv("{0:x}", RT.getKeyUnsafe()) << "\n";
2004 });
2005 std::vector<ResourceManager *> CurrentResourceManagers;
2006
2007 JITDylib::AsynchronousSymbolQuerySet QueriesToFail;
2008 std::shared_ptr<SymbolDependenceMap> FailedSymbols;
2009
2010 runSessionLocked([&] {
2011 CurrentResourceManagers = ResourceManagers;
2012 RT.makeDefunct();
2013 std::tie(QueriesToFail, FailedSymbols) = RT.getJITDylib().removeTracker(RT);
2014 });
2015
2016 Error Err = Error::success();
2017
2018 for (auto *L : reverse(CurrentResourceManagers))
2019 Err =
2020 joinErrors(std::move(Err), L->handleRemoveResources(RT.getKeyUnsafe()));
2021
2022 for (auto &Q : QueriesToFail)
2023 Q->handleFailed(make_error<FailedToMaterialize>(FailedSymbols));
2024
2025 return Err;
2026 }
2027
transferResourceTracker(ResourceTracker & DstRT,ResourceTracker & SrcRT)2028 void ExecutionSession::transferResourceTracker(ResourceTracker &DstRT,
2029 ResourceTracker &SrcRT) {
2030 LLVM_DEBUG({
2031 dbgs() << "In " << SrcRT.getJITDylib().getName()
2032 << " transfering resources from tracker "
2033 << formatv("{0:x}", SrcRT.getKeyUnsafe()) << " to tracker "
2034 << formatv("{0:x}", DstRT.getKeyUnsafe()) << "\n";
2035 });
2036
2037 // No-op transfers are allowed and do not invalidate the source.
2038 if (&DstRT == &SrcRT)
2039 return;
2040
2041 assert(&DstRT.getJITDylib() == &SrcRT.getJITDylib() &&
2042 "Can't transfer resources between JITDylibs");
2043 runSessionLocked([&]() {
2044 SrcRT.makeDefunct();
2045 auto &JD = DstRT.getJITDylib();
2046 JD.transferTracker(DstRT, SrcRT);
2047 for (auto *L : reverse(ResourceManagers))
2048 L->handleTransferResources(DstRT.getKeyUnsafe(), SrcRT.getKeyUnsafe());
2049 });
2050 }
2051
destroyResourceTracker(ResourceTracker & RT)2052 void ExecutionSession::destroyResourceTracker(ResourceTracker &RT) {
2053 runSessionLocked([&]() {
2054 LLVM_DEBUG({
2055 dbgs() << "In " << RT.getJITDylib().getName() << " destroying tracker "
2056 << formatv("{0:x}", RT.getKeyUnsafe()) << "\n";
2057 });
2058 if (!RT.isDefunct())
2059 transferResourceTracker(*RT.getJITDylib().getDefaultResourceTracker(),
2060 RT);
2061 });
2062 }
2063
IL_updateCandidatesFor(JITDylib & JD,JITDylibLookupFlags JDLookupFlags,SymbolLookupSet & Candidates,SymbolLookupSet * NonCandidates)2064 Error ExecutionSession::IL_updateCandidatesFor(
2065 JITDylib &JD, JITDylibLookupFlags JDLookupFlags,
2066 SymbolLookupSet &Candidates, SymbolLookupSet *NonCandidates) {
2067 return Candidates.forEachWithRemoval(
2068 [&](const SymbolStringPtr &Name,
2069 SymbolLookupFlags SymLookupFlags) -> Expected<bool> {
2070 /// Search for the symbol. If not found then continue without
2071 /// removal.
2072 auto SymI = JD.Symbols.find(Name);
2073 if (SymI == JD.Symbols.end())
2074 return false;
2075
2076 // If this is a non-exported symbol and we're matching exported
2077 // symbols only then remove this symbol from the candidates list.
2078 //
2079 // If we're tracking non-candidates then add this to the non-candidate
2080 // list.
2081 if (!SymI->second.getFlags().isExported() &&
2082 JDLookupFlags == JITDylibLookupFlags::MatchExportedSymbolsOnly) {
2083 if (NonCandidates)
2084 NonCandidates->add(Name, SymLookupFlags);
2085 return true;
2086 }
2087
2088 // If we match against a materialization-side-effects only symbol
2089 // then make sure it is weakly-referenced. Otherwise bail out with
2090 // an error.
2091 // FIXME: Use a "materialization-side-effects-only symbols must be
2092 // weakly referenced" specific error here to reduce confusion.
2093 if (SymI->second.getFlags().hasMaterializationSideEffectsOnly() &&
2094 SymLookupFlags != SymbolLookupFlags::WeaklyReferencedSymbol)
2095 return make_error<SymbolsNotFound>(SymbolNameVector({Name}));
2096
2097 // If we matched against this symbol but it is in the error state
2098 // then bail out and treat it as a failure to materialize.
2099 if (SymI->second.getFlags().hasError()) {
2100 auto FailedSymbolsMap = std::make_shared<SymbolDependenceMap>();
2101 (*FailedSymbolsMap)[&JD] = {Name};
2102 return make_error<FailedToMaterialize>(std::move(FailedSymbolsMap));
2103 }
2104
2105 // Otherwise this is a match. Remove it from the candidate set.
2106 return true;
2107 });
2108 }
2109
OL_applyQueryPhase1(std::unique_ptr<InProgressLookupState> IPLS,Error Err)2110 void ExecutionSession::OL_applyQueryPhase1(
2111 std::unique_ptr<InProgressLookupState> IPLS, Error Err) {
2112
2113 LLVM_DEBUG({
2114 dbgs() << "Entering OL_applyQueryPhase1:\n"
2115 << " Lookup kind: " << IPLS->K << "\n"
2116 << " Search order: " << IPLS->SearchOrder
2117 << ", Current index = " << IPLS->CurSearchOrderIndex
2118 << (IPLS->NewJITDylib ? " (entering new JITDylib)" : "") << "\n"
2119 << " Lookup set: " << IPLS->LookupSet << "\n"
2120 << " Definition generator candidates: "
2121 << IPLS->DefGeneratorCandidates << "\n"
2122 << " Definition generator non-candidates: "
2123 << IPLS->DefGeneratorNonCandidates << "\n";
2124 });
2125
2126 // FIXME: We should attach the query as we go: This provides a result in a
2127 // single pass in the common case where all symbols have already reached the
2128 // required state. The query could be detached again in the 'fail' method on
2129 // IPLS. Phase 2 would be reduced to collecting and dispatching the MUs.
2130
2131 while (IPLS->CurSearchOrderIndex != IPLS->SearchOrder.size()) {
2132
2133 // If we've been handed an error or received one back from a generator then
2134 // fail the query. We don't need to unlink: At this stage the query hasn't
2135 // actually been lodged.
2136 if (Err)
2137 return IPLS->fail(std::move(Err));
2138
2139 // Get the next JITDylib and lookup flags.
2140 auto &KV = IPLS->SearchOrder[IPLS->CurSearchOrderIndex];
2141 auto &JD = *KV.first;
2142 auto JDLookupFlags = KV.second;
2143
2144 LLVM_DEBUG({
2145 dbgs() << "Visiting \"" << JD.getName() << "\" (" << JDLookupFlags
2146 << ") with lookup set " << IPLS->LookupSet << ":\n";
2147 });
2148
2149 // If we've just reached a new JITDylib then perform some setup.
2150 if (IPLS->NewJITDylib) {
2151
2152 // Acquire the generator lock for this JITDylib.
2153 IPLS->GeneratorLock = std::unique_lock<std::mutex>(JD.GeneratorsMutex);
2154
2155 // Add any non-candidates from the last JITDylib (if any) back on to the
2156 // list of definition candidates for this JITDylib, reset definition
2157 // non-candiates to the empty set.
2158 SymbolLookupSet Tmp;
2159 std::swap(IPLS->DefGeneratorNonCandidates, Tmp);
2160 IPLS->DefGeneratorCandidates.append(std::move(Tmp));
2161
2162 LLVM_DEBUG({
2163 dbgs() << " First time visiting " << JD.getName()
2164 << ", resetting candidate sets and building generator stack\n";
2165 });
2166
2167 // Build the definition generator stack for this JITDylib.
2168 for (auto &DG : reverse(JD.DefGenerators))
2169 IPLS->CurDefGeneratorStack.push_back(DG);
2170
2171 // Flag that we've done our initialization.
2172 IPLS->NewJITDylib = false;
2173 }
2174
2175 // Remove any generation candidates that are already defined (and match) in
2176 // this JITDylib.
2177 runSessionLocked([&] {
2178 // Update the list of candidates (and non-candidates) for definition
2179 // generation.
2180 LLVM_DEBUG(dbgs() << " Updating candidate set...\n");
2181 Err = IL_updateCandidatesFor(
2182 JD, JDLookupFlags, IPLS->DefGeneratorCandidates,
2183 JD.DefGenerators.empty() ? nullptr
2184 : &IPLS->DefGeneratorNonCandidates);
2185 LLVM_DEBUG({
2186 dbgs() << " Remaining candidates = " << IPLS->DefGeneratorCandidates
2187 << "\n";
2188 });
2189 });
2190
2191 // If we encountered an error while filtering generation candidates then
2192 // bail out.
2193 if (Err)
2194 return IPLS->fail(std::move(Err));
2195
2196 /// Apply any definition generators on the stack.
2197 LLVM_DEBUG({
2198 if (IPLS->CurDefGeneratorStack.empty())
2199 LLVM_DEBUG(dbgs() << " No generators to run for this JITDylib.\n");
2200 else if (IPLS->DefGeneratorCandidates.empty())
2201 LLVM_DEBUG(dbgs() << " No candidates to generate.\n");
2202 else
2203 dbgs() << " Running " << IPLS->CurDefGeneratorStack.size()
2204 << " remaining generators for "
2205 << IPLS->DefGeneratorCandidates.size() << " candidates\n";
2206 });
2207 while (!IPLS->CurDefGeneratorStack.empty() &&
2208 !IPLS->DefGeneratorCandidates.empty()) {
2209 auto DG = IPLS->CurDefGeneratorStack.back().lock();
2210 IPLS->CurDefGeneratorStack.pop_back();
2211
2212 if (!DG)
2213 return IPLS->fail(make_error<StringError>(
2214 "DefinitionGenerator removed while lookup in progress",
2215 inconvertibleErrorCode()));
2216
2217 auto K = IPLS->K;
2218 auto &LookupSet = IPLS->DefGeneratorCandidates;
2219
2220 // Run the generator. If the generator takes ownership of QA then this
2221 // will break the loop.
2222 {
2223 LLVM_DEBUG(dbgs() << " Attempting to generate " << LookupSet << "\n");
2224 LookupState LS(std::move(IPLS));
2225 Err = DG->tryToGenerate(LS, K, JD, JDLookupFlags, LookupSet);
2226 IPLS = std::move(LS.IPLS);
2227 }
2228
2229 // If there was an error then fail the query.
2230 if (Err) {
2231 LLVM_DEBUG({
2232 dbgs() << " Error attempting to generate " << LookupSet << "\n";
2233 });
2234 assert(IPLS && "LS cannot be retained if error is returned");
2235 return IPLS->fail(std::move(Err));
2236 }
2237
2238 // Otherwise if QA was captured then break the loop.
2239 if (!IPLS) {
2240 LLVM_DEBUG(
2241 { dbgs() << " LookupState captured. Exiting phase1 for now.\n"; });
2242 return;
2243 }
2244
2245 // Otherwise if we're continuing around the loop then update candidates
2246 // for the next round.
2247 runSessionLocked([&] {
2248 LLVM_DEBUG(dbgs() << " Updating candidate set post-generation\n");
2249 Err = IL_updateCandidatesFor(
2250 JD, JDLookupFlags, IPLS->DefGeneratorCandidates,
2251 JD.DefGenerators.empty() ? nullptr
2252 : &IPLS->DefGeneratorNonCandidates);
2253 });
2254
2255 // If updating candidates failed then fail the query.
2256 if (Err) {
2257 LLVM_DEBUG(dbgs() << " Error encountered while updating candidates\n");
2258 return IPLS->fail(std::move(Err));
2259 }
2260 }
2261
2262 // If we get here then we've moved on to the next JITDylib.
2263 LLVM_DEBUG(dbgs() << "Phase 1 moving to next JITDylib.\n");
2264 ++IPLS->CurSearchOrderIndex;
2265 IPLS->NewJITDylib = true;
2266 }
2267
2268 // Remove any weakly referenced candidates that could not be found/generated.
2269 IPLS->DefGeneratorCandidates.remove_if(
2270 [](const SymbolStringPtr &Name, SymbolLookupFlags SymLookupFlags) {
2271 return SymLookupFlags == SymbolLookupFlags::WeaklyReferencedSymbol;
2272 });
2273
2274 // If we get here then we've finished searching all JITDylibs.
2275 // If we matched all symbols then move to phase 2, otherwise fail the query
2276 // with a SymbolsNotFound error.
2277 if (IPLS->DefGeneratorCandidates.empty()) {
2278 LLVM_DEBUG(dbgs() << "Phase 1 succeeded.\n");
2279 IPLS->complete(std::move(IPLS));
2280 } else {
2281 LLVM_DEBUG(dbgs() << "Phase 1 failed with unresolved symbols.\n");
2282 IPLS->fail(make_error<SymbolsNotFound>(
2283 IPLS->DefGeneratorCandidates.getSymbolNames()));
2284 }
2285 }
2286
OL_completeLookup(std::unique_ptr<InProgressLookupState> IPLS,std::shared_ptr<AsynchronousSymbolQuery> Q,RegisterDependenciesFunction RegisterDependencies)2287 void ExecutionSession::OL_completeLookup(
2288 std::unique_ptr<InProgressLookupState> IPLS,
2289 std::shared_ptr<AsynchronousSymbolQuery> Q,
2290 RegisterDependenciesFunction RegisterDependencies) {
2291
2292 LLVM_DEBUG({
2293 dbgs() << "Entering OL_completeLookup:\n"
2294 << " Lookup kind: " << IPLS->K << "\n"
2295 << " Search order: " << IPLS->SearchOrder
2296 << ", Current index = " << IPLS->CurSearchOrderIndex
2297 << (IPLS->NewJITDylib ? " (entering new JITDylib)" : "") << "\n"
2298 << " Lookup set: " << IPLS->LookupSet << "\n"
2299 << " Definition generator candidates: "
2300 << IPLS->DefGeneratorCandidates << "\n"
2301 << " Definition generator non-candidates: "
2302 << IPLS->DefGeneratorNonCandidates << "\n";
2303 });
2304
2305 bool QueryComplete = false;
2306 DenseMap<JITDylib *, JITDylib::UnmaterializedInfosList> CollectedUMIs;
2307
2308 auto LodgingErr = runSessionLocked([&]() -> Error {
2309 for (auto &KV : IPLS->SearchOrder) {
2310 auto &JD = *KV.first;
2311 auto JDLookupFlags = KV.second;
2312 LLVM_DEBUG({
2313 dbgs() << "Visiting \"" << JD.getName() << "\" (" << JDLookupFlags
2314 << ") with lookup set " << IPLS->LookupSet << ":\n";
2315 });
2316
2317 auto Err = IPLS->LookupSet.forEachWithRemoval(
2318 [&](const SymbolStringPtr &Name,
2319 SymbolLookupFlags SymLookupFlags) -> Expected<bool> {
2320 LLVM_DEBUG({
2321 dbgs() << " Attempting to match \"" << Name << "\" ("
2322 << SymLookupFlags << ")... ";
2323 });
2324
2325 /// Search for the symbol. If not found then continue without
2326 /// removal.
2327 auto SymI = JD.Symbols.find(Name);
2328 if (SymI == JD.Symbols.end()) {
2329 LLVM_DEBUG(dbgs() << "skipping: not present\n");
2330 return false;
2331 }
2332
2333 // If this is a non-exported symbol and we're matching exported
2334 // symbols only then skip this symbol without removal.
2335 if (!SymI->second.getFlags().isExported() &&
2336 JDLookupFlags ==
2337 JITDylibLookupFlags::MatchExportedSymbolsOnly) {
2338 LLVM_DEBUG(dbgs() << "skipping: not exported\n");
2339 return false;
2340 }
2341
2342 // If we match against a materialization-side-effects only symbol
2343 // then make sure it is weakly-referenced. Otherwise bail out with
2344 // an error.
2345 // FIXME: Use a "materialization-side-effects-only symbols must be
2346 // weakly referenced" specific error here to reduce confusion.
2347 if (SymI->second.getFlags().hasMaterializationSideEffectsOnly() &&
2348 SymLookupFlags != SymbolLookupFlags::WeaklyReferencedSymbol) {
2349 LLVM_DEBUG({
2350 dbgs() << "error: "
2351 "required, but symbol is has-side-effects-only\n";
2352 });
2353 return make_error<SymbolsNotFound>(SymbolNameVector({Name}));
2354 }
2355
2356 // If we matched against this symbol but it is in the error state
2357 // then bail out and treat it as a failure to materialize.
2358 if (SymI->second.getFlags().hasError()) {
2359 LLVM_DEBUG(dbgs() << "error: symbol is in error state\n");
2360 auto FailedSymbolsMap = std::make_shared<SymbolDependenceMap>();
2361 (*FailedSymbolsMap)[&JD] = {Name};
2362 return make_error<FailedToMaterialize>(
2363 std::move(FailedSymbolsMap));
2364 }
2365
2366 // Otherwise this is a match.
2367
2368 // If this symbol is already in the requried state then notify the
2369 // query, remove the symbol and continue.
2370 if (SymI->second.getState() >= Q->getRequiredState()) {
2371 LLVM_DEBUG(dbgs()
2372 << "matched, symbol already in required state\n");
2373 Q->notifySymbolMetRequiredState(Name, SymI->second.getSymbol());
2374 return true;
2375 }
2376
2377 // Otherwise this symbol does not yet meet the required state. Check
2378 // whether it has a materializer attached, and if so prepare to run
2379 // it.
2380 if (SymI->second.hasMaterializerAttached()) {
2381 assert(SymI->second.getAddress() == 0 &&
2382 "Symbol not resolved but already has address?");
2383 auto UMII = JD.UnmaterializedInfos.find(Name);
2384 assert(UMII != JD.UnmaterializedInfos.end() &&
2385 "Lazy symbol should have UnmaterializedInfo");
2386
2387 auto UMI = UMII->second;
2388 assert(UMI->MU && "Materializer should not be null");
2389 assert(UMI->RT && "Tracker should not be null");
2390 LLVM_DEBUG({
2391 dbgs() << "matched, preparing to dispatch MU@" << UMI->MU.get()
2392 << " (" << UMI->MU->getName() << ")\n";
2393 });
2394
2395 // Move all symbols associated with this MaterializationUnit into
2396 // materializing state.
2397 for (auto &KV : UMI->MU->getSymbols()) {
2398 auto SymK = JD.Symbols.find(KV.first);
2399 assert(SymK != JD.Symbols.end() &&
2400 "No entry for symbol covered by MaterializationUnit");
2401 SymK->second.setMaterializerAttached(false);
2402 SymK->second.setState(SymbolState::Materializing);
2403 JD.UnmaterializedInfos.erase(KV.first);
2404 }
2405
2406 // Add MU to the list of MaterializationUnits to be materialized.
2407 CollectedUMIs[&JD].push_back(std::move(UMI));
2408 } else
2409 LLVM_DEBUG(dbgs() << "matched, registering query");
2410
2411 // Add the query to the PendingQueries list and continue, deleting
2412 // the element from the lookup set.
2413 assert(SymI->second.getState() != SymbolState::NeverSearched &&
2414 SymI->second.getState() != SymbolState::Ready &&
2415 "By this line the symbol should be materializing");
2416 auto &MI = JD.MaterializingInfos[Name];
2417 MI.addQuery(Q);
2418 Q->addQueryDependence(JD, Name);
2419
2420 return true;
2421 });
2422
2423 // Handle failure.
2424 if (Err) {
2425
2426 LLVM_DEBUG({
2427 dbgs() << "Lookup failed. Detaching query and replacing MUs.\n";
2428 });
2429
2430 // Detach the query.
2431 Q->detach();
2432
2433 // Replace the MUs.
2434 for (auto &KV : CollectedUMIs) {
2435 auto &JD = *KV.first;
2436 for (auto &UMI : KV.second)
2437 for (auto &KV2 : UMI->MU->getSymbols()) {
2438 assert(!JD.UnmaterializedInfos.count(KV2.first) &&
2439 "Unexpected materializer in map");
2440 auto SymI = JD.Symbols.find(KV2.first);
2441 assert(SymI != JD.Symbols.end() && "Missing symbol entry");
2442 assert(SymI->second.getState() == SymbolState::Materializing &&
2443 "Can not replace symbol that is not materializing");
2444 assert(!SymI->second.hasMaterializerAttached() &&
2445 "MaterializerAttached flag should not be set");
2446 SymI->second.setMaterializerAttached(true);
2447 JD.UnmaterializedInfos[KV2.first] = UMI;
2448 }
2449 }
2450
2451 return Err;
2452 }
2453 }
2454
2455 LLVM_DEBUG(dbgs() << "Stripping unmatched weakly-refererced symbols\n");
2456 IPLS->LookupSet.forEachWithRemoval(
2457 [&](const SymbolStringPtr &Name, SymbolLookupFlags SymLookupFlags) {
2458 if (SymLookupFlags == SymbolLookupFlags::WeaklyReferencedSymbol) {
2459 Q->dropSymbol(Name);
2460 return true;
2461 } else
2462 return false;
2463 });
2464
2465 if (!IPLS->LookupSet.empty()) {
2466 LLVM_DEBUG(dbgs() << "Failing due to unresolved symbols\n");
2467 return make_error<SymbolsNotFound>(IPLS->LookupSet.getSymbolNames());
2468 }
2469
2470 // Record whether the query completed.
2471 QueryComplete = Q->isComplete();
2472
2473 LLVM_DEBUG({
2474 dbgs() << "Query successfully "
2475 << (QueryComplete ? "completed" : "lodged") << "\n";
2476 });
2477
2478 // Move the collected MUs to the OutstandingMUs list.
2479 if (!CollectedUMIs.empty()) {
2480 std::lock_guard<std::recursive_mutex> Lock(OutstandingMUsMutex);
2481
2482 LLVM_DEBUG(dbgs() << "Adding MUs to dispatch:\n");
2483 for (auto &KV : CollectedUMIs) {
2484 auto &JD = *KV.first;
2485 LLVM_DEBUG({
2486 dbgs() << " For " << JD.getName() << ": Adding " << KV.second.size()
2487 << " MUs.\n";
2488 });
2489 for (auto &UMI : KV.second) {
2490 std::unique_ptr<MaterializationResponsibility> MR(
2491 new MaterializationResponsibility(
2492 &JD, std::move(UMI->MU->SymbolFlags),
2493 std::move(UMI->MU->InitSymbol)));
2494 JD.MRTrackers[MR.get()] = UMI->RT;
2495 OutstandingMUs.push_back(
2496 std::make_pair(std::move(UMI->MU), std::move(MR)));
2497 }
2498 }
2499 } else
2500 LLVM_DEBUG(dbgs() << "No MUs to dispatch.\n");
2501
2502 if (RegisterDependencies && !Q->QueryRegistrations.empty()) {
2503 LLVM_DEBUG(dbgs() << "Registering dependencies\n");
2504 RegisterDependencies(Q->QueryRegistrations);
2505 } else
2506 LLVM_DEBUG(dbgs() << "No dependencies to register\n");
2507
2508 return Error::success();
2509 });
2510
2511 if (LodgingErr) {
2512 LLVM_DEBUG(dbgs() << "Failing query\n");
2513 Q->detach();
2514 Q->handleFailed(std::move(LodgingErr));
2515 return;
2516 }
2517
2518 if (QueryComplete) {
2519 LLVM_DEBUG(dbgs() << "Completing query\n");
2520 Q->handleComplete();
2521 }
2522
2523 dispatchOutstandingMUs();
2524 }
2525
OL_completeLookupFlags(std::unique_ptr<InProgressLookupState> IPLS,unique_function<void (Expected<SymbolFlagsMap>)> OnComplete)2526 void ExecutionSession::OL_completeLookupFlags(
2527 std::unique_ptr<InProgressLookupState> IPLS,
2528 unique_function<void(Expected<SymbolFlagsMap>)> OnComplete) {
2529
2530 auto Result = runSessionLocked([&]() -> Expected<SymbolFlagsMap> {
2531 LLVM_DEBUG({
2532 dbgs() << "Entering OL_completeLookupFlags:\n"
2533 << " Lookup kind: " << IPLS->K << "\n"
2534 << " Search order: " << IPLS->SearchOrder
2535 << ", Current index = " << IPLS->CurSearchOrderIndex
2536 << (IPLS->NewJITDylib ? " (entering new JITDylib)" : "") << "\n"
2537 << " Lookup set: " << IPLS->LookupSet << "\n"
2538 << " Definition generator candidates: "
2539 << IPLS->DefGeneratorCandidates << "\n"
2540 << " Definition generator non-candidates: "
2541 << IPLS->DefGeneratorNonCandidates << "\n";
2542 });
2543
2544 SymbolFlagsMap Result;
2545
2546 // Attempt to find flags for each symbol.
2547 for (auto &KV : IPLS->SearchOrder) {
2548 auto &JD = *KV.first;
2549 auto JDLookupFlags = KV.second;
2550 LLVM_DEBUG({
2551 dbgs() << "Visiting \"" << JD.getName() << "\" (" << JDLookupFlags
2552 << ") with lookup set " << IPLS->LookupSet << ":\n";
2553 });
2554
2555 IPLS->LookupSet.forEachWithRemoval([&](const SymbolStringPtr &Name,
2556 SymbolLookupFlags SymLookupFlags) {
2557 LLVM_DEBUG({
2558 dbgs() << " Attempting to match \"" << Name << "\" ("
2559 << SymLookupFlags << ")... ";
2560 });
2561
2562 // Search for the symbol. If not found then continue without removing
2563 // from the lookup set.
2564 auto SymI = JD.Symbols.find(Name);
2565 if (SymI == JD.Symbols.end()) {
2566 LLVM_DEBUG(dbgs() << "skipping: not present\n");
2567 return false;
2568 }
2569
2570 // If this is a non-exported symbol then it doesn't match. Skip it.
2571 if (!SymI->second.getFlags().isExported() &&
2572 JDLookupFlags == JITDylibLookupFlags::MatchExportedSymbolsOnly) {
2573 LLVM_DEBUG(dbgs() << "skipping: not exported\n");
2574 return false;
2575 }
2576
2577 LLVM_DEBUG({
2578 dbgs() << "matched, \"" << Name << "\" -> " << SymI->second.getFlags()
2579 << "\n";
2580 });
2581 Result[Name] = SymI->second.getFlags();
2582 return true;
2583 });
2584 }
2585
2586 // Remove any weakly referenced symbols that haven't been resolved.
2587 IPLS->LookupSet.remove_if(
2588 [](const SymbolStringPtr &Name, SymbolLookupFlags SymLookupFlags) {
2589 return SymLookupFlags == SymbolLookupFlags::WeaklyReferencedSymbol;
2590 });
2591
2592 if (!IPLS->LookupSet.empty()) {
2593 LLVM_DEBUG(dbgs() << "Failing due to unresolved symbols\n");
2594 return make_error<SymbolsNotFound>(IPLS->LookupSet.getSymbolNames());
2595 }
2596
2597 LLVM_DEBUG(dbgs() << "Succeded, result = " << Result << "\n");
2598 return Result;
2599 });
2600
2601 // Run the callback on the result.
2602 LLVM_DEBUG(dbgs() << "Sending result to handler.\n");
2603 OnComplete(std::move(Result));
2604 }
2605
OL_destroyMaterializationResponsibility(MaterializationResponsibility & MR)2606 void ExecutionSession::OL_destroyMaterializationResponsibility(
2607 MaterializationResponsibility &MR) {
2608
2609 assert(MR.SymbolFlags.empty() &&
2610 "All symbols should have been explicitly materialized or failed");
2611 MR.JD->unlinkMaterializationResponsibility(MR);
2612 }
2613
OL_getRequestedSymbols(const MaterializationResponsibility & MR)2614 SymbolNameSet ExecutionSession::OL_getRequestedSymbols(
2615 const MaterializationResponsibility &MR) {
2616 return MR.JD->getRequestedSymbols(MR.SymbolFlags);
2617 }
2618
OL_notifyResolved(MaterializationResponsibility & MR,const SymbolMap & Symbols)2619 Error ExecutionSession::OL_notifyResolved(MaterializationResponsibility &MR,
2620 const SymbolMap &Symbols) {
2621 LLVM_DEBUG({
2622 dbgs() << "In " << MR.JD->getName() << " resolving " << Symbols << "\n";
2623 });
2624 #ifndef NDEBUG
2625 for (auto &KV : Symbols) {
2626 auto WeakFlags = JITSymbolFlags::Weak | JITSymbolFlags::Common;
2627 auto I = MR.SymbolFlags.find(KV.first);
2628 assert(I != MR.SymbolFlags.end() &&
2629 "Resolving symbol outside this responsibility set");
2630 assert(!I->second.hasMaterializationSideEffectsOnly() &&
2631 "Can't resolve materialization-side-effects-only symbol");
2632 assert((KV.second.getFlags() & ~WeakFlags) == (I->second & ~WeakFlags) &&
2633 "Resolving symbol with incorrect flags");
2634 }
2635 #endif
2636
2637 return MR.JD->resolve(MR, Symbols);
2638 }
2639
OL_notifyEmitted(MaterializationResponsibility & MR)2640 Error ExecutionSession::OL_notifyEmitted(MaterializationResponsibility &MR) {
2641 LLVM_DEBUG({
2642 dbgs() << "In " << MR.JD->getName() << " emitting " << MR.SymbolFlags << "\n";
2643 });
2644
2645 if (auto Err = MR.JD->emit(MR, MR.SymbolFlags))
2646 return Err;
2647
2648 MR.SymbolFlags.clear();
2649 return Error::success();
2650 }
2651
OL_defineMaterializing(MaterializationResponsibility & MR,SymbolFlagsMap NewSymbolFlags)2652 Error ExecutionSession::OL_defineMaterializing(
2653 MaterializationResponsibility &MR, SymbolFlagsMap NewSymbolFlags) {
2654
2655 LLVM_DEBUG({
2656 dbgs() << "In " << MR.JD->getName() << " defining materializing symbols "
2657 << NewSymbolFlags << "\n";
2658 });
2659 if (auto AcceptedDefs = MR.JD->defineMaterializing(std::move(NewSymbolFlags))) {
2660 // Add all newly accepted symbols to this responsibility object.
2661 for (auto &KV : *AcceptedDefs)
2662 MR.SymbolFlags.insert(KV);
2663 return Error::success();
2664 } else
2665 return AcceptedDefs.takeError();
2666 }
2667
OL_notifyFailed(MaterializationResponsibility & MR)2668 void ExecutionSession::OL_notifyFailed(MaterializationResponsibility &MR) {
2669
2670 LLVM_DEBUG({
2671 dbgs() << "In " << MR.JD->getName() << " failing materialization for "
2672 << MR.SymbolFlags << "\n";
2673 });
2674
2675 JITDylib::FailedSymbolsWorklist Worklist;
2676
2677 for (auto &KV : MR.SymbolFlags)
2678 Worklist.push_back(std::make_pair(MR.JD.get(), KV.first));
2679 MR.SymbolFlags.clear();
2680
2681 if (Worklist.empty())
2682 return;
2683
2684 JITDylib::AsynchronousSymbolQuerySet FailedQueries;
2685 std::shared_ptr<SymbolDependenceMap> FailedSymbols;
2686
2687 runSessionLocked([&]() {
2688 auto RTI = MR.JD->MRTrackers.find(&MR);
2689 assert(RTI != MR.JD->MRTrackers.end() && "No tracker for this");
2690 if (RTI->second->isDefunct())
2691 return;
2692
2693 std::tie(FailedQueries, FailedSymbols) =
2694 JITDylib::failSymbols(std::move(Worklist));
2695 });
2696
2697 for (auto &Q : FailedQueries)
2698 Q->handleFailed(make_error<FailedToMaterialize>(FailedSymbols));
2699 }
2700
OL_replace(MaterializationResponsibility & MR,std::unique_ptr<MaterializationUnit> MU)2701 Error ExecutionSession::OL_replace(MaterializationResponsibility &MR,
2702 std::unique_ptr<MaterializationUnit> MU) {
2703 for (auto &KV : MU->getSymbols()) {
2704 assert(MR.SymbolFlags.count(KV.first) &&
2705 "Replacing definition outside this responsibility set");
2706 MR.SymbolFlags.erase(KV.first);
2707 }
2708
2709 if (MU->getInitializerSymbol() == MR.InitSymbol)
2710 MR.InitSymbol = nullptr;
2711
2712 LLVM_DEBUG(MR.JD->getExecutionSession().runSessionLocked([&]() {
2713 dbgs() << "In " << MR.JD->getName() << " replacing symbols with " << *MU
2714 << "\n";
2715 }););
2716
2717 return MR.JD->replace(MR, std::move(MU));
2718 }
2719
2720 Expected<std::unique_ptr<MaterializationResponsibility>>
OL_delegate(MaterializationResponsibility & MR,const SymbolNameSet & Symbols)2721 ExecutionSession::OL_delegate(MaterializationResponsibility &MR,
2722 const SymbolNameSet &Symbols) {
2723
2724 SymbolStringPtr DelegatedInitSymbol;
2725 SymbolFlagsMap DelegatedFlags;
2726
2727 for (auto &Name : Symbols) {
2728 auto I = MR.SymbolFlags.find(Name);
2729 assert(I != MR.SymbolFlags.end() &&
2730 "Symbol is not tracked by this MaterializationResponsibility "
2731 "instance");
2732
2733 DelegatedFlags[Name] = std::move(I->second);
2734 if (Name == MR.InitSymbol)
2735 std::swap(MR.InitSymbol, DelegatedInitSymbol);
2736
2737 MR.SymbolFlags.erase(I);
2738 }
2739
2740 return MR.JD->delegate(MR, std::move(DelegatedFlags),
2741 std::move(DelegatedInitSymbol));
2742 }
2743
OL_addDependencies(MaterializationResponsibility & MR,const SymbolStringPtr & Name,const SymbolDependenceMap & Dependencies)2744 void ExecutionSession::OL_addDependencies(
2745 MaterializationResponsibility &MR, const SymbolStringPtr &Name,
2746 const SymbolDependenceMap &Dependencies) {
2747 LLVM_DEBUG({
2748 dbgs() << "Adding dependencies for " << Name << ": " << Dependencies
2749 << "\n";
2750 });
2751 assert(MR.SymbolFlags.count(Name) &&
2752 "Symbol not covered by this MaterializationResponsibility instance");
2753 MR.JD->addDependencies(Name, Dependencies);
2754 }
2755
OL_addDependenciesForAll(MaterializationResponsibility & MR,const SymbolDependenceMap & Dependencies)2756 void ExecutionSession::OL_addDependenciesForAll(
2757 MaterializationResponsibility &MR,
2758 const SymbolDependenceMap &Dependencies) {
2759 LLVM_DEBUG({
2760 dbgs() << "Adding dependencies for all symbols in " << MR.SymbolFlags << ": "
2761 << Dependencies << "\n";
2762 });
2763 for (auto &KV : MR.SymbolFlags)
2764 MR.JD->addDependencies(KV.first, Dependencies);
2765 }
2766
2767 #ifndef NDEBUG
dumpDispatchInfo(JITDylib & JD,MaterializationUnit & MU)2768 void ExecutionSession::dumpDispatchInfo(JITDylib &JD, MaterializationUnit &MU) {
2769 runSessionLocked([&]() {
2770 dbgs() << "Dispatching " << MU << " for " << JD.getName() << "\n";
2771 });
2772 }
2773 #endif // NDEBUG
2774
2775 } // End namespace orc.
2776 } // End namespace llvm.
2777