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