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