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