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