Line data Source code
1 : //===--- Core.cpp - Core ORC APIs (MaterializationUnit, JITDylib, etc.) ---===//
2 : //
3 : // The LLVM Compiler Infrastructure
4 : //
5 : // This file is distributed under the University of Illinois Open Source
6 : // License. See LICENSE.TXT for details.
7 : //
8 : //===----------------------------------------------------------------------===//
9 :
10 : #include "llvm/ExecutionEngine/Orc/Core.h"
11 : #include "llvm/Config/llvm-config.h"
12 : #include "llvm/ExecutionEngine/Orc/OrcError.h"
13 : #include "llvm/IR/Mangler.h"
14 : #include "llvm/Support/CommandLine.h"
15 : #include "llvm/Support/Debug.h"
16 : #include "llvm/Support/Format.h"
17 :
18 : #if LLVM_ENABLE_THREADS
19 : #include <future>
20 : #endif
21 :
22 : #define DEBUG_TYPE "orc"
23 :
24 : using namespace llvm;
25 :
26 : namespace {
27 :
28 : #ifndef NDEBUG
29 :
30 : cl::opt<bool> PrintHidden("debug-orc-print-hidden", cl::init(false),
31 : cl::desc("debug print hidden symbols defined by "
32 : "materialization units"),
33 : cl::Hidden);
34 :
35 : cl::opt<bool> PrintCallable("debug-orc-print-callable", cl::init(false),
36 : cl::desc("debug print callable symbols defined by "
37 : "materialization units"),
38 : cl::Hidden);
39 :
40 : cl::opt<bool> PrintData("debug-orc-print-data", cl::init(false),
41 : cl::desc("debug print data symbols defined by "
42 : "materialization units"),
43 : cl::Hidden);
44 :
45 : #endif // NDEBUG
46 :
47 : // SetPrinter predicate that prints every element.
48 : template <typename T> struct PrintAll {
49 0 : bool operator()(const T &E) { return true; }
50 : };
51 :
52 : bool anyPrintSymbolOptionSet() {
53 : #ifndef NDEBUG
54 : return PrintHidden || PrintCallable || PrintData;
55 : #else
56 : return false;
57 : #endif // NDEBUG
58 : }
59 :
60 0 : bool flagsMatchCLOpts(const JITSymbolFlags &Flags) {
61 : #ifndef NDEBUG
62 : // Bail out early if this is a hidden symbol and we're not printing hiddens.
63 : if (!PrintHidden && !Flags.isExported())
64 : return false;
65 :
66 : // Return true if this is callable and we're printing callables.
67 : if (PrintCallable && Flags.isCallable())
68 : return true;
69 :
70 : // Return true if this is data and we're printing data.
71 : if (PrintData && !Flags.isCallable())
72 : return true;
73 :
74 : // otherwise return false.
75 : return false;
76 : #else
77 0 : return false;
78 : #endif // NDEBUG
79 : }
80 :
81 : // Prints a set of items, filtered by an user-supplied predicate.
82 : template <typename Set, typename Pred = PrintAll<typename Set::value_type>>
83 : class SetPrinter {
84 : public:
85 0 : SetPrinter(const Set &S, Pred ShouldPrint = Pred())
86 0 : : S(S), ShouldPrint(std::move(ShouldPrint)) {}
87 0 :
88 0 : void printTo(llvm::raw_ostream &OS) const {
89 0 : bool PrintComma = false;
90 0 : OS << "{";
91 0 : for (auto &E : S) {
92 0 : if (ShouldPrint(E)) {
93 0 : if (PrintComma)
94 0 : OS << ',';
95 : OS << ' ' << E;
96 0 : PrintComma = true;
97 : }
98 0 : }
99 0 : OS << " }";
100 : }
101 0 :
102 : private:
103 0 : const Set &S;
104 : mutable Pred ShouldPrint;
105 : };
106 :
107 0 : template <typename Set, typename Pred>
108 0 : SetPrinter<Set, Pred> printSet(const Set &S, Pred P = Pred()) {
109 0 : return SetPrinter<Set, Pred>(S, std::move(P));
110 : }
111 0 :
112 0 : // Render a SetPrinter by delegating to its printTo method.
113 : template <typename Set, typename Pred>
114 0 : llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
115 : const SetPrinter<Set, Pred> &Printer) {
116 0 : Printer.printTo(OS);
117 : return OS;
118 : }
119 :
120 0 : struct PrintSymbolFlagsMapElemsMatchingCLOpts {
121 0 : bool operator()(const orc::SymbolFlagsMap::value_type &KV) {
122 0 : return flagsMatchCLOpts(KV.second);
123 : }
124 0 : };
125 0 :
126 : struct PrintSymbolMapElemsMatchingCLOpts {
127 : bool operator()(const orc::SymbolMap::value_type &KV) {
128 : return flagsMatchCLOpts(KV.second.getFlags());
129 : }
130 : };
131 :
132 : } // end anonymous namespace
133 0 :
134 0 : namespace llvm {
135 0 : namespace orc {
136 :
137 0 : SymbolStringPool::PoolMapEntry SymbolStringPtr::Tombstone(0);
138 0 :
139 : char FailedToMaterialize::ID = 0;
140 : char SymbolsNotFound::ID = 0;
141 : char SymbolsCouldNotBeRemoved::ID = 0;
142 :
143 : RegisterDependenciesFunction NoDependenciesToRegister =
144 : RegisterDependenciesFunction();
145 :
146 0 : void MaterializationUnit::anchor() {}
147 0 :
148 0 : raw_ostream &operator<<(raw_ostream &OS, const SymbolStringPtr &Sym) {
149 : return OS << *Sym;
150 0 : }
151 0 :
152 : raw_ostream &operator<<(raw_ostream &OS, const SymbolNameSet &Symbols) {
153 0 : return OS << printSet(Symbols, PrintAll<SymbolStringPtr>());
154 : }
155 0 :
156 : raw_ostream &operator<<(raw_ostream &OS, const JITSymbolFlags &Flags) {
157 : if (Flags.isCallable())
158 : OS << "[Callable]";
159 0 : else
160 0 : OS << "[Data]";
161 : if (Flags.isWeak())
162 : OS << "[Weak]";
163 : else if (Flags.isCommon())
164 : OS << "[Common]";
165 :
166 : if (!Flags.isExported())
167 : OS << "[Hidden]";
168 0 :
169 0 : return OS;
170 : }
171 0 :
172 0 : raw_ostream &operator<<(raw_ostream &OS, const JITEvaluatedSymbol &Sym) {
173 : return OS << format("0x%016x", Sym.getAddress()) << " " << Sym.getFlags();
174 0 : }
175 0 :
176 : raw_ostream &operator<<(raw_ostream &OS, const SymbolFlagsMap::value_type &KV) {
177 0 : return OS << "(\"" << KV.first << "\", " << KV.second << ")";
178 0 : }
179 :
180 0 : raw_ostream &operator<<(raw_ostream &OS, const SymbolMap::value_type &KV) {
181 0 : return OS << "(\"" << KV.first << "\": " << KV.second << ")";
182 : }
183 :
184 : raw_ostream &operator<<(raw_ostream &OS, const SymbolFlagsMap &SymbolFlags) {
185 : return OS << printSet(SymbolFlags, PrintSymbolFlagsMapElemsMatchingCLOpts());
186 : }
187 :
188 0 : raw_ostream &operator<<(raw_ostream &OS, const SymbolMap &Symbols) {
189 : return OS << printSet(Symbols, PrintSymbolMapElemsMatchingCLOpts());
190 : }
191 :
192 : raw_ostream &operator<<(raw_ostream &OS,
193 0 : const SymbolDependenceMap::value_type &KV) {
194 0 : return OS << "(" << KV.first << ", " << KV.second << ")";
195 : }
196 :
197 : raw_ostream &operator<<(raw_ostream &OS, const SymbolDependenceMap &Deps) {
198 : return OS << printSet(Deps, PrintAll<SymbolDependenceMap::value_type>());
199 0 : }
200 0 :
201 : raw_ostream &operator<<(raw_ostream &OS, const MaterializationUnit &MU) {
202 : OS << "MU@" << &MU << " (\"" << MU.getName() << "\"";
203 : if (anyPrintSymbolOptionSet())
204 : OS << ", " << MU.getSymbols();
205 : return OS << ")";
206 : }
207 :
208 : raw_ostream &operator<<(raw_ostream &OS, const JITDylibList &JDs) {
209 : OS << "[";
210 : if (!JDs.empty()) {
211 : assert(JDs.front() && "JITDylibList entries must not be null");
212 : OS << " " << JDs.front()->getName();
213 : for (auto *JD : make_range(std::next(JDs.begin()), JDs.end())) {
214 : assert(JD && "JITDylibList entries must not be null");
215 : OS << ", " << JD->getName();
216 : }
217 : }
218 0 : OS << " ]";
219 : return OS;
220 0 : }
221 0 :
222 : FailedToMaterialize::FailedToMaterialize(SymbolNameSet Symbols)
223 : : Symbols(std::move(Symbols)) {
224 0 : assert(!this->Symbols.empty() && "Can not fail to resolve an empty set");
225 0 : }
226 :
227 : std::error_code FailedToMaterialize::convertToErrorCode() const {
228 0 : return orcError(OrcErrorCode::UnknownORCError);
229 0 : }
230 0 :
231 : void FailedToMaterialize::log(raw_ostream &OS) const {
232 0 : OS << "Failed to materialize symbols: " << Symbols;
233 0 : }
234 0 :
235 0 : SymbolsNotFound::SymbolsNotFound(SymbolNameSet Symbols)
236 0 : : Symbols(std::move(Symbols)) {
237 : assert(!this->Symbols.empty() && "Can not fail to resolve an empty set");
238 0 : }
239 0 :
240 : std::error_code SymbolsNotFound::convertToErrorCode() const {
241 0 : return orcError(OrcErrorCode::UnknownORCError);
242 : }
243 :
244 0 : void SymbolsNotFound::log(raw_ostream &OS) const {
245 0 : OS << "Symbols not found: " << Symbols;
246 : }
247 :
248 0 : SymbolsCouldNotBeRemoved::SymbolsCouldNotBeRemoved(SymbolNameSet Symbols)
249 0 : : Symbols(std::move(Symbols)) {
250 : assert(!this->Symbols.empty() && "Can not fail to resolve an empty set");
251 : }
252 0 :
253 0 : std::error_code SymbolsCouldNotBeRemoved::convertToErrorCode() const {
254 : return orcError(OrcErrorCode::UnknownORCError);
255 : }
256 0 :
257 0 : void SymbolsCouldNotBeRemoved::log(raw_ostream &OS) const {
258 : OS << "Symbols could not be removed: " << Symbols;
259 : }
260 0 :
261 0 : AsynchronousSymbolQuery::AsynchronousSymbolQuery(
262 : const SymbolNameSet &Symbols, SymbolsResolvedCallback NotifySymbolsResolved,
263 : SymbolsReadyCallback NotifySymbolsReady)
264 0 : : NotifySymbolsResolved(std::move(NotifySymbolsResolved)),
265 : NotifySymbolsReady(std::move(NotifySymbolsReady)) {
266 0 : NotYetResolvedCount = NotYetReadyCount = Symbols.size();
267 :
268 : for (auto &S : Symbols)
269 0 : ResolvedSymbols[S] = nullptr;
270 0 : }
271 :
272 : void AsynchronousSymbolQuery::resolve(const SymbolStringPtr &Name,
273 0 : JITEvaluatedSymbol Sym) {
274 0 : auto I = ResolvedSymbols.find(Name);
275 : assert(I != ResolvedSymbols.end() &&
276 : "Resolving symbol outside the requested set");
277 0 : assert(I->second.getAddress() == 0 && "Redundantly resolving symbol Name");
278 : I->second = std::move(Sym);
279 : --NotYetResolvedCount;
280 0 : }
281 0 :
282 0 : void AsynchronousSymbolQuery::handleFullyResolved() {
283 : assert(NotYetResolvedCount == 0 && "Not fully resolved?");
284 0 :
285 0 : if (!NotifySymbolsResolved) {
286 : // handleFullyResolved may be called by handleFullyReady (see comments in
287 0 : // that method), in which case this is a no-op, so bail out.
288 : assert(!NotifySymbolsReady &&
289 : "NotifySymbolsResolved already called or an error occurred");
290 0 : return;
291 0 : }
292 :
293 : auto TmpNotifySymbolsResolved = std::move(NotifySymbolsResolved);
294 1 : NotifySymbolsResolved = SymbolsResolvedCallback();
295 1 : TmpNotifySymbolsResolved(std::move(ResolvedSymbols));
296 : }
297 1 :
298 : void AsynchronousSymbolQuery::notifySymbolReady() {
299 0 : assert(NotYetReadyCount != 0 && "All symbols already emitted");
300 0 : --NotYetReadyCount;
301 : }
302 :
303 0 : void AsynchronousSymbolQuery::handleFullyReady() {
304 0 : assert(NotifySymbolsReady &&
305 0 : "NotifySymbolsReady already called or an error occurred");
306 :
307 1 : auto TmpNotifySymbolsReady = std::move(NotifySymbolsReady);
308 1 : NotifySymbolsReady = SymbolsReadyCallback();
309 :
310 1 : if (NotYetResolvedCount == 0 && NotifySymbolsResolved) {
311 : // The NotifyResolved callback of one query must have caused this query to
312 0 : // become ready (i.e. there is still a handleFullyResolved callback waiting
313 0 : // to be made back up the stack). Fold the handleFullyResolved call into
314 : // this one before proceeding. This will cause the call further up the
315 : // stack to become a no-op.
316 0 : handleFullyResolved();
317 0 : }
318 0 :
319 : assert(QueryRegistrations.empty() &&
320 1 : "Query is still registered with some symbols");
321 1 : assert(!NotifySymbolsResolved && "Resolution not applied yet");
322 : TmpNotifySymbolsReady(Error::success());
323 1 : }
324 :
325 0 : bool AsynchronousSymbolQuery::canStillFail() {
326 0 : return (NotifySymbolsResolved || NotifySymbolsReady);
327 : }
328 :
329 0 : void AsynchronousSymbolQuery::handleFailed(Error Err) {
330 0 : assert(QueryRegistrations.empty() && ResolvedSymbols.empty() &&
331 0 : NotYetResolvedCount == 0 && NotYetReadyCount == 0 &&
332 : "Query should already have been abandoned");
333 155 : if (NotifySymbolsResolved) {
334 : NotifySymbolsResolved(std::move(Err));
335 155 : NotifySymbolsResolved = SymbolsResolvedCallback();
336 : } else {
337 155 : assert(NotifySymbolsReady && "Failed after both callbacks issued?");
338 155 : NotifySymbolsReady(std::move(Err));
339 : }
340 332 : NotifySymbolsReady = SymbolsReadyCallback();
341 177 : }
342 155 :
343 : void AsynchronousSymbolQuery::addQueryDependence(JITDylib &JD,
344 174 : SymbolStringPtr Name) {
345 : bool Added = QueryRegistrations[&JD].insert(std::move(Name)).second;
346 174 : (void)Added;
347 : assert(Added && "Duplicate dependence notification?");
348 : }
349 :
350 174 : void AsynchronousSymbolQuery::removeQueryDependence(
351 174 : JITDylib &JD, const SymbolStringPtr &Name) {
352 174 : auto QRI = QueryRegistrations.find(&JD);
353 : assert(QRI != QueryRegistrations.end() &&
354 153 : "No dependencies registered for JD");
355 : assert(QRI->second.count(Name) && "No dependency on Name in JD");
356 : QRI->second.erase(Name);
357 153 : if (QRI->second.empty())
358 : QueryRegistrations.erase(QRI);
359 : }
360 :
361 : void AsynchronousSymbolQuery::detach() {
362 0 : ResolvedSymbols.clear();
363 : NotYetResolvedCount = 0;
364 : NotYetReadyCount = 0;
365 153 : for (auto &KV : QueryRegistrations)
366 306 : KV.first->detachQueryHelper(*this, KV.second);
367 153 : QueryRegistrations.clear();
368 : }
369 :
370 174 : MaterializationResponsibility::MaterializationResponsibility(
371 : JITDylib &JD, SymbolFlagsMap SymbolFlags, VModuleKey K)
372 174 : : JD(JD), SymbolFlags(std::move(SymbolFlags)), K(std::move(K)) {
373 174 : assert(!this->SymbolFlags.empty() && "Materializing nothing?");
374 :
375 153 : #ifndef NDEBUG
376 : for (auto &KV : this->SymbolFlags)
377 : KV.second |= JITSymbolFlags::Materializing;
378 : #endif
379 153 : }
380 153 :
381 : MaterializationResponsibility::~MaterializationResponsibility() {
382 153 : assert(SymbolFlags.empty() &&
383 : "All symbols should have been explicitly materialized or failed");
384 : }
385 :
386 : SymbolNameSet MaterializationResponsibility::getRequestedSymbols() const {
387 : return JD.getRequestedSymbols(SymbolFlags);
388 0 : }
389 :
390 : void MaterializationResponsibility::resolve(const SymbolMap &Symbols) {
391 : LLVM_DEBUG(dbgs() << "In " << JD.getName() << " resolving " << Symbols
392 : << "\n");
393 : #ifndef NDEBUG
394 153 : for (auto &KV : Symbols) {
395 153 : auto I = SymbolFlags.find(KV.first);
396 : assert(I != SymbolFlags.end() &&
397 1 : "Resolving symbol outside this responsibility set");
398 1 : assert(I->second.isMaterializing() && "Duplicate resolution");
399 : I->second &= ~JITSymbolFlags::Materializing;
400 : if (I->second.isWeak())
401 2 : assert(I->second == (KV.second.getFlags() | JITSymbolFlags::Weak) &&
402 : "Resolving symbol with incorrect flags");
403 : else
404 : assert(I->second == KV.second.getFlags() &&
405 2 : "Resolving symbol with incorrect flags");
406 2 : }
407 4 : #endif
408 :
409 : JD.resolve(Symbols);
410 0 : }
411 :
412 2 : void MaterializationResponsibility::emit() {
413 2 : #ifndef NDEBUG
414 : for (auto &KV : SymbolFlags)
415 103 : assert(!KV.second.isMaterializing() &&
416 : "Failed to resolve symbol before emission");
417 103 : #endif // NDEBUG
418 :
419 : JD.emit(SymbolFlags);
420 103 : SymbolFlags.clear();
421 : }
422 101 :
423 : Error MaterializationResponsibility::defineMaterializing(
424 101 : const SymbolFlagsMap &NewSymbolFlags) {
425 : // Add the given symbols to this responsibility object.
426 : // It's ok if we hit a duplicate here: In that case the new version will be
427 : // discarded, and the JITDylib::defineMaterializing method will return a
428 : // duplicate symbol error.
429 101 : for (auto &KV : NewSymbolFlags) {
430 87 : auto I = SymbolFlags.insert(KV).first;
431 101 : (void)I;
432 : #ifndef NDEBUG
433 3 : I->second |= JITSymbolFlags::Materializing;
434 3 : #endif
435 3 : }
436 3 :
437 4 : return JD.defineMaterializing(NewSymbolFlags);
438 1 : }
439 3 :
440 3 : void MaterializationResponsibility::failMaterialization() {
441 :
442 117 : SymbolNameSet FailedSymbols;
443 117 : for (auto &KV : SymbolFlags)
444 234 : FailedSymbols.insert(KV.first);
445 :
446 : JD.notifyFailed(FailedSymbols);
447 : SymbolFlags.clear();
448 : }
449 :
450 : void MaterializationResponsibility::replace(
451 117 : std::unique_ptr<MaterializationUnit> MU) {
452 : for (auto &KV : MU->getSymbols())
453 323 : SymbolFlags.erase(KV.first);
454 :
455 : LLVM_DEBUG(JD.getExecutionSession().runSessionLocked([&]() {
456 323 : dbgs() << "In " << JD.getName() << " replacing symbols with " << *MU
457 : << "\n";
458 52 : }););
459 52 :
460 : JD.replace(std::move(MU));
461 : }
462 95 :
463 : MaterializationResponsibility
464 : MaterializationResponsibility::delegate(const SymbolNameSet &Symbols,
465 : VModuleKey NewKey) {
466 :
467 : if (NewKey == VModuleKey())
468 : NewKey = K;
469 :
470 : SymbolFlagsMap DelegatedFlags;
471 :
472 : for (auto &Name : Symbols) {
473 : auto I = SymbolFlags.find(Name);
474 : assert(I != SymbolFlags.end() &&
475 : "Symbol is not tracked by this MaterializationResponsibility "
476 : "instance");
477 :
478 : DelegatedFlags[Name] = std::move(I->second);
479 : SymbolFlags.erase(I);
480 : }
481 95 :
482 95 : return MaterializationResponsibility(JD, std::move(DelegatedFlags),
483 : std::move(NewKey));
484 95 : }
485 :
486 : void MaterializationResponsibility::addDependencies(
487 : const SymbolStringPtr &Name, const SymbolDependenceMap &Dependencies) {
488 : assert(SymbolFlags.count(Name) &&
489 : "Symbol not covered by this MaterializationResponsibility instance");
490 : JD.addDependencies(Name, Dependencies);
491 95 : }
492 95 :
493 95 : void MaterializationResponsibility::addDependenciesForAll(
494 : const SymbolDependenceMap &Dependencies) {
495 7 : for (auto &KV : SymbolFlags)
496 : JD.addDependencies(KV.first, Dependencies);
497 : }
498 :
499 : AbsoluteSymbolsMaterializationUnit::AbsoluteSymbolsMaterializationUnit(
500 : SymbolMap Symbols, VModuleKey K)
501 23 : : MaterializationUnit(extractFlags(Symbols), std::move(K)),
502 9 : Symbols(std::move(Symbols)) {}
503 :
504 : StringRef AbsoluteSymbolsMaterializationUnit::getName() const {
505 : return "<Absolute Symbols>";
506 : }
507 :
508 : void AbsoluteSymbolsMaterializationUnit::materialize(
509 7 : MaterializationResponsibility R) {
510 : R.resolve(Symbols);
511 : R.emit();
512 1 : }
513 :
514 : void AbsoluteSymbolsMaterializationUnit::discard(const JITDylib &JD,
515 4 : const SymbolStringPtr &Name) {
516 2 : assert(Symbols.count(Name) && "Symbol is not part of this MU");
517 : Symbols.erase(Name);
518 1 : }
519 1 :
520 1 : SymbolFlagsMap
521 : AbsoluteSymbolsMaterializationUnit::extractFlags(const SymbolMap &Symbols) {
522 61 : SymbolFlagsMap Flags;
523 : for (const auto &KV : Symbols)
524 189 : Flags[KV.first] = KV.second.getFlags();
525 67 : return Flags;
526 : }
527 :
528 : ReExportsMaterializationUnit::ReExportsMaterializationUnit(
529 : JITDylib *SourceJD, SymbolAliasMap Aliases, VModuleKey K)
530 : : MaterializationUnit(extractFlags(Aliases), std::move(K)),
531 : SourceJD(SourceJD), Aliases(std::move(Aliases)) {}
532 122 :
533 61 : StringRef ReExportsMaterializationUnit::getName() const {
534 : return "<Reexports>";
535 : }
536 10 :
537 : void ReExportsMaterializationUnit::materialize(
538 : MaterializationResponsibility R) {
539 10 :
540 10 : auto &ES = R.getTargetJITDylib().getExecutionSession();
541 : JITDylib &TgtJD = R.getTargetJITDylib();
542 : JITDylib &SrcJD = SourceJD ? *SourceJD : TgtJD;
543 :
544 20 : // Find the set of requested aliases and aliasees. Return any unrequested
545 10 : // aliases back to the JITDylib so as to not prematurely materialize any
546 : // aliasees.
547 : auto RequestedSymbols = R.getRequestedSymbols();
548 : SymbolAliasMap RequestedAliases;
549 :
550 10 : for (auto &Name : RequestedSymbols) {
551 10 : auto I = Aliases.find(Name);
552 : assert(I != Aliases.end() && "Symbol not found in aliases map?");
553 : RequestedAliases[Name] = std::move(I->second);
554 : Aliases.erase(I);
555 20 : }
556 :
557 : if (!Aliases.empty()) {
558 8 : if (SourceJD)
559 : R.replace(reexports(*SourceJD, std::move(Aliases)));
560 : else
561 : R.replace(symbolAliases(std::move(Aliases)));
562 8 : }
563 8 :
564 : // The OnResolveInfo struct will hold the aliases and responsibilty for each
565 18 : // query in the list.
566 : struct OnResolveInfo {
567 57 : OnResolveInfo(MaterializationResponsibility R, SymbolAliasMap Aliases)
568 21 : : R(std::move(R)), Aliases(std::move(Aliases)) {}
569 18 :
570 : MaterializationResponsibility R;
571 34 : SymbolAliasMap Aliases;
572 34 : };
573 34 :
574 68 : // Build a list of queries to issue. In each round we build the largest set of
575 : // aliases that we can resolve without encountering a chain definition of the
576 0 : // form Foo -> Bar, Bar -> Baz. Such a form would deadlock as the query would
577 0 : // be waitin on a symbol that it itself had to resolve. Usually this will just
578 : // involve one round and a single query.
579 :
580 18 : std::vector<std::pair<SymbolNameSet, std::shared_ptr<OnResolveInfo>>>
581 : QueryInfos;
582 18 : while (!RequestedAliases.empty()) {
583 18 : SymbolNameSet ResponsibilitySymbols;
584 18 : SymbolNameSet QuerySymbols;
585 : SymbolAliasMap QueryAliases;
586 0 :
587 : // Collect as many aliases as we can without including a chain.
588 : for (auto &KV : RequestedAliases) {
589 0 : // Chain detected. Skip this symbol for this round.
590 0 : if (&SrcJD == &TgtJD && (QueryAliases.count(KV.second.Aliasee) ||
591 : RequestedAliases.count(KV.second.Aliasee)))
592 : continue;
593 34 :
594 : ResponsibilitySymbols.insert(KV.first);
595 119 : QuerySymbols.insert(KV.second.Aliasee);
596 51 : QueryAliases[KV.first] = std::move(KV.second);
597 34 : }
598 :
599 : // Remove the aliases collected this round from the RequestedAliases map.
600 20 : for (auto &KV : QueryAliases)
601 20 : RequestedAliases.erase(KV.first);
602 20 :
603 40 : assert(!QuerySymbols.empty() && "Alias cycle detected!");
604 :
605 0 : auto QueryInfo = std::make_shared<OnResolveInfo>(
606 0 : R.delegate(ResponsibilitySymbols), std::move(QueryAliases));
607 : QueryInfos.push_back(
608 : make_pair(std::move(QuerySymbols), std::move(QueryInfo)));
609 8 : }
610 :
611 : // Issue the queries.
612 8 : while (!QueryInfos.empty()) {
613 : auto QuerySymbols = std::move(QueryInfos.back().first);
614 8 : auto QueryInfo = std::move(QueryInfos.back().second);
615 :
616 : QueryInfos.pop_back();
617 :
618 : auto RegisterDependencies = [QueryInfo,
619 8 : &SrcJD](const SymbolDependenceMap &Deps) {
620 : // If there were no materializing symbols, just bail out.
621 : if (Deps.empty())
622 17 : return;
623 9 :
624 : // Otherwise the only deps should be on SrcJD.
625 : assert(Deps.size() == 1 && Deps.count(&SrcJD) &&
626 9 : "Unexpected dependencies for reexports");
627 :
628 : auto &SrcJDDeps = Deps.find(&SrcJD)->second;
629 8 : SymbolDependenceMap PerAliasDepsMap;
630 2 : auto &PerAliasDeps = PerAliasDepsMap[&SrcJD];
631 6 :
632 : for (auto &KV : QueryInfo->Aliases)
633 0 : if (SrcJDDeps.count(KV.second.Aliasee)) {
634 : PerAliasDeps = {KV.second.Aliasee};
635 : QueryInfo->R.addDependencies(KV.first, PerAliasDepsMap);
636 : }
637 : };
638 :
639 : auto OnResolve = [QueryInfo](Expected<SymbolMap> Result) {
640 0 : if (Result) {
641 : SymbolMap ResolutionMap;
642 : for (auto &KV : QueryInfo->Aliases) {
643 : assert(Result->count(KV.second.Aliasee) &&
644 : "Result map missing entry?");
645 : ResolutionMap[KV.first] = JITEvaluatedSymbol(
646 : (*Result)[KV.second.Aliasee].getAddress(), KV.second.AliasFlags);
647 : }
648 : QueryInfo->R.resolve(ResolutionMap);
649 : QueryInfo->R.emit();
650 : } else {
651 : auto &ES = QueryInfo->R.getTargetJITDylib().getExecutionSession();
652 : ES.reportError(Result.takeError());
653 8 : QueryInfo->R.failMaterialization();
654 17 : }
655 : };
656 :
657 : auto OnReady = [&ES](Error Err) { ES.reportError(std::move(Err)); };
658 :
659 : ES.lookup({&SrcJD}, QuerySymbols, std::move(OnResolve), std::move(OnReady),
660 28 : std::move(RegisterDependencies), nullptr, true);
661 : }
662 10 : }
663 :
664 1 : void ReExportsMaterializationUnit::discard(const JITDylib &JD,
665 : const SymbolStringPtr &Name) {
666 9 : assert(Aliases.count(Name) &&
667 9 : "Symbol not covered by this MaterializationUnit");
668 : Aliases.erase(Name);
669 : }
670 :
671 : SymbolFlagsMap
672 27 : ReExportsMaterializationUnit::extractFlags(const SymbolAliasMap &Aliases) {
673 9 : SymbolFlagsMap SymbolFlags;
674 : for (auto &KV : Aliases)
675 : SymbolFlags[KV.first] = KV.second.AliasFlags;
676 :
677 : return SymbolFlags;
678 18 : }
679 :
680 9 : Expected<SymbolAliasMap>
681 : buildSimpleReexportsAliasMap(JITDylib &SourceJD, const SymbolNameSet &Symbols) {
682 : auto Flags = SourceJD.lookupFlags(Symbols);
683 :
684 17 : if (Flags.size() != Symbols.size()) {
685 : SymbolNameSet Unresolved = Symbols;
686 : for (auto &KV : Flags)
687 : Unresolved.erase(KV.first);
688 : return make_error<SymbolsNotFound>(std::move(Unresolved));
689 : }
690 :
691 18 : SymbolAliasMap Result;
692 : for (auto &Name : Symbols) {
693 : assert(Flags.count(Name) && "Missing entry in flags map");
694 : Result[Name] = SymbolAliasMapEntry(Name, Flags[Name]);
695 : }
696 :
697 : return Result;
698 : }
699 :
700 : ReexportsGenerator::ReexportsGenerator(JITDylib &SourceJD,
701 : SymbolPredicate Allow)
702 : : SourceJD(SourceJD), Allow(std::move(Allow)) {}
703 :
704 : SymbolNameSet ReexportsGenerator::operator()(JITDylib &JD,
705 : const SymbolNameSet &Names) {
706 : orc::SymbolNameSet Added;
707 : orc::SymbolAliasMap AliasMap;
708 :
709 9 : auto Flags = SourceJD.lookupFlags(Names);
710 :
711 9 : for (auto &KV : Flags) {
712 : if (Allow && !Allow(KV.first))
713 : continue;
714 : AliasMap[KV.first] = SymbolAliasMapEntry(KV.first, KV.second);
715 : Added.insert(KV.first);
716 : }
717 :
718 : if (!Added.empty())
719 : cantFail(JD.define(reexports(SourceJD, AliasMap)));
720 :
721 : return Added;
722 : }
723 :
724 : Error JITDylib::defineMaterializing(const SymbolFlagsMap &SymbolFlags) {
725 : return ES.runSessionLocked([&]() -> Error {
726 : std::vector<SymbolMap::iterator> AddedSyms;
727 :
728 : for (auto &KV : SymbolFlags) {
729 : SymbolMap::iterator EntryItr;
730 : bool Added;
731 45 :
732 : auto NewFlags = KV.second;
733 : NewFlags |= JITSymbolFlags::Materializing;
734 8 :
735 : std::tie(EntryItr, Added) = Symbols.insert(
736 1 : std::make_pair(KV.first, JITEvaluatedSymbol(0, NewFlags)));
737 :
738 : if (Added)
739 : AddedSyms.push_back(EntryItr);
740 1 : else {
741 1 : // Remove any symbols already added.
742 : for (auto &SI : AddedSyms)
743 : Symbols.erase(SI);
744 20 :
745 : // FIXME: Return all duplicates.
746 54 : return make_error<DuplicateDefinition>(*KV.first);
747 14 : }
748 : }
749 20 :
750 : return Error::success();
751 : });
752 : }
753 0 :
754 0 : void JITDylib::replace(std::unique_ptr<MaterializationUnit> MU) {
755 : assert(MU != nullptr && "Can not replace with a null MaterializationUnit");
756 0 :
757 : auto MustRunMU =
758 0 : ES.runSessionLocked([&, this]() -> std::unique_ptr<MaterializationUnit> {
759 0 :
760 : #ifndef NDEBUG
761 : for (auto &KV : MU->getSymbols()) {
762 : auto SymI = Symbols.find(KV.first);
763 : assert(SymI != Symbols.end() && "Replacing unknown symbol");
764 0 : assert(!SymI->second.getFlags().isLazy() &&
765 : SymI->second.getFlags().isMaterializing() &&
766 : "Can not replace symbol that is not materializing");
767 : assert(UnmaterializedInfos.count(KV.first) == 0 &&
768 : "Symbol being replaced should have no UnmaterializedInfo");
769 : }
770 : #endif // NDEBUG
771 :
772 1 : // If any symbol has pending queries against it then we need to
773 1 : // materialize MU immediately.
774 2 : for (auto &KV : MU->getSymbols()) {
775 : auto MII = MaterializingInfos.find(KV.first);
776 1 : if (MII != MaterializingInfos.end()) {
777 : if (!MII->second.PendingQueries.empty())
778 : return std::move(MU);
779 : }
780 : }
781 1 :
782 : // Otherwise, make MU responsible for all the symbols.
783 4 : auto UMI = std::make_shared<UnmaterializedInfo>(std::move(MU));
784 6 : for (auto &KV : UMI->MU->getSymbols()) {
785 : assert(!KV.second.isLazy() &&
786 1 : "Lazy flag should be managed internally.");
787 : assert(!KV.second.isMaterializing() &&
788 : "Materializing flags should be managed internally.");
789 :
790 1 : auto SymI = Symbols.find(KV.first);
791 3 : JITSymbolFlags ReplaceFlags = KV.second;
792 : ReplaceFlags |= JITSymbolFlags::Lazy;
793 1 : SymI->second = JITEvaluatedSymbol(SymI->second.getAddress(),
794 : std::move(ReplaceFlags));
795 : UnmaterializedInfos[KV.first] = UMI;
796 7 : }
797 7 :
798 : return nullptr;
799 : });
800 :
801 : if (MustRunMU)
802 : ES.dispatchMaterialization(*this, std::move(MustRunMU));
803 : }
804 :
805 : SymbolNameSet
806 : JITDylib::getRequestedSymbols(const SymbolFlagsMap &SymbolFlags) const {
807 : return ES.runSessionLocked([&]() {
808 : SymbolNameSet RequestedSymbols;
809 :
810 : for (auto &KV : SymbolFlags) {
811 : assert(Symbols.count(KV.first) && "JITDylib does not cover this symbol?");
812 : assert(Symbols.find(KV.first)->second.getFlags().isMaterializing() &&
813 : "getRequestedSymbols can only be called for materializing "
814 : "symbols");
815 : auto I = MaterializingInfos.find(KV.first);
816 : if (I == MaterializingInfos.end())
817 : continue;
818 :
819 : if (!I->second.PendingQueries.empty())
820 : RequestedSymbols.insert(KV.first);
821 : }
822 :
823 7 : return RequestedSymbols;
824 : });
825 : }
826 61 :
827 : void JITDylib::addDependencies(const SymbolStringPtr &Name,
828 : const SymbolDependenceMap &Dependencies) {
829 : assert(Symbols.count(Name) && "Name not in symbol table");
830 61 : assert((Symbols[Name].getFlags().isLazy() ||
831 : Symbols[Name].getFlags().isMaterializing()) &&
832 : "Symbol is not lazy or materializing");
833 :
834 : auto &MI = MaterializingInfos[Name];
835 : assert(!MI.IsEmitted && "Can not add dependencies to an emitted symbol");
836 :
837 : for (auto &KV : Dependencies) {
838 : assert(KV.first && "Null JITDylib in dependency?");
839 : auto &OtherJITDylib = *KV.first;
840 : auto &DepsOnOtherJITDylib = MI.UnemittedDependencies[&OtherJITDylib];
841 :
842 : for (auto &OtherSymbol : KV.second) {
843 : #ifndef NDEBUG
844 : // Assert that this symbol exists and has not been emitted already.
845 : auto SymI = OtherJITDylib.Symbols.find(OtherSymbol);
846 : assert(SymI != OtherJITDylib.Symbols.end() &&
847 : (SymI->second.getFlags().isLazy() ||
848 : SymI->second.getFlags().isMaterializing()) &&
849 : "Dependency on emitted symbol");
850 : #endif
851 :
852 : auto &OtherMI = OtherJITDylib.MaterializingInfos[OtherSymbol];
853 :
854 : if (OtherMI.IsEmitted)
855 : transferEmittedNodeDependencies(MI, Name, OtherMI);
856 : else if (&OtherJITDylib != this || OtherSymbol != Name) {
857 : OtherMI.Dependants[this].insert(Name);
858 : DepsOnOtherJITDylib.insert(OtherSymbol);
859 : }
860 : }
861 :
862 : if (DepsOnOtherJITDylib.empty())
863 : MI.UnemittedDependencies.erase(&OtherJITDylib);
864 : }
865 : }
866 :
867 : void JITDylib::resolve(const SymbolMap &Resolved) {
868 : auto FullyResolvedQueries = ES.runSessionLocked([&, this]() {
869 : AsynchronousSymbolQuerySet FullyResolvedQueries;
870 : for (const auto &KV : Resolved) {
871 61 : auto &Name = KV.first;
872 : auto Sym = KV.second;
873 61 :
874 39 : assert(!Sym.getFlags().isLazy() && !Sym.getFlags().isMaterializing() &&
875 61 : "Materializing flags should be managed internally");
876 :
877 : auto I = Symbols.find(Name);
878 52 :
879 52 : assert(I != Symbols.end() && "Symbol not found");
880 : assert(!I->second.getFlags().isLazy() &&
881 : I->second.getFlags().isMaterializing() &&
882 : "Symbol should be materializing");
883 : assert(I->second.getAddress() == 0 && "Symbol has already been resolved");
884 :
885 : assert((Sym.getFlags() & ~JITSymbolFlags::Weak) ==
886 : (JITSymbolFlags::stripTransientFlags(I->second.getFlags()) &
887 : ~JITSymbolFlags::Weak) &&
888 : "Resolved flags should match the declared flags");
889 :
890 : // Once resolved, symbols can never be weak.
891 : JITSymbolFlags ResolvedFlags = Sym.getFlags();
892 : ResolvedFlags &= ~JITSymbolFlags::Weak;
893 : ResolvedFlags |= JITSymbolFlags::Materializing;
894 : I->second = JITEvaluatedSymbol(Sym.getAddress(), ResolvedFlags);
895 :
896 52 : auto &MI = MaterializingInfos[Name];
897 : for (auto &Q : MI.PendingQueries) {
898 : Q->resolve(Name, Sym);
899 29 : if (Q->isFullyResolved())
900 : FullyResolvedQueries.insert(Q);
901 : }
902 : }
903 :
904 : return FullyResolvedQueries;
905 : });
906 29 :
907 : for (auto &Q : FullyResolvedQueries) {
908 : assert(Q->isFullyResolved() && "Q not fully resolved");
909 61 : Q->handleFullyResolved();
910 : }
911 32 : }
912 32 :
913 : void JITDylib::emit(const SymbolFlagsMap &Emitted) {
914 72 : auto FullyReadyQueries = ES.runSessionLocked([&, this]() {
915 : AsynchronousSymbolQuerySet ReadyQueries;
916 :
917 : for (const auto &KV : Emitted) {
918 : const auto &Name = KV.first;
919 :
920 : auto MII = MaterializingInfos.find(Name);
921 : assert(MII != MaterializingInfos.end() &&
922 : "Missing MaterializingInfo entry");
923 :
924 40 : auto &MI = MII->second;
925 :
926 40 : // For each dependant, transfer this node's emitted dependencies to
927 3 : // it. If the dependant node is ready (i.e. has no unemitted
928 37 : // dependencies) then notify any pending queries.
929 68 : for (auto &KV : MI.Dependants) {
930 : auto &DependantJD = *KV.first;
931 : for (auto &DependantName : KV.second) {
932 : auto DependantMII =
933 : DependantJD.MaterializingInfos.find(DependantName);
934 32 : assert(DependantMII != DependantJD.MaterializingInfos.end() &&
935 0 : "Dependant should have MaterializingInfo");
936 :
937 29 : auto &DependantMI = DependantMII->second;
938 :
939 95 : // Remove the dependant's dependency on this node.
940 95 : assert(DependantMI.UnemittedDependencies[this].count(Name) &&
941 : "Dependant does not count this symbol as a dependency?");
942 : DependantMI.UnemittedDependencies[this].erase(Name);
943 : if (DependantMI.UnemittedDependencies[this].empty())
944 : DependantMI.UnemittedDependencies.erase(this);
945 :
946 : // Transfer unemitted dependencies from this node to the dependant.
947 : DependantJD.transferEmittedNodeDependencies(DependantMI,
948 : DependantName, MI);
949 :
950 : // If the dependant is emitted and this node was the last of its
951 : // unemitted dependencies then the dependant node is now ready, so
952 : // notify any pending queries on the dependant node.
953 : if (DependantMI.IsEmitted &&
954 : DependantMI.UnemittedDependencies.empty()) {
955 : assert(DependantMI.Dependants.empty() &&
956 : "Dependants should be empty by now");
957 : for (auto &Q : DependantMI.PendingQueries) {
958 : Q->notifySymbolReady();
959 : if (Q->isFullyReady())
960 : ReadyQueries.insert(Q);
961 : Q->removeQueryDependence(DependantJD, DependantName);
962 : }
963 :
964 : // Since this dependant is now ready, we erase its MaterializingInfo
965 : // and update its materializing state.
966 : assert(DependantJD.Symbols.count(DependantName) &&
967 : "Dependant has no entry in the Symbols table");
968 : auto &DependantSym = DependantJD.Symbols[DependantName];
969 : DependantSym.setFlags(DependantSym.getFlags() &
970 : ~JITSymbolFlags::Materializing);
971 : DependantJD.MaterializingInfos.erase(DependantMII);
972 : }
973 : }
974 : }
975 : MI.Dependants.clear();
976 : MI.IsEmitted = true;
977 95 :
978 : if (MI.UnemittedDependencies.empty()) {
979 176 : for (auto &Q : MI.PendingQueries) {
980 : Q->notifySymbolReady();
981 81 : if (Q->isFullyReady())
982 : ReadyQueries.insert(Q);
983 95 : Q->removeQueryDependence(*this, Name);
984 : }
985 95 : assert(Symbols.count(Name) &&
986 95 : "Symbol has no entry in the Symbols table");
987 : auto &Sym = Symbols[Name];
988 : Sym.setFlags(Sym.getFlags() & ~JITSymbolFlags::Materializing);
989 : MaterializingInfos.erase(MII);
990 : }
991 : }
992 :
993 : return ReadyQueries;
994 : });
995 :
996 : for (auto &Q : FullyReadyQueries) {
997 : assert(Q->isFullyReady() && "Q is not fully ready");
998 : Q->handleFullyReady();
999 : }
1000 : }
1001 :
1002 : void JITDylib::notifyFailed(const SymbolNameSet &FailedSymbols) {
1003 :
1004 : // FIXME: This should fail any transitively dependant symbols too.
1005 :
1006 : auto FailedQueriesToNotify = ES.runSessionLocked([&, this]() {
1007 : AsynchronousSymbolQuerySet FailedQueries;
1008 :
1009 : for (auto &Name : FailedSymbols) {
1010 : auto I = Symbols.find(Name);
1011 : assert(I != Symbols.end() && "Symbol not present in this JITDylib");
1012 : Symbols.erase(I);
1013 :
1014 : auto MII = MaterializingInfos.find(Name);
1015 :
1016 : // If we have not created a MaterializingInfo for this symbol yet then
1017 : // there is nobody to notify.
1018 : if (MII == MaterializingInfos.end())
1019 : continue;
1020 :
1021 : // Copy all the queries to the FailedQueries list, then abandon them.
1022 : // This has to be a copy, and the copy has to come before the abandon
1023 : // operation: Each Q.detach() call will reach back into this
1024 : // PendingQueries list to remove Q.
1025 : for (auto &Q : MII->second.PendingQueries)
1026 : FailedQueries.insert(Q);
1027 :
1028 : for (auto &Q : FailedQueries)
1029 : Q->detach();
1030 :
1031 : assert(MII->second.PendingQueries.empty() &&
1032 : "Queries remain after symbol was failed");
1033 :
1034 : MaterializingInfos.erase(MII);
1035 : }
1036 :
1037 : return FailedQueries;
1038 : });
1039 :
1040 : for (auto &Q : FailedQueriesToNotify)
1041 : Q->handleFailed(make_error<FailedToMaterialize>(FailedSymbols));
1042 : }
1043 :
1044 : void JITDylib::setSearchOrder(JITDylibList NewSearchOrder,
1045 : bool SearchThisJITDylibFirst) {
1046 : if (SearchThisJITDylibFirst && NewSearchOrder.front() != this)
1047 : NewSearchOrder.insert(NewSearchOrder.begin(), this);
1048 :
1049 : ES.runSessionLocked([&]() { SearchOrder = std::move(NewSearchOrder); });
1050 : }
1051 :
1052 : void JITDylib::addToSearchOrder(JITDylib &JD) {
1053 : ES.runSessionLocked([&]() { SearchOrder.push_back(&JD); });
1054 : }
1055 :
1056 : void JITDylib::replaceInSearchOrder(JITDylib &OldJD, JITDylib &NewJD) {
1057 : ES.runSessionLocked([&]() {
1058 : auto I = std::find(SearchOrder.begin(), SearchOrder.end(), &OldJD);
1059 :
1060 : if (I != SearchOrder.end())
1061 : *I = &NewJD;
1062 : });
1063 : }
1064 :
1065 : void JITDylib::removeFromSearchOrder(JITDylib &JD) {
1066 95 : ES.runSessionLocked([&]() {
1067 : auto I = std::find(SearchOrder.begin(), SearchOrder.end(), &JD);
1068 178 : if (I != SearchOrder.end())
1069 : SearchOrder.erase(I);
1070 83 : });
1071 : }
1072 95 :
1073 : Error JITDylib::remove(const SymbolNameSet &Names) {
1074 1 : return ES.runSessionLocked([&]() -> Error {
1075 : using SymbolMaterializerItrPair =
1076 : std::pair<SymbolMap::iterator, UnmaterializedInfosMap::iterator>;
1077 : std::vector<SymbolMaterializerItrPair> SymbolsToRemove;
1078 1 : SymbolNameSet Missing;
1079 : SymbolNameSet Materializing;
1080 :
1081 : for (auto &Name : Names) {
1082 : auto I = Symbols.find(Name);
1083 :
1084 : // Note symbol missing.
1085 : if (I == Symbols.end()) {
1086 : Missing.insert(Name);
1087 : continue;
1088 : }
1089 :
1090 : // Note symbol materializing.
1091 : if (I->second.getFlags().isMaterializing()) {
1092 : Materializing.insert(Name);
1093 : continue;
1094 : }
1095 :
1096 : auto UMII = I->second.getFlags().isLazy() ? UnmaterializedInfos.find(Name)
1097 : : UnmaterializedInfos.end();
1098 : SymbolsToRemove.push_back(std::make_pair(I, UMII));
1099 : }
1100 :
1101 : // If any of the symbols are not defined, return an error.
1102 : if (!Missing.empty())
1103 : return make_error<SymbolsNotFound>(std::move(Missing));
1104 :
1105 : // If any of the symbols are currently materializing, return an error.
1106 : if (!Materializing.empty())
1107 : return make_error<SymbolsCouldNotBeRemoved>(std::move(Materializing));
1108 :
1109 : // Remove the symbols.
1110 1 : for (auto &SymbolMaterializerItrPair : SymbolsToRemove) {
1111 : auto UMII = SymbolMaterializerItrPair.second;
1112 2 :
1113 2 : // If there is a materializer attached, call discard.
1114 1 : if (UMII != UnmaterializedInfos.end()) {
1115 : UMII->second->MU->doDiscard(*this, UMII->first);
1116 12 : UnmaterializedInfos.erase(UMII);
1117 : }
1118 12 :
1119 0 : auto SymI = SymbolMaterializerItrPair.first;
1120 : Symbols.erase(SymI);
1121 24 : }
1122 12 :
1123 : return Error::success();
1124 61 : });
1125 122 : }
1126 61 :
1127 : SymbolFlagsMap JITDylib::lookupFlags(const SymbolNameSet &Names) {
1128 0 : return ES.runSessionLocked([&, this]() {
1129 0 : SymbolFlagsMap Result;
1130 : auto Unresolved = lookupFlagsImpl(Result, Names);
1131 : if (DefGenerator && !Unresolved.empty()) {
1132 : auto NewDefs = DefGenerator(*this, Unresolved);
1133 : if (!NewDefs.empty()) {
1134 : auto Unresolved2 = lookupFlagsImpl(Result, NewDefs);
1135 0 : (void)Unresolved2;
1136 : assert(Unresolved2.empty() &&
1137 0 : "All fallback defs should have been found by lookupFlagsImpl");
1138 0 : }
1139 : };
1140 : return Result;
1141 : });
1142 : }
1143 0 :
1144 : SymbolNameSet JITDylib::lookupFlagsImpl(SymbolFlagsMap &Flags,
1145 3 : const SymbolNameSet &Names) {
1146 3 : SymbolNameSet Unresolved;
1147 :
1148 : for (auto &Name : Names) {
1149 : auto I = Symbols.find(Name);
1150 :
1151 : if (I == Symbols.end()) {
1152 : Unresolved.insert(Name);
1153 : continue;
1154 : }
1155 :
1156 : assert(!Flags.count(Name) && "Symbol already present in Flags map");
1157 : Flags[Name] = JITSymbolFlags::stripTransientFlags(I->second.getFlags());
1158 : }
1159 :
1160 : return Unresolved;
1161 : }
1162 :
1163 : void JITDylib::lodgeQuery(std::shared_ptr<AsynchronousSymbolQuery> &Q,
1164 : SymbolNameSet &Unresolved,
1165 : JITDylib *MatchNonExportedInJD, bool MatchNonExported,
1166 : MaterializationUnitList &MUs) {
1167 : assert(Q && "Query can not be null");
1168 :
1169 : lodgeQueryImpl(Q, Unresolved, MatchNonExportedInJD, MatchNonExported, MUs);
1170 : if (DefGenerator && !Unresolved.empty()) {
1171 : auto NewDefs = DefGenerator(*this, Unresolved);
1172 : if (!NewDefs.empty()) {
1173 : for (auto &D : NewDefs)
1174 : Unresolved.erase(D);
1175 : lodgeQueryImpl(Q, NewDefs, MatchNonExportedInJD, MatchNonExported, MUs);
1176 : assert(NewDefs.empty() &&
1177 : "All fallback defs should have been found by lookupImpl");
1178 : }
1179 : }
1180 : }
1181 :
1182 : void JITDylib::lodgeQueryImpl(
1183 : std::shared_ptr<AsynchronousSymbolQuery> &Q, SymbolNameSet &Unresolved,
1184 : JITDylib *MatchNonExportedInJD, bool MatchNonExported,
1185 : std::vector<std::unique_ptr<MaterializationUnit>> &MUs) {
1186 :
1187 : std::vector<SymbolStringPtr> ToRemove;
1188 : for (auto Name : Unresolved) {
1189 : // Search for the name in Symbols. Skip it if not found.
1190 : auto SymI = Symbols.find(Name);
1191 : if (SymI == Symbols.end())
1192 : continue;
1193 :
1194 : // If this is a non-exported symbol, then check the values of
1195 : // MatchNonExportedInJD and MatchNonExported. Skip if we should not match
1196 3 : // against this symbol.
1197 : if (!SymI->second.getFlags().isExported())
1198 : if (!MatchNonExported && MatchNonExportedInJD != this)
1199 4 : continue;
1200 4 :
1201 : // If we matched against Name in JD, mark it to be removed from the Unresolved
1202 : // set.
1203 : ToRemove.push_back(Name);
1204 :
1205 : // If the symbol has an address then resolve it.
1206 : if (SymI->second.getAddress() != 0)
1207 : Q->resolve(Name, SymI->second);
1208 :
1209 : // If the symbol is lazy, get the MaterialiaztionUnit for it.
1210 : if (SymI->second.getFlags().isLazy()) {
1211 : assert(SymI->second.getAddress() == 0 &&
1212 : "Lazy symbol should not have a resolved address");
1213 4 : assert(!SymI->second.getFlags().isMaterializing() &&
1214 : "Materializing and lazy should not both be set");
1215 : auto UMII = UnmaterializedInfos.find(Name);
1216 5 : assert(UMII != UnmaterializedInfos.end() &&
1217 : "Lazy symbol should have UnmaterializedInfo");
1218 : auto MU = std::move(UMII->second->MU);
1219 : assert(MU != nullptr && "Materializer should not be null");
1220 17 :
1221 12 : // Move all symbols associated with this MaterializationUnit into
1222 : // materializing state.
1223 12 : for (auto &KV : MU->getSymbols()) {
1224 : auto SymK = Symbols.find(KV.first);
1225 6 : auto Flags = SymK->second.getFlags();
1226 : Flags &= ~JITSymbolFlags::Lazy;
1227 : Flags |= JITSymbolFlags::Materializing;
1228 : SymK->second.setFlags(Flags);
1229 6 : UnmaterializedInfos.erase(KV.first);
1230 : }
1231 :
1232 5 : // Add MU to the list of MaterializationUnits to be materialized.
1233 : MUs.push_back(std::move(MU));
1234 : } else if (!SymI->second.getFlags().isMaterializing()) {
1235 126 : // The symbol is neither lazy nor materializing, so it must be
1236 : // ready. Notify the query and continue.
1237 : Q->notifySymbolReady();
1238 : continue;
1239 : }
1240 :
1241 126 : // Add the query to the PendingQueries list.
1242 126 : assert(SymI->second.getFlags().isMaterializing() &&
1243 : "By this line the symbol should be materializing");
1244 8 : auto &MI = MaterializingInfos[Name];
1245 8 : MI.PendingQueries.push_back(Q);
1246 : Q->addQueryDependence(*this, Name);
1247 4 : }
1248 :
1249 : // Remove any symbols that we found.
1250 : for (auto &Name : ToRemove)
1251 : Unresolved.erase(Name);
1252 126 : }
1253 :
1254 130 : SymbolNameSet JITDylib::legacyLookup(std::shared_ptr<AsynchronousSymbolQuery> Q,
1255 : SymbolNameSet Names) {
1256 : assert(Q && "Query can not be null");
1257 :
1258 : ES.runOutstandingMUs();
1259 130 :
1260 249 : LookupImplActionFlags ActionFlags = None;
1261 : std::vector<std::unique_ptr<MaterializationUnit>> MUs;
1262 119 :
1263 119 : SymbolNameSet Unresolved = std::move(Names);
1264 : ES.runSessionLocked([&, this]() {
1265 : ActionFlags = lookupImpl(Q, MUs, Unresolved);
1266 : if (DefGenerator && !Unresolved.empty()) {
1267 : assert(ActionFlags == None &&
1268 : "ActionFlags set but unresolved symbols remain?");
1269 108 : auto NewDefs = DefGenerator(*this, Unresolved);
1270 12 : if (!NewDefs.empty()) {
1271 : for (auto &D : NewDefs)
1272 : Unresolved.erase(D);
1273 : ActionFlags = lookupImpl(Q, MUs, NewDefs);
1274 : assert(NewDefs.empty() &&
1275 106 : "All fallback defs should have been found by lookupImpl");
1276 : }
1277 : }
1278 106 : });
1279 8 :
1280 : assert((MUs.empty() || ActionFlags == None) &&
1281 : "If action flags are set, there should be no work to do (so no MUs)");
1282 106 :
1283 : if (ActionFlags & NotifyFullyResolved)
1284 : Q->handleFullyResolved();
1285 :
1286 : if (ActionFlags & NotifyFullyReady)
1287 92 : Q->handleFullyReady();
1288 :
1289 : // FIXME: Swap back to the old code below once RuntimeDyld works with
1290 92 : // callbacks from asynchronous queries.
1291 : // Add MUs to the OutstandingMUs list.
1292 : {
1293 : std::lock_guard<std::recursive_mutex> Lock(ES.OutstandingMUsMutex);
1294 : for (auto &MU : MUs)
1295 330 : ES.OutstandingMUs.push_back(make_pair(this, std::move(MU)));
1296 146 : }
1297 : ES.runOutstandingMUs();
1298 :
1299 : // Dispatch any required MaterializationUnits for materialization.
1300 : // for (auto &MU : MUs)
1301 146 : // ES.dispatchMaterialization(*this, std::move(MU));
1302 :
1303 : return Unresolved;
1304 : }
1305 :
1306 14 : JITDylib::LookupImplActionFlags
1307 : JITDylib::lookupImpl(std::shared_ptr<AsynchronousSymbolQuery> &Q,
1308 : std::vector<std::unique_ptr<MaterializationUnit>> &MUs,
1309 6 : SymbolNameSet &Unresolved) {
1310 6 : LookupImplActionFlags ActionFlags = None;
1311 : std::vector<SymbolStringPtr> ToRemove;
1312 :
1313 : for (auto Name : Unresolved) {
1314 :
1315 : // Search for the name in Symbols. Skip it if not found.
1316 100 : auto SymI = Symbols.find(Name);
1317 100 : if (SymI == Symbols.end())
1318 200 : continue;
1319 :
1320 : // If we found Name, mark it to be removed from the Unresolved set.
1321 : ToRemove.push_back(Name);
1322 236 :
1323 : // If the symbol has an address then resolve it.
1324 130 : if (SymI->second.getAddress() != 0) {
1325 : Q->resolve(Name, SymI->second);
1326 3 : if (Q->isFullyResolved())
1327 : ActionFlags |= NotifyFullyResolved;
1328 : }
1329 :
1330 3 : // If the symbol is lazy, get the MaterialiaztionUnit for it.
1331 : if (SymI->second.getFlags().isLazy()) {
1332 3 : assert(SymI->second.getAddress() == 0 &&
1333 3 : "Lazy symbol should not have a resolved address");
1334 : assert(!SymI->second.getFlags().isMaterializing() &&
1335 : "Materializing and lazy should not both be set");
1336 3 : auto UMII = UnmaterializedInfos.find(Name);
1337 : assert(UMII != UnmaterializedInfos.end() &&
1338 : "Lazy symbol should have UnmaterializedInfo");
1339 : auto MU = std::move(UMII->second->MU);
1340 : assert(MU != nullptr && "Materializer should not be null");
1341 :
1342 : // Kick all symbols associated with this MaterializationUnit into
1343 : // materializing state.
1344 : for (auto &KV : MU->getSymbols()) {
1345 : auto SymK = Symbols.find(KV.first);
1346 : auto Flags = SymK->second.getFlags();
1347 : Flags &= ~JITSymbolFlags::Lazy;
1348 : Flags |= JITSymbolFlags::Materializing;
1349 : SymK->second.setFlags(Flags);
1350 : UnmaterializedInfos.erase(KV.first);
1351 : }
1352 :
1353 : // Add MU to the list of MaterializationUnits to be materialized.
1354 : MUs.push_back(std::move(MU));
1355 6 : } else if (!SymI->second.getFlags().isMaterializing()) {
1356 0 : // The symbol is neither lazy nor materializing, so it must be ready.
1357 : // Notify the query and continue.
1358 6 : Q->notifySymbolReady();
1359 0 : if (Q->isFullyReady())
1360 : ActionFlags |= NotifyFullyReady;
1361 : continue;
1362 : }
1363 :
1364 : // Add the query to the PendingQueries list.
1365 3 : assert(SymI->second.getFlags().isMaterializing() &&
1366 5 : "By this line the symbol should be materializing");
1367 4 : auto &MI = MaterializingInfos[Name];
1368 : MI.PendingQueries.push_back(Q);
1369 3 : Q->addQueryDependence(*this, Name);
1370 : }
1371 :
1372 : // Remove any marked symbols from the Unresolved set.
1373 : for (auto &Name : ToRemove)
1374 : Unresolved.erase(Name);
1375 3 :
1376 : return ActionFlags;
1377 : }
1378 :
1379 3 : void JITDylib::dump(raw_ostream &OS) {
1380 : ES.runSessionLocked([&, this]() {
1381 : OS << "JITDylib \"" << JITDylibName
1382 : << "\" (ES: " << format("0x%016x", reinterpret_cast<uintptr_t>(&ES))
1383 3 : << "):\n"
1384 : << "Symbol table:\n";
1385 7 :
1386 : for (auto &KV : Symbols) {
1387 : OS << " \"" << *KV.first << "\": ";
1388 4 : if (auto Addr = KV.second.getAddress())
1389 4 : OS << format("0x%016x", Addr);
1390 : else
1391 : OS << "<not resolved>";
1392 : if (KV.second.getFlags().isLazy() ||
1393 3 : KV.second.getFlags().isMaterializing()) {
1394 : OS << " (";
1395 : if (KV.second.getFlags().isLazy()) {
1396 3 : auto I = UnmaterializedInfos.find(KV.first);
1397 0 : assert(I != UnmaterializedInfos.end() &&
1398 0 : "Lazy symbol should have UnmaterializedInfo");
1399 : OS << " Lazy (MU=" << I->second->MU.get() << ")";
1400 : }
1401 : if (KV.second.getFlags().isMaterializing())
1402 : OS << " Materializing";
1403 3 : OS << " )\n";
1404 : } else
1405 : OS << "\n";
1406 : }
1407 :
1408 2 : if (!MaterializingInfos.empty())
1409 : OS << " MaterializingInfos entries:\n";
1410 : for (auto &KV : MaterializingInfos) {
1411 2 : OS << " \"" << *KV.first << "\":\n"
1412 : << " IsEmitted = " << (KV.second.IsEmitted ? "true" : "false")
1413 : << "\n"
1414 : << " " << KV.second.PendingQueries.size()
1415 : << " pending queries: { ";
1416 7 : for (auto &Q : KV.second.PendingQueries)
1417 3 : OS << Q.get() << " ";
1418 : OS << "}\n Dependants:\n";
1419 : for (auto &KV2 : KV.second.Dependants)
1420 : OS << " " << KV2.first->getName() << ": " << KV2.second << "\n";
1421 : OS << " Unemitted Dependencies:\n";
1422 3 : for (auto &KV2 : KV.second.UnemittedDependencies)
1423 : OS << " " << KV2.first->getName() << ": " << KV2.second << "\n";
1424 : }
1425 : });
1426 : }
1427 1 :
1428 : JITDylib::JITDylib(ExecutionSession &ES, std::string Name)
1429 : : ES(ES), JITDylibName(std::move(Name)) {
1430 0 : SearchOrder.push_back(this);
1431 0 : }
1432 :
1433 0 : Error JITDylib::defineImpl(MaterializationUnit &MU) {
1434 : SymbolNameSet Duplicates;
1435 : SymbolNameSet MUDefsOverridden;
1436 :
1437 : struct ExistingDefOverriddenEntry {
1438 : SymbolMap::iterator ExistingDefItr;
1439 3 : JITSymbolFlags NewFlags;
1440 3 : };
1441 6 : std::vector<ExistingDefOverriddenEntry> ExistingDefsOverridden;
1442 :
1443 : for (auto &KV : MU.getSymbols()) {
1444 : assert(!KV.second.isLazy() && "Lazy flag should be managed internally.");
1445 6 : assert(!KV.second.isMaterializing() &&
1446 : "Materializing flags should be managed internally.");
1447 :
1448 3 : SymbolMap::iterator EntryItr;
1449 : bool Added;
1450 :
1451 0 : auto NewFlags = KV.second;
1452 0 : NewFlags |= JITSymbolFlags::Lazy;
1453 :
1454 : std::tie(EntryItr, Added) = Symbols.insert(
1455 : std::make_pair(KV.first, JITEvaluatedSymbol(0, NewFlags)));
1456 :
1457 : if (!Added) {
1458 : if (KV.second.isStrong()) {
1459 : if (EntryItr->second.getFlags().isStrong() ||
1460 : (EntryItr->second.getFlags() & JITSymbolFlags::Materializing))
1461 : Duplicates.insert(KV.first);
1462 : else
1463 : ExistingDefsOverridden.push_back({EntryItr, NewFlags});
1464 : } else
1465 : MUDefsOverridden.insert(KV.first);
1466 : }
1467 : }
1468 :
1469 : if (!Duplicates.empty()) {
1470 : // We need to remove the symbols we added.
1471 : for (auto &KV : MU.getSymbols()) {
1472 : if (Duplicates.count(KV.first))
1473 : continue;
1474 :
1475 : bool Found = false;
1476 : for (const auto &EDO : ExistingDefsOverridden)
1477 : if (EDO.ExistingDefItr->first == KV.first)
1478 : Found = true;
1479 :
1480 : if (!Found)
1481 : Symbols.erase(KV.first);
1482 : }
1483 :
1484 : // FIXME: Return all duplicates.
1485 : return make_error<DuplicateDefinition>(**Duplicates.begin());
1486 : }
1487 :
1488 : // Update flags on existing defs and call discard on their materializers.
1489 : for (auto &EDO : ExistingDefsOverridden) {
1490 : assert(EDO.ExistingDefItr->second.getFlags().isLazy() &&
1491 : !EDO.ExistingDefItr->second.getFlags().isMaterializing() &&
1492 : "Overridden existing def should be in the Lazy state");
1493 :
1494 : EDO.ExistingDefItr->second.setFlags(EDO.NewFlags);
1495 :
1496 : auto UMII = UnmaterializedInfos.find(EDO.ExistingDefItr->first);
1497 : assert(UMII != UnmaterializedInfos.end() &&
1498 0 : "Overridden existing def should have an UnmaterializedInfo");
1499 :
1500 224 : UMII->second->MU->doDiscard(*this, EDO.ExistingDefItr->first);
1501 448 : }
1502 224 :
1503 224 : // Discard overridden symbols povided by MU.
1504 : for (auto &Sym : MUDefsOverridden)
1505 96 : MU.doDiscard(*this, Sym);
1506 :
1507 : return Error::success();
1508 : }
1509 :
1510 : void JITDylib::detachQueryHelper(AsynchronousSymbolQuery &Q,
1511 : const SymbolNameSet &QuerySymbols) {
1512 : for (auto &QuerySymbol : QuerySymbols) {
1513 : assert(MaterializingInfos.count(QuerySymbol) &&
1514 : "QuerySymbol does not have MaterializingInfo");
1515 343 : auto &MI = MaterializingInfos[QuerySymbol];
1516 :
1517 : auto IdenticalQuery =
1518 : [&](const std::shared_ptr<AsynchronousSymbolQuery> &R) {
1519 : return R.get() == &Q;
1520 151 : };
1521 :
1522 : auto I = std::find_if(MI.PendingQueries.begin(), MI.PendingQueries.end(),
1523 151 : IdenticalQuery);
1524 : assert(I != MI.PendingQueries.end() &&
1525 : "Query Q should be in the PendingQueries list for QuerySymbol");
1526 151 : MI.PendingQueries.erase(I);
1527 151 : }
1528 : }
1529 151 :
1530 : void JITDylib::transferEmittedNodeDependencies(
1531 5 : MaterializingInfo &DependantMI, const SymbolStringPtr &DependantName,
1532 : MaterializingInfo &EmittedMI) {
1533 1 : for (auto &KV : EmittedMI.UnemittedDependencies) {
1534 : auto &DependencyJD = *KV.first;
1535 4 : SymbolNameSet *UnemittedDependenciesOnDependencyJD = nullptr;
1536 :
1537 3 : for (auto &DependencyName : KV.second) {
1538 : auto &DependencyMI = DependencyJD.MaterializingInfos[DependencyName];
1539 :
1540 : // Do not add self dependencies.
1541 96 : if (&DependencyMI == &DependantMI)
1542 : continue;
1543 3 :
1544 1 : // If we haven't looked up the dependencies for DependencyJD yet, do it
1545 1 : // now and cache the result.
1546 : if (!UnemittedDependenciesOnDependencyJD)
1547 : UnemittedDependenciesOnDependencyJD =
1548 0 : &DependantMI.UnemittedDependencies[&DependencyJD];
1549 0 :
1550 : DependencyMI.Dependants[this].insert(DependantName);
1551 : UnemittedDependenciesOnDependencyJD->insert(DependencyName);
1552 0 : }
1553 0 : }
1554 : }
1555 :
1556 : ExecutionSession::ExecutionSession(std::shared_ptr<SymbolStringPool> SSP)
1557 2 : : SSP(SSP ? std::move(SSP) : std::make_shared<SymbolStringPool>()) {
1558 : // Construct the main dylib.
1559 : JDs.push_back(std::unique_ptr<JITDylib>(new JITDylib(*this, "<main>")));
1560 : }
1561 99 :
1562 : JITDylib &ExecutionSession::getMainJITDylib() {
1563 : return runSessionLocked([this]() -> JITDylib & { return *JDs.front(); });
1564 : }
1565 :
1566 4 : JITDylib &ExecutionSession::createJITDylib(std::string Name,
1567 : bool AddToMainDylibSearchOrder) {
1568 4 : return runSessionLocked([&, this]() -> JITDylib & {
1569 : JDs.push_back(
1570 : std::unique_ptr<JITDylib>(new JITDylib(*this, std::move(Name))));
1571 : if (AddToMainDylibSearchOrder)
1572 8 : JDs.front()->addToSearchOrder(*JDs.back());
1573 : return *JDs.back();
1574 : });
1575 : }
1576 98 :
1577 : void ExecutionSession::legacyFailQuery(AsynchronousSymbolQuery &Q, Error Err) {
1578 : assert(!!Err && "Error should be in failure state");
1579 :
1580 : bool SendErrorToQuery;
1581 : runSessionLocked([&]() {
1582 1 : Q.detach();
1583 : SendErrorToQuery = Q.canStillFail();
1584 3 : });
1585 :
1586 : if (SendErrorToQuery)
1587 2 : Q.handleFailed(std::move(Err));
1588 : else
1589 : reportError(std::move(Err));
1590 : }
1591 0 :
1592 : Expected<SymbolMap> ExecutionSession::legacyLookup(
1593 : LegacyAsyncLookupFunction AsyncLookup, SymbolNameSet Names,
1594 : bool WaitUntilReady, RegisterDependenciesFunction RegisterDependencies) {
1595 : #if LLVM_ENABLE_THREADS
1596 : // In the threaded case we use promises to return the results.
1597 : std::promise<SymbolMap> PromisedResult;
1598 2 : std::mutex ErrMutex;
1599 : Error ResolutionError = Error::success();
1600 1 : std::promise<void> PromisedReady;
1601 : Error ReadyError = Error::success();
1602 48 : auto OnResolve = [&](Expected<SymbolMap> R) {
1603 : if (R)
1604 : PromisedResult.set_value(std::move(*R));
1605 62 : else {
1606 14 : {
1607 : ErrorAsOutParameter _(&ResolutionError);
1608 : std::lock_guard<std::mutex> Lock(ErrMutex);
1609 31 : ResolutionError = R.takeError();
1610 17 : }
1611 : PromisedResult.set_value(SymbolMap());
1612 : }
1613 17 : };
1614 :
1615 : std::function<void(Error)> OnReady;
1616 : if (WaitUntilReady) {
1617 : OnReady = [&](Error Err) {
1618 13 : if (Err) {
1619 : ErrorAsOutParameter _(&ReadyError);
1620 12 : std::lock_guard<std::mutex> Lock(ErrMutex);
1621 : ReadyError = std::move(Err);
1622 26 : }
1623 : PromisedReady.set_value();
1624 : };
1625 : } else {
1626 48 : OnReady = [&](Error Err) {
1627 : if (Err)
1628 163 : reportError(std::move(Err));
1629 489 : };
1630 : }
1631 326 :
1632 163 : #else
1633 : SymbolMap Result;
1634 13 : Error ResolutionError = Error::success();
1635 13 : Error ReadyError = Error::success();
1636 :
1637 : auto OnResolve = [&](Expected<SymbolMap> R) {
1638 61 : ErrorAsOutParameter _(&ResolutionError);
1639 : if (R)
1640 : Result = std::move(*R);
1641 : else
1642 : ResolutionError = R.takeError();
1643 : };
1644 :
1645 : std::function<void(Error)> OnReady;
1646 61 : if (WaitUntilReady) {
1647 : OnReady = [&](Error Err) {
1648 : ErrorAsOutParameter _(&ReadyError);
1649 1 : if (Err)
1650 : ReadyError = std::move(Err);
1651 : };
1652 : } else {
1653 1 : OnReady = [&](Error Err) {
1654 : if (Err)
1655 : reportError(std::move(Err));
1656 : };
1657 : }
1658 1 : #endif
1659 2 :
1660 : auto Query = std::make_shared<AsynchronousSymbolQuery>(
1661 0 : Names, std::move(OnResolve), std::move(OnReady));
1662 1 : // FIXME: This should be run session locked along with the registration code
1663 : // and error reporting below.
1664 0 : SymbolNameSet UnresolvedSymbols = AsyncLookup(Query, std::move(Names));
1665 :
1666 : // If the query was lodged successfully then register the dependencies,
1667 : // otherwise fail it with an error.
1668 : if (UnresolvedSymbols.empty())
1669 0 : RegisterDependencies(Query->QueryRegistrations);
1670 0 : else {
1671 : bool DeliverError = runSessionLocked([&]() {
1672 0 : Query->detach();
1673 : return Query->canStillFail();
1674 : });
1675 : auto Err = make_error<SymbolsNotFound>(std::move(UnresolvedSymbols));
1676 : if (DeliverError)
1677 : Query->handleFailed(std::move(Err));
1678 : else
1679 : reportError(std::move(Err));
1680 : }
1681 :
1682 : #if LLVM_ENABLE_THREADS
1683 : auto ResultFuture = PromisedResult.get_future();
1684 : auto Result = ResultFuture.get();
1685 0 :
1686 : {
1687 : std::lock_guard<std::mutex> Lock(ErrMutex);
1688 0 : if (ResolutionError) {
1689 : // ReadyError will never be assigned. Consume the success value.
1690 : cantFail(std::move(ReadyError));
1691 : return std::move(ResolutionError);
1692 : }
1693 : }
1694 :
1695 : if (WaitUntilReady) {
1696 0 : auto ReadyFuture = PromisedReady.get_future();
1697 : ReadyFuture.get();
1698 :
1699 : {
1700 : std::lock_guard<std::mutex> Lock(ErrMutex);
1701 0 : if (ReadyError)
1702 : return std::move(ReadyError);
1703 : }
1704 : } else
1705 : cantFail(std::move(ReadyError));
1706 :
1707 : return std::move(Result);
1708 :
1709 : #else
1710 : if (ResolutionError) {
1711 : // ReadyError will never be assigned. Consume the success value.
1712 : cantFail(std::move(ReadyError));
1713 : return std::move(ResolutionError);
1714 : }
1715 :
1716 : if (ReadyError)
1717 : return std::move(ReadyError);
1718 :
1719 : return Result;
1720 : #endif
1721 : }
1722 :
1723 : void ExecutionSession::lookup(const JITDylibList &JDs, SymbolNameSet Symbols,
1724 : SymbolsResolvedCallback OnResolve,
1725 : SymbolsReadyCallback OnReady,
1726 : RegisterDependenciesFunction RegisterDependencies,
1727 : JITDylib *MatchNonExportedInJD,
1728 : bool MatchNonExported) {
1729 :
1730 : // lookup can be re-entered recursively if running on a single thread. Run any
1731 : // outstanding MUs in case this query depends on them, otherwise this lookup
1732 : // will starve waiting for a result from an MU that is stuck in the queue.
1733 : runOutstandingMUs();
1734 :
1735 : auto Unresolved = std::move(Symbols);
1736 0 : std::map<JITDylib *, MaterializationUnitList> CollectedMUsMap;
1737 : auto Q = std::make_shared<AsynchronousSymbolQuery>(
1738 : Unresolved, std::move(OnResolve), std::move(OnReady));
1739 : bool QueryIsFullyResolved = false;
1740 0 : bool QueryIsFullyReady = false;
1741 0 : bool QueryFailed = false;
1742 :
1743 0 : runSessionLocked([&]() {
1744 : for (auto *JD : JDs) {
1745 : assert(JD && "JITDylibList entries must not be null");
1746 : assert(!CollectedMUsMap.count(JD) &&
1747 : "JITDylibList should not contain duplicate entries");
1748 0 : JD->lodgeQuery(Q, Unresolved, MatchNonExportedInJD, MatchNonExported,
1749 0 : CollectedMUsMap[JD]);
1750 : }
1751 0 :
1752 : if (Unresolved.empty()) {
1753 : // Query lodged successfully.
1754 :
1755 : // Record whether this query is fully ready / resolved. We will use
1756 0 : // this to call handleFullyResolved/handleFullyReady outside the session
1757 : // lock.
1758 : QueryIsFullyResolved = Q->isFullyResolved();
1759 : QueryIsFullyReady = Q->isFullyReady();
1760 0 :
1761 : // Call the register dependencies function.
1762 : if (RegisterDependencies && !Q->QueryRegistrations.empty())
1763 : RegisterDependencies(Q->QueryRegistrations);
1764 : } else {
1765 : // Query failed due to unresolved symbols.
1766 : QueryFailed = true;
1767 0 :
1768 : // Disconnect the query from its dependencies.
1769 0 : Q->detach();
1770 :
1771 : // Replace the MUs.
1772 : for (auto &KV : CollectedMUsMap)
1773 0 : for (auto &MU : KV.second)
1774 : KV.first->replace(std::move(MU));
1775 : }
1776 : });
1777 :
1778 : if (QueryFailed) {
1779 : Q->handleFailed(make_error<SymbolsNotFound>(std::move(Unresolved)));
1780 : return;
1781 : } else {
1782 : if (QueryIsFullyResolved)
1783 : Q->handleFullyResolved();
1784 : if (QueryIsFullyReady)
1785 : Q->handleFullyReady();
1786 : }
1787 :
1788 : // Move the MUs to the OutstandingMUs list, then materialize.
1789 : {
1790 : std::lock_guard<std::recursive_mutex> Lock(OutstandingMUsMutex);
1791 :
1792 : for (auto &KV : CollectedMUsMap)
1793 : for (auto &MU : KV.second)
1794 : OutstandingMUs.push_back(std::make_pair(KV.first, std::move(MU)));
1795 111 : }
1796 :
1797 : runOutstandingMUs();
1798 : }
1799 :
1800 : Expected<SymbolMap>
1801 : ExecutionSession::lookup(const JITDylibList &JDs, const SymbolNameSet &Symbols,
1802 : RegisterDependenciesFunction RegisterDependencies,
1803 : bool WaitUntilReady, JITDylib *MatchNonExportedInJD,
1804 : bool MatchNonExported) {
1805 111 : #if LLVM_ENABLE_THREADS
1806 : // In the threaded case we use promises to return the results.
1807 : std::promise<SymbolMap> PromisedResult;
1808 : std::mutex ErrMutex;
1809 : Error ResolutionError = Error::success();
1810 : std::promise<void> PromisedReady;
1811 111 : Error ReadyError = Error::success();
1812 111 : auto OnResolve = [&](Expected<SymbolMap> R) {
1813 111 : if (R)
1814 : PromisedResult.set_value(std::move(*R));
1815 111 : else {
1816 : {
1817 : ErrorAsOutParameter _(&ResolutionError);
1818 : std::lock_guard<std::mutex> Lock(ErrMutex);
1819 : ResolutionError = R.takeError();
1820 : }
1821 : PromisedResult.set_value(SymbolMap());
1822 : }
1823 : };
1824 :
1825 : std::function<void(Error)> OnReady;
1826 : if (WaitUntilReady) {
1827 : OnReady = [&](Error Err) {
1828 : if (Err) {
1829 : ErrorAsOutParameter _(&ReadyError);
1830 : std::lock_guard<std::mutex> Lock(ErrMutex);
1831 : ReadyError = std::move(Err);
1832 : }
1833 : PromisedReady.set_value();
1834 : };
1835 : } else {
1836 : OnReady = [&](Error Err) {
1837 : if (Err)
1838 : reportError(std::move(Err));
1839 : };
1840 : }
1841 :
1842 : #else
1843 : SymbolMap Result;
1844 : Error ResolutionError = Error::success();
1845 : Error ReadyError = Error::success();
1846 :
1847 : auto OnResolve = [&](Expected<SymbolMap> R) {
1848 : ErrorAsOutParameter _(&ResolutionError);
1849 : if (R)
1850 111 : Result = std::move(*R);
1851 0 : else
1852 : ResolutionError = R.takeError();
1853 : };
1854 111 :
1855 31 : std::function<void(Error)> OnReady;
1856 111 : if (WaitUntilReady) {
1857 29 : OnReady = [&](Error Err) {
1858 : ErrorAsOutParameter _(&ReadyError);
1859 : if (Err)
1860 : ReadyError = std::move(Err);
1861 : };
1862 111 : } else {
1863 : OnReady = [&](Error Err) {
1864 237 : if (Err)
1865 218 : reportError(std::move(Err));
1866 184 : };
1867 : }
1868 : #endif
1869 111 :
1870 : // Perform the asynchronous lookup.
1871 : lookup(JDs, Symbols, OnResolve, OnReady, RegisterDependencies,
1872 : MatchNonExportedInJD, MatchNonExported);
1873 74 :
1874 : #if LLVM_ENABLE_THREADS
1875 : auto ResultFuture = PromisedResult.get_future();
1876 : auto Result = ResultFuture.get();
1877 :
1878 : {
1879 148 : std::lock_guard<std::mutex> Lock(ErrMutex);
1880 74 : if (ResolutionError) {
1881 : // ReadyError will never be assigned. Consume the success value.
1882 148 : cantFail(std::move(ReadyError));
1883 : return std::move(ResolutionError);
1884 : }
1885 : }
1886 :
1887 : if (WaitUntilReady) {
1888 : auto ReadyFuture = PromisedReady.get_future();
1889 : ReadyFuture.get();
1890 :
1891 : {
1892 : std::lock_guard<std::mutex> Lock(ErrMutex);
1893 : if (ReadyError)
1894 : return std::move(ReadyError);
1895 : }
1896 : } else
1897 : cantFail(std::move(ReadyError));
1898 74 :
1899 : return std::move(Result);
1900 :
1901 : #else
1902 : if (ResolutionError) {
1903 : // ReadyError will never be assigned. Consume the success value.
1904 : cantFail(std::move(ReadyError));
1905 : return std::move(ResolutionError);
1906 74 : }
1907 :
1908 : if (ReadyError)
1909 : return std::move(ReadyError);
1910 :
1911 0 : return Result;
1912 : #endif
1913 : }
1914 :
1915 : /// Look up a symbol by searching a list of JDs.
1916 : Expected<JITEvaluatedSymbol> ExecutionSession::lookup(const JITDylibList &JDs,
1917 : SymbolStringPtr Name,
1918 : bool MatchNonExported) {
1919 : SymbolNameSet Names({Name});
1920 :
1921 : if (auto ResultMap = lookup(JDs, std::move(Names), NoDependenciesToRegister,
1922 : true, nullptr, MatchNonExported)) {
1923 : assert(ResultMap->size() == 1 && "Unexpected number of results");
1924 : assert(ResultMap->count(Name) && "Missing result for symbol");
1925 : return std::move(ResultMap->begin()->second);
1926 : } else
1927 : return ResultMap.takeError();
1928 : }
1929 :
1930 : Expected<JITEvaluatedSymbol> ExecutionSession::lookup(const JITDylibList &JDs,
1931 : StringRef Name,
1932 : bool MatchNonExported) {
1933 : return lookup(JDs, intern(Name), MatchNonExported);
1934 : }
1935 :
1936 : void ExecutionSession::dump(raw_ostream &OS) {
1937 : runSessionLocked([this, &OS]() {
1938 : for (auto &JD : JDs)
1939 : JD->dump(OS);
1940 : });
1941 : }
1942 :
1943 222 : void ExecutionSession::runOutstandingMUs() {
1944 : while (1) {
1945 : std::pair<JITDylib *, std::unique_ptr<MaterializationUnit>> JITDylibAndMU;
1946 :
1947 : {
1948 74 : std::lock_guard<std::recursive_mutex> Lock(OutstandingMUsMutex);
1949 : if (!OutstandingMUs.empty()) {
1950 : JITDylibAndMU = std::move(OutstandingMUs.back());
1951 : OutstandingMUs.pop_back();
1952 74 : }
1953 : }
1954 :
1955 : if (JITDylibAndMU.first) {
1956 : assert(JITDylibAndMU.second && "JITDylib, but no MU?");
1957 : dispatchMaterialization(*JITDylibAndMU.first,
1958 : std::move(JITDylibAndMU.second));
1959 73 : } else
1960 : break;
1961 73 : }
1962 : }
1963 :
1964 : MangleAndInterner::MangleAndInterner(ExecutionSession &ES, const DataLayout &DL)
1965 73 : : ES(ES), DL(DL) {}
1966 :
1967 : SymbolStringPtr MangleAndInterner::operator()(StringRef Name) {
1968 : std::string MangledName;
1969 : {
1970 : raw_string_ostream MangledNameStream(MangledName);
1971 : Mangler::getNameWithPrefix(MangledNameStream, Name, DL);
1972 : }
1973 : return ES.intern(MangledName);
1974 : }
1975 :
1976 : } // End namespace orc.
1977 : } // End namespace llvm.
|