• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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