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