OSDN Git Service

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