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