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