1 //===------ Core.h -- Core ORC APIs (Layer, JITDylib, etc.) -----*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 // Contains core ORC APIs.
11 //===----------------------------------------------------------------------===//
13 #ifndef LLVM_EXECUTIONENGINE_ORC_CORE_H
14 #define LLVM_EXECUTIONENGINE_ORC_CORE_H
16 #include "llvm/ADT/BitmaskEnum.h"
17 #include "llvm/ADT/FunctionExtras.h"
18 #include "llvm/ExecutionEngine/JITSymbol.h"
19 #include "llvm/ExecutionEngine/Orc/SymbolStringPool.h"
20 #include "llvm/ExecutionEngine/OrcV1Deprecation.h"
21 #include "llvm/IR/Module.h"
22 #include "llvm/Support/Debug.h"
27 #define DEBUG_TYPE "orc"
32 // Forward declare some classes.
33 class AsynchronousSymbolQuery;
34 class ExecutionSession;
35 class MaterializationUnit;
36 class MaterializationResponsibility;
38 enum class SymbolState : uint8_t;
40 /// VModuleKey provides a unique identifier (allocated and managed by
41 /// ExecutionSessions) for a module added to the JIT.
42 using VModuleKey = uint64_t;
44 /// A set of symbol names (represented by SymbolStringPtrs for
46 using SymbolNameSet = DenseSet<SymbolStringPtr>;
48 /// A vector of symbol names.
49 using SymbolNameVector = std::vector<SymbolStringPtr>;
51 /// A map from symbol names (as SymbolStringPtrs) to JITSymbols
52 /// (address/flags pairs).
53 using SymbolMap = DenseMap<SymbolStringPtr, JITEvaluatedSymbol>;
55 /// A map from symbol names (as SymbolStringPtrs) to JITSymbolFlags.
56 using SymbolFlagsMap = DenseMap<SymbolStringPtr, JITSymbolFlags>;
58 /// A map from JITDylibs to sets of symbols.
59 using SymbolDependenceMap = DenseMap<JITDylib *, SymbolNameSet>;
61 /// Lookup flags that apply to each dylib in the search order for a lookup.
63 /// If MatchHiddenSymbolsOnly is used (the default) for a given dylib, then
64 /// only symbols in that Dylib's interface will be searched. If
65 /// MatchHiddenSymbols is used then symbols with hidden visibility will match
67 enum class JITDylibLookupFlags { MatchExportedSymbolsOnly, MatchAllSymbols };
69 /// Lookup flags that apply to each symbol in a lookup.
71 /// If RequiredSymbol is used (the default) for a given symbol then that symbol
72 /// must be found during the lookup or the lookup will fail returning a
73 /// SymbolNotFound error. If WeaklyReferencedSymbol is used and the given
74 /// symbol is not found then the query will continue, and no result for the
75 /// missing symbol will be present in the result (assuming the rest of the
77 enum class SymbolLookupFlags { RequiredSymbol, WeaklyReferencedSymbol };
79 /// Describes the kind of lookup being performed. The lookup kind is passed to
80 /// symbol generators (if they're invoked) to help them determine what
81 /// definitions to generate.
83 /// Static -- Lookup is being performed as-if at static link time (e.g.
84 /// generators representing static archives should pull in new
87 /// DLSym -- Lookup is being performed as-if at runtime (e.g. generators
88 /// representing static archives should not pull in new definitions).
89 enum class LookupKind { Static, DLSym };
91 /// A list of (JITDylib*, JITDylibLookupFlags) pairs to be used as a search
92 /// order during symbol lookup.
93 using JITDylibSearchOrder =
94 std::vector<std::pair<JITDylib *, JITDylibLookupFlags>>;
96 /// Convenience function for creating a search order from an ArrayRef of
97 /// JITDylib*, all with the same flags.
98 inline JITDylibSearchOrder makeJITDylibSearchOrder(
99 ArrayRef<JITDylib *> JDs,
100 JITDylibLookupFlags Flags = JITDylibLookupFlags::MatchExportedSymbolsOnly) {
101 JITDylibSearchOrder O;
102 O.reserve(JDs.size());
104 O.push_back(std::make_pair(JD, Flags));
108 /// A set of symbols to look up, each associated with a SymbolLookupFlags
111 /// This class is backed by a vector and optimized for fast insertion,
112 /// deletion and iteration. It does not guarantee a stable order between
113 /// operations, and will not automatically detect duplicate elements (they
114 /// can be manually checked by calling the validate method).
115 class SymbolLookupSet {
117 using value_type = std::pair<SymbolStringPtr, SymbolLookupFlags>;
118 using UnderlyingVector = std::vector<value_type>;
119 using iterator = UnderlyingVector::iterator;
120 using const_iterator = UnderlyingVector::const_iterator;
122 SymbolLookupSet() = default;
124 explicit SymbolLookupSet(
125 SymbolStringPtr Name,
126 SymbolLookupFlags Flags = SymbolLookupFlags::RequiredSymbol) {
127 add(std::move(Name), Flags);
130 /// Construct a SymbolLookupSet from an initializer list of SymbolStringPtrs.
131 explicit SymbolLookupSet(
132 std::initializer_list<SymbolStringPtr> Names,
133 SymbolLookupFlags Flags = SymbolLookupFlags::RequiredSymbol) {
134 Symbols.reserve(Names.size());
135 for (auto &Name : Names)
136 add(std::move(Name), Flags);
139 /// Construct a SymbolLookupSet from a SymbolNameSet with the given
140 /// Flags used for each value.
141 explicit SymbolLookupSet(
142 const SymbolNameSet &Names,
143 SymbolLookupFlags Flags = SymbolLookupFlags::RequiredSymbol) {
144 Symbols.reserve(Names.size());
145 for (const auto &Name : Names)
149 /// Construct a SymbolLookupSet from a vector of symbols with the given Flags
150 /// used for each value.
151 /// If the ArrayRef contains duplicates it is up to the client to remove these
152 /// before using this instance for lookup.
153 explicit SymbolLookupSet(
154 ArrayRef<SymbolStringPtr> Names,
155 SymbolLookupFlags Flags = SymbolLookupFlags::RequiredSymbol) {
156 Symbols.reserve(Names.size());
157 for (const auto &Name : Names)
161 /// Add an element to the set. The client is responsible for checking that
162 /// duplicates are not added.
163 void add(SymbolStringPtr Name,
164 SymbolLookupFlags Flags = SymbolLookupFlags::RequiredSymbol) {
165 Symbols.push_back(std::make_pair(std::move(Name), Flags));
168 bool empty() const { return Symbols.empty(); }
169 UnderlyingVector::size_type size() const { return Symbols.size(); }
170 iterator begin() { return Symbols.begin(); }
171 iterator end() { return Symbols.end(); }
172 const_iterator begin() const { return Symbols.begin(); }
173 const_iterator end() const { return Symbols.end(); }
175 /// Removes the Ith element of the vector, replacing it with the last element.
176 void remove(UnderlyingVector::size_type I) {
177 std::swap(Symbols[I], Symbols.back());
181 /// Removes the element pointed to by the given iterator. This iterator and
182 /// all subsequent ones (including end()) are invalidated.
183 void remove(iterator I) { remove(I - begin()); }
185 /// Removes all elements matching the given predicate, which must be callable
186 /// as bool(const SymbolStringPtr &, SymbolLookupFlags Flags).
187 template <typename PredFn> void remove_if(PredFn &&Pred) {
188 UnderlyingVector::size_type I = 0;
189 while (I != Symbols.size()) {
190 const auto &Name = Symbols[I].first;
191 auto Flags = Symbols[I].second;
192 if (Pred(Name, Flags))
199 /// Loop over the elements of this SymbolLookupSet, applying the Body function
200 /// to each one. Body must be callable as
201 /// bool(const SymbolStringPtr &, SymbolLookupFlags).
202 /// If Body returns true then the element just passed in is removed from the
203 /// set. If Body returns false then the element is retained.
204 template <typename BodyFn>
205 auto forEachWithRemoval(BodyFn &&Body) -> typename std::enable_if<
206 std::is_same<decltype(Body(std::declval<const SymbolStringPtr &>(),
207 std::declval<SymbolLookupFlags>())),
208 bool>::value>::type {
209 UnderlyingVector::size_type I = 0;
210 while (I != Symbols.size()) {
211 const auto &Name = Symbols[I].first;
212 auto Flags = Symbols[I].second;
213 if (Body(Name, Flags))
220 /// Loop over the elements of this SymbolLookupSet, applying the Body function
221 /// to each one. Body must be callable as
222 /// Expected<bool>(const SymbolStringPtr &, SymbolLookupFlags).
223 /// If Body returns a failure value, the loop exits immediately. If Body
224 /// returns true then the element just passed in is removed from the set. If
225 /// Body returns false then the element is retained.
226 template <typename BodyFn>
227 auto forEachWithRemoval(BodyFn &&Body) -> typename std::enable_if<
228 std::is_same<decltype(Body(std::declval<const SymbolStringPtr &>(),
229 std::declval<SymbolLookupFlags>())),
230 Expected<bool>>::value,
232 UnderlyingVector::size_type I = 0;
233 while (I != Symbols.size()) {
234 const auto &Name = Symbols[I].first;
235 auto Flags = Symbols[I].second;
236 auto Remove = Body(Name, Flags);
238 return Remove.takeError();
244 return Error::success();
247 /// Construct a SymbolNameVector from this instance by dropping the Flags
249 SymbolNameVector getSymbolNames() const {
250 SymbolNameVector Names;
251 Names.reserve(Symbols.size());
252 for (auto &KV : Symbols)
253 Names.push_back(KV.first);
257 /// Sort the lookup set by pointer value. This sort is fast but sensitive to
258 /// allocation order and so should not be used where a consistent order is
260 void sortByAddress() {
261 llvm::sort(Symbols, [](const value_type &LHS, const value_type &RHS) {
262 return LHS.first < RHS.first;
266 /// Sort the lookup set lexicographically. This sort is slow but the order
267 /// is unaffected by allocation order.
269 llvm::sort(Symbols, [](const value_type &LHS, const value_type &RHS) {
270 return *LHS.first < *RHS.first;
274 /// Remove any duplicate elements. If a SymbolLookupSet is not duplicate-free
275 /// by construction, this method can be used to turn it into a proper set.
276 void removeDuplicates() {
278 auto LastI = std::unique(Symbols.begin(), Symbols.end());
279 Symbols.erase(LastI, Symbols.end());
283 /// Returns true if this set contains any duplicates. This should only be used
285 bool containsDuplicates() {
286 if (Symbols.size() < 2)
289 for (UnderlyingVector::size_type I = 1; I != Symbols.size(); ++I)
290 if (Symbols[I].first == Symbols[I - 1].first)
297 UnderlyingVector Symbols;
300 struct SymbolAliasMapEntry {
301 SymbolAliasMapEntry() = default;
302 SymbolAliasMapEntry(SymbolStringPtr Aliasee, JITSymbolFlags AliasFlags)
303 : Aliasee(std::move(Aliasee)), AliasFlags(AliasFlags) {}
305 SymbolStringPtr Aliasee;
306 JITSymbolFlags AliasFlags;
309 /// A map of Symbols to (Symbol, Flags) pairs.
310 using SymbolAliasMap = DenseMap<SymbolStringPtr, SymbolAliasMapEntry>;
312 /// Render a SymbolStringPtr.
313 raw_ostream &operator<<(raw_ostream &OS, const SymbolStringPtr &Sym);
315 /// Render a SymbolNameSet.
316 raw_ostream &operator<<(raw_ostream &OS, const SymbolNameSet &Symbols);
318 /// Render a SymbolNameVector.
319 raw_ostream &operator<<(raw_ostream &OS, const SymbolNameVector &Symbols);
321 /// Render a SymbolFlagsMap entry.
322 raw_ostream &operator<<(raw_ostream &OS, const SymbolFlagsMap::value_type &KV);
324 /// Render a SymbolMap entry.
325 raw_ostream &operator<<(raw_ostream &OS, const SymbolMap::value_type &KV);
327 /// Render a SymbolFlagsMap.
328 raw_ostream &operator<<(raw_ostream &OS, const SymbolFlagsMap &SymbolFlags);
330 /// Render a SymbolMap.
331 raw_ostream &operator<<(raw_ostream &OS, const SymbolMap &Symbols);
333 /// Render a SymbolDependenceMap entry.
334 raw_ostream &operator<<(raw_ostream &OS,
335 const SymbolDependenceMap::value_type &KV);
337 /// Render a SymbolDependendeMap.
338 raw_ostream &operator<<(raw_ostream &OS, const SymbolDependenceMap &Deps);
340 /// Render a MaterializationUnit.
341 raw_ostream &operator<<(raw_ostream &OS, const MaterializationUnit &MU);
343 //// Render a JITDylibLookupFlags instance.
344 raw_ostream &operator<<(raw_ostream &OS,
345 const JITDylibLookupFlags &JDLookupFlags);
347 /// Rendar a SymbolLookupFlags instance.
348 raw_ostream &operator<<(raw_ostream &OS, const SymbolLookupFlags &LookupFlags);
350 /// Render a JITDylibLookupFlags instance.
351 raw_ostream &operator<<(raw_ostream &OS, const LookupKind &K);
353 /// Render a SymbolLookupSet entry.
354 raw_ostream &operator<<(raw_ostream &OS, const SymbolLookupSet::value_type &KV);
356 /// Render a SymbolLookupSet.
357 raw_ostream &operator<<(raw_ostream &OS, const SymbolLookupSet &LookupSet);
359 /// Render a JITDylibSearchOrder.
360 raw_ostream &operator<<(raw_ostream &OS,
361 const JITDylibSearchOrder &SearchOrder);
363 /// Render a SymbolAliasMap.
364 raw_ostream &operator<<(raw_ostream &OS, const SymbolAliasMap &Aliases);
366 /// Render a SymbolState.
367 raw_ostream &operator<<(raw_ostream &OS, const SymbolState &S);
369 /// Render a LookupKind.
370 raw_ostream &operator<<(raw_ostream &OS, const LookupKind &K);
372 /// Callback to notify client that symbols have been resolved.
373 using SymbolsResolvedCallback = unique_function<void(Expected<SymbolMap>)>;
375 /// Callback to register the dependencies for a given query.
376 using RegisterDependenciesFunction =
377 std::function<void(const SymbolDependenceMap &)>;
379 /// This can be used as the value for a RegisterDependenciesFunction if there
380 /// are no dependants to register with.
381 extern RegisterDependenciesFunction NoDependenciesToRegister;
383 /// Used to notify a JITDylib that the given set of symbols failed to
385 class FailedToMaterialize : public ErrorInfo<FailedToMaterialize> {
389 FailedToMaterialize(std::shared_ptr<SymbolDependenceMap> Symbols);
390 std::error_code convertToErrorCode() const override;
391 void log(raw_ostream &OS) const override;
392 const SymbolDependenceMap &getSymbols() const { return *Symbols; }
395 std::shared_ptr<SymbolDependenceMap> Symbols;
398 /// Used to notify clients when symbols can not be found during a lookup.
399 class SymbolsNotFound : public ErrorInfo<SymbolsNotFound> {
403 SymbolsNotFound(SymbolNameSet Symbols);
404 SymbolsNotFound(SymbolNameVector Symbols);
405 std::error_code convertToErrorCode() const override;
406 void log(raw_ostream &OS) const override;
407 const SymbolNameVector &getSymbols() const { return Symbols; }
410 SymbolNameVector Symbols;
413 /// Used to notify clients that a set of symbols could not be removed.
414 class SymbolsCouldNotBeRemoved : public ErrorInfo<SymbolsCouldNotBeRemoved> {
418 SymbolsCouldNotBeRemoved(SymbolNameSet Symbols);
419 std::error_code convertToErrorCode() const override;
420 void log(raw_ostream &OS) const override;
421 const SymbolNameSet &getSymbols() const { return Symbols; }
424 SymbolNameSet Symbols;
427 /// Tracks responsibility for materialization, and mediates interactions between
428 /// MaterializationUnits and JDs.
430 /// An instance of this class is passed to MaterializationUnits when their
431 /// materialize method is called. It allows MaterializationUnits to resolve and
432 /// emit symbols, or abandon materialization by notifying any unmaterialized
433 /// symbols of an error.
434 class MaterializationResponsibility {
435 friend class MaterializationUnit;
437 MaterializationResponsibility(MaterializationResponsibility &&) = default;
438 MaterializationResponsibility &
439 operator=(MaterializationResponsibility &&) = delete;
441 /// Destruct a MaterializationResponsibility instance. In debug mode
442 /// this asserts that all symbols being tracked have been either
443 /// emitted or notified of an error.
444 ~MaterializationResponsibility();
446 /// Returns the target JITDylib that these symbols are being materialized
448 JITDylib &getTargetJITDylib() const { return JD; }
450 /// Returns the VModuleKey for this instance.
451 VModuleKey getVModuleKey() const { return K; }
453 /// Returns the symbol flags map for this responsibility instance.
454 /// Note: The returned flags may have transient flags (Lazy, Materializing)
455 /// set. These should be stripped with JITSymbolFlags::stripTransientFlags
457 const SymbolFlagsMap &getSymbols() const { return SymbolFlags; }
459 /// Returns the names of any symbols covered by this
460 /// MaterializationResponsibility object that have queries pending. This
461 /// information can be used to return responsibility for unrequested symbols
462 /// back to the JITDylib via the delegate method.
463 SymbolNameSet getRequestedSymbols() const;
465 /// Notifies the target JITDylib that the given symbols have been resolved.
466 /// This will update the given symbols' addresses in the JITDylib, and notify
467 /// any pending queries on the given symbols of their resolution. The given
468 /// symbols must be ones covered by this MaterializationResponsibility
469 /// instance. Individual calls to this method may resolve a subset of the
470 /// symbols, but all symbols must have been resolved prior to calling emit.
472 /// This method will return an error if any symbols being resolved have been
473 /// moved to the error state due to the failure of a dependency. If this
474 /// method returns an error then clients should log it and call
475 /// failMaterialize. If no dependencies have been registered for the
476 /// symbols covered by this MaterializationResponsibiility then this method
477 /// is guaranteed to return Error::success() and can be wrapped with cantFail.
478 Error notifyResolved(const SymbolMap &Symbols);
480 /// Notifies the target JITDylib (and any pending queries on that JITDylib)
481 /// that all symbols covered by this MaterializationResponsibility instance
482 /// have been emitted.
484 /// This method will return an error if any symbols being resolved have been
485 /// moved to the error state due to the failure of a dependency. If this
486 /// method returns an error then clients should log it and call
487 /// failMaterialize. If no dependencies have been registered for the
488 /// symbols covered by this MaterializationResponsibiility then this method
489 /// is guaranteed to return Error::success() and can be wrapped with cantFail.
490 Error notifyEmitted();
492 /// Attempt to claim responsibility for new definitions. This method can be
493 /// used to claim responsibility for symbols that are added to a
494 /// materialization unit during the compilation process (e.g. literal pool
495 /// symbols). Symbol linkage rules are the same as for symbols that are
496 /// defined up front: duplicate strong definitions will result in errors.
497 /// Duplicate weak definitions will be discarded (in which case they will
498 /// not be added to this responsibility instance).
500 /// This method can be used by materialization units that want to add
501 /// additional symbols at materialization time (e.g. stubs, compile
502 /// callbacks, metadata).
503 Error defineMaterializing(SymbolFlagsMap SymbolFlags);
505 /// Notify all not-yet-emitted covered by this MaterializationResponsibility
506 /// instance that an error has occurred.
507 /// This will remove all symbols covered by this MaterializationResponsibilty
508 /// from the target JITDylib, and send an error to any queries waiting on
510 void failMaterialization();
512 /// Transfers responsibility to the given MaterializationUnit for all
513 /// symbols defined by that MaterializationUnit. This allows
514 /// materializers to break up work based on run-time information (e.g.
515 /// by introspecting which symbols have actually been looked up and
516 /// materializing only those).
517 void replace(std::unique_ptr<MaterializationUnit> MU);
519 /// Delegates responsibility for the given symbols to the returned
520 /// materialization responsibility. Useful for breaking up work between
521 /// threads, or different kinds of materialization processes.
522 MaterializationResponsibility delegate(const SymbolNameSet &Symbols,
523 VModuleKey NewKey = VModuleKey());
525 void addDependencies(const SymbolStringPtr &Name,
526 const SymbolDependenceMap &Dependencies);
528 /// Add dependencies that apply to all symbols covered by this instance.
529 void addDependenciesForAll(const SymbolDependenceMap &Dependencies);
532 /// Create a MaterializationResponsibility for the given JITDylib and
534 MaterializationResponsibility(JITDylib &JD, SymbolFlagsMap SymbolFlags,
538 SymbolFlagsMap SymbolFlags;
542 /// A MaterializationUnit represents a set of symbol definitions that can
543 /// be materialized as a group, or individually discarded (when
544 /// overriding definitions are encountered).
546 /// MaterializationUnits are used when providing lazy definitions of symbols to
547 /// JITDylibs. The JITDylib will call materialize when the address of a symbol
548 /// is requested via the lookup method. The JITDylib will call discard if a
549 /// stronger definition is added or already present.
550 class MaterializationUnit {
552 MaterializationUnit(SymbolFlagsMap InitalSymbolFlags, VModuleKey K)
553 : SymbolFlags(std::move(InitalSymbolFlags)), K(std::move(K)) {}
555 virtual ~MaterializationUnit() {}
557 /// Return the name of this materialization unit. Useful for debugging
559 virtual StringRef getName() const = 0;
561 /// Return the set of symbols that this source provides.
562 const SymbolFlagsMap &getSymbols() const { return SymbolFlags; }
564 /// Called by materialization dispatchers (see
565 /// ExecutionSession::DispatchMaterializationFunction) to trigger
566 /// materialization of this MaterializationUnit.
567 void doMaterialize(JITDylib &JD) {
568 materialize(MaterializationResponsibility(JD, std::move(SymbolFlags),
572 /// Called by JITDylibs to notify MaterializationUnits that the given symbol
573 /// has been overridden.
574 void doDiscard(const JITDylib &JD, const SymbolStringPtr &Name) {
575 SymbolFlags.erase(Name);
576 discard(JD, std::move(Name));
580 SymbolFlagsMap SymbolFlags;
584 virtual void anchor();
586 /// Implementations of this method should materialize all symbols
587 /// in the materialzation unit, except for those that have been
588 /// previously discarded.
589 virtual void materialize(MaterializationResponsibility R) = 0;
591 /// Implementations of this method should discard the given symbol
592 /// from the source (e.g. if the source is an LLVM IR Module and the
593 /// symbol is a function, delete the function body or mark it available
595 virtual void discard(const JITDylib &JD, const SymbolStringPtr &Name) = 0;
598 using MaterializationUnitList =
599 std::vector<std::unique_ptr<MaterializationUnit>>;
601 /// A MaterializationUnit implementation for pre-existing absolute symbols.
603 /// All symbols will be resolved and marked ready as soon as the unit is
605 class AbsoluteSymbolsMaterializationUnit : public MaterializationUnit {
607 AbsoluteSymbolsMaterializationUnit(SymbolMap Symbols, VModuleKey K);
609 StringRef getName() const override;
612 void materialize(MaterializationResponsibility R) override;
613 void discard(const JITDylib &JD, const SymbolStringPtr &Name) override;
614 static SymbolFlagsMap extractFlags(const SymbolMap &Symbols);
619 /// Create an AbsoluteSymbolsMaterializationUnit with the given symbols.
620 /// Useful for inserting absolute symbols into a JITDylib. E.g.:
622 /// JITDylib &JD = ...;
623 /// SymbolStringPtr Foo = ...;
624 /// JITEvaluatedSymbol FooSym = ...;
625 /// if (auto Err = JD.define(absoluteSymbols({{Foo, FooSym}})))
629 inline std::unique_ptr<AbsoluteSymbolsMaterializationUnit>
630 absoluteSymbols(SymbolMap Symbols, VModuleKey K = VModuleKey()) {
631 return std::make_unique<AbsoluteSymbolsMaterializationUnit>(
632 std::move(Symbols), std::move(K));
635 /// A materialization unit for symbol aliases. Allows existing symbols to be
636 /// aliased with alternate flags.
637 class ReExportsMaterializationUnit : public MaterializationUnit {
639 /// SourceJD is allowed to be nullptr, in which case the source JITDylib is
640 /// taken to be whatever JITDylib these definitions are materialized in (and
641 /// MatchNonExported has no effect). This is useful for defining aliases
642 /// within a JITDylib.
644 /// Note: Care must be taken that no sets of aliases form a cycle, as such
645 /// a cycle will result in a deadlock when any symbol in the cycle is
647 ReExportsMaterializationUnit(JITDylib *SourceJD,
648 JITDylibLookupFlags SourceJDLookupFlags,
649 SymbolAliasMap Aliases, VModuleKey K);
651 StringRef getName() const override;
654 void materialize(MaterializationResponsibility R) override;
655 void discard(const JITDylib &JD, const SymbolStringPtr &Name) override;
656 static SymbolFlagsMap extractFlags(const SymbolAliasMap &Aliases);
658 JITDylib *SourceJD = nullptr;
659 JITDylibLookupFlags SourceJDLookupFlags;
660 SymbolAliasMap Aliases;
663 /// Create a ReExportsMaterializationUnit with the given aliases.
664 /// Useful for defining symbol aliases.: E.g., given a JITDylib JD containing
665 /// symbols "foo" and "bar", we can define aliases "baz" (for "foo") and "qux"
666 /// (for "bar") with: \code{.cpp}
667 /// SymbolStringPtr Baz = ...;
668 /// SymbolStringPtr Qux = ...;
669 /// if (auto Err = JD.define(symbolAliases({
670 /// {Baz, { Foo, JITSymbolFlags::Exported }},
671 /// {Qux, { Bar, JITSymbolFlags::Weak }}}))
674 inline std::unique_ptr<ReExportsMaterializationUnit>
675 symbolAliases(SymbolAliasMap Aliases, VModuleKey K = VModuleKey()) {
676 return std::make_unique<ReExportsMaterializationUnit>(
677 nullptr, JITDylibLookupFlags::MatchAllSymbols, std::move(Aliases),
681 /// Create a materialization unit for re-exporting symbols from another JITDylib
682 /// with alternative names/flags.
683 /// SourceJD will be searched using the given JITDylibLookupFlags.
684 inline std::unique_ptr<ReExportsMaterializationUnit>
685 reexports(JITDylib &SourceJD, SymbolAliasMap Aliases,
686 JITDylibLookupFlags SourceJDLookupFlags =
687 JITDylibLookupFlags::MatchExportedSymbolsOnly,
688 VModuleKey K = VModuleKey()) {
689 return std::make_unique<ReExportsMaterializationUnit>(
690 &SourceJD, SourceJDLookupFlags, std::move(Aliases), std::move(K));
693 /// Build a SymbolAliasMap for the common case where you want to re-export
694 /// symbols from another JITDylib with the same linkage/flags.
695 Expected<SymbolAliasMap>
696 buildSimpleReexportsAAliasMap(JITDylib &SourceJD, const SymbolNameSet &Symbols);
698 /// Represents the state that a symbol has reached during materialization.
699 enum class SymbolState : uint8_t {
700 Invalid, /// No symbol should be in this state.
701 NeverSearched, /// Added to the symbol table, never queried.
702 Materializing, /// Queried, materialization begun.
703 Resolved, /// Assigned address, still materializing.
704 Emitted, /// Emitted to memory, but waiting on transitive dependencies.
705 Ready = 0x3f /// Ready and safe for clients to access.
708 /// A symbol query that returns results via a callback when results are
711 /// makes a callback when all symbols are available.
712 class AsynchronousSymbolQuery {
713 friend class ExecutionSession;
714 friend class JITDylib;
715 friend class JITSymbolResolverAdapter;
718 /// Create a query for the given symbols. The NotifyComplete
719 /// callback will be called once all queried symbols reach the given
721 AsynchronousSymbolQuery(const SymbolLookupSet &Symbols,
722 SymbolState RequiredState,
723 SymbolsResolvedCallback NotifyComplete);
725 /// Notify the query that a requested symbol has reached the required state.
726 void notifySymbolMetRequiredState(const SymbolStringPtr &Name,
727 JITEvaluatedSymbol Sym);
729 /// Remove a symbol from the query. This is used to drop weakly referenced
730 /// symbols that are not found.
731 void dropSymbol(const SymbolStringPtr &Name) {
732 assert(ResolvedSymbols.count(Name) &&
733 "Redundant removal of weakly-referenced symbol");
734 ResolvedSymbols.erase(Name);
735 --OutstandingSymbolsCount;
738 /// Returns true if all symbols covered by this query have been
740 bool isComplete() const { return OutstandingSymbolsCount == 0; }
742 /// Call the NotifyComplete callback.
744 /// This should only be called if all symbols covered by the query have
745 /// reached the specified state.
746 void handleComplete();
749 SymbolState getRequiredState() { return RequiredState; }
751 void addQueryDependence(JITDylib &JD, SymbolStringPtr Name);
753 void removeQueryDependence(JITDylib &JD, const SymbolStringPtr &Name);
757 void handleFailed(Error Err);
761 SymbolsResolvedCallback NotifyComplete;
762 SymbolDependenceMap QueryRegistrations;
763 SymbolMap ResolvedSymbols;
764 size_t OutstandingSymbolsCount;
765 SymbolState RequiredState;
768 /// A symbol table that supports asynchoronous symbol queries.
770 /// Represents a virtual shared object. Instances can not be copied or moved, so
771 /// their addresses may be used as keys for resource management.
772 /// JITDylib state changes must be made via an ExecutionSession to guarantee
773 /// that they are synchronized with respect to other JITDylib operations.
775 friend class AsynchronousSymbolQuery;
776 friend class ExecutionSession;
777 friend class MaterializationResponsibility;
779 /// Definition generators can be attached to JITDylibs to generate new
780 /// definitions for otherwise unresolved symbols during lookup.
781 class DefinitionGenerator {
783 virtual ~DefinitionGenerator();
785 /// DefinitionGenerators should override this method to insert new
786 /// definitions into the parent JITDylib. K specifies the kind of this
787 /// lookup. JD specifies the target JITDylib being searched, and
788 /// JDLookupFlags specifies whether the search should match against
789 /// hidden symbols. Finally, Symbols describes the set of unresolved
790 /// symbols and their associated lookup flags.
791 virtual Error tryToGenerate(LookupKind K, JITDylib &JD,
792 JITDylibLookupFlags JDLookupFlags,
793 const SymbolLookupSet &LookupSet) = 0;
796 using AsynchronousSymbolQuerySet =
797 std::set<std::shared_ptr<AsynchronousSymbolQuery>>;
799 JITDylib(const JITDylib &) = delete;
800 JITDylib &operator=(const JITDylib &) = delete;
801 JITDylib(JITDylib &&) = delete;
802 JITDylib &operator=(JITDylib &&) = delete;
804 /// Get the name for this JITDylib.
805 const std::string &getName() const { return JITDylibName; }
807 /// Get a reference to the ExecutionSession for this JITDylib.
808 ExecutionSession &getExecutionSession() const { return ES; }
810 /// Adds a definition generator to this JITDylib and returns a referenece to
813 /// When JITDylibs are searched during lookup, if no existing definition of
814 /// a symbol is found, then any generators that have been added are run (in
815 /// the order that they were added) to potentially generate a definition.
816 template <typename GeneratorT>
817 GeneratorT &addGenerator(std::unique_ptr<GeneratorT> DefGenerator);
819 /// Remove a definition generator from this JITDylib.
821 /// The given generator must exist in this JITDylib's generators list (i.e.
822 /// have been added and not yet removed).
823 void removeGenerator(DefinitionGenerator &G);
825 /// Set the search order to be used when fixing up definitions in JITDylib.
826 /// This will replace the previous search order, and apply to any symbol
827 /// resolutions made for definitions in this JITDylib after the call to
828 /// setSearchOrder (even if the definition itself was added before the
831 /// If SearchThisJITDylibFirst is set, which by default it is, then this
832 /// JITDylib will add itself to the beginning of the SearchOrder (Clients
833 /// should *not* put this JITDylib in the list in this case, to avoid
834 /// redundant lookups).
836 /// If SearchThisJITDylibFirst is false then the search order will be used as
837 /// given. The main motivation for this feature is to support deliberate
838 /// shadowing of symbols in this JITDylib by a facade JITDylib. For example,
839 /// the facade may resolve function names to stubs, and the stubs may compile
840 /// lazily by looking up symbols in this dylib. Adding the facade dylib
841 /// as the first in the search order (instead of this dylib) ensures that
842 /// definitions within this dylib resolve to the lazy-compiling stubs,
843 /// rather than immediately materializing the definitions in this dylib.
844 void setSearchOrder(JITDylibSearchOrder NewSearchOrder,
845 bool SearchThisJITDylibFirst = true);
847 /// Add the given JITDylib to the search order for definitions in this
849 void addToSearchOrder(JITDylib &JD,
850 JITDylibLookupFlags JDLookupFlags =
851 JITDylibLookupFlags::MatchExportedSymbolsOnly);
853 /// Replace OldJD with NewJD in the search order if OldJD is present.
854 /// Otherwise this operation is a no-op.
855 void replaceInSearchOrder(JITDylib &OldJD, JITDylib &NewJD,
856 JITDylibLookupFlags JDLookupFlags =
857 JITDylibLookupFlags::MatchExportedSymbolsOnly);
859 /// Remove the given JITDylib from the search order for this JITDylib if it is
860 /// present. Otherwise this operation is a no-op.
861 void removeFromSearchOrder(JITDylib &JD);
863 /// Do something with the search order (run under the session lock).
864 template <typename Func>
865 auto withSearchOrderDo(Func &&F)
866 -> decltype(F(std::declval<const JITDylibSearchOrder &>()));
868 /// Define all symbols provided by the materialization unit to be part of this
871 /// This overload always takes ownership of the MaterializationUnit. If any
872 /// errors occur, the MaterializationUnit consumed.
873 template <typename MaterializationUnitType>
874 Error define(std::unique_ptr<MaterializationUnitType> &&MU);
876 /// Define all symbols provided by the materialization unit to be part of this
879 /// This overload only takes ownership of the MaterializationUnit no error is
880 /// generated. If an error occurs, ownership remains with the caller. This
881 /// may allow the caller to modify the MaterializationUnit to correct the
882 /// issue, then re-call define.
883 template <typename MaterializationUnitType>
884 Error define(std::unique_ptr<MaterializationUnitType> &MU);
886 /// Tries to remove the given symbols.
888 /// If any symbols are not defined in this JITDylib this method will return
889 /// a SymbolsNotFound error covering the missing symbols.
891 /// If all symbols are found but some symbols are in the process of being
892 /// materialized this method will return a SymbolsCouldNotBeRemoved error.
894 /// On success, all symbols are removed. On failure, the JITDylib state is
895 /// left unmodified (no symbols are removed).
896 Error remove(const SymbolNameSet &Names);
898 /// Search the given JITDylib for the symbols in Symbols. If found, store
899 /// the flags for each symbol in Flags. If any required symbols are not found
900 /// then an error will be returned.
901 Expected<SymbolFlagsMap> lookupFlags(LookupKind K,
902 JITDylibLookupFlags JDLookupFlags,
903 SymbolLookupSet LookupSet);
905 /// Dump current JITDylib state to OS.
906 void dump(raw_ostream &OS);
908 /// FIXME: Remove this when we remove the old ORC layers.
909 /// Search the given JITDylibs in order for the symbols in Symbols. Results
910 /// (once they become available) will be returned via the given Query.
912 /// If any symbol is not found then the unresolved symbols will be returned,
913 /// and the query will not be applied. The Query is not failed and can be
914 /// re-used in a subsequent lookup once the symbols have been added, or
916 Expected<SymbolNameSet>
917 legacyLookup(std::shared_ptr<AsynchronousSymbolQuery> Q, SymbolNameSet Names);
920 using AsynchronousSymbolQueryList =
921 std::vector<std::shared_ptr<AsynchronousSymbolQuery>>;
923 struct UnmaterializedInfo {
924 UnmaterializedInfo(std::unique_ptr<MaterializationUnit> MU)
925 : MU(std::move(MU)) {}
927 std::unique_ptr<MaterializationUnit> MU;
930 using UnmaterializedInfosMap =
931 DenseMap<SymbolStringPtr, std::shared_ptr<UnmaterializedInfo>>;
933 struct MaterializingInfo {
934 SymbolDependenceMap Dependants;
935 SymbolDependenceMap UnemittedDependencies;
937 void addQuery(std::shared_ptr<AsynchronousSymbolQuery> Q);
938 void removeQuery(const AsynchronousSymbolQuery &Q);
939 AsynchronousSymbolQueryList takeQueriesMeeting(SymbolState RequiredState);
940 AsynchronousSymbolQueryList takeAllPendingQueries() {
941 return std::move(PendingQueries);
943 bool hasQueriesPending() const { return !PendingQueries.empty(); }
944 const AsynchronousSymbolQueryList &pendingQueries() const {
945 return PendingQueries;
948 AsynchronousSymbolQueryList PendingQueries;
951 using MaterializingInfosMap = DenseMap<SymbolStringPtr, MaterializingInfo>;
953 class SymbolTableEntry {
955 SymbolTableEntry() = default;
956 SymbolTableEntry(JITSymbolFlags Flags)
957 : Flags(Flags), State(static_cast<uint8_t>(SymbolState::NeverSearched)),
958 MaterializerAttached(false), PendingRemoval(false) {}
960 JITTargetAddress getAddress() const { return Addr; }
961 JITSymbolFlags getFlags() const { return Flags; }
962 SymbolState getState() const { return static_cast<SymbolState>(State); }
964 bool isInMaterializationPhase() const {
965 return getState() == SymbolState::Materializing ||
966 getState() == SymbolState::Resolved;
969 bool hasMaterializerAttached() const { return MaterializerAttached; }
970 bool isPendingRemoval() const { return PendingRemoval; }
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);
980 void setMaterializerAttached(bool MaterializerAttached) {
981 this->MaterializerAttached = MaterializerAttached;
984 void setPendingRemoval(bool PendingRemoval) {
985 this->PendingRemoval = PendingRemoval;
988 JITEvaluatedSymbol getSymbol() const {
989 return JITEvaluatedSymbol(Addr, Flags);
993 JITTargetAddress Addr = 0;
994 JITSymbolFlags Flags;
996 uint8_t MaterializerAttached : 1;
997 uint8_t PendingRemoval : 1;
1000 using SymbolTable = DenseMap<SymbolStringPtr, SymbolTableEntry>;
1002 JITDylib(ExecutionSession &ES, std::string Name);
1004 Error defineImpl(MaterializationUnit &MU);
1006 void lookupFlagsImpl(SymbolFlagsMap &Result, LookupKind K,
1007 JITDylibLookupFlags JDLookupFlags,
1008 SymbolLookupSet &Unresolved);
1010 Error lodgeQuery(MaterializationUnitList &MUs,
1011 std::shared_ptr<AsynchronousSymbolQuery> &Q, LookupKind K,
1012 JITDylibLookupFlags JDLookupFlags,
1013 SymbolLookupSet &Unresolved);
1015 Error lodgeQueryImpl(MaterializationUnitList &MUs,
1016 std::shared_ptr<AsynchronousSymbolQuery> &Q,
1017 LookupKind K, JITDylibLookupFlags JDLookupFlags,
1018 SymbolLookupSet &Unresolved);
1020 bool lookupImpl(std::shared_ptr<AsynchronousSymbolQuery> &Q,
1021 std::vector<std::unique_ptr<MaterializationUnit>> &MUs,
1022 SymbolLookupSet &Unresolved);
1024 void detachQueryHelper(AsynchronousSymbolQuery &Q,
1025 const SymbolNameSet &QuerySymbols);
1027 void transferEmittedNodeDependencies(MaterializingInfo &DependantMI,
1028 const SymbolStringPtr &DependantName,
1029 MaterializingInfo &EmittedMI);
1031 Expected<SymbolFlagsMap> defineMaterializing(SymbolFlagsMap SymbolFlags);
1033 void replace(std::unique_ptr<MaterializationUnit> MU);
1035 SymbolNameSet getRequestedSymbols(const SymbolFlagsMap &SymbolFlags) const;
1037 void addDependencies(const SymbolStringPtr &Name,
1038 const SymbolDependenceMap &Dependants);
1040 Error resolve(const SymbolMap &Resolved);
1042 Error emit(const SymbolFlagsMap &Emitted);
1044 using FailedSymbolsWorklist =
1045 std::vector<std::pair<JITDylib *, SymbolStringPtr>>;
1046 static void notifyFailed(FailedSymbolsWorklist FailedSymbols);
1048 ExecutionSession &ES;
1049 std::string JITDylibName;
1050 SymbolTable Symbols;
1051 UnmaterializedInfosMap UnmaterializedInfos;
1052 MaterializingInfosMap MaterializingInfos;
1053 std::vector<std::unique_ptr<DefinitionGenerator>> DefGenerators;
1054 JITDylibSearchOrder SearchOrder;
1057 /// An ExecutionSession represents a running JIT program.
1058 class ExecutionSession {
1059 // FIXME: Remove this when we remove the old ORC layers.
1060 friend class JITDylib;
1063 /// For reporting errors.
1064 using ErrorReporter = std::function<void(Error)>;
1066 /// For dispatching MaterializationUnit::materialize calls.
1067 using DispatchMaterializationFunction = std::function<void(
1068 JITDylib &JD, std::unique_ptr<MaterializationUnit> MU)>;
1070 /// Construct an ExecutionSession.
1072 /// SymbolStringPools may be shared between ExecutionSessions.
1073 ExecutionSession(std::shared_ptr<SymbolStringPool> SSP = nullptr);
1075 /// Add a symbol name to the SymbolStringPool and return a pointer to it.
1076 SymbolStringPtr intern(StringRef SymName) { return SSP->intern(SymName); }
1078 /// Returns a shared_ptr to the SymbolStringPool for this ExecutionSession.
1079 std::shared_ptr<SymbolStringPool> getSymbolStringPool() const { return SSP; }
1081 /// Run the given lambda with the session mutex locked.
1082 template <typename Func> auto runSessionLocked(Func &&F) -> decltype(F()) {
1083 std::lock_guard<std::recursive_mutex> Lock(SessionMutex);
1087 /// Return a pointer to the "name" JITDylib.
1088 /// Ownership of JITDylib remains within Execution Session
1089 JITDylib *getJITDylibByName(StringRef Name);
1091 /// Add a new JITDylib to this ExecutionSession.
1093 /// The JITDylib Name is required to be unique. Clients should verify that
1094 /// names are not being re-used (e.g. by calling getJITDylibByName) if names
1095 /// are based on user input.
1096 JITDylib &createJITDylib(std::string Name);
1098 /// Allocate a module key for a new module to add to the JIT.
1099 VModuleKey allocateVModule() {
1100 return runSessionLocked([this]() { return ++LastKey; });
1103 /// Return a module key to the ExecutionSession so that it can be
1104 /// re-used. This should only be done once all resources associated
1105 /// with the original key have been released.
1106 void releaseVModule(VModuleKey Key) { /* FIXME: Recycle keys */
1109 /// Set the error reporter function.
1110 ExecutionSession &setErrorReporter(ErrorReporter ReportError) {
1111 this->ReportError = std::move(ReportError);
1115 /// Report a error for this execution session.
1117 /// Unhandled errors can be sent here to log them.
1118 void reportError(Error Err) { ReportError(std::move(Err)); }
1120 /// Set the materialization dispatch function.
1121 ExecutionSession &setDispatchMaterialization(
1122 DispatchMaterializationFunction DispatchMaterialization) {
1123 this->DispatchMaterialization = std::move(DispatchMaterialization);
1127 void legacyFailQuery(AsynchronousSymbolQuery &Q, Error Err);
1129 using LegacyAsyncLookupFunction = std::function<SymbolNameSet(
1130 std::shared_ptr<AsynchronousSymbolQuery> Q, SymbolNameSet Names)>;
1132 /// A legacy lookup function for JITSymbolResolverAdapter.
1133 /// Do not use -- this will be removed soon.
1135 legacyLookup(LegacyAsyncLookupFunction AsyncLookup, SymbolNameSet Names,
1136 SymbolState RequiredState,
1137 RegisterDependenciesFunction RegisterDependencies);
1139 /// Search the given JITDylib list for the given symbols.
1141 /// SearchOrder lists the JITDylibs to search. For each dylib, the associated
1142 /// boolean indicates whether the search should match against non-exported
1143 /// (hidden visibility) symbols in that dylib (true means match against
1144 /// non-exported symbols, false means do not match).
1146 /// The NotifyComplete callback will be called once all requested symbols
1147 /// reach the required state.
1149 /// If all symbols are found, the RegisterDependencies function will be called
1150 /// while the session lock is held. This gives clients a chance to register
1151 /// dependencies for on the queried symbols for any symbols they are
1152 /// materializing (if a MaterializationResponsibility instance is present,
1153 /// this can be implemented by calling
1154 /// MaterializationResponsibility::addDependencies). If there are no
1155 /// dependenant symbols for this query (e.g. it is being made by a top level
1156 /// client to get an address to call) then the value NoDependenciesToRegister
1158 void lookup(LookupKind K, const JITDylibSearchOrder &SearchOrder,
1159 SymbolLookupSet Symbols, SymbolState RequiredState,
1160 SymbolsResolvedCallback NotifyComplete,
1161 RegisterDependenciesFunction RegisterDependencies);
1163 /// Blocking version of lookup above. Returns the resolved symbol map.
1164 /// If WaitUntilReady is true (the default), will not return until all
1165 /// requested symbols are ready (or an error occurs). If WaitUntilReady is
1166 /// false, will return as soon as all requested symbols are resolved,
1167 /// or an error occurs. If WaitUntilReady is false and an error occurs
1168 /// after resolution, the function will return a success value, but the
1169 /// error will be reported via reportErrors.
1170 Expected<SymbolMap> lookup(const JITDylibSearchOrder &SearchOrder,
1171 const SymbolLookupSet &Symbols,
1172 LookupKind K = LookupKind::Static,
1173 SymbolState RequiredState = SymbolState::Ready,
1174 RegisterDependenciesFunction RegisterDependencies =
1175 NoDependenciesToRegister);
1177 /// Convenience version of blocking lookup.
1178 /// Searches each of the JITDylibs in the search order in turn for the given
1180 Expected<JITEvaluatedSymbol> lookup(const JITDylibSearchOrder &SearchOrder,
1181 SymbolStringPtr Symbol);
1183 /// Convenience version of blocking lookup.
1184 /// Searches each of the JITDylibs in the search order in turn for the given
1185 /// symbol. The search will not find non-exported symbols.
1186 Expected<JITEvaluatedSymbol> lookup(ArrayRef<JITDylib *> SearchOrder,
1187 SymbolStringPtr Symbol);
1189 /// Convenience version of blocking lookup.
1190 /// Searches each of the JITDylibs in the search order in turn for the given
1191 /// symbol. The search will not find non-exported symbols.
1192 Expected<JITEvaluatedSymbol> lookup(ArrayRef<JITDylib *> SearchOrder,
1195 /// Materialize the given unit.
1196 void dispatchMaterialization(JITDylib &JD,
1197 std::unique_ptr<MaterializationUnit> MU) {
1199 runSessionLocked([&]() {
1200 dbgs() << "Dispatching " << *MU << " for " << JD.getName() << "\n";
1203 DispatchMaterialization(JD, std::move(MU));
1206 /// Dump the state of all the JITDylibs in this session.
1207 void dump(raw_ostream &OS);
1210 static void logErrorsToStdErr(Error Err) {
1211 logAllUnhandledErrors(std::move(Err), errs(), "JIT session error: ");
1215 materializeOnCurrentThread(JITDylib &JD,
1216 std::unique_ptr<MaterializationUnit> MU) {
1217 MU->doMaterialize(JD);
1220 void runOutstandingMUs();
1222 mutable std::recursive_mutex SessionMutex;
1223 std::shared_ptr<SymbolStringPool> SSP;
1224 VModuleKey LastKey = 0;
1225 ErrorReporter ReportError = logErrorsToStdErr;
1226 DispatchMaterializationFunction DispatchMaterialization =
1227 materializeOnCurrentThread;
1229 std::vector<std::unique_ptr<JITDylib>> JDs;
1231 // FIXME: Remove this (and runOutstandingMUs) once the linking layer works
1232 // with callbacks from asynchronous queries.
1233 mutable std::recursive_mutex OutstandingMUsMutex;
1234 std::vector<std::pair<JITDylib *, std::unique_ptr<MaterializationUnit>>>
1238 template <typename GeneratorT>
1239 GeneratorT &JITDylib::addGenerator(std::unique_ptr<GeneratorT> DefGenerator) {
1240 auto &G = *DefGenerator;
1241 ES.runSessionLocked(
1242 [&]() { DefGenerators.push_back(std::move(DefGenerator)); });
1246 template <typename Func>
1247 auto JITDylib::withSearchOrderDo(Func &&F)
1248 -> decltype(F(std::declval<const JITDylibSearchOrder &>())) {
1249 return ES.runSessionLocked([&]() { return F(SearchOrder); });
1252 template <typename MaterializationUnitType>
1253 Error JITDylib::define(std::unique_ptr<MaterializationUnitType> &&MU) {
1254 assert(MU && "Can not define with a null MU");
1255 return ES.runSessionLocked([&, this]() -> Error {
1256 if (auto Err = defineImpl(*MU))
1259 /// defineImpl succeeded.
1260 auto UMI = std::make_shared<UnmaterializedInfo>(std::move(MU));
1261 for (auto &KV : UMI->MU->getSymbols())
1262 UnmaterializedInfos[KV.first] = UMI;
1264 return Error::success();
1268 template <typename MaterializationUnitType>
1269 Error JITDylib::define(std::unique_ptr<MaterializationUnitType> &MU) {
1270 assert(MU && "Can not define with a null MU");
1272 return ES.runSessionLocked([&, this]() -> Error {
1273 if (auto Err = defineImpl(*MU))
1276 /// defineImpl succeeded.
1277 auto UMI = std::make_shared<UnmaterializedInfo>(std::move(MU));
1278 for (auto &KV : UMI->MU->getSymbols())
1279 UnmaterializedInfos[KV.first] = UMI;
1281 return Error::success();
1285 /// ReexportsGenerator can be used with JITDylib::addGenerator to automatically
1286 /// re-export a subset of the source JITDylib's symbols in the target.
1287 class ReexportsGenerator : public JITDylib::DefinitionGenerator {
1289 using SymbolPredicate = std::function<bool(SymbolStringPtr)>;
1291 /// Create a reexports generator. If an Allow predicate is passed, only
1292 /// symbols for which the predicate returns true will be reexported. If no
1293 /// Allow predicate is passed, all symbols will be exported.
1294 ReexportsGenerator(JITDylib &SourceJD,
1295 JITDylibLookupFlags SourceJDLookupFlags,
1296 SymbolPredicate Allow = SymbolPredicate());
1298 Error tryToGenerate(LookupKind K, JITDylib &JD,
1299 JITDylibLookupFlags JDLookupFlags,
1300 const SymbolLookupSet &LookupSet) override;
1304 JITDylibLookupFlags SourceJDLookupFlags;
1305 SymbolPredicate Allow;
1308 /// Mangles symbol names then uniques them in the context of an
1309 /// ExecutionSession.
1310 class MangleAndInterner {
1312 MangleAndInterner(ExecutionSession &ES, const DataLayout &DL);
1313 SymbolStringPtr operator()(StringRef Name);
1316 ExecutionSession &ES;
1317 const DataLayout &DL;
1320 } // End namespace orc
1321 } // End namespace llvm
1323 #undef DEBUG_TYPE // "orc"
1325 #endif // LLVM_EXECUTIONENGINE_ORC_CORE_H