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