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