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