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