LLVM  8.0.1
Core.h
Go to the documentation of this file.
1 //===------ Core.h -- Core ORC APIs (Layer, JITDylib, etc.) -----*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // Contains core ORC APIs.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_EXECUTIONENGINE_ORC_CORE_H
15 #define LLVM_EXECUTIONENGINE_ORC_CORE_H
16 
17 #include "llvm/ADT/BitmaskEnum.h"
20 #include "llvm/IR/Module.h"
21 #include "llvm/Support/Debug.h"
22 
23 #include <memory>
24 #include <vector>
25 
26 #define DEBUG_TYPE "orc"
27 
28 namespace llvm {
29 namespace orc {
30 
31 // Forward declare some classes.
32 class AsynchronousSymbolQuery;
33 class ExecutionSession;
34 class MaterializationUnit;
35 class MaterializationResponsibility;
36 class JITDylib;
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).
45 
46 /// A map from symbol names (as SymbolStringPtrs) to JITSymbols
47 /// (address/flags pairs).
49 
50 /// A map from symbol names (as SymbolStringPtrs) to JITSymbolFlags.
52 
53 /// A base class for materialization failures that allows the failing
54 /// symbols to be obtained for logging.
56 
57 /// A list of (JITDylib*, bool) pairs.
58 using JITDylibSearchList = std::vector<std::pair<JITDylib *, bool>>;
59 
60 /// Render a SymbolStringPtr.
62 
63 /// Render a SymbolNameSet.
64 raw_ostream &operator<<(raw_ostream &OS, const SymbolNameSet &Symbols);
65 
66 /// Render a SymbolFlagsMap entry.
68 
69 /// Render a SymbolMap entry.
71 
72 /// Render a SymbolFlagsMap.
73 raw_ostream &operator<<(raw_ostream &OS, const SymbolFlagsMap &SymbolFlags);
74 
75 /// Render a SymbolMap.
76 raw_ostream &operator<<(raw_ostream &OS, const SymbolMap &Symbols);
77 
78 /// Render a SymbolDependenceMap entry.
81 
82 /// Render a SymbolDependendeMap.
84 
85 /// Render a MaterializationUnit.
87 
88 /// Render a JITDylibSearchList.
90 
91 /// Callback to notify client that symbols have been resolved.
92 using SymbolsResolvedCallback = std::function<void(Expected<SymbolMap>)>;
93 
94 /// Callback to notify client that symbols are ready for execution.
95 using SymbolsReadyCallback = std::function<void(Error)>;
96 
97 /// Callback to register the dependencies for a given query.
99  std::function<void(const SymbolDependenceMap &)>;
100 
101 /// This can be used as the value for a RegisterDependenciesFunction if there
102 /// are no dependants to register with.
104 
105 /// Used to notify a JITDylib that the given set of symbols failed to
106 /// materialize.
107 class FailedToMaterialize : public ErrorInfo<FailedToMaterialize> {
108 public:
109  static char ID;
110 
112  std::error_code convertToErrorCode() const override;
113  void log(raw_ostream &OS) const override;
114  const SymbolNameSet &getSymbols() const { return Symbols; }
115 
116 private:
117  SymbolNameSet Symbols;
118 };
119 
120 /// Used to notify clients when symbols can not be found during a lookup.
121 class SymbolsNotFound : public ErrorInfo<SymbolsNotFound> {
122 public:
123  static char ID;
124 
126  std::error_code convertToErrorCode() const override;
127  void log(raw_ostream &OS) const override;
128  const SymbolNameSet &getSymbols() const { return Symbols; }
129 
130 private:
131  SymbolNameSet Symbols;
132 };
133 
134 /// Used to notify clients that a set of symbols could not be removed.
135 class SymbolsCouldNotBeRemoved : public ErrorInfo<SymbolsCouldNotBeRemoved> {
136 public:
137  static char ID;
138 
140  std::error_code convertToErrorCode() const override;
141  void log(raw_ostream &OS) const override;
142  const SymbolNameSet &getSymbols() const { return Symbols; }
143 
144 private:
145  SymbolNameSet Symbols;
146 };
147 
148 /// Tracks responsibility for materialization, and mediates interactions between
149 /// MaterializationUnits and JDs.
150 ///
151 /// An instance of this class is passed to MaterializationUnits when their
152 /// materialize method is called. It allows MaterializationUnits to resolve and
153 /// emit symbols, or abandon materialization by notifying any unmaterialized
154 /// symbols of an error.
156  friend class MaterializationUnit;
157 public:
160  operator=(MaterializationResponsibility &&) = delete;
161 
162  /// Destruct a MaterializationResponsibility instance. In debug mode
163  /// this asserts that all symbols being tracked have been either
164  /// emitted or notified of an error.
166 
167  /// Returns the target JITDylib that these symbols are being materialized
168  /// into.
169  JITDylib &getTargetJITDylib() const { return JD; }
170 
171  /// Returns the VModuleKey for this instance.
172  VModuleKey getVModuleKey() const { return K; }
173 
174  /// Returns the symbol flags map for this responsibility instance.
175  /// Note: The returned flags may have transient flags (Lazy, Materializing)
176  /// set. These should be stripped with JITSymbolFlags::stripTransientFlags
177  /// before using.
178  const SymbolFlagsMap &getSymbols() { return SymbolFlags; }
179 
180  /// Returns the names of any symbols covered by this
181  /// MaterializationResponsibility object that have queries pending. This
182  /// information can be used to return responsibility for unrequested symbols
183  /// back to the JITDylib via the delegate method.
184  SymbolNameSet getRequestedSymbols() const;
185 
186  /// Notifies the target JITDylib that the given symbols have been resolved.
187  /// This will update the given symbols' addresses in the JITDylib, and notify
188  /// any pending queries on the given symbols of their resolution. The given
189  /// symbols must be ones covered by this MaterializationResponsibility
190  /// instance. Individual calls to this method may resolve a subset of the
191  /// symbols, but all symbols must have been resolved prior to calling emit.
192  void resolve(const SymbolMap &Symbols);
193 
194  /// Notifies the target JITDylib (and any pending queries on that JITDylib)
195  /// that all symbols covered by this MaterializationResponsibility instance
196  /// have been emitted.
197  void emit();
198 
199  /// Adds new symbols to the JITDylib and this responsibility instance.
200  /// JITDylib entries start out in the materializing state.
201  ///
202  /// This method can be used by materialization units that want to add
203  /// additional symbols at materialization time (e.g. stubs, compile
204  /// callbacks, metadata).
205  Error defineMaterializing(const SymbolFlagsMap &SymbolFlags);
206 
207  /// Notify all not-yet-emitted covered by this MaterializationResponsibility
208  /// instance that an error has occurred.
209  /// This will remove all symbols covered by this MaterializationResponsibilty
210  /// from the target JITDylib, and send an error to any queries waiting on
211  /// these symbols.
212  void failMaterialization();
213 
214  /// Transfers responsibility to the given MaterializationUnit for all
215  /// symbols defined by that MaterializationUnit. This allows
216  /// materializers to break up work based on run-time information (e.g.
217  /// by introspecting which symbols have actually been looked up and
218  /// materializing only those).
219  void replace(std::unique_ptr<MaterializationUnit> MU);
220 
221  /// Delegates responsibility for the given symbols to the returned
222  /// materialization responsibility. Useful for breaking up work between
223  /// threads, or different kinds of materialization processes.
224  MaterializationResponsibility delegate(const SymbolNameSet &Symbols,
225  VModuleKey NewKey = VModuleKey());
226 
227  void addDependencies(const SymbolStringPtr &Name,
228  const SymbolDependenceMap &Dependencies);
229 
230  /// Add dependencies that apply to all symbols covered by this instance.
231  void addDependenciesForAll(const SymbolDependenceMap &Dependencies);
232 
233 private:
234  /// Create a MaterializationResponsibility for the given JITDylib and
235  /// initial symbols.
237  VModuleKey K);
238 
239  JITDylib &JD;
240  SymbolFlagsMap SymbolFlags;
241  VModuleKey K;
242 };
243 
244 /// A MaterializationUnit represents a set of symbol definitions that can
245 /// be materialized as a group, or individually discarded (when
246 /// overriding definitions are encountered).
247 ///
248 /// MaterializationUnits are used when providing lazy definitions of symbols to
249 /// JITDylibs. The JITDylib will call materialize when the address of a symbol
250 /// is requested via the lookup method. The JITDylib will call discard if a
251 /// stronger definition is added or already present.
253 public:
255  : SymbolFlags(std::move(InitalSymbolFlags)), K(std::move(K)) {}
256 
257  virtual ~MaterializationUnit() {}
258 
259  /// Return the name of this materialization unit. Useful for debugging
260  /// output.
261  virtual StringRef getName() const = 0;
262 
263  /// Return the set of symbols that this source provides.
264  const SymbolFlagsMap &getSymbols() const { return SymbolFlags; }
265 
266  /// Called by materialization dispatchers (see
267  /// ExecutionSession::DispatchMaterializationFunction) to trigger
268  /// materialization of this MaterializationUnit.
270  materialize(MaterializationResponsibility(JD, std::move(SymbolFlags),
271  std::move(K)));
272  }
273 
274  /// Called by JITDylibs to notify MaterializationUnits that the given symbol
275  /// has been overridden.
276  void doDiscard(const JITDylib &JD, const SymbolStringPtr &Name) {
277  SymbolFlags.erase(Name);
278  discard(JD, std::move(Name));
279  }
280 
281 protected:
284 
285 private:
286  virtual void anchor();
287 
288  /// Implementations of this method should materialize all symbols
289  /// in the materialzation unit, except for those that have been
290  /// previously discarded.
291  virtual void materialize(MaterializationResponsibility R) = 0;
292 
293  /// Implementations of this method should discard the given symbol
294  /// from the source (e.g. if the source is an LLVM IR Module and the
295  /// symbol is a function, delete the function body or mark it available
296  /// externally).
297  virtual void discard(const JITDylib &JD, const SymbolStringPtr &Name) = 0;
298 };
299 
301  std::vector<std::unique_ptr<MaterializationUnit>>;
302 
303 /// A MaterializationUnit implementation for pre-existing absolute symbols.
304 ///
305 /// All symbols will be resolved and marked ready as soon as the unit is
306 /// materialized.
308 public:
310 
311  StringRef getName() const override;
312 
313 private:
314  void materialize(MaterializationResponsibility R) override;
315  void discard(const JITDylib &JD, const SymbolStringPtr &Name) override;
316  static SymbolFlagsMap extractFlags(const SymbolMap &Symbols);
317 
318  SymbolMap Symbols;
319 };
320 
321 /// Create an AbsoluteSymbolsMaterializationUnit with the given symbols.
322 /// Useful for inserting absolute symbols into a JITDylib. E.g.:
323 /// \code{.cpp}
324 /// JITDylib &JD = ...;
325 /// SymbolStringPtr Foo = ...;
326 /// JITEvaluatedSymbol FooSym = ...;
327 /// if (auto Err = JD.define(absoluteSymbols({{Foo, FooSym}})))
328 /// return Err;
329 /// \endcode
330 ///
331 inline std::unique_ptr<AbsoluteSymbolsMaterializationUnit>
333  return llvm::make_unique<AbsoluteSymbolsMaterializationUnit>(
334  std::move(Symbols), std::move(K));
335 }
336 
338  SymbolAliasMapEntry() = default;
340  : Aliasee(std::move(Aliasee)), AliasFlags(AliasFlags) {}
341 
344 };
345 
346 /// A map of Symbols to (Symbol, Flags) pairs.
348 
349 /// A materialization unit for symbol aliases. Allows existing symbols to be
350 /// aliased with alternate flags.
352 public:
353  /// SourceJD is allowed to be nullptr, in which case the source JITDylib is
354  /// taken to be whatever JITDylib these definitions are materialized in (and
355  /// MatchNonExported has no effect). This is useful for defining aliases
356  /// within a JITDylib.
357  ///
358  /// Note: Care must be taken that no sets of aliases form a cycle, as such
359  /// a cycle will result in a deadlock when any symbol in the cycle is
360  /// resolved.
361  ReExportsMaterializationUnit(JITDylib *SourceJD, bool MatchNonExported,
362  SymbolAliasMap Aliases, VModuleKey K);
363 
364  StringRef getName() const override;
365 
366 private:
367  void materialize(MaterializationResponsibility R) override;
368  void discard(const JITDylib &JD, const SymbolStringPtr &Name) override;
369  static SymbolFlagsMap extractFlags(const SymbolAliasMap &Aliases);
370 
371  JITDylib *SourceJD = nullptr;
372  bool MatchNonExported = false;
373  SymbolAliasMap Aliases;
374 };
375 
376 /// Create a ReExportsMaterializationUnit with the given aliases.
377 /// Useful for defining symbol aliases.: E.g., given a JITDylib JD containing
378 /// symbols "foo" and "bar", we can define aliases "baz" (for "foo") and "qux"
379 /// (for "bar") with: \code{.cpp}
380 /// SymbolStringPtr Baz = ...;
381 /// SymbolStringPtr Qux = ...;
382 /// if (auto Err = JD.define(symbolAliases({
383 /// {Baz, { Foo, JITSymbolFlags::Exported }},
384 /// {Qux, { Bar, JITSymbolFlags::Weak }}}))
385 /// return Err;
386 /// \endcode
387 inline std::unique_ptr<ReExportsMaterializationUnit>
389  return llvm::make_unique<ReExportsMaterializationUnit>(
390  nullptr, true, std::move(Aliases), std::move(K));
391 }
392 
393 /// Create a materialization unit for re-exporting symbols from another JITDylib
394 /// with alternative names/flags.
395 /// If MatchNonExported is true then non-exported symbols from SourceJD can be
396 /// re-exported. If it is false, attempts to re-export a non-exported symbol
397 /// will result in a "symbol not found" error.
398 inline std::unique_ptr<ReExportsMaterializationUnit>
399 reexports(JITDylib &SourceJD, SymbolAliasMap Aliases,
400  bool MatchNonExported = false, VModuleKey K = VModuleKey()) {
401  return llvm::make_unique<ReExportsMaterializationUnit>(
402  &SourceJD, MatchNonExported, std::move(Aliases), std::move(K));
403 }
404 
405 /// Build a SymbolAliasMap for the common case where you want to re-export
406 /// symbols from another JITDylib with the same linkage/flags.
408 buildSimpleReexportsAliasMap(JITDylib &SourceJD, const SymbolNameSet &Symbols);
409 
410 /// ReexportsGenerator can be used with JITDylib::setGenerator to automatically
411 /// re-export a subset of the source JITDylib's symbols in the target.
413 public:
414  using SymbolPredicate = std::function<bool(SymbolStringPtr)>;
415 
416  /// Create a reexports generator. If an Allow predicate is passed, only
417  /// symbols for which the predicate returns true will be reexported. If no
418  /// Allow predicate is passed, all symbols will be exported.
419  ReexportsGenerator(JITDylib &SourceJD, bool MatchNonExported = false,
420  SymbolPredicate Allow = SymbolPredicate());
421 
422  SymbolNameSet operator()(JITDylib &JD, const SymbolNameSet &Names);
423 
424 private:
425  JITDylib &SourceJD;
426  bool MatchNonExported = false;
427  SymbolPredicate Allow;
428 };
429 
430 /// A symbol query that returns results via a callback when results are
431 /// ready.
432 ///
433 /// makes a callback when all symbols are available.
435  friend class ExecutionSession;
436  friend class JITDylib;
438 
439 public:
440 
441  /// Create a query for the given symbols, notify-resolved and
442  /// notify-ready callbacks.
443  AsynchronousSymbolQuery(const SymbolNameSet &Symbols,
444  SymbolsResolvedCallback NotifySymbolsResolved,
445  SymbolsReadyCallback NotifySymbolsReady);
446 
447  /// Set the resolved symbol information for the given symbol name.
448  void resolve(const SymbolStringPtr &Name, JITEvaluatedSymbol Sym);
449 
450  /// Returns true if all symbols covered by this query have been
451  /// resolved.
452  bool isFullyResolved() const { return NotYetResolvedCount == 0; }
453 
454  /// Call the NotifySymbolsResolved callback.
455  ///
456  /// This should only be called if all symbols covered by the query have been
457  /// resolved.
458  void handleFullyResolved();
459 
460  /// Notify the query that a requested symbol is ready for execution.
461  void notifySymbolReady();
462 
463  /// Returns true if all symbols covered by this query are ready.
464  bool isFullyReady() const { return NotYetReadyCount == 0; }
465 
466  /// Calls the NotifySymbolsReady callback.
467  ///
468  /// This should only be called if all symbols covered by this query are ready.
469  void handleFullyReady();
470 
471 private:
472  void addQueryDependence(JITDylib &JD, SymbolStringPtr Name);
473 
474  void removeQueryDependence(JITDylib &JD, const SymbolStringPtr &Name);
475 
476  bool canStillFail();
477 
478  void handleFailed(Error Err);
479 
480  void detach();
481 
482  SymbolsResolvedCallback NotifySymbolsResolved;
483  SymbolsReadyCallback NotifySymbolsReady;
484  SymbolDependenceMap QueryRegistrations;
485  SymbolMap ResolvedSymbols;
486  size_t NotYetResolvedCount;
487  size_t NotYetReadyCount;
488 };
489 
490 /// A symbol table that supports asynchoronous symbol queries.
491 ///
492 /// Represents a virtual shared object. Instances can not be copied or moved, so
493 /// their addresses may be used as keys for resource management.
494 /// JITDylib state changes must be made via an ExecutionSession to guarantee
495 /// that they are synchronized with respect to other JITDylib operations.
496 class JITDylib {
498  friend class ExecutionSession;
500 public:
502  JITDylib &Parent, const SymbolNameSet &Names)>;
503 
505  std::set<std::shared_ptr<AsynchronousSymbolQuery>>;
506 
507  JITDylib(const JITDylib &) = delete;
508  JITDylib &operator=(const JITDylib &) = delete;
509  JITDylib(JITDylib &&) = delete;
510  JITDylib &operator=(JITDylib &&) = delete;
511 
512  /// Get the name for this JITDylib.
513  const std::string &getName() const { return JITDylibName; }
514 
515  /// Get a reference to the ExecutionSession for this JITDylib.
516  ExecutionSession &getExecutionSession() const { return ES; }
517 
518  /// Set a definition generator. If set, whenever a symbol fails to resolve
519  /// within this JITDylib, lookup and lookupFlags will pass the unresolved
520  /// symbols set to the definition generator. The generator can optionally
521  /// add a definition for the unresolved symbols to the dylib.
522  void setGenerator(GeneratorFunction DefGenerator) {
523  this->DefGenerator = std::move(DefGenerator);
524  }
525 
526  /// Set the search order to be used when fixing up definitions in JITDylib.
527  /// This will replace the previous search order, and apply to any symbol
528  /// resolutions made for definitions in this JITDylib after the call to
529  /// setSearchOrder (even if the definition itself was added before the
530  /// call).
531  ///
532  /// If SearchThisJITDylibFirst is set, which by default it is, then this
533  /// JITDylib will add itself to the beginning of the SearchOrder (Clients
534  /// should *not* put this JITDylib in the list in this case, to avoid
535  /// redundant lookups).
536  ///
537  /// If SearchThisJITDylibFirst is false then the search order will be used as
538  /// given. The main motivation for this feature is to support deliberate
539  /// shadowing of symbols in this JITDylib by a facade JITDylib. For example,
540  /// the facade may resolve function names to stubs, and the stubs may compile
541  /// lazily by looking up symbols in this dylib. Adding the facade dylib
542  /// as the first in the search order (instead of this dylib) ensures that
543  /// definitions within this dylib resolve to the lazy-compiling stubs,
544  /// rather than immediately materializing the definitions in this dylib.
545  void setSearchOrder(JITDylibSearchList NewSearchOrder,
546  bool SearchThisJITDylibFirst = true,
547  bool MatchNonExportedInThisDylib = true);
548 
549  /// Add the given JITDylib to the search order for definitions in this
550  /// JITDylib.
551  void addToSearchOrder(JITDylib &JD, bool MatcNonExported = false);
552 
553  /// Replace OldJD with NewJD in the search order if OldJD is present.
554  /// Otherwise this operation is a no-op.
555  void replaceInSearchOrder(JITDylib &OldJD, JITDylib &NewJD,
556  bool MatchNonExported = false);
557 
558  /// Remove the given JITDylib from the search order for this JITDylib if it is
559  /// present. Otherwise this operation is a no-op.
560  void removeFromSearchOrder(JITDylib &JD);
561 
562  /// Do something with the search order (run under the session lock).
563  template <typename Func>
564  auto withSearchOrderDo(Func &&F)
565  -> decltype(F(std::declval<const JITDylibSearchList &>()));
566 
567  /// Define all symbols provided by the materialization unit to be part of this
568  /// JITDylib.
569  ///
570  /// This overload always takes ownership of the MaterializationUnit. If any
571  /// errors occur, the MaterializationUnit consumed.
572  template <typename MaterializationUnitType>
573  Error define(std::unique_ptr<MaterializationUnitType> &&MU);
574 
575  /// Define all symbols provided by the materialization unit to be part of this
576  /// JITDylib.
577  ///
578  /// This overload only takes ownership of the MaterializationUnit no error is
579  /// generated. If an error occurs, ownership remains with the caller. This
580  /// may allow the caller to modify the MaterializationUnit to correct the
581  /// issue, then re-call define.
582  template <typename MaterializationUnitType>
583  Error define(std::unique_ptr<MaterializationUnitType> &MU);
584 
585  /// Tries to remove the given symbols.
586  ///
587  /// If any symbols are not defined in this JITDylib this method will return
588  /// a SymbolsNotFound error covering the missing symbols.
589  ///
590  /// If all symbols are found but some symbols are in the process of being
591  /// materialized this method will return a SymbolsCouldNotBeRemoved error.
592  ///
593  /// On success, all symbols are removed. On failure, the JITDylib state is
594  /// left unmodified (no symbols are removed).
595  Error remove(const SymbolNameSet &Names);
596 
597  /// Search the given JITDylib for the symbols in Symbols. If found, store
598  /// the flags for each symbol in Flags. Returns any unresolved symbols.
599  SymbolFlagsMap lookupFlags(const SymbolNameSet &Names);
600 
601  /// Dump current JITDylib state to OS.
602  void dump(raw_ostream &OS);
603 
604  /// FIXME: Remove this when we remove the old ORC layers.
605  /// Search the given JITDylibs in order for the symbols in Symbols. Results
606  /// (once they become available) will be returned via the given Query.
607  ///
608  /// If any symbol is not found then the unresolved symbols will be returned,
609  /// and the query will not be applied. The Query is not failed and can be
610  /// re-used in a subsequent lookup once the symbols have been added, or
611  /// manually failed.
612  SymbolNameSet legacyLookup(std::shared_ptr<AsynchronousSymbolQuery> Q,
613  SymbolNameSet Names);
614 
615 private:
616  using AsynchronousSymbolQueryList =
617  std::vector<std::shared_ptr<AsynchronousSymbolQuery>>;
618 
619  struct UnmaterializedInfo {
620  UnmaterializedInfo(std::unique_ptr<MaterializationUnit> MU)
621  : MU(std::move(MU)) {}
622 
623  std::unique_ptr<MaterializationUnit> MU;
624  };
625 
626  using UnmaterializedInfosMap =
628 
629  struct MaterializingInfo {
630  AsynchronousSymbolQueryList PendingQueries;
631  SymbolDependenceMap Dependants;
632  SymbolDependenceMap UnemittedDependencies;
633  bool IsEmitted = false;
634  };
635 
637 
638  using LookupImplActionFlags = enum {
639  None = 0,
640  NotifyFullyResolved = 1 << 0U,
641  NotifyFullyReady = 1 << 1U,
642  LLVM_MARK_AS_BITMASK_ENUM(NotifyFullyReady)
643  };
644 
645  JITDylib(ExecutionSession &ES, std::string Name);
646 
647  Error defineImpl(MaterializationUnit &MU);
648 
649  SymbolNameSet lookupFlagsImpl(SymbolFlagsMap &Flags,
650  const SymbolNameSet &Names);
651 
652  void lodgeQuery(std::shared_ptr<AsynchronousSymbolQuery> &Q,
653  SymbolNameSet &Unresolved, bool MatchNonExported,
655 
656  void lodgeQueryImpl(std::shared_ptr<AsynchronousSymbolQuery> &Q,
657  SymbolNameSet &Unresolved, bool MatchNonExported,
659 
660  LookupImplActionFlags
661  lookupImpl(std::shared_ptr<AsynchronousSymbolQuery> &Q,
662  std::vector<std::unique_ptr<MaterializationUnit>> &MUs,
663  SymbolNameSet &Unresolved);
664 
665  void detachQueryHelper(AsynchronousSymbolQuery &Q,
666  const SymbolNameSet &QuerySymbols);
667 
668  void transferEmittedNodeDependencies(MaterializingInfo &DependantMI,
669  const SymbolStringPtr &DependantName,
670  MaterializingInfo &EmittedMI);
671 
672  Error defineMaterializing(const SymbolFlagsMap &SymbolFlags);
673 
674  void replace(std::unique_ptr<MaterializationUnit> MU);
675 
676  SymbolNameSet getRequestedSymbols(const SymbolFlagsMap &SymbolFlags) const;
677 
678  void addDependencies(const SymbolStringPtr &Name,
679  const SymbolDependenceMap &Dependants);
680 
681  void resolve(const SymbolMap &Resolved);
682 
683  void emit(const SymbolFlagsMap &Emitted);
684 
685  void notifyFailed(const SymbolNameSet &FailedSymbols);
686 
687  ExecutionSession &ES;
688  std::string JITDylibName;
689  SymbolMap Symbols;
690  UnmaterializedInfosMap UnmaterializedInfos;
691  MaterializingInfosMap MaterializingInfos;
692  GeneratorFunction DefGenerator;
693  JITDylibSearchList SearchOrder;
694 };
695 
696 /// An ExecutionSession represents a running JIT program.
698  // FIXME: Remove this when we remove the old ORC layers.
699  friend class JITDylib;
700 
701 public:
702  /// For reporting errors.
703  using ErrorReporter = std::function<void(Error)>;
704 
705  /// For dispatching MaterializationUnit::materialize calls.
707  JITDylib &JD, std::unique_ptr<MaterializationUnit> MU)>;
708 
709  /// Construct an ExecutionSession.
710  ///
711  /// SymbolStringPools may be shared between ExecutionSessions.
712  ExecutionSession(std::shared_ptr<SymbolStringPool> SSP = nullptr);
713 
714  /// Add a symbol name to the SymbolStringPool and return a pointer to it.
715  SymbolStringPtr intern(StringRef SymName) { return SSP->intern(SymName); }
716 
717  /// Returns a shared_ptr to the SymbolStringPool for this ExecutionSession.
718  std::shared_ptr<SymbolStringPool> getSymbolStringPool() const { return SSP; }
719 
720  /// Run the given lambda with the session mutex locked.
721  template <typename Func> auto runSessionLocked(Func &&F) -> decltype(F()) {
722  std::lock_guard<std::recursive_mutex> Lock(SessionMutex);
723  return F();
724  }
725 
726  /// Get the "main" JITDylib, which is created automatically on construction of
727  /// the ExecutionSession.
728  JITDylib &getMainJITDylib();
729 
730  /// Add a new JITDylib to this ExecutionSession.
731  JITDylib &createJITDylib(std::string Name,
732  bool AddToMainDylibSearchOrder = true);
733 
734  /// Allocate a module key for a new module to add to the JIT.
736  return runSessionLocked([this]() { return ++LastKey; });
737  }
738 
739  /// Return a module key to the ExecutionSession so that it can be
740  /// re-used. This should only be done once all resources associated
741  /// with the original key have been released.
742  void releaseVModule(VModuleKey Key) { /* FIXME: Recycle keys */
743  }
744 
745  /// Set the error reporter function.
747  this->ReportError = std::move(ReportError);
748  return *this;
749  }
750 
751  /// Report a error for this execution session.
752  ///
753  /// Unhandled errors can be sent here to log them.
754  void reportError(Error Err) { ReportError(std::move(Err)); }
755 
756  /// Set the materialization dispatch function.
758  DispatchMaterializationFunction DispatchMaterialization) {
759  this->DispatchMaterialization = std::move(DispatchMaterialization);
760  return *this;
761  }
762 
763  void legacyFailQuery(AsynchronousSymbolQuery &Q, Error Err);
764 
766  std::shared_ptr<AsynchronousSymbolQuery> Q, SymbolNameSet Names)>;
767 
768  /// A legacy lookup function for JITSymbolResolverAdapter.
769  /// Do not use -- this will be removed soon.
771  legacyLookup(LegacyAsyncLookupFunction AsyncLookup, SymbolNameSet Names,
772  bool WaiUntilReady,
773  RegisterDependenciesFunction RegisterDependencies);
774 
775  /// Search the given JITDylib list for the given symbols.
776  ///
777  /// SearchOrder lists the JITDylibs to search. For each dylib, the associated
778  /// boolean indicates whether the search should match against non-exported
779  /// (hidden visibility) symbols in that dylib (true means match against
780  /// non-exported symbols, false means do not match).
781  ///
782  /// The OnResolve callback will be called once all requested symbols are
783  /// resolved, or if an error occurs prior to resolution.
784  ///
785  /// The OnReady callback will be called once all requested symbols are ready,
786  /// or if an error occurs after resolution but before all symbols are ready.
787  ///
788  /// If all symbols are found, the RegisterDependencies function will be called
789  /// while the session lock is held. This gives clients a chance to register
790  /// dependencies for on the queried symbols for any symbols they are
791  /// materializing (if a MaterializationResponsibility instance is present,
792  /// this can be implemented by calling
793  /// MaterializationResponsibility::addDependencies). If there are no
794  /// dependenant symbols for this query (e.g. it is being made by a top level
795  /// client to get an address to call) then the value NoDependenciesToRegister
796  /// can be used.
797  void lookup(const JITDylibSearchList &SearchOrder, SymbolNameSet Symbols,
799  RegisterDependenciesFunction RegisterDependencies);
800 
801  /// Blocking version of lookup above. Returns the resolved symbol map.
802  /// If WaitUntilReady is true (the default), will not return until all
803  /// requested symbols are ready (or an error occurs). If WaitUntilReady is
804  /// false, will return as soon as all requested symbols are resolved,
805  /// or an error occurs. If WaitUntilReady is false and an error occurs
806  /// after resolution, the function will return a success value, but the
807  /// error will be reported via reportErrors.
808  Expected<SymbolMap> lookup(const JITDylibSearchList &SearchOrder,
809  const SymbolNameSet &Symbols,
810  RegisterDependenciesFunction RegisterDependencies =
811  NoDependenciesToRegister,
812  bool WaitUntilReady = true);
813 
814  /// Convenience version of blocking lookup.
815  /// Searches each of the JITDylibs in the search order in turn for the given
816  /// symbol.
819 
820  /// Convenience version of blocking lookup.
821  /// Searches each of the JITDylibs in the search order in turn for the given
822  /// symbol. The search will not find non-exported symbols.
825 
826  /// Convenience version of blocking lookup.
827  /// Searches each of the JITDylibs in the search order in turn for the given
828  /// symbol. The search will not find non-exported symbols.
830  StringRef Symbol);
831 
832  /// Materialize the given unit.
834  std::unique_ptr<MaterializationUnit> MU) {
835  LLVM_DEBUG(runSessionLocked([&]() {
836  dbgs() << "Compiling, for " << JD.getName() << ", " << *MU
837  << "\n";
838  }););
839  DispatchMaterialization(JD, std::move(MU));
840  }
841 
842  /// Dump the state of all the JITDylibs in this session.
843  void dump(raw_ostream &OS);
844 
845 private:
846  static void logErrorsToStdErr(Error Err) {
847  logAllUnhandledErrors(std::move(Err), errs(), "JIT session error: ");
848  }
849 
850  static void
851  materializeOnCurrentThread(JITDylib &JD,
852  std::unique_ptr<MaterializationUnit> MU) {
853  MU->doMaterialize(JD);
854  }
855 
856  void runOutstandingMUs();
857 
858  mutable std::recursive_mutex SessionMutex;
859  std::shared_ptr<SymbolStringPool> SSP;
860  VModuleKey LastKey = 0;
861  ErrorReporter ReportError = logErrorsToStdErr;
862  DispatchMaterializationFunction DispatchMaterialization =
863  materializeOnCurrentThread;
864 
865  std::vector<std::unique_ptr<JITDylib>> JDs;
866 
867  // FIXME: Remove this (and runOutstandingMUs) once the linking layer works
868  // with callbacks from asynchronous queries.
869  mutable std::recursive_mutex OutstandingMUsMutex;
870  std::vector<std::pair<JITDylib *, std::unique_ptr<MaterializationUnit>>>
871  OutstandingMUs;
872 };
873 
874 template <typename Func>
876  -> decltype(F(std::declval<const JITDylibSearchList &>())) {
877  return ES.runSessionLocked([&]() { return F(SearchOrder); });
878 }
879 
880 template <typename MaterializationUnitType>
881 Error JITDylib::define(std::unique_ptr<MaterializationUnitType> &&MU) {
882  assert(MU && "Can not define with a null MU");
883  return ES.runSessionLocked([&, this]() -> Error {
884  if (auto Err = defineImpl(*MU))
885  return Err;
886 
887  /// defineImpl succeeded.
888  auto UMI = std::make_shared<UnmaterializedInfo>(std::move(MU));
889  for (auto &KV : UMI->MU->getSymbols())
890  UnmaterializedInfos[KV.first] = UMI;
891 
892  return Error::success();
893  });
894 }
895 
896 template <typename MaterializationUnitType>
897 Error JITDylib::define(std::unique_ptr<MaterializationUnitType> &MU) {
898  assert(MU && "Can not define with a null MU");
899 
900  return ES.runSessionLocked([&, this]() -> Error {
901  if (auto Err = defineImpl(*MU))
902  return Err;
903 
904  /// defineImpl succeeded.
905  auto UMI = std::make_shared<UnmaterializedInfo>(std::move(MU));
906  for (auto &KV : UMI->MU->getSymbols())
907  UnmaterializedInfos[KV.first] = UMI;
908 
909  return Error::success();
910  });
911 }
912 
913 /// Mangles symbol names then uniques them in the context of an
914 /// ExecutionSession.
916 public:
918  SymbolStringPtr operator()(StringRef Name);
919 
920 private:
921  ExecutionSession &ES;
922  const DataLayout &DL;
923 };
924 
925 } // End namespace orc
926 } // End namespace llvm
927 
928 #undef DEBUG_TYPE // "orc"
929 
930 #endif // LLVM_EXECUTIONENGINE_ORC_CORE_H
const NoneType None
Definition: None.h:24
JITSymbolFlags AliasFlags
Definition: Core.h:343
A parsed version of the target data layout string in and methods for querying it. ...
Definition: DataLayout.h:111
std::shared_ptr< SymbolStringPool > getSymbolStringPool() const
Returns a shared_ptr to the SymbolStringPool for this ExecutionSession.
Definition: Core.h:718
const SymbolNameSet & getSymbols() const
Definition: Core.h:114
#define LLVM_MARK_AS_BITMASK_ENUM(LargestValue)
LLVM_MARK_AS_BITMASK_ENUM lets you opt in an individual enum type so you can perform bitwise operatio...
Definition: BitmaskEnum.h:42
ExecutionSession & setDispatchMaterialization(DispatchMaterializationFunction DispatchMaterialization)
Set the materialization dispatch function.
Definition: Core.h:757
raw_ostream & errs()
This returns a reference to a raw_ostream for standard error.
This class represents lattice values for constants.
Definition: AllocatorList.h:24
void dispatchMaterialization(JITDylib &JD, std::unique_ptr< MaterializationUnit > MU)
Materialize the given unit.
Definition: Core.h:833
Implements a dense probed hash-table based set.
Definition: DenseSet.h:250
std::function< void(const SymbolDependenceMap &)> RegisterDependenciesFunction
Callback to register the dependencies for a given query.
Definition: Core.h:99
void doDiscard(const JITDylib &JD, const SymbolStringPtr &Name)
Called by JITDylibs to notify MaterializationUnits that the given symbol has been overridden...
Definition: Core.h:276
static sys::Mutex Lock
F(f)
void setGenerator(GeneratorFunction DefGenerator)
Set a definition generator.
Definition: Core.h:522
uint64_t VModuleKey
VModuleKey provides a unique identifier (allocated and managed by ExecutionSessions) for a module add...
Definition: Core.h:40
Used to notify a JITDylib that the given set of symbols failed to materialize.
Definition: Core.h:107
std::function< bool(SymbolStringPtr)> SymbolPredicate
Definition: Core.h:414
std::unique_ptr< AbsoluteSymbolsMaterializationUnit > absoluteSymbols(SymbolMap Symbols, VModuleKey K=VModuleKey())
Create an AbsoluteSymbolsMaterializationUnit with the given symbols.
Definition: Core.h:332
void doMaterialize(JITDylib &JD)
Called by materialization dispatchers (see ExecutionSession::DispatchMaterializationFunction) to trig...
Definition: Core.h:269
amdgpu Simplify well known AMD library false Value Value const Twine & Name
Definition: BitVector.h:938
SymbolStringPtr intern(StringRef SymName)
Add a symbol name to the SymbolStringPool and return a pointer to it.
Definition: Core.h:715
std::function< SymbolNameSet(JITDylib &Parent, const SymbolNameSet &Names)> GeneratorFunction
Definition: Core.h:502
std::vector< std::pair< JITDylib *, bool > > JITDylibSearchList
A list of (JITDylib*, bool) pairs.
Definition: Core.h:58
SymbolFlagsMap SymbolFlags
Definition: Core.h:282
Error define(std::unique_ptr< MaterializationUnitType > &&MU)
Define all symbols provided by the materialization unit to be part of this JITDylib.
Definition: Core.h:881
Mangles symbol names then uniques them in the context of an ExecutionSession.
Definition: Core.h:915
static StringRef getName(Value *V)
raw_ostream & operator<<(raw_ostream &OS, const SymbolStringPtr &Sym)
Render a SymbolStringPtr.
Definition: Core.cpp:148
Tagged union holding either a T or a Error.
Definition: CachePruning.h:23
std::function< SymbolNameSet(std::shared_ptr< AsynchronousSymbolQuery > Q, SymbolNameSet Names)> LegacyAsyncLookupFunction
Definition: Core.h:766
static const uint16_t * lookup(unsigned opcode, unsigned domain, ArrayRef< uint16_t[3]> Table)
Tracks responsibility for materialization, and mediates interactions between MaterializationUnits and...
Definition: Core.h:155
virtual ~MaterializationUnit()
Definition: Core.h:257
void releaseVModule(VModuleKey Key)
Return a module key to the ExecutionSession so that it can be re-used.
Definition: Core.h:742
Key
PAL metadata keys.
auto withSearchOrderDo(Func &&F) -> decltype(F(std::declval< const JITDylibSearchList &>()))
Do something with the search order (run under the session lock).
Definition: Core.h:875
std::set< std::shared_ptr< AsynchronousSymbolQuery > > AsynchronousSymbolQuerySet
Definition: Core.h:505
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
Definition: APInt.h:33
Legacy adapter. Remove once we kill off the old ORC layers.
Definition: Legacy.h:94
JITDylib & getTargetJITDylib() const
Returns the target JITDylib that these symbols are being materialized into.
Definition: Core.h:169
ExecutionSession & getExecutionSession() const
Get a reference to the ExecutionSession for this JITDylib.
Definition: Core.h:516
std::unique_ptr< ReExportsMaterializationUnit > reexports(JITDylib &SourceJD, SymbolAliasMap Aliases, bool MatchNonExported=false, VModuleKey K=VModuleKey())
Create a materialization unit for re-exporting symbols from another JITDylib with alternative names/f...
Definition: Core.h:399
Expected< SymbolAliasMap > buildSimpleReexportsAliasMap(JITDylib &SourceJD, const SymbolNameSet &Symbols)
Build a SymbolAliasMap for the common case where you want to re-export symbols from another JITDylib ...
Definition: Core.cpp:687
std::unique_ptr< ReExportsMaterializationUnit > symbolAliases(SymbolAliasMap Aliases, VModuleKey K=VModuleKey())
Create a ReExportsMaterializationUnit with the given aliases.
Definition: Core.h:388
Pointer to a pooled string representing a symbol name.
DenseSet< SymbolStringPtr > SymbolNameSet
A set of symbol names (represented by SymbolStringPtrs for.
Definition: Core.h:44
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
void log(raw_ostream &OS) const override
Print an error message to an output stream.
Definition: Core.cpp:234
VModuleKey getVModuleKey() const
Returns the VModuleKey for this instance.
Definition: Core.h:172
A materialization unit for symbol aliases.
Definition: Core.h:351
const SymbolNameSet & getSymbols() const
Definition: Core.h:142
FailedToMaterialize(SymbolNameSet Symbols)
Definition: Core.cpp:225
VModuleKey allocateVModule()
Allocate a module key for a new module to add to the JIT.
Definition: Core.h:735
std::function< void(Expected< SymbolMap >)> SymbolsResolvedCallback
Callback to notify client that symbols have been resolved.
Definition: Core.h:92
Flags for symbols in the JIT.
Definition: JITSymbol.h:56
static void replace(Module &M, GlobalVariable *Old, GlobalVariable *New)
std::error_code convertToErrorCode() const override
Convert this error to a std::error_code.
Definition: Core.cpp:230
Used to notify clients when symbols can not be found during a lookup.
Definition: Core.h:121
void logAllUnhandledErrors(Error E, raw_ostream &OS, Twine ErrorBanner={})
Log all errors (if any) in E to OS.
Definition: Error.cpp:62
A MaterializationUnit represents a set of symbol definitions that can be materialized as a group...
Definition: Core.h:252
static ErrorSuccess success()
Create a success value.
Definition: Error.h:327
Module.h This file contains the declarations for the Module class.
SymbolStringPtr Aliasee
Definition: Core.h:342
An ExecutionSession represents a running JIT program.
Definition: Core.h:697
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:133
Represents a symbol that has been evaluated to an address already.
Definition: JITSymbol.h:209
Base class for user error types.
Definition: Error.h:345
A symbol query that returns results via a callback when results are ready.
Definition: Core.h:434
std::vector< std::unique_ptr< MaterializationUnit > > MaterializationUnitList
Definition: Core.h:301
const SymbolFlagsMap & getSymbols() const
Return the set of symbols that this source provides.
Definition: Core.h:264
void reportError(Error Err)
Report a error for this execution session.
Definition: Core.h:754
auto runSessionLocked(Func &&F) -> decltype(F())
Run the given lambda with the session mutex locked.
Definition: Core.h:721
A MaterializationUnit implementation for pre-existing absolute symbols.
Definition: Core.h:307
const std::string & getName() const
Get the name for this JITDylib.
Definition: Core.h:513
ExecutionSession & setErrorReporter(ErrorReporter ReportError)
Set the error reporter function.
Definition: Core.h:746
const SymbolNameSet & getSymbols() const
Definition: Core.h:128
bool isFullyReady() const
Returns true if all symbols covered by this query are ready.
Definition: Core.h:464
std::function< void(Error)> SymbolsReadyCallback
Callback to notify client that symbols are ready for execution.
Definition: Core.h:95
MaterializationUnit(SymbolFlagsMap InitalSymbolFlags, VModuleKey K)
Definition: Core.h:254
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
const SymbolFlagsMap & getSymbols()
Returns the symbol flags map for this responsibility instance.
Definition: Core.h:178
Lightweight error class with error context and mandatory checking.
Definition: Error.h:158
Used to notify clients that a set of symbols could not be removed.
Definition: Core.h:135
std::function< void(Error)> ErrorReporter
For reporting errors.
Definition: Core.h:703
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:46
print Print MemDeps of function
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:49
bool isFullyResolved() const
Returns true if all symbols covered by this query have been resolved.
Definition: Core.h:452
RegisterDependenciesFunction NoDependenciesToRegister
This can be used as the value for a RegisterDependenciesFunction if there are no dependants to regist...
Definition: Core.cpp:143
SymbolAliasMapEntry(SymbolStringPtr Aliasee, JITSymbolFlags AliasFlags)
Definition: Core.h:339
#define LLVM_DEBUG(X)
Definition: Debug.h:123
static void LLVM_ATTRIBUTE_NORETURN ReportError(uint32_t StartOffset, const char *ErrorMsg)
std::function< void(JITDylib &JD, std::unique_ptr< MaterializationUnit > MU)> DispatchMaterializationFunction
For dispatching MaterializationUnit::materialize calls.
Definition: Core.h:707
A symbol table that supports asynchoronous symbol queries.
Definition: Core.h:496
ReexportsGenerator can be used with JITDylib::setGenerator to automatically re-export a subset of the...
Definition: Core.h:412