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