1 //===------ Core.h -- Core ORC APIs (Layer, JITDylib, etc.) -----*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Contains core ORC APIs.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #ifndef LLVM_EXECUTIONENGINE_ORC_CORE_H
14 #define LLVM_EXECUTIONENGINE_ORC_CORE_H
15
16 #include "llvm/ADT/BitmaskEnum.h"
17 #include "llvm/ADT/DenseSet.h"
18 #include "llvm/ADT/FunctionExtras.h"
19 #include "llvm/ADT/IntrusiveRefCntPtr.h"
20 #include "llvm/ExecutionEngine/JITLink/JITLinkDylib.h"
21 #include "llvm/ExecutionEngine/JITSymbol.h"
22 #include "llvm/ExecutionEngine/Orc/SymbolStringPool.h"
23 #include "llvm/ExecutionEngine/OrcV1Deprecation.h"
24 #include "llvm/Support/Debug.h"
25 #include "llvm/Support/ExtensibleRTTI.h"
26
27 #include <atomic>
28 #include <memory>
29 #include <vector>
30
31 namespace llvm {
32 namespace orc {
33
34 // Forward declare some classes.
35 class AsynchronousSymbolQuery;
36 class ExecutionSession;
37 class MaterializationUnit;
38 class MaterializationResponsibility;
39 class JITDylib;
40 class ResourceTracker;
41 class InProgressLookupState;
42
43 enum class SymbolState : uint8_t;
44
45 using ResourceTrackerSP = IntrusiveRefCntPtr<ResourceTracker>;
46 using JITDylibSP = IntrusiveRefCntPtr<JITDylib>;
47
48 using ResourceKey = uintptr_t;
49
50 /// API to remove / transfer ownership of JIT resources.
51 class ResourceTracker : public ThreadSafeRefCountedBase<ResourceTracker> {
52 private:
53 friend class ExecutionSession;
54 friend class JITDylib;
55 friend class MaterializationResponsibility;
56
57 public:
58 ResourceTracker(const ResourceTracker &) = delete;
59 ResourceTracker &operator=(const ResourceTracker &) = delete;
60 ResourceTracker(ResourceTracker &&) = delete;
61 ResourceTracker &operator=(ResourceTracker &&) = delete;
62
63 ~ResourceTracker();
64
65 /// Return the JITDylib targeted by this tracker.
getJITDylib()66 JITDylib &getJITDylib() const {
67 return *reinterpret_cast<JITDylib *>(JDAndFlag.load() &
68 ~static_cast<uintptr_t>(1));
69 }
70
71 /// Remove all resources associated with this key.
72 Error remove();
73
74 /// Transfer all resources associated with this key to the given
75 /// tracker, which must target the same JITDylib as this one.
76 void transferTo(ResourceTracker &DstRT);
77
78 /// Return true if this tracker has become defunct.
isDefunct()79 bool isDefunct() const { return JDAndFlag.load() & 0x1; }
80
81 /// Returns the key associated with this tracker.
82 /// This method should not be used except for debug logging: there is no
83 /// guarantee that the returned value will remain valid.
getKeyUnsafe()84 ResourceKey getKeyUnsafe() const { return reinterpret_cast<uintptr_t>(this); }
85
86 private:
87 ResourceTracker(JITDylibSP JD);
88
89 void makeDefunct();
90
91 std::atomic_uintptr_t JDAndFlag;
92 };
93
94 /// Listens for ResourceTracker operations.
95 class ResourceManager {
96 public:
97 virtual ~ResourceManager();
98 virtual Error handleRemoveResources(ResourceKey K) = 0;
99 virtual void handleTransferResources(ResourceKey DstK, ResourceKey SrcK) = 0;
100 };
101
102 /// A set of symbol names (represented by SymbolStringPtrs for
103 // efficiency).
104 using SymbolNameSet = DenseSet<SymbolStringPtr>;
105
106 /// A vector of symbol names.
107 using SymbolNameVector = std::vector<SymbolStringPtr>;
108
109 /// A map from symbol names (as SymbolStringPtrs) to JITSymbols
110 /// (address/flags pairs).
111 using SymbolMap = DenseMap<SymbolStringPtr, JITEvaluatedSymbol>;
112
113 /// A map from symbol names (as SymbolStringPtrs) to JITSymbolFlags.
114 using SymbolFlagsMap = DenseMap<SymbolStringPtr, JITSymbolFlags>;
115
116 /// A map from JITDylibs to sets of symbols.
117 using SymbolDependenceMap = DenseMap<JITDylib *, SymbolNameSet>;
118
119 /// Lookup flags that apply to each dylib in the search order for a lookup.
120 ///
121 /// If MatchHiddenSymbolsOnly is used (the default) for a given dylib, then
122 /// only symbols in that Dylib's interface will be searched. If
123 /// MatchHiddenSymbols is used then symbols with hidden visibility will match
124 /// as well.
125 enum class JITDylibLookupFlags { MatchExportedSymbolsOnly, MatchAllSymbols };
126
127 /// Lookup flags that apply to each symbol in a lookup.
128 ///
129 /// If RequiredSymbol is used (the default) for a given symbol then that symbol
130 /// must be found during the lookup or the lookup will fail returning a
131 /// SymbolNotFound error. If WeaklyReferencedSymbol is used and the given
132 /// symbol is not found then the query will continue, and no result for the
133 /// missing symbol will be present in the result (assuming the rest of the
134 /// lookup succeeds).
135 enum class SymbolLookupFlags { RequiredSymbol, WeaklyReferencedSymbol };
136
137 /// Describes the kind of lookup being performed. The lookup kind is passed to
138 /// symbol generators (if they're invoked) to help them determine what
139 /// definitions to generate.
140 ///
141 /// Static -- Lookup is being performed as-if at static link time (e.g.
142 /// generators representing static archives should pull in new
143 /// definitions).
144 ///
145 /// DLSym -- Lookup is being performed as-if at runtime (e.g. generators
146 /// representing static archives should not pull in new definitions).
147 enum class LookupKind { Static, DLSym };
148
149 /// A list of (JITDylib*, JITDylibLookupFlags) pairs to be used as a search
150 /// order during symbol lookup.
151 using JITDylibSearchOrder =
152 std::vector<std::pair<JITDylib *, JITDylibLookupFlags>>;
153
154 /// Convenience function for creating a search order from an ArrayRef of
155 /// JITDylib*, all with the same flags.
156 inline JITDylibSearchOrder makeJITDylibSearchOrder(
157 ArrayRef<JITDylib *> JDs,
158 JITDylibLookupFlags Flags = JITDylibLookupFlags::MatchExportedSymbolsOnly) {
159 JITDylibSearchOrder O;
160 O.reserve(JDs.size());
161 for (auto *JD : JDs)
162 O.push_back(std::make_pair(JD, Flags));
163 return O;
164 }
165
166 /// A set of symbols to look up, each associated with a SymbolLookupFlags
167 /// value.
168 ///
169 /// This class is backed by a vector and optimized for fast insertion,
170 /// deletion and iteration. It does not guarantee a stable order between
171 /// operations, and will not automatically detect duplicate elements (they
172 /// can be manually checked by calling the validate method).
173 class SymbolLookupSet {
174 public:
175 using value_type = std::pair<SymbolStringPtr, SymbolLookupFlags>;
176 using UnderlyingVector = std::vector<value_type>;
177 using iterator = UnderlyingVector::iterator;
178 using const_iterator = UnderlyingVector::const_iterator;
179
180 SymbolLookupSet() = default;
181
182 explicit SymbolLookupSet(
183 SymbolStringPtr Name,
184 SymbolLookupFlags Flags = SymbolLookupFlags::RequiredSymbol) {
185 add(std::move(Name), Flags);
186 }
187
188 /// Construct a SymbolLookupSet from an initializer list of SymbolStringPtrs.
189 explicit SymbolLookupSet(
190 std::initializer_list<SymbolStringPtr> Names,
191 SymbolLookupFlags Flags = SymbolLookupFlags::RequiredSymbol) {
192 Symbols.reserve(Names.size());
193 for (auto &Name : Names)
194 add(std::move(Name), Flags);
195 }
196
197 /// Construct a SymbolLookupSet from a SymbolNameSet with the given
198 /// Flags used for each value.
199 explicit SymbolLookupSet(
200 const SymbolNameSet &Names,
201 SymbolLookupFlags Flags = SymbolLookupFlags::RequiredSymbol) {
202 Symbols.reserve(Names.size());
203 for (const auto &Name : Names)
204 add(Name, Flags);
205 }
206
207 /// Construct a SymbolLookupSet from a vector of symbols with the given Flags
208 /// used for each value.
209 /// If the ArrayRef contains duplicates it is up to the client to remove these
210 /// before using this instance for lookup.
211 explicit SymbolLookupSet(
212 ArrayRef<SymbolStringPtr> Names,
213 SymbolLookupFlags Flags = SymbolLookupFlags::RequiredSymbol) {
214 Symbols.reserve(Names.size());
215 for (const auto &Name : Names)
216 add(Name, Flags);
217 }
218
219 /// Add an element to the set. The client is responsible for checking that
220 /// duplicates are not added.
221 SymbolLookupSet &
222 add(SymbolStringPtr Name,
223 SymbolLookupFlags Flags = SymbolLookupFlags::RequiredSymbol) {
224 Symbols.push_back(std::make_pair(std::move(Name), Flags));
225 return *this;
226 }
227
228 /// Quickly append one lookup set to another.
append(SymbolLookupSet Other)229 SymbolLookupSet &append(SymbolLookupSet Other) {
230 Symbols.reserve(Symbols.size() + Other.size());
231 for (auto &KV : Other)
232 Symbols.push_back(std::move(KV));
233 return *this;
234 }
235
empty()236 bool empty() const { return Symbols.empty(); }
size()237 UnderlyingVector::size_type size() const { return Symbols.size(); }
begin()238 iterator begin() { return Symbols.begin(); }
end()239 iterator end() { return Symbols.end(); }
begin()240 const_iterator begin() const { return Symbols.begin(); }
end()241 const_iterator end() const { return Symbols.end(); }
242
243 /// Removes the Ith element of the vector, replacing it with the last element.
remove(UnderlyingVector::size_type I)244 void remove(UnderlyingVector::size_type I) {
245 std::swap(Symbols[I], Symbols.back());
246 Symbols.pop_back();
247 }
248
249 /// Removes the element pointed to by the given iterator. This iterator and
250 /// all subsequent ones (including end()) are invalidated.
remove(iterator I)251 void remove(iterator I) { remove(I - begin()); }
252
253 /// Removes all elements matching the given predicate, which must be callable
254 /// as bool(const SymbolStringPtr &, SymbolLookupFlags Flags).
remove_if(PredFn && Pred)255 template <typename PredFn> void remove_if(PredFn &&Pred) {
256 UnderlyingVector::size_type I = 0;
257 while (I != Symbols.size()) {
258 const auto &Name = Symbols[I].first;
259 auto Flags = Symbols[I].second;
260 if (Pred(Name, Flags))
261 remove(I);
262 else
263 ++I;
264 }
265 }
266
267 /// Loop over the elements of this SymbolLookupSet, applying the Body function
268 /// to each one. Body must be callable as
269 /// bool(const SymbolStringPtr &, SymbolLookupFlags).
270 /// If Body returns true then the element just passed in is removed from the
271 /// set. If Body returns false then the element is retained.
272 template <typename BodyFn>
273 auto forEachWithRemoval(BodyFn &&Body) -> std::enable_if_t<
274 std::is_same<decltype(Body(std::declval<const SymbolStringPtr &>(),
275 std::declval<SymbolLookupFlags>())),
276 bool>::value> {
277 UnderlyingVector::size_type I = 0;
278 while (I != Symbols.size()) {
279 const auto &Name = Symbols[I].first;
280 auto Flags = Symbols[I].second;
281 if (Body(Name, Flags))
282 remove(I);
283 else
284 ++I;
285 }
286 }
287
288 /// Loop over the elements of this SymbolLookupSet, applying the Body function
289 /// to each one. Body must be callable as
290 /// Expected<bool>(const SymbolStringPtr &, SymbolLookupFlags).
291 /// If Body returns a failure value, the loop exits immediately. If Body
292 /// returns true then the element just passed in is removed from the set. If
293 /// Body returns false then the element is retained.
294 template <typename BodyFn>
295 auto forEachWithRemoval(BodyFn &&Body) -> std::enable_if_t<
296 std::is_same<decltype(Body(std::declval<const SymbolStringPtr &>(),
297 std::declval<SymbolLookupFlags>())),
298 Expected<bool>>::value,
299 Error> {
300 UnderlyingVector::size_type I = 0;
301 while (I != Symbols.size()) {
302 const auto &Name = Symbols[I].first;
303 auto Flags = Symbols[I].second;
304 auto Remove = Body(Name, Flags);
305 if (!Remove)
306 return Remove.takeError();
307 if (*Remove)
308 remove(I);
309 else
310 ++I;
311 }
312 return Error::success();
313 }
314
315 /// Construct a SymbolNameVector from this instance by dropping the Flags
316 /// values.
getSymbolNames()317 SymbolNameVector getSymbolNames() const {
318 SymbolNameVector Names;
319 Names.reserve(Symbols.size());
320 for (auto &KV : Symbols)
321 Names.push_back(KV.first);
322 return Names;
323 }
324
325 /// Sort the lookup set by pointer value. This sort is fast but sensitive to
326 /// allocation order and so should not be used where a consistent order is
327 /// required.
sortByAddress()328 void sortByAddress() {
329 llvm::sort(Symbols, [](const value_type &LHS, const value_type &RHS) {
330 return LHS.first < RHS.first;
331 });
332 }
333
334 /// Sort the lookup set lexicographically. This sort is slow but the order
335 /// is unaffected by allocation order.
sortByName()336 void sortByName() {
337 llvm::sort(Symbols, [](const value_type &LHS, const value_type &RHS) {
338 return *LHS.first < *RHS.first;
339 });
340 }
341
342 /// Remove any duplicate elements. If a SymbolLookupSet is not duplicate-free
343 /// by construction, this method can be used to turn it into a proper set.
removeDuplicates()344 void removeDuplicates() {
345 sortByAddress();
346 auto LastI = std::unique(Symbols.begin(), Symbols.end());
347 Symbols.erase(LastI, Symbols.end());
348 }
349
350 #ifndef NDEBUG
351 /// Returns true if this set contains any duplicates. This should only be used
352 /// in assertions.
containsDuplicates()353 bool containsDuplicates() {
354 if (Symbols.size() < 2)
355 return false;
356 sortByAddress();
357 for (UnderlyingVector::size_type I = 1; I != Symbols.size(); ++I)
358 if (Symbols[I].first == Symbols[I - 1].first)
359 return true;
360 return false;
361 }
362 #endif
363
364 private:
365 UnderlyingVector Symbols;
366 };
367
368 struct SymbolAliasMapEntry {
369 SymbolAliasMapEntry() = default;
SymbolAliasMapEntrySymbolAliasMapEntry370 SymbolAliasMapEntry(SymbolStringPtr Aliasee, JITSymbolFlags AliasFlags)
371 : Aliasee(std::move(Aliasee)), AliasFlags(AliasFlags) {}
372
373 SymbolStringPtr Aliasee;
374 JITSymbolFlags AliasFlags;
375 };
376
377 /// A map of Symbols to (Symbol, Flags) pairs.
378 using SymbolAliasMap = DenseMap<SymbolStringPtr, SymbolAliasMapEntry>;
379
380 /// Callback to notify client that symbols have been resolved.
381 using SymbolsResolvedCallback = unique_function<void(Expected<SymbolMap>)>;
382
383 /// Callback to register the dependencies for a given query.
384 using RegisterDependenciesFunction =
385 std::function<void(const SymbolDependenceMap &)>;
386
387 /// This can be used as the value for a RegisterDependenciesFunction if there
388 /// are no dependants to register with.
389 extern RegisterDependenciesFunction NoDependenciesToRegister;
390
391 class ResourceTrackerDefunct : public ErrorInfo<ResourceTrackerDefunct> {
392 public:
393 static char ID;
394
395 ResourceTrackerDefunct(ResourceTrackerSP RT);
396 std::error_code convertToErrorCode() const override;
397 void log(raw_ostream &OS) const override;
398
399 private:
400 ResourceTrackerSP RT;
401 };
402
403 /// Used to notify a JITDylib that the given set of symbols failed to
404 /// materialize.
405 class FailedToMaterialize : public ErrorInfo<FailedToMaterialize> {
406 public:
407 static char ID;
408
409 FailedToMaterialize(std::shared_ptr<SymbolDependenceMap> Symbols);
410 std::error_code convertToErrorCode() const override;
411 void log(raw_ostream &OS) const override;
getSymbols()412 const SymbolDependenceMap &getSymbols() const { return *Symbols; }
413
414 private:
415 std::shared_ptr<SymbolDependenceMap> Symbols;
416 };
417
418 /// Used to notify clients when symbols can not be found during a lookup.
419 class SymbolsNotFound : public ErrorInfo<SymbolsNotFound> {
420 public:
421 static char ID;
422
423 SymbolsNotFound(SymbolNameSet Symbols);
424 SymbolsNotFound(SymbolNameVector Symbols);
425 std::error_code convertToErrorCode() const override;
426 void log(raw_ostream &OS) const override;
getSymbols()427 const SymbolNameVector &getSymbols() const { return Symbols; }
428
429 private:
430 SymbolNameVector Symbols;
431 };
432
433 /// Used to notify clients that a set of symbols could not be removed.
434 class SymbolsCouldNotBeRemoved : public ErrorInfo<SymbolsCouldNotBeRemoved> {
435 public:
436 static char ID;
437
438 SymbolsCouldNotBeRemoved(SymbolNameSet Symbols);
439 std::error_code convertToErrorCode() const override;
440 void log(raw_ostream &OS) const override;
getSymbols()441 const SymbolNameSet &getSymbols() const { return Symbols; }
442
443 private:
444 SymbolNameSet Symbols;
445 };
446
447 /// Errors of this type should be returned if a module fails to include
448 /// definitions that are claimed by the module's associated
449 /// MaterializationResponsibility. If this error is returned it is indicative of
450 /// a broken transformation / compiler / object cache.
451 class MissingSymbolDefinitions : public ErrorInfo<MissingSymbolDefinitions> {
452 public:
453 static char ID;
454
MissingSymbolDefinitions(std::string ModuleName,SymbolNameVector Symbols)455 MissingSymbolDefinitions(std::string ModuleName, SymbolNameVector Symbols)
456 : ModuleName(std::move(ModuleName)), Symbols(std::move(Symbols)) {}
457 std::error_code convertToErrorCode() const override;
458 void log(raw_ostream &OS) const override;
getModuleName()459 const std::string &getModuleName() const { return ModuleName; }
getSymbols()460 const SymbolNameVector &getSymbols() const { return Symbols; }
461 private:
462 std::string ModuleName;
463 SymbolNameVector Symbols;
464 };
465
466 /// Errors of this type should be returned if a module contains definitions for
467 /// symbols that are not claimed by the module's associated
468 /// MaterializationResponsibility. If this error is returned it is indicative of
469 /// a broken transformation / compiler / object cache.
470 class UnexpectedSymbolDefinitions : public ErrorInfo<UnexpectedSymbolDefinitions> {
471 public:
472 static char ID;
473
UnexpectedSymbolDefinitions(std::string ModuleName,SymbolNameVector Symbols)474 UnexpectedSymbolDefinitions(std::string ModuleName, SymbolNameVector Symbols)
475 : ModuleName(std::move(ModuleName)), Symbols(std::move(Symbols)) {}
476 std::error_code convertToErrorCode() const override;
477 void log(raw_ostream &OS) const override;
getModuleName()478 const std::string &getModuleName() const { return ModuleName; }
getSymbols()479 const SymbolNameVector &getSymbols() const { return Symbols; }
480 private:
481 std::string ModuleName;
482 SymbolNameVector Symbols;
483 };
484
485 /// Tracks responsibility for materialization, and mediates interactions between
486 /// MaterializationUnits and JDs.
487 ///
488 /// An instance of this class is passed to MaterializationUnits when their
489 /// materialize method is called. It allows MaterializationUnits to resolve and
490 /// emit symbols, or abandon materialization by notifying any unmaterialized
491 /// symbols of an error.
492 class MaterializationResponsibility {
493 friend class ExecutionSession;
494
495 public:
496 MaterializationResponsibility(MaterializationResponsibility &&) = delete;
497 MaterializationResponsibility &
498 operator=(MaterializationResponsibility &&) = delete;
499
500 /// Destruct a MaterializationResponsibility instance. In debug mode
501 /// this asserts that all symbols being tracked have been either
502 /// emitted or notified of an error.
503 ~MaterializationResponsibility();
504
505 /// Returns the ResourceTracker for this instance.
506 template <typename Func> Error withResourceKeyDo(Func &&F) const;
507
508 /// Returns the target JITDylib that these symbols are being materialized
509 /// into.
getTargetJITDylib()510 JITDylib &getTargetJITDylib() const { return *JD; }
511
512 /// Returns the ExecutionSession for this instance.
513 ExecutionSession &getExecutionSession();
514
515 /// Returns the symbol flags map for this responsibility instance.
516 /// Note: The returned flags may have transient flags (Lazy, Materializing)
517 /// set. These should be stripped with JITSymbolFlags::stripTransientFlags
518 /// before using.
getSymbols()519 const SymbolFlagsMap &getSymbols() const { return SymbolFlags; }
520
521 /// Returns the initialization pseudo-symbol, if any. This symbol will also
522 /// be present in the SymbolFlagsMap for this MaterializationResponsibility
523 /// object.
getInitializerSymbol()524 const SymbolStringPtr &getInitializerSymbol() const { return InitSymbol; }
525
526 /// Returns the names of any symbols covered by this
527 /// MaterializationResponsibility object that have queries pending. This
528 /// information can be used to return responsibility for unrequested symbols
529 /// back to the JITDylib via the delegate method.
530 SymbolNameSet getRequestedSymbols() const;
531
532 /// Notifies the target JITDylib that the given symbols have been resolved.
533 /// This will update the given symbols' addresses in the JITDylib, and notify
534 /// any pending queries on the given symbols of their resolution. The given
535 /// symbols must be ones covered by this MaterializationResponsibility
536 /// instance. Individual calls to this method may resolve a subset of the
537 /// symbols, but all symbols must have been resolved prior to calling emit.
538 ///
539 /// This method will return an error if any symbols being resolved have been
540 /// moved to the error state due to the failure of a dependency. If this
541 /// method returns an error then clients should log it and call
542 /// failMaterialize. If no dependencies have been registered for the
543 /// symbols covered by this MaterializationResponsibiility then this method
544 /// is guaranteed to return Error::success() and can be wrapped with cantFail.
545 Error notifyResolved(const SymbolMap &Symbols);
546
547 /// Notifies the target JITDylib (and any pending queries on that JITDylib)
548 /// that all symbols covered by this MaterializationResponsibility instance
549 /// have been emitted.
550 ///
551 /// This method will return an error if any symbols being resolved have been
552 /// moved to the error state due to the failure of a dependency. If this
553 /// method returns an error then clients should log it and call
554 /// failMaterialize. If no dependencies have been registered for the
555 /// symbols covered by this MaterializationResponsibiility then this method
556 /// is guaranteed to return Error::success() and can be wrapped with cantFail.
557 Error notifyEmitted();
558
559 /// Attempt to claim responsibility for new definitions. This method can be
560 /// used to claim responsibility for symbols that are added to a
561 /// materialization unit during the compilation process (e.g. literal pool
562 /// symbols). Symbol linkage rules are the same as for symbols that are
563 /// defined up front: duplicate strong definitions will result in errors.
564 /// Duplicate weak definitions will be discarded (in which case they will
565 /// not be added to this responsibility instance).
566 ///
567 /// This method can be used by materialization units that want to add
568 /// additional symbols at materialization time (e.g. stubs, compile
569 /// callbacks, metadata).
570 Error defineMaterializing(SymbolFlagsMap SymbolFlags);
571
572 /// Define the given symbols as non-existent, removing it from the symbol
573 /// table and notifying any pending queries. Queries that lookup up the
574 /// symbol using the SymbolLookupFlags::WeaklyReferencedSymbol flag will
575 /// behave as if the symbol had not been matched in the first place. Queries
576 /// that required this symbol will fail with a missing symbol definition
577 /// error.
578 ///
579 /// This method is intended to support cleanup of special symbols like
580 /// initializer symbols: Queries using
581 /// SymbolLookupFlags::WeaklyReferencedSymbol can be used to trigger their
582 /// emission, and this method can be used to remove them from the JITDylib
583 /// once materialization is complete.
584 void defineNonExistent(ArrayRef<SymbolStringPtr> Symbols);
585
586 /// Notify all not-yet-emitted covered by this MaterializationResponsibility
587 /// instance that an error has occurred.
588 /// This will remove all symbols covered by this MaterializationResponsibilty
589 /// from the target JITDylib, and send an error to any queries waiting on
590 /// these symbols.
591 void failMaterialization();
592
593 /// Transfers responsibility to the given MaterializationUnit for all
594 /// symbols defined by that MaterializationUnit. This allows
595 /// materializers to break up work based on run-time information (e.g.
596 /// by introspecting which symbols have actually been looked up and
597 /// materializing only those).
598 Error replace(std::unique_ptr<MaterializationUnit> MU);
599
600 /// Delegates responsibility for the given symbols to the returned
601 /// materialization responsibility. Useful for breaking up work between
602 /// threads, or different kinds of materialization processes.
603 Expected<std::unique_ptr<MaterializationResponsibility>>
604 delegate(const SymbolNameSet &Symbols);
605
606 void addDependencies(const SymbolStringPtr &Name,
607 const SymbolDependenceMap &Dependencies);
608
609 /// Add dependencies that apply to all symbols covered by this instance.
610 void addDependenciesForAll(const SymbolDependenceMap &Dependencies);
611
612 private:
613 /// Create a MaterializationResponsibility for the given JITDylib and
614 /// initial symbols.
MaterializationResponsibility(JITDylibSP JD,SymbolFlagsMap SymbolFlags,SymbolStringPtr InitSymbol)615 MaterializationResponsibility(JITDylibSP JD, SymbolFlagsMap SymbolFlags,
616 SymbolStringPtr InitSymbol)
617 : JD(std::move(JD)), SymbolFlags(std::move(SymbolFlags)),
618 InitSymbol(std::move(InitSymbol)) {
619 assert(this->JD && "Cannot initialize with null JITDylib");
620 assert(!this->SymbolFlags.empty() && "Materializing nothing?");
621 }
622
623 JITDylibSP JD;
624 SymbolFlagsMap SymbolFlags;
625 SymbolStringPtr InitSymbol;
626 };
627
628 /// A MaterializationUnit represents a set of symbol definitions that can
629 /// be materialized as a group, or individually discarded (when
630 /// overriding definitions are encountered).
631 ///
632 /// MaterializationUnits are used when providing lazy definitions of symbols to
633 /// JITDylibs. The JITDylib will call materialize when the address of a symbol
634 /// is requested via the lookup method. The JITDylib will call discard if a
635 /// stronger definition is added or already present.
636 class MaterializationUnit {
637 friend class ExecutionSession;
638 friend class JITDylib;
639
640 public:
641 static char ID;
642
MaterializationUnit(SymbolFlagsMap InitalSymbolFlags,SymbolStringPtr InitSymbol)643 MaterializationUnit(SymbolFlagsMap InitalSymbolFlags,
644 SymbolStringPtr InitSymbol)
645 : SymbolFlags(std::move(InitalSymbolFlags)),
646 InitSymbol(std::move(InitSymbol)) {
647 assert((!this->InitSymbol || this->SymbolFlags.count(this->InitSymbol)) &&
648 "If set, InitSymbol should appear in InitialSymbolFlags map");
649 }
650
~MaterializationUnit()651 virtual ~MaterializationUnit() {}
652
653 /// Return the name of this materialization unit. Useful for debugging
654 /// output.
655 virtual StringRef getName() const = 0;
656
657 /// Return the set of symbols that this source provides.
getSymbols()658 const SymbolFlagsMap &getSymbols() const { return SymbolFlags; }
659
660 /// Returns the initialization symbol for this MaterializationUnit (if any).
getInitializerSymbol()661 const SymbolStringPtr &getInitializerSymbol() const { return InitSymbol; }
662
663 /// Implementations of this method should materialize all symbols
664 /// in the materialzation unit, except for those that have been
665 /// previously discarded.
666 virtual void
667 materialize(std::unique_ptr<MaterializationResponsibility> R) = 0;
668
669 /// Called by JITDylibs to notify MaterializationUnits that the given symbol
670 /// has been overridden.
doDiscard(const JITDylib & JD,const SymbolStringPtr & Name)671 void doDiscard(const JITDylib &JD, const SymbolStringPtr &Name) {
672 SymbolFlags.erase(Name);
673 discard(JD, std::move(Name));
674 }
675
676 protected:
677 SymbolFlagsMap SymbolFlags;
678 SymbolStringPtr InitSymbol;
679
680 private:
681 virtual void anchor();
682
683 /// Implementations of this method should discard the given symbol
684 /// from the source (e.g. if the source is an LLVM IR Module and the
685 /// symbol is a function, delete the function body or mark it available
686 /// externally).
687 virtual void discard(const JITDylib &JD, const SymbolStringPtr &Name) = 0;
688 };
689
690 /// A MaterializationUnit implementation for pre-existing absolute symbols.
691 ///
692 /// All symbols will be resolved and marked ready as soon as the unit is
693 /// materialized.
694 class AbsoluteSymbolsMaterializationUnit : public MaterializationUnit {
695 public:
696 AbsoluteSymbolsMaterializationUnit(SymbolMap Symbols);
697
698 StringRef getName() const override;
699
700 private:
701 void materialize(std::unique_ptr<MaterializationResponsibility> R) override;
702 void discard(const JITDylib &JD, const SymbolStringPtr &Name) override;
703 static SymbolFlagsMap extractFlags(const SymbolMap &Symbols);
704
705 SymbolMap Symbols;
706 };
707
708 /// Create an AbsoluteSymbolsMaterializationUnit with the given symbols.
709 /// Useful for inserting absolute symbols into a JITDylib. E.g.:
710 /// \code{.cpp}
711 /// JITDylib &JD = ...;
712 /// SymbolStringPtr Foo = ...;
713 /// JITEvaluatedSymbol FooSym = ...;
714 /// if (auto Err = JD.define(absoluteSymbols({{Foo, FooSym}})))
715 /// return Err;
716 /// \endcode
717 ///
718 inline std::unique_ptr<AbsoluteSymbolsMaterializationUnit>
absoluteSymbols(SymbolMap Symbols)719 absoluteSymbols(SymbolMap Symbols) {
720 return std::make_unique<AbsoluteSymbolsMaterializationUnit>(
721 std::move(Symbols));
722 }
723
724 /// A materialization unit for symbol aliases. Allows existing symbols to be
725 /// aliased with alternate flags.
726 class ReExportsMaterializationUnit : public MaterializationUnit {
727 public:
728 /// SourceJD is allowed to be nullptr, in which case the source JITDylib is
729 /// taken to be whatever JITDylib these definitions are materialized in (and
730 /// MatchNonExported has no effect). This is useful for defining aliases
731 /// within a JITDylib.
732 ///
733 /// Note: Care must be taken that no sets of aliases form a cycle, as such
734 /// a cycle will result in a deadlock when any symbol in the cycle is
735 /// resolved.
736 ReExportsMaterializationUnit(JITDylib *SourceJD,
737 JITDylibLookupFlags SourceJDLookupFlags,
738 SymbolAliasMap Aliases);
739
740 StringRef getName() const override;
741
742 private:
743 void materialize(std::unique_ptr<MaterializationResponsibility> R) override;
744 void discard(const JITDylib &JD, const SymbolStringPtr &Name) override;
745 static SymbolFlagsMap extractFlags(const SymbolAliasMap &Aliases);
746
747 JITDylib *SourceJD = nullptr;
748 JITDylibLookupFlags SourceJDLookupFlags;
749 SymbolAliasMap Aliases;
750 };
751
752 /// Create a ReExportsMaterializationUnit with the given aliases.
753 /// Useful for defining symbol aliases.: E.g., given a JITDylib JD containing
754 /// symbols "foo" and "bar", we can define aliases "baz" (for "foo") and "qux"
755 /// (for "bar") with: \code{.cpp}
756 /// SymbolStringPtr Baz = ...;
757 /// SymbolStringPtr Qux = ...;
758 /// if (auto Err = JD.define(symbolAliases({
759 /// {Baz, { Foo, JITSymbolFlags::Exported }},
760 /// {Qux, { Bar, JITSymbolFlags::Weak }}}))
761 /// return Err;
762 /// \endcode
763 inline std::unique_ptr<ReExportsMaterializationUnit>
symbolAliases(SymbolAliasMap Aliases)764 symbolAliases(SymbolAliasMap Aliases) {
765 return std::make_unique<ReExportsMaterializationUnit>(
766 nullptr, JITDylibLookupFlags::MatchAllSymbols, std::move(Aliases));
767 }
768
769 /// Create a materialization unit for re-exporting symbols from another JITDylib
770 /// with alternative names/flags.
771 /// SourceJD will be searched using the given JITDylibLookupFlags.
772 inline std::unique_ptr<ReExportsMaterializationUnit>
773 reexports(JITDylib &SourceJD, SymbolAliasMap Aliases,
774 JITDylibLookupFlags SourceJDLookupFlags =
775 JITDylibLookupFlags::MatchExportedSymbolsOnly) {
776 return std::make_unique<ReExportsMaterializationUnit>(
777 &SourceJD, SourceJDLookupFlags, std::move(Aliases));
778 }
779
780 /// Build a SymbolAliasMap for the common case where you want to re-export
781 /// symbols from another JITDylib with the same linkage/flags.
782 Expected<SymbolAliasMap>
783 buildSimpleReexportsAAliasMap(JITDylib &SourceJD, const SymbolNameSet &Symbols);
784
785 /// Represents the state that a symbol has reached during materialization.
786 enum class SymbolState : uint8_t {
787 Invalid, /// No symbol should be in this state.
788 NeverSearched, /// Added to the symbol table, never queried.
789 Materializing, /// Queried, materialization begun.
790 Resolved, /// Assigned address, still materializing.
791 Emitted, /// Emitted to memory, but waiting on transitive dependencies.
792 Ready = 0x3f /// Ready and safe for clients to access.
793 };
794
795 /// A symbol query that returns results via a callback when results are
796 /// ready.
797 ///
798 /// makes a callback when all symbols are available.
799 class AsynchronousSymbolQuery {
800 friend class ExecutionSession;
801 friend class InProgressFullLookupState;
802 friend class JITDylib;
803 friend class JITSymbolResolverAdapter;
804 friend class MaterializationResponsibility;
805
806 public:
807 /// Create a query for the given symbols. The NotifyComplete
808 /// callback will be called once all queried symbols reach the given
809 /// minimum state.
810 AsynchronousSymbolQuery(const SymbolLookupSet &Symbols,
811 SymbolState RequiredState,
812 SymbolsResolvedCallback NotifyComplete);
813
814 /// Notify the query that a requested symbol has reached the required state.
815 void notifySymbolMetRequiredState(const SymbolStringPtr &Name,
816 JITEvaluatedSymbol Sym);
817
818 /// Returns true if all symbols covered by this query have been
819 /// resolved.
isComplete()820 bool isComplete() const { return OutstandingSymbolsCount == 0; }
821
822
823 private:
824 void handleComplete(ExecutionSession &ES);
825
getRequiredState()826 SymbolState getRequiredState() { return RequiredState; }
827
828 void addQueryDependence(JITDylib &JD, SymbolStringPtr Name);
829
830 void removeQueryDependence(JITDylib &JD, const SymbolStringPtr &Name);
831
832 void dropSymbol(const SymbolStringPtr &Name);
833
834 void handleFailed(Error Err);
835
836 void detach();
837
838 SymbolsResolvedCallback NotifyComplete;
839 SymbolDependenceMap QueryRegistrations;
840 SymbolMap ResolvedSymbols;
841 size_t OutstandingSymbolsCount;
842 SymbolState RequiredState;
843 };
844
845 /// Wraps state for a lookup-in-progress.
846 /// DefinitionGenerators can optionally take ownership of a LookupState object
847 /// to suspend a lookup-in-progress while they search for definitions.
848 class LookupState {
849 friend class OrcV2CAPIHelper;
850 friend class ExecutionSession;
851
852 public:
853 LookupState();
854 LookupState(LookupState &&);
855 LookupState &operator=(LookupState &&);
856 ~LookupState();
857
858 /// Continue the lookup. This can be called by DefinitionGenerators
859 /// to re-start a captured query-application operation.
860 void continueLookup(Error Err);
861
862 private:
863 LookupState(std::unique_ptr<InProgressLookupState> IPLS);
864
865 // For C API.
866 void reset(InProgressLookupState *IPLS);
867
868 std::unique_ptr<InProgressLookupState> IPLS;
869 };
870
871 /// Definition generators can be attached to JITDylibs to generate new
872 /// definitions for otherwise unresolved symbols during lookup.
873 class DefinitionGenerator {
874 public:
875 virtual ~DefinitionGenerator();
876
877 /// DefinitionGenerators should override this method to insert new
878 /// definitions into the parent JITDylib. K specifies the kind of this
879 /// lookup. JD specifies the target JITDylib being searched, and
880 /// JDLookupFlags specifies whether the search should match against
881 /// hidden symbols. Finally, Symbols describes the set of unresolved
882 /// symbols and their associated lookup flags.
883 virtual Error tryToGenerate(LookupState &LS, LookupKind K, JITDylib &JD,
884 JITDylibLookupFlags JDLookupFlags,
885 const SymbolLookupSet &LookupSet) = 0;
886 };
887
888 /// A symbol table that supports asynchoronous symbol queries.
889 ///
890 /// Represents a virtual shared object. Instances can not be copied or moved, so
891 /// their addresses may be used as keys for resource management.
892 /// JITDylib state changes must be made via an ExecutionSession to guarantee
893 /// that they are synchronized with respect to other JITDylib operations.
894 class JITDylib : public ThreadSafeRefCountedBase<JITDylib>,
895 public jitlink::JITLinkDylib {
896 friend class AsynchronousSymbolQuery;
897 friend class ExecutionSession;
898 friend class Platform;
899 friend class MaterializationResponsibility;
900 public:
901
902 using AsynchronousSymbolQuerySet =
903 std::set<std::shared_ptr<AsynchronousSymbolQuery>>;
904
905 JITDylib(const JITDylib &) = delete;
906 JITDylib &operator=(const JITDylib &) = delete;
907 JITDylib(JITDylib &&) = delete;
908 JITDylib &operator=(JITDylib &&) = delete;
909
910 /// Get the name for this JITDylib.
getName()911 const std::string &getName() const { return JITDylibName; }
912
913 /// Get a reference to the ExecutionSession for this JITDylib.
getExecutionSession()914 ExecutionSession &getExecutionSession() const { return ES; }
915
916 /// Calls remove on all trackers currently associated with this JITDylib.
917 /// Does not run static deinits.
918 ///
919 /// Note that removal happens outside the session lock, so new code may be
920 /// added concurrently while the clear is underway, and the newly added
921 /// code will *not* be cleared. Adding new code concurrently with a clear
922 /// is usually a bug and should be avoided.
923 Error clear();
924
925 /// Get the default resource tracker for this JITDylib.
926 ResourceTrackerSP getDefaultResourceTracker();
927
928 /// Create a resource tracker for this JITDylib.
929 ResourceTrackerSP createResourceTracker();
930
931 /// Adds a definition generator to this JITDylib and returns a referenece to
932 /// it.
933 ///
934 /// When JITDylibs are searched during lookup, if no existing definition of
935 /// a symbol is found, then any generators that have been added are run (in
936 /// the order that they were added) to potentially generate a definition.
937 template <typename GeneratorT>
938 GeneratorT &addGenerator(std::unique_ptr<GeneratorT> DefGenerator);
939
940 /// Remove a definition generator from this JITDylib.
941 ///
942 /// The given generator must exist in this JITDylib's generators list (i.e.
943 /// have been added and not yet removed).
944 void removeGenerator(DefinitionGenerator &G);
945
946 /// Set the link order to be used when fixing up definitions in JITDylib.
947 /// This will replace the previous link order, and apply to any symbol
948 /// resolutions made for definitions in this JITDylib after the call to
949 /// setLinkOrder (even if the definition itself was added before the
950 /// call).
951 ///
952 /// If LinkAgainstThisJITDylibFirst is true (the default) then this JITDylib
953 /// will add itself to the beginning of the LinkOrder (Clients should not
954 /// put this JITDylib in the list in this case, to avoid redundant lookups).
955 ///
956 /// If LinkAgainstThisJITDylibFirst is false then the link order will be used
957 /// as-is. The primary motivation for this feature is to support deliberate
958 /// shadowing of symbols in this JITDylib by a facade JITDylib. For example,
959 /// the facade may resolve function names to stubs, and the stubs may compile
960 /// lazily by looking up symbols in this dylib. Adding the facade dylib
961 /// as the first in the link order (instead of this dylib) ensures that
962 /// definitions within this dylib resolve to the lazy-compiling stubs,
963 /// rather than immediately materializing the definitions in this dylib.
964 void setLinkOrder(JITDylibSearchOrder NewSearchOrder,
965 bool LinkAgainstThisJITDylibFirst = true);
966
967 /// Add the given JITDylib to the link order for definitions in this
968 /// JITDylib.
969 void addToLinkOrder(JITDylib &JD,
970 JITDylibLookupFlags JDLookupFlags =
971 JITDylibLookupFlags::MatchExportedSymbolsOnly);
972
973 /// Replace OldJD with NewJD in the link order if OldJD is present.
974 /// Otherwise this operation is a no-op.
975 void replaceInLinkOrder(JITDylib &OldJD, JITDylib &NewJD,
976 JITDylibLookupFlags JDLookupFlags =
977 JITDylibLookupFlags::MatchExportedSymbolsOnly);
978
979 /// Remove the given JITDylib from the link order for this JITDylib if it is
980 /// present. Otherwise this operation is a no-op.
981 void removeFromLinkOrder(JITDylib &JD);
982
983 /// Do something with the link order (run under the session lock).
984 template <typename Func>
985 auto withLinkOrderDo(Func &&F)
986 -> decltype(F(std::declval<const JITDylibSearchOrder &>()));
987
988 /// Define all symbols provided by the materialization unit to be part of this
989 /// JITDylib.
990 ///
991 /// If RT is not specified then the default resource tracker will be used.
992 ///
993 /// This overload always takes ownership of the MaterializationUnit. If any
994 /// errors occur, the MaterializationUnit consumed.
995 template <typename MaterializationUnitType>
996 Error define(std::unique_ptr<MaterializationUnitType> &&MU,
997 ResourceTrackerSP RT = nullptr);
998
999 /// Define all symbols provided by the materialization unit to be part of this
1000 /// JITDylib.
1001 ///
1002 /// This overload only takes ownership of the MaterializationUnit no error is
1003 /// generated. If an error occurs, ownership remains with the caller. This
1004 /// may allow the caller to modify the MaterializationUnit to correct the
1005 /// issue, then re-call define.
1006 template <typename MaterializationUnitType>
1007 Error define(std::unique_ptr<MaterializationUnitType> &MU,
1008 ResourceTrackerSP RT = nullptr);
1009
1010 /// Tries to remove the given symbols.
1011 ///
1012 /// If any symbols are not defined in this JITDylib this method will return
1013 /// a SymbolsNotFound error covering the missing symbols.
1014 ///
1015 /// If all symbols are found but some symbols are in the process of being
1016 /// materialized this method will return a SymbolsCouldNotBeRemoved error.
1017 ///
1018 /// On success, all symbols are removed. On failure, the JITDylib state is
1019 /// left unmodified (no symbols are removed).
1020 Error remove(const SymbolNameSet &Names);
1021
1022 /// Dump current JITDylib state to OS.
1023 void dump(raw_ostream &OS);
1024
1025 /// Returns the given JITDylibs and all of their transitive dependencies in
1026 /// DFS order (based on linkage relationships). Each JITDylib will appear
1027 /// only once.
1028 static std::vector<JITDylibSP> getDFSLinkOrder(ArrayRef<JITDylibSP> JDs);
1029
1030 /// Returns the given JITDylibs and all of their transitive dependensies in
1031 /// reverse DFS order (based on linkage relationships). Each JITDylib will
1032 /// appear only once.
1033 static std::vector<JITDylibSP>
1034 getReverseDFSLinkOrder(ArrayRef<JITDylibSP> JDs);
1035
1036 /// Return this JITDylib and its transitive dependencies in DFS order
1037 /// based on linkage relationships.
1038 std::vector<JITDylibSP> getDFSLinkOrder();
1039
1040 /// Rteurn this JITDylib and its transitive dependencies in reverse DFS order
1041 /// based on linkage relationships.
1042 std::vector<JITDylibSP> getReverseDFSLinkOrder();
1043
1044 private:
1045 using AsynchronousSymbolQueryList =
1046 std::vector<std::shared_ptr<AsynchronousSymbolQuery>>;
1047
1048 struct UnmaterializedInfo {
UnmaterializedInfoUnmaterializedInfo1049 UnmaterializedInfo(std::unique_ptr<MaterializationUnit> MU,
1050 ResourceTracker *RT)
1051 : MU(std::move(MU)), RT(RT) {}
1052
1053 std::unique_ptr<MaterializationUnit> MU;
1054 ResourceTracker *RT;
1055 };
1056
1057 using UnmaterializedInfosMap =
1058 DenseMap<SymbolStringPtr, std::shared_ptr<UnmaterializedInfo>>;
1059
1060 using UnmaterializedInfosList =
1061 std::vector<std::shared_ptr<UnmaterializedInfo>>;
1062
1063 struct MaterializingInfo {
1064 SymbolDependenceMap Dependants;
1065 SymbolDependenceMap UnemittedDependencies;
1066
1067 void addQuery(std::shared_ptr<AsynchronousSymbolQuery> Q);
1068 void removeQuery(const AsynchronousSymbolQuery &Q);
1069 AsynchronousSymbolQueryList takeQueriesMeeting(SymbolState RequiredState);
takeAllPendingQueriesMaterializingInfo1070 AsynchronousSymbolQueryList takeAllPendingQueries() {
1071 return std::move(PendingQueries);
1072 }
hasQueriesPendingMaterializingInfo1073 bool hasQueriesPending() const { return !PendingQueries.empty(); }
pendingQueriesMaterializingInfo1074 const AsynchronousSymbolQueryList &pendingQueries() const {
1075 return PendingQueries;
1076 }
1077 private:
1078 AsynchronousSymbolQueryList PendingQueries;
1079 };
1080
1081 using MaterializingInfosMap = DenseMap<SymbolStringPtr, MaterializingInfo>;
1082
1083 class SymbolTableEntry {
1084 public:
1085 SymbolTableEntry() = default;
SymbolTableEntry(JITSymbolFlags Flags)1086 SymbolTableEntry(JITSymbolFlags Flags)
1087 : Flags(Flags), State(static_cast<uint8_t>(SymbolState::NeverSearched)),
1088 MaterializerAttached(false), PendingRemoval(false) {}
1089
getAddress()1090 JITTargetAddress getAddress() const { return Addr; }
getFlags()1091 JITSymbolFlags getFlags() const { return Flags; }
getState()1092 SymbolState getState() const { return static_cast<SymbolState>(State); }
1093
hasMaterializerAttached()1094 bool hasMaterializerAttached() const { return MaterializerAttached; }
isPendingRemoval()1095 bool isPendingRemoval() const { return PendingRemoval; }
1096
setAddress(JITTargetAddress Addr)1097 void setAddress(JITTargetAddress Addr) { this->Addr = Addr; }
setFlags(JITSymbolFlags Flags)1098 void setFlags(JITSymbolFlags Flags) { this->Flags = Flags; }
setState(SymbolState State)1099 void setState(SymbolState State) {
1100 assert(static_cast<uint8_t>(State) < (1 << 6) &&
1101 "State does not fit in bitfield");
1102 this->State = static_cast<uint8_t>(State);
1103 }
1104
setMaterializerAttached(bool MaterializerAttached)1105 void setMaterializerAttached(bool MaterializerAttached) {
1106 this->MaterializerAttached = MaterializerAttached;
1107 }
1108
setPendingRemoval(bool PendingRemoval)1109 void setPendingRemoval(bool PendingRemoval) {
1110 this->PendingRemoval = PendingRemoval;
1111 }
1112
getSymbol()1113 JITEvaluatedSymbol getSymbol() const {
1114 return JITEvaluatedSymbol(Addr, Flags);
1115 }
1116
1117 private:
1118 JITTargetAddress Addr = 0;
1119 JITSymbolFlags Flags;
1120 uint8_t State : 6;
1121 uint8_t MaterializerAttached : 1;
1122 uint8_t PendingRemoval : 1;
1123 };
1124
1125 using SymbolTable = DenseMap<SymbolStringPtr, SymbolTableEntry>;
1126
1127 JITDylib(ExecutionSession &ES, std::string Name);
1128
1129 ResourceTrackerSP getTracker(MaterializationResponsibility &MR);
1130 std::pair<AsynchronousSymbolQuerySet, std::shared_ptr<SymbolDependenceMap>>
1131 removeTracker(ResourceTracker &RT);
1132
1133 void transferTracker(ResourceTracker &DstRT, ResourceTracker &SrcRT);
1134
1135 Error defineImpl(MaterializationUnit &MU);
1136
1137 void installMaterializationUnit(std::unique_ptr<MaterializationUnit> MU,
1138 ResourceTracker &RT);
1139
1140 void detachQueryHelper(AsynchronousSymbolQuery &Q,
1141 const SymbolNameSet &QuerySymbols);
1142
1143 void transferEmittedNodeDependencies(MaterializingInfo &DependantMI,
1144 const SymbolStringPtr &DependantName,
1145 MaterializingInfo &EmittedMI);
1146
1147 Expected<SymbolFlagsMap> defineMaterializing(SymbolFlagsMap SymbolFlags);
1148
1149 Error replace(MaterializationResponsibility &FromMR,
1150 std::unique_ptr<MaterializationUnit> MU);
1151
1152 Expected<std::unique_ptr<MaterializationResponsibility>>
1153 delegate(MaterializationResponsibility &FromMR, SymbolFlagsMap SymbolFlags,
1154 SymbolStringPtr InitSymbol);
1155
1156 SymbolNameSet getRequestedSymbols(const SymbolFlagsMap &SymbolFlags) const;
1157
1158 void addDependencies(const SymbolStringPtr &Name,
1159 const SymbolDependenceMap &Dependants);
1160
1161 Error resolve(MaterializationResponsibility &MR, const SymbolMap &Resolved);
1162
1163 Error emit(MaterializationResponsibility &MR, const SymbolFlagsMap &Emitted);
1164
1165 void unlinkMaterializationResponsibility(MaterializationResponsibility &MR);
1166
1167 using FailedSymbolsWorklist =
1168 std::vector<std::pair<JITDylib *, SymbolStringPtr>>;
1169
1170 static std::pair<AsynchronousSymbolQuerySet,
1171 std::shared_ptr<SymbolDependenceMap>>
1172 failSymbols(FailedSymbolsWorklist);
1173
1174 ExecutionSession &ES;
1175 std::string JITDylibName;
1176 std::mutex GeneratorsMutex;
1177 bool Open = true;
1178 SymbolTable Symbols;
1179 UnmaterializedInfosMap UnmaterializedInfos;
1180 MaterializingInfosMap MaterializingInfos;
1181 std::vector<std::shared_ptr<DefinitionGenerator>> DefGenerators;
1182 JITDylibSearchOrder LinkOrder;
1183 ResourceTrackerSP DefaultTracker;
1184
1185 // Map trackers to sets of symbols tracked.
1186 DenseMap<ResourceTracker *, SymbolNameVector> TrackerSymbols;
1187 DenseMap<MaterializationResponsibility *, ResourceTracker *> MRTrackers;
1188 };
1189
1190 /// Platforms set up standard symbols and mediate interactions between dynamic
1191 /// initializers (e.g. C++ static constructors) and ExecutionSession state.
1192 /// Note that Platforms do not automatically run initializers: clients are still
1193 /// responsible for doing this.
1194 class Platform {
1195 public:
1196 virtual ~Platform();
1197
1198 /// This method will be called outside the session lock each time a JITDylib
1199 /// is created (unless it is created with EmptyJITDylib set) to allow the
1200 /// Platform to install any JITDylib specific standard symbols (e.g
1201 /// __dso_handle).
1202 virtual Error setupJITDylib(JITDylib &JD) = 0;
1203
1204 /// This method will be called under the ExecutionSession lock each time a
1205 /// MaterializationUnit is added to a JITDylib.
1206 virtual Error notifyAdding(ResourceTracker &RT,
1207 const MaterializationUnit &MU) = 0;
1208
1209 /// This method will be called under the ExecutionSession lock when a
1210 /// ResourceTracker is removed.
1211 virtual Error notifyRemoving(ResourceTracker &RT) = 0;
1212
1213 /// A utility function for looking up initializer symbols. Performs a blocking
1214 /// lookup for the given symbols in each of the given JITDylibs.
1215 static Expected<DenseMap<JITDylib *, SymbolMap>>
1216 lookupInitSymbols(ExecutionSession &ES,
1217 const DenseMap<JITDylib *, SymbolLookupSet> &InitSyms);
1218 };
1219
1220 /// Represents an abstract task for ORC to run.
1221 class Task : public RTTIExtends<Task, RTTIRoot> {
1222 public:
1223 static char ID;
1224
1225 /// Description of the task to be performed. Used for logging.
1226 virtual void printDescription(raw_ostream &OS) = 0;
1227
1228 /// Run the task.
1229 virtual void run() = 0;
1230
1231 private:
1232 void anchor() override;
1233 };
1234
1235 /// A materialization task.
1236 class MaterializationTask : public RTTIExtends<MaterializationTask, Task> {
1237 public:
1238 static char ID;
1239
MaterializationTask(std::unique_ptr<MaterializationUnit> MU,std::unique_ptr<MaterializationResponsibility> MR)1240 MaterializationTask(std::unique_ptr<MaterializationUnit> MU,
1241 std::unique_ptr<MaterializationResponsibility> MR)
1242 : MU(std::move(MU)), MR(std::move(MR)) {}
1243 void printDescription(raw_ostream &OS) override;
1244 void run() override;
1245
1246 private:
1247 std::unique_ptr<MaterializationUnit> MU;
1248 std::unique_ptr<MaterializationResponsibility> MR;
1249 };
1250
1251 /// An ExecutionSession represents a running JIT program.
1252 class ExecutionSession {
1253 friend class InProgressLookupFlagsState;
1254 friend class InProgressFullLookupState;
1255 friend class JITDylib;
1256 friend class LookupState;
1257 friend class MaterializationResponsibility;
1258 friend class ResourceTracker;
1259
1260 public:
1261 /// For reporting errors.
1262 using ErrorReporter = std::function<void(Error)>;
1263
1264 /// For dispatching ORC tasks (typically materialization tasks).
1265 using DispatchTaskFunction = unique_function<void(std::unique_ptr<Task> T)>;
1266
1267 /// Construct an ExecutionSession.
1268 ///
1269 /// SymbolStringPools may be shared between ExecutionSessions.
1270 ExecutionSession(std::shared_ptr<SymbolStringPool> SSP = nullptr);
1271
1272 /// End the session. Closes all JITDylibs.
1273 Error endSession();
1274
1275 /// Add a symbol name to the SymbolStringPool and return a pointer to it.
intern(StringRef SymName)1276 SymbolStringPtr intern(StringRef SymName) { return SSP->intern(SymName); }
1277
1278 /// Returns a shared_ptr to the SymbolStringPool for this ExecutionSession.
getSymbolStringPool()1279 std::shared_ptr<SymbolStringPool> getSymbolStringPool() const { return SSP; }
1280
1281 /// Set the Platform for this ExecutionSession.
setPlatform(std::unique_ptr<Platform> P)1282 void setPlatform(std::unique_ptr<Platform> P) { this->P = std::move(P); }
1283
1284 /// Get the Platform for this session.
1285 /// Will return null if no Platform has been set for this ExecutionSession.
getPlatform()1286 Platform *getPlatform() { return P.get(); }
1287
1288 /// Run the given lambda with the session mutex locked.
decltype(auto)1289 template <typename Func> decltype(auto) runSessionLocked(Func &&F) {
1290 std::lock_guard<std::recursive_mutex> Lock(SessionMutex);
1291 return F();
1292 }
1293
1294 /// Register the given ResourceManager with this ExecutionSession.
1295 /// Managers will be notified of events in reverse order of registration.
1296 void registerResourceManager(ResourceManager &RM);
1297
1298 /// Deregister the given ResourceManager with this ExecutionSession.
1299 /// Manager must have been previously registered.
1300 void deregisterResourceManager(ResourceManager &RM);
1301
1302 /// Return a pointer to the "name" JITDylib.
1303 /// Ownership of JITDylib remains within Execution Session
1304 JITDylib *getJITDylibByName(StringRef Name);
1305
1306 /// Add a new bare JITDylib to this ExecutionSession.
1307 ///
1308 /// The JITDylib Name is required to be unique. Clients should verify that
1309 /// names are not being re-used (E.g. by calling getJITDylibByName) if names
1310 /// are based on user input.
1311 ///
1312 /// This call does not install any library code or symbols into the newly
1313 /// created JITDylib. The client is responsible for all configuration.
1314 JITDylib &createBareJITDylib(std::string Name);
1315
1316 /// Add a new JITDylib to this ExecutionSession.
1317 ///
1318 /// The JITDylib Name is required to be unique. Clients should verify that
1319 /// names are not being re-used (e.g. by calling getJITDylibByName) if names
1320 /// are based on user input.
1321 ///
1322 /// If a Platform is attached then Platform::setupJITDylib will be called to
1323 /// install standard platform symbols (e.g. standard library interposes).
1324 /// If no Platform is attached this call is equivalent to createBareJITDylib.
1325 Expected<JITDylib &> createJITDylib(std::string Name);
1326
1327 /// Set the error reporter function.
setErrorReporter(ErrorReporter ReportError)1328 ExecutionSession &setErrorReporter(ErrorReporter ReportError) {
1329 this->ReportError = std::move(ReportError);
1330 return *this;
1331 }
1332
1333 /// Report a error for this execution session.
1334 ///
1335 /// Unhandled errors can be sent here to log them.
reportError(Error Err)1336 void reportError(Error Err) { ReportError(std::move(Err)); }
1337
1338 /// Set the task dispatch function.
setDispatchTask(DispatchTaskFunction DispatchTask)1339 ExecutionSession &setDispatchTask(DispatchTaskFunction DispatchTask) {
1340 this->DispatchTask = std::move(DispatchTask);
1341 return *this;
1342 }
1343
1344 /// Search the given JITDylibs to find the flags associated with each of the
1345 /// given symbols.
1346 void lookupFlags(LookupKind K, JITDylibSearchOrder SearchOrder,
1347 SymbolLookupSet Symbols,
1348 unique_function<void(Expected<SymbolFlagsMap>)> OnComplete);
1349
1350 /// Blocking version of lookupFlags.
1351 Expected<SymbolFlagsMap> lookupFlags(LookupKind K,
1352 JITDylibSearchOrder SearchOrder,
1353 SymbolLookupSet Symbols);
1354
1355 /// Search the given JITDylibs for the given symbols.
1356 ///
1357 /// SearchOrder lists the JITDylibs to search. For each dylib, the associated
1358 /// boolean indicates whether the search should match against non-exported
1359 /// (hidden visibility) symbols in that dylib (true means match against
1360 /// non-exported symbols, false means do not match).
1361 ///
1362 /// The NotifyComplete callback will be called once all requested symbols
1363 /// reach the required state.
1364 ///
1365 /// If all symbols are found, the RegisterDependencies function will be called
1366 /// while the session lock is held. This gives clients a chance to register
1367 /// dependencies for on the queried symbols for any symbols they are
1368 /// materializing (if a MaterializationResponsibility instance is present,
1369 /// this can be implemented by calling
1370 /// MaterializationResponsibility::addDependencies). If there are no
1371 /// dependenant symbols for this query (e.g. it is being made by a top level
1372 /// client to get an address to call) then the value NoDependenciesToRegister
1373 /// can be used.
1374 void lookup(LookupKind K, const JITDylibSearchOrder &SearchOrder,
1375 SymbolLookupSet Symbols, SymbolState RequiredState,
1376 SymbolsResolvedCallback NotifyComplete,
1377 RegisterDependenciesFunction RegisterDependencies);
1378
1379 /// Blocking version of lookup above. Returns the resolved symbol map.
1380 /// If WaitUntilReady is true (the default), will not return until all
1381 /// requested symbols are ready (or an error occurs). If WaitUntilReady is
1382 /// false, will return as soon as all requested symbols are resolved,
1383 /// or an error occurs. If WaitUntilReady is false and an error occurs
1384 /// after resolution, the function will return a success value, but the
1385 /// error will be reported via reportErrors.
1386 Expected<SymbolMap> lookup(const JITDylibSearchOrder &SearchOrder,
1387 const SymbolLookupSet &Symbols,
1388 LookupKind K = LookupKind::Static,
1389 SymbolState RequiredState = SymbolState::Ready,
1390 RegisterDependenciesFunction RegisterDependencies =
1391 NoDependenciesToRegister);
1392
1393 /// Convenience version of blocking lookup.
1394 /// Searches each of the JITDylibs in the search order in turn for the given
1395 /// symbol.
1396 Expected<JITEvaluatedSymbol>
1397 lookup(const JITDylibSearchOrder &SearchOrder, SymbolStringPtr Symbol,
1398 SymbolState RequiredState = SymbolState::Ready);
1399
1400 /// Convenience version of blocking lookup.
1401 /// Searches each of the JITDylibs in the search order in turn for the given
1402 /// symbol. The search will not find non-exported symbols.
1403 Expected<JITEvaluatedSymbol>
1404 lookup(ArrayRef<JITDylib *> SearchOrder, SymbolStringPtr Symbol,
1405 SymbolState RequiredState = SymbolState::Ready);
1406
1407 /// Convenience version of blocking lookup.
1408 /// Searches each of the JITDylibs in the search order in turn for the given
1409 /// symbol. The search will not find non-exported symbols.
1410 Expected<JITEvaluatedSymbol>
1411 lookup(ArrayRef<JITDylib *> SearchOrder, StringRef Symbol,
1412 SymbolState RequiredState = SymbolState::Ready);
1413
1414 /// Materialize the given unit.
dispatchTask(std::unique_ptr<Task> T)1415 void dispatchTask(std::unique_ptr<Task> T) {
1416 assert(T && "T must be non-null");
1417 DEBUG_WITH_TYPE("orc", dumpDispatchInfo(*T));
1418 DispatchTask(std::move(T));
1419 }
1420
1421 /// Dump the state of all the JITDylibs in this session.
1422 void dump(raw_ostream &OS);
1423
1424 private:
logErrorsToStdErr(Error Err)1425 static void logErrorsToStdErr(Error Err) {
1426 logAllUnhandledErrors(std::move(Err), errs(), "JIT session error: ");
1427 }
1428
runOnCurrentThread(std::unique_ptr<Task> T)1429 static void runOnCurrentThread(std::unique_ptr<Task> T) { T->run(); }
1430
1431 void dispatchOutstandingMUs();
1432
1433 static std::unique_ptr<MaterializationResponsibility>
createMaterializationResponsibility(ResourceTracker & RT,SymbolFlagsMap Symbols,SymbolStringPtr InitSymbol)1434 createMaterializationResponsibility(ResourceTracker &RT,
1435 SymbolFlagsMap Symbols,
1436 SymbolStringPtr InitSymbol) {
1437 auto &JD = RT.getJITDylib();
1438 std::unique_ptr<MaterializationResponsibility> MR(
1439 new MaterializationResponsibility(&JD, std::move(Symbols),
1440 std::move(InitSymbol)));
1441 JD.MRTrackers[MR.get()] = &RT;
1442 return MR;
1443 }
1444
1445 Error removeResourceTracker(ResourceTracker &RT);
1446 void transferResourceTracker(ResourceTracker &DstRT, ResourceTracker &SrcRT);
1447 void destroyResourceTracker(ResourceTracker &RT);
1448
1449 // State machine functions for query application..
1450
1451 /// IL_updateCandidatesFor is called to remove already-defined symbols that
1452 /// match a given query from the set of candidate symbols to generate
1453 /// definitions for (no need to generate a definition if one already exists).
1454 Error IL_updateCandidatesFor(JITDylib &JD, JITDylibLookupFlags JDLookupFlags,
1455 SymbolLookupSet &Candidates,
1456 SymbolLookupSet *NonCandidates);
1457
1458 /// OL_applyQueryPhase1 is an optionally re-startable loop for triggering
1459 /// definition generation. It is called when a lookup is performed, and again
1460 /// each time that LookupState::continueLookup is called.
1461 void OL_applyQueryPhase1(std::unique_ptr<InProgressLookupState> IPLS,
1462 Error Err);
1463
1464 /// OL_completeLookup is run once phase 1 successfully completes for a lookup
1465 /// call. It attempts to attach the symbol to all symbol table entries and
1466 /// collect all MaterializationUnits to dispatch. If this method fails then
1467 /// all MaterializationUnits will be left un-materialized.
1468 void OL_completeLookup(std::unique_ptr<InProgressLookupState> IPLS,
1469 std::shared_ptr<AsynchronousSymbolQuery> Q,
1470 RegisterDependenciesFunction RegisterDependencies);
1471
1472 /// OL_completeLookupFlags is run once phase 1 successfully completes for a
1473 /// lookupFlags call.
1474 void OL_completeLookupFlags(
1475 std::unique_ptr<InProgressLookupState> IPLS,
1476 unique_function<void(Expected<SymbolFlagsMap>)> OnComplete);
1477
1478 // State machine functions for MaterializationResponsibility.
1479 void OL_destroyMaterializationResponsibility(
1480 MaterializationResponsibility &MR);
1481 SymbolNameSet OL_getRequestedSymbols(const MaterializationResponsibility &MR);
1482 Error OL_notifyResolved(MaterializationResponsibility &MR,
1483 const SymbolMap &Symbols);
1484 Error OL_notifyEmitted(MaterializationResponsibility &MR);
1485 Error OL_defineMaterializing(MaterializationResponsibility &MR,
1486 SymbolFlagsMap SymbolFlags);
1487 void OL_notifyFailed(MaterializationResponsibility &MR);
1488 Error OL_replace(MaterializationResponsibility &MR,
1489 std::unique_ptr<MaterializationUnit> MU);
1490 Expected<std::unique_ptr<MaterializationResponsibility>>
1491 OL_delegate(MaterializationResponsibility &MR, const SymbolNameSet &Symbols);
1492 void OL_addDependencies(MaterializationResponsibility &MR,
1493 const SymbolStringPtr &Name,
1494 const SymbolDependenceMap &Dependencies);
1495 void OL_addDependenciesForAll(MaterializationResponsibility &MR,
1496 const SymbolDependenceMap &Dependencies);
1497
1498 #ifndef NDEBUG
1499 void dumpDispatchInfo(Task &T);
1500 #endif // NDEBUG
1501
1502 mutable std::recursive_mutex SessionMutex;
1503 bool SessionOpen = true;
1504 std::shared_ptr<SymbolStringPool> SSP;
1505 std::unique_ptr<Platform> P;
1506 ErrorReporter ReportError = logErrorsToStdErr;
1507 DispatchTaskFunction DispatchTask = runOnCurrentThread;
1508
1509 std::vector<ResourceManager *> ResourceManagers;
1510
1511 std::vector<JITDylibSP> JDs;
1512
1513 // FIXME: Remove this (and runOutstandingMUs) once the linking layer works
1514 // with callbacks from asynchronous queries.
1515 mutable std::recursive_mutex OutstandingMUsMutex;
1516 std::vector<std::pair<std::unique_ptr<MaterializationUnit>,
1517 std::unique_ptr<MaterializationResponsibility>>>
1518 OutstandingMUs;
1519 };
1520
getExecutionSession()1521 inline ExecutionSession &MaterializationResponsibility::getExecutionSession() {
1522 return JD->getExecutionSession();
1523 }
1524
1525 template <typename Func>
withResourceKeyDo(Func && F)1526 Error MaterializationResponsibility::withResourceKeyDo(Func &&F) const {
1527 return JD->getExecutionSession().runSessionLocked([&]() -> Error {
1528 auto I = JD->MRTrackers.find(this);
1529 assert(I != JD->MRTrackers.end() && "No tracker for this MR");
1530 if (I->second->isDefunct())
1531 return make_error<ResourceTrackerDefunct>(I->second);
1532 F(I->second->getKeyUnsafe());
1533 return Error::success();
1534 });
1535 }
1536
1537 template <typename GeneratorT>
addGenerator(std::unique_ptr<GeneratorT> DefGenerator)1538 GeneratorT &JITDylib::addGenerator(std::unique_ptr<GeneratorT> DefGenerator) {
1539 auto &G = *DefGenerator;
1540 std::lock_guard<std::mutex> Lock(GeneratorsMutex);
1541 DefGenerators.push_back(std::move(DefGenerator));
1542 return G;
1543 }
1544
1545 template <typename Func>
1546 auto JITDylib::withLinkOrderDo(Func &&F)
1547 -> decltype(F(std::declval<const JITDylibSearchOrder &>())) {
1548 return ES.runSessionLocked([&]() { return F(LinkOrder); });
1549 }
1550
1551 template <typename MaterializationUnitType>
define(std::unique_ptr<MaterializationUnitType> && MU,ResourceTrackerSP RT)1552 Error JITDylib::define(std::unique_ptr<MaterializationUnitType> &&MU,
1553 ResourceTrackerSP RT) {
1554 assert(MU && "Can not define with a null MU");
1555
1556 if (MU->getSymbols().empty()) {
1557 // Empty MUs are allowable but pathological, so issue a warning.
1558 DEBUG_WITH_TYPE("orc", {
1559 dbgs() << "Warning: Discarding empty MU " << MU->getName() << " for "
1560 << getName() << "\n";
1561 });
1562 return Error::success();
1563 } else
1564 DEBUG_WITH_TYPE("orc", {
1565 dbgs() << "Defining MU " << MU->getName() << " for " << getName()
1566 << " (tracker: ";
1567 if (RT == getDefaultResourceTracker())
1568 dbgs() << "default)";
1569 else if (RT)
1570 dbgs() << RT.get() << ")\n";
1571 else
1572 dbgs() << "0x0, default will be used)\n";
1573 });
1574
1575 return ES.runSessionLocked([&, this]() -> Error {
1576 if (auto Err = defineImpl(*MU))
1577 return Err;
1578
1579 if (!RT)
1580 RT = getDefaultResourceTracker();
1581
1582 if (auto *P = ES.getPlatform()) {
1583 if (auto Err = P->notifyAdding(*RT, *MU))
1584 return Err;
1585 }
1586
1587 installMaterializationUnit(std::move(MU), *RT);
1588 return Error::success();
1589 });
1590 }
1591
1592 template <typename MaterializationUnitType>
define(std::unique_ptr<MaterializationUnitType> & MU,ResourceTrackerSP RT)1593 Error JITDylib::define(std::unique_ptr<MaterializationUnitType> &MU,
1594 ResourceTrackerSP RT) {
1595 assert(MU && "Can not define with a null MU");
1596
1597 if (MU->getSymbols().empty()) {
1598 // Empty MUs are allowable but pathological, so issue a warning.
1599 DEBUG_WITH_TYPE("orc", {
1600 dbgs() << "Warning: Discarding empty MU " << MU->getName() << getName()
1601 << "\n";
1602 });
1603 return Error::success();
1604 } else
1605 DEBUG_WITH_TYPE("orc", {
1606 dbgs() << "Defining MU " << MU->getName() << " for " << getName()
1607 << " (tracker: ";
1608 if (RT == getDefaultResourceTracker())
1609 dbgs() << "default)";
1610 else if (RT)
1611 dbgs() << RT.get() << ")\n";
1612 else
1613 dbgs() << "0x0, default will be used)\n";
1614 });
1615
1616 return ES.runSessionLocked([&, this]() -> Error {
1617 if (auto Err = defineImpl(*MU))
1618 return Err;
1619
1620 if (!RT)
1621 RT = getDefaultResourceTracker();
1622
1623 if (auto *P = ES.getPlatform()) {
1624 if (auto Err = P->notifyAdding(*RT, *MU))
1625 return Err;
1626 }
1627
1628 installMaterializationUnit(std::move(MU), *RT);
1629 return Error::success();
1630 });
1631 }
1632
1633 /// ReexportsGenerator can be used with JITDylib::addGenerator to automatically
1634 /// re-export a subset of the source JITDylib's symbols in the target.
1635 class ReexportsGenerator : public DefinitionGenerator {
1636 public:
1637 using SymbolPredicate = std::function<bool(SymbolStringPtr)>;
1638
1639 /// Create a reexports generator. If an Allow predicate is passed, only
1640 /// symbols for which the predicate returns true will be reexported. If no
1641 /// Allow predicate is passed, all symbols will be exported.
1642 ReexportsGenerator(JITDylib &SourceJD,
1643 JITDylibLookupFlags SourceJDLookupFlags,
1644 SymbolPredicate Allow = SymbolPredicate());
1645
1646 Error tryToGenerate(LookupState &LS, LookupKind K, JITDylib &JD,
1647 JITDylibLookupFlags JDLookupFlags,
1648 const SymbolLookupSet &LookupSet) override;
1649
1650 private:
1651 JITDylib &SourceJD;
1652 JITDylibLookupFlags SourceJDLookupFlags;
1653 SymbolPredicate Allow;
1654 };
1655
1656 // --------------- IMPLEMENTATION --------------
1657 // Implementations for inline functions/methods.
1658 // ---------------------------------------------
1659
~MaterializationResponsibility()1660 inline MaterializationResponsibility::~MaterializationResponsibility() {
1661 JD->getExecutionSession().OL_destroyMaterializationResponsibility(*this);
1662 }
1663
getRequestedSymbols()1664 inline SymbolNameSet MaterializationResponsibility::getRequestedSymbols() const {
1665 return JD->getExecutionSession().OL_getRequestedSymbols(*this);
1666 }
1667
notifyResolved(const SymbolMap & Symbols)1668 inline Error MaterializationResponsibility::notifyResolved(
1669 const SymbolMap &Symbols) {
1670 return JD->getExecutionSession().OL_notifyResolved(*this, Symbols);
1671 }
1672
notifyEmitted()1673 inline Error MaterializationResponsibility::notifyEmitted() {
1674 return JD->getExecutionSession().OL_notifyEmitted(*this);
1675 }
1676
defineMaterializing(SymbolFlagsMap SymbolFlags)1677 inline Error MaterializationResponsibility::defineMaterializing(
1678 SymbolFlagsMap SymbolFlags) {
1679 return JD->getExecutionSession().OL_defineMaterializing(
1680 *this, std::move(SymbolFlags));
1681 }
1682
failMaterialization()1683 inline void MaterializationResponsibility::failMaterialization() {
1684 JD->getExecutionSession().OL_notifyFailed(*this);
1685 }
1686
replace(std::unique_ptr<MaterializationUnit> MU)1687 inline Error MaterializationResponsibility::replace(
1688 std::unique_ptr<MaterializationUnit> MU) {
1689 return JD->getExecutionSession().OL_replace(*this, std::move(MU));
1690 }
1691
1692 inline Expected<std::unique_ptr<MaterializationResponsibility>>
delegate(const SymbolNameSet & Symbols)1693 MaterializationResponsibility::delegate(const SymbolNameSet &Symbols) {
1694 return JD->getExecutionSession().OL_delegate(*this, Symbols);
1695 }
1696
addDependencies(const SymbolStringPtr & Name,const SymbolDependenceMap & Dependencies)1697 inline void MaterializationResponsibility::addDependencies(
1698 const SymbolStringPtr &Name, const SymbolDependenceMap &Dependencies) {
1699 JD->getExecutionSession().OL_addDependencies(*this, Name, Dependencies);
1700 }
1701
addDependenciesForAll(const SymbolDependenceMap & Dependencies)1702 inline void MaterializationResponsibility::addDependenciesForAll(
1703 const SymbolDependenceMap &Dependencies) {
1704 JD->getExecutionSession().OL_addDependenciesForAll(*this, Dependencies);
1705 }
1706
1707 } // End namespace orc
1708 } // End namespace llvm
1709
1710 #endif // LLVM_EXECUTIONENGINE_ORC_CORE_H
1711