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 map from symbol names (as SymbolStringPtrs) to JITSymbols
49 /// (address/flags pairs).
50 using SymbolMap
= DenseMap
<SymbolStringPtr
, JITEvaluatedSymbol
>;
52 /// A map from symbol names (as SymbolStringPtrs) to JITSymbolFlags.
53 using SymbolFlagsMap
= DenseMap
<SymbolStringPtr
, JITSymbolFlags
>;
55 /// A map from JITDylibs to sets of symbols.
56 using SymbolDependenceMap
= DenseMap
<JITDylib
*, SymbolNameSet
>;
58 /// A list of (JITDylib*, bool) pairs.
59 using JITDylibSearchList
= std::vector
<std::pair
<JITDylib
*, bool>>;
61 struct SymbolAliasMapEntry
{
62 SymbolAliasMapEntry() = default;
63 SymbolAliasMapEntry(SymbolStringPtr Aliasee
, JITSymbolFlags AliasFlags
)
64 : Aliasee(std::move(Aliasee
)), AliasFlags(AliasFlags
) {}
66 SymbolStringPtr Aliasee
;
67 JITSymbolFlags AliasFlags
;
70 /// A map of Symbols to (Symbol, Flags) pairs.
71 using SymbolAliasMap
= DenseMap
<SymbolStringPtr
, SymbolAliasMapEntry
>;
73 /// Render a SymbolStringPtr.
74 raw_ostream
&operator<<(raw_ostream
&OS
, const SymbolStringPtr
&Sym
);
76 /// Render a SymbolNameSet.
77 raw_ostream
&operator<<(raw_ostream
&OS
, const SymbolNameSet
&Symbols
);
79 /// Render a SymbolFlagsMap entry.
80 raw_ostream
&operator<<(raw_ostream
&OS
, const SymbolFlagsMap::value_type
&KV
);
82 /// Render a SymbolMap entry.
83 raw_ostream
&operator<<(raw_ostream
&OS
, const SymbolMap::value_type
&KV
);
85 /// Render a SymbolFlagsMap.
86 raw_ostream
&operator<<(raw_ostream
&OS
, const SymbolFlagsMap
&SymbolFlags
);
88 /// Render a SymbolMap.
89 raw_ostream
&operator<<(raw_ostream
&OS
, const SymbolMap
&Symbols
);
91 /// Render a SymbolDependenceMap entry.
92 raw_ostream
&operator<<(raw_ostream
&OS
,
93 const SymbolDependenceMap::value_type
&KV
);
95 /// Render a SymbolDependendeMap.
96 raw_ostream
&operator<<(raw_ostream
&OS
, const SymbolDependenceMap
&Deps
);
98 /// Render a MaterializationUnit.
99 raw_ostream
&operator<<(raw_ostream
&OS
, const MaterializationUnit
&MU
);
101 /// Render a JITDylibSearchList.
102 raw_ostream
&operator<<(raw_ostream
&OS
, const JITDylibSearchList
&JDs
);
104 /// Render a SymbolAliasMap.
105 raw_ostream
&operator<<(raw_ostream
&OS
, const SymbolAliasMap
&Aliases
);
107 /// Render a SymbolState.
108 raw_ostream
&operator<<(raw_ostream
&OS
, const SymbolState
&S
);
110 /// Callback to notify client that symbols have been resolved.
111 using SymbolsResolvedCallback
= unique_function
<void(Expected
<SymbolMap
>)>;
113 /// Callback to register the dependencies for a given query.
114 using RegisterDependenciesFunction
=
115 std::function
<void(const SymbolDependenceMap
&)>;
117 /// This can be used as the value for a RegisterDependenciesFunction if there
118 /// are no dependants to register with.
119 extern RegisterDependenciesFunction NoDependenciesToRegister
;
121 /// Used to notify a JITDylib that the given set of symbols failed to
123 class FailedToMaterialize
: public ErrorInfo
<FailedToMaterialize
> {
127 FailedToMaterialize(std::shared_ptr
<SymbolDependenceMap
> Symbols
);
128 std::error_code
convertToErrorCode() const override
;
129 void log(raw_ostream
&OS
) const override
;
130 const SymbolDependenceMap
&getSymbols() const { return *Symbols
; }
133 std::shared_ptr
<SymbolDependenceMap
> Symbols
;
136 /// Used to notify clients when symbols can not be found during a lookup.
137 class SymbolsNotFound
: public ErrorInfo
<SymbolsNotFound
> {
141 SymbolsNotFound(SymbolNameSet Symbols
);
142 std::error_code
convertToErrorCode() const override
;
143 void log(raw_ostream
&OS
) const override
;
144 const SymbolNameSet
&getSymbols() const { return Symbols
; }
147 SymbolNameSet Symbols
;
150 /// Used to notify clients that a set of symbols could not be removed.
151 class SymbolsCouldNotBeRemoved
: public ErrorInfo
<SymbolsCouldNotBeRemoved
> {
155 SymbolsCouldNotBeRemoved(SymbolNameSet Symbols
);
156 std::error_code
convertToErrorCode() const override
;
157 void log(raw_ostream
&OS
) const override
;
158 const SymbolNameSet
&getSymbols() const { return Symbols
; }
161 SymbolNameSet Symbols
;
164 /// Tracks responsibility for materialization, and mediates interactions between
165 /// MaterializationUnits and JDs.
167 /// An instance of this class is passed to MaterializationUnits when their
168 /// materialize method is called. It allows MaterializationUnits to resolve and
169 /// emit symbols, or abandon materialization by notifying any unmaterialized
170 /// symbols of an error.
171 class MaterializationResponsibility
{
172 friend class MaterializationUnit
;
174 MaterializationResponsibility(MaterializationResponsibility
&&) = default;
175 MaterializationResponsibility
&
176 operator=(MaterializationResponsibility
&&) = delete;
178 /// Destruct a MaterializationResponsibility instance. In debug mode
179 /// this asserts that all symbols being tracked have been either
180 /// emitted or notified of an error.
181 ~MaterializationResponsibility();
183 /// Returns the target JITDylib that these symbols are being materialized
185 JITDylib
&getTargetJITDylib() const { return JD
; }
187 /// Returns the VModuleKey for this instance.
188 VModuleKey
getVModuleKey() const { return K
; }
190 /// Returns the symbol flags map for this responsibility instance.
191 /// Note: The returned flags may have transient flags (Lazy, Materializing)
192 /// set. These should be stripped with JITSymbolFlags::stripTransientFlags
194 const SymbolFlagsMap
&getSymbols() const { return SymbolFlags
; }
196 /// Returns the names of any symbols covered by this
197 /// MaterializationResponsibility object that have queries pending. This
198 /// information can be used to return responsibility for unrequested symbols
199 /// back to the JITDylib via the delegate method.
200 SymbolNameSet
getRequestedSymbols() const;
202 /// Notifies the target JITDylib that the given symbols have been resolved.
203 /// This will update the given symbols' addresses in the JITDylib, and notify
204 /// any pending queries on the given symbols of their resolution. The given
205 /// symbols must be ones covered by this MaterializationResponsibility
206 /// instance. Individual calls to this method may resolve a subset of the
207 /// symbols, but all symbols must have been resolved prior to calling emit.
209 /// This method will return an error if any symbols being resolved have been
210 /// moved to the error state due to the failure of a dependency. If this
211 /// method returns an error then clients should log it and call
212 /// failMaterialize. If no dependencies have been registered for the
213 /// symbols covered by this MaterializationResponsibiility then this method
214 /// is guaranteed to return Error::success() and can be wrapped with cantFail.
215 Error
notifyResolved(const SymbolMap
&Symbols
);
217 /// Notifies the target JITDylib (and any pending queries on that JITDylib)
218 /// that all symbols covered by this MaterializationResponsibility instance
219 /// have been emitted.
221 /// This method will return an error if any symbols being resolved have been
222 /// moved to the error state due to the failure of a dependency. If this
223 /// method returns an error then clients should log it and call
224 /// failMaterialize. If no dependencies have been registered for the
225 /// symbols covered by this MaterializationResponsibiility then this method
226 /// is guaranteed to return Error::success() and can be wrapped with cantFail.
227 Error
notifyEmitted();
229 /// Adds new symbols to the JITDylib and this responsibility instance.
230 /// JITDylib entries start out in the materializing state.
232 /// This method can be used by materialization units that want to add
233 /// additional symbols at materialization time (e.g. stubs, compile
234 /// callbacks, metadata).
235 Error
defineMaterializing(const SymbolFlagsMap
&SymbolFlags
);
237 /// Notify all not-yet-emitted covered by this MaterializationResponsibility
238 /// instance that an error has occurred.
239 /// This will remove all symbols covered by this MaterializationResponsibilty
240 /// from the target JITDylib, and send an error to any queries waiting on
242 void failMaterialization();
244 /// Transfers responsibility to the given MaterializationUnit for all
245 /// symbols defined by that MaterializationUnit. This allows
246 /// materializers to break up work based on run-time information (e.g.
247 /// by introspecting which symbols have actually been looked up and
248 /// materializing only those).
249 void replace(std::unique_ptr
<MaterializationUnit
> MU
);
251 /// Delegates responsibility for the given symbols to the returned
252 /// materialization responsibility. Useful for breaking up work between
253 /// threads, or different kinds of materialization processes.
254 MaterializationResponsibility
delegate(const SymbolNameSet
&Symbols
,
255 VModuleKey NewKey
= VModuleKey());
257 void addDependencies(const SymbolStringPtr
&Name
,
258 const SymbolDependenceMap
&Dependencies
);
260 /// Add dependencies that apply to all symbols covered by this instance.
261 void addDependenciesForAll(const SymbolDependenceMap
&Dependencies
);
264 /// Create a MaterializationResponsibility for the given JITDylib and
266 MaterializationResponsibility(JITDylib
&JD
, SymbolFlagsMap SymbolFlags
,
270 SymbolFlagsMap SymbolFlags
;
274 /// A MaterializationUnit represents a set of symbol definitions that can
275 /// be materialized as a group, or individually discarded (when
276 /// overriding definitions are encountered).
278 /// MaterializationUnits are used when providing lazy definitions of symbols to
279 /// JITDylibs. The JITDylib will call materialize when the address of a symbol
280 /// is requested via the lookup method. The JITDylib will call discard if a
281 /// stronger definition is added or already present.
282 class MaterializationUnit
{
284 MaterializationUnit(SymbolFlagsMap InitalSymbolFlags
, VModuleKey K
)
285 : SymbolFlags(std::move(InitalSymbolFlags
)), K(std::move(K
)) {}
287 virtual ~MaterializationUnit() {}
289 /// Return the name of this materialization unit. Useful for debugging
291 virtual StringRef
getName() const = 0;
293 /// Return the set of symbols that this source provides.
294 const SymbolFlagsMap
&getSymbols() const { return SymbolFlags
; }
296 /// Called by materialization dispatchers (see
297 /// ExecutionSession::DispatchMaterializationFunction) to trigger
298 /// materialization of this MaterializationUnit.
299 void doMaterialize(JITDylib
&JD
) {
300 materialize(MaterializationResponsibility(JD
, std::move(SymbolFlags
),
304 /// Called by JITDylibs to notify MaterializationUnits that the given symbol
305 /// has been overridden.
306 void doDiscard(const JITDylib
&JD
, const SymbolStringPtr
&Name
) {
307 SymbolFlags
.erase(Name
);
308 discard(JD
, std::move(Name
));
312 SymbolFlagsMap SymbolFlags
;
316 virtual void anchor();
318 /// Implementations of this method should materialize all symbols
319 /// in the materialzation unit, except for those that have been
320 /// previously discarded.
321 virtual void materialize(MaterializationResponsibility R
) = 0;
323 /// Implementations of this method should discard the given symbol
324 /// from the source (e.g. if the source is an LLVM IR Module and the
325 /// symbol is a function, delete the function body or mark it available
327 virtual void discard(const JITDylib
&JD
, const SymbolStringPtr
&Name
) = 0;
330 using MaterializationUnitList
=
331 std::vector
<std::unique_ptr
<MaterializationUnit
>>;
333 /// A MaterializationUnit implementation for pre-existing absolute symbols.
335 /// All symbols will be resolved and marked ready as soon as the unit is
337 class AbsoluteSymbolsMaterializationUnit
: public MaterializationUnit
{
339 AbsoluteSymbolsMaterializationUnit(SymbolMap Symbols
, VModuleKey K
);
341 StringRef
getName() const override
;
344 void materialize(MaterializationResponsibility R
) override
;
345 void discard(const JITDylib
&JD
, const SymbolStringPtr
&Name
) override
;
346 static SymbolFlagsMap
extractFlags(const SymbolMap
&Symbols
);
351 /// Create an AbsoluteSymbolsMaterializationUnit with the given symbols.
352 /// Useful for inserting absolute symbols into a JITDylib. E.g.:
354 /// JITDylib &JD = ...;
355 /// SymbolStringPtr Foo = ...;
356 /// JITEvaluatedSymbol FooSym = ...;
357 /// if (auto Err = JD.define(absoluteSymbols({{Foo, FooSym}})))
361 inline std::unique_ptr
<AbsoluteSymbolsMaterializationUnit
>
362 absoluteSymbols(SymbolMap Symbols
, VModuleKey K
= VModuleKey()) {
363 return std::make_unique
<AbsoluteSymbolsMaterializationUnit
>(
364 std::move(Symbols
), std::move(K
));
367 /// A materialization unit for symbol aliases. Allows existing symbols to be
368 /// aliased with alternate flags.
369 class ReExportsMaterializationUnit
: public MaterializationUnit
{
371 /// SourceJD is allowed to be nullptr, in which case the source JITDylib is
372 /// taken to be whatever JITDylib these definitions are materialized in (and
373 /// MatchNonExported has no effect). This is useful for defining aliases
374 /// within a JITDylib.
376 /// Note: Care must be taken that no sets of aliases form a cycle, as such
377 /// a cycle will result in a deadlock when any symbol in the cycle is
379 ReExportsMaterializationUnit(JITDylib
*SourceJD
, bool MatchNonExported
,
380 SymbolAliasMap Aliases
, VModuleKey K
);
382 StringRef
getName() const override
;
385 void materialize(MaterializationResponsibility R
) override
;
386 void discard(const JITDylib
&JD
, const SymbolStringPtr
&Name
) override
;
387 static SymbolFlagsMap
extractFlags(const SymbolAliasMap
&Aliases
);
389 JITDylib
*SourceJD
= nullptr;
390 bool MatchNonExported
= false;
391 SymbolAliasMap Aliases
;
394 /// Create a ReExportsMaterializationUnit with the given aliases.
395 /// Useful for defining symbol aliases.: E.g., given a JITDylib JD containing
396 /// symbols "foo" and "bar", we can define aliases "baz" (for "foo") and "qux"
397 /// (for "bar") with: \code{.cpp}
398 /// SymbolStringPtr Baz = ...;
399 /// SymbolStringPtr Qux = ...;
400 /// if (auto Err = JD.define(symbolAliases({
401 /// {Baz, { Foo, JITSymbolFlags::Exported }},
402 /// {Qux, { Bar, JITSymbolFlags::Weak }}}))
405 inline std::unique_ptr
<ReExportsMaterializationUnit
>
406 symbolAliases(SymbolAliasMap Aliases
, VModuleKey K
= VModuleKey()) {
407 return std::make_unique
<ReExportsMaterializationUnit
>(
408 nullptr, true, std::move(Aliases
), std::move(K
));
411 /// Create a materialization unit for re-exporting symbols from another JITDylib
412 /// with alternative names/flags.
413 /// If MatchNonExported is true then non-exported symbols from SourceJD can be
414 /// re-exported. If it is false, attempts to re-export a non-exported symbol
415 /// will result in a "symbol not found" error.
416 inline std::unique_ptr
<ReExportsMaterializationUnit
>
417 reexports(JITDylib
&SourceJD
, SymbolAliasMap Aliases
,
418 bool MatchNonExported
= false, VModuleKey K
= VModuleKey()) {
419 return std::make_unique
<ReExportsMaterializationUnit
>(
420 &SourceJD
, MatchNonExported
, std::move(Aliases
), std::move(K
));
423 /// Build a SymbolAliasMap for the common case where you want to re-export
424 /// symbols from another JITDylib with the same linkage/flags.
425 Expected
<SymbolAliasMap
>
426 buildSimpleReexportsAliasMap(JITDylib
&SourceJD
, const SymbolNameSet
&Symbols
);
428 /// Represents the state that a symbol has reached during materialization.
429 enum class SymbolState
: uint8_t {
430 Invalid
, /// No symbol should be in this state.
431 NeverSearched
, /// Added to the symbol table, never queried.
432 Materializing
, /// Queried, materialization begun.
433 Resolved
, /// Assigned address, still materializing.
434 Emitted
, /// Emitted to memory, but waiting on transitive dependencies.
435 Ready
= 0x3f /// Ready and safe for clients to access.
438 /// A symbol query that returns results via a callback when results are
441 /// makes a callback when all symbols are available.
442 class AsynchronousSymbolQuery
{
443 friend class ExecutionSession
;
444 friend class JITDylib
;
445 friend class JITSymbolResolverAdapter
;
448 /// Create a query for the given symbols. The NotifyComplete
449 /// callback will be called once all queried symbols reach the given
451 AsynchronousSymbolQuery(const SymbolNameSet
&Symbols
,
452 SymbolState RequiredState
,
453 SymbolsResolvedCallback NotifyComplete
);
455 /// Notify the query that a requested symbol has reached the required state.
456 void notifySymbolMetRequiredState(const SymbolStringPtr
&Name
,
457 JITEvaluatedSymbol Sym
);
459 /// Returns true if all symbols covered by this query have been
461 bool isComplete() const { return OutstandingSymbolsCount
== 0; }
463 /// Call the NotifyComplete callback.
465 /// This should only be called if all symbols covered by the query have
466 /// reached the specified state.
467 void handleComplete();
470 SymbolState
getRequiredState() { return RequiredState
; }
472 void addQueryDependence(JITDylib
&JD
, SymbolStringPtr Name
);
474 void removeQueryDependence(JITDylib
&JD
, const SymbolStringPtr
&Name
);
478 void handleFailed(Error Err
);
482 SymbolsResolvedCallback NotifyComplete
;
483 SymbolDependenceMap QueryRegistrations
;
484 SymbolMap ResolvedSymbols
;
485 size_t OutstandingSymbolsCount
;
486 SymbolState RequiredState
;
489 /// A symbol table that supports asynchoronous symbol queries.
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.
496 friend class AsynchronousSymbolQuery
;
497 friend class ExecutionSession
;
498 friend class MaterializationResponsibility
;
500 class DefinitionGenerator
{
502 virtual ~DefinitionGenerator();
503 virtual Expected
<SymbolNameSet
>
504 tryToGenerate(JITDylib
&Parent
, const SymbolNameSet
&Names
) = 0;
507 using AsynchronousSymbolQuerySet
=
508 std::set
<std::shared_ptr
<AsynchronousSymbolQuery
>>;
510 JITDylib(const JITDylib
&) = delete;
511 JITDylib
&operator=(const JITDylib
&) = delete;
512 JITDylib(JITDylib
&&) = delete;
513 JITDylib
&operator=(JITDylib
&&) = delete;
515 /// Get the name for this JITDylib.
516 const std::string
&getName() const { return JITDylibName
; }
518 /// Get a reference to the ExecutionSession for this JITDylib.
519 ExecutionSession
&getExecutionSession() const { return ES
; }
521 /// Adds a definition generator to this JITDylib and returns a referenece to
524 /// When JITDylibs are searched during lookup, if no existing definition of
525 /// a symbol is found, then any generators that have been added are run (in
526 /// the order that they were added) to potentially generate a definition.
527 template <typename GeneratorT
>
528 GeneratorT
&addGenerator(std::unique_ptr
<GeneratorT
> DefGenerator
);
530 /// Remove a definition generator from this JITDylib.
532 /// The given generator must exist in this JITDylib's generators list (i.e.
533 /// have been added and not yet removed).
534 void removeGenerator(DefinitionGenerator
&G
);
536 /// Set the search order to be used when fixing up definitions in JITDylib.
537 /// This will replace the previous search order, and apply to any symbol
538 /// resolutions made for definitions in this JITDylib after the call to
539 /// setSearchOrder (even if the definition itself was added before the
542 /// If SearchThisJITDylibFirst is set, which by default it is, then this
543 /// JITDylib will add itself to the beginning of the SearchOrder (Clients
544 /// should *not* put this JITDylib in the list in this case, to avoid
545 /// redundant lookups).
547 /// If SearchThisJITDylibFirst is false then the search order will be used as
548 /// given. The main motivation for this feature is to support deliberate
549 /// shadowing of symbols in this JITDylib by a facade JITDylib. For example,
550 /// the facade may resolve function names to stubs, and the stubs may compile
551 /// lazily by looking up symbols in this dylib. Adding the facade dylib
552 /// as the first in the search order (instead of this dylib) ensures that
553 /// definitions within this dylib resolve to the lazy-compiling stubs,
554 /// rather than immediately materializing the definitions in this dylib.
555 void setSearchOrder(JITDylibSearchList NewSearchOrder
,
556 bool SearchThisJITDylibFirst
= true,
557 bool MatchNonExportedInThisDylib
= true);
559 /// Add the given JITDylib to the search order for definitions in this
561 void addToSearchOrder(JITDylib
&JD
, bool MatcNonExported
= false);
563 /// Replace OldJD with NewJD in the search order if OldJD is present.
564 /// Otherwise this operation is a no-op.
565 void replaceInSearchOrder(JITDylib
&OldJD
, JITDylib
&NewJD
,
566 bool MatchNonExported
= false);
568 /// Remove the given JITDylib from the search order for this JITDylib if it is
569 /// present. Otherwise this operation is a no-op.
570 void removeFromSearchOrder(JITDylib
&JD
);
572 /// Do something with the search order (run under the session lock).
573 template <typename Func
>
574 auto withSearchOrderDo(Func
&&F
)
575 -> decltype(F(std::declval
<const JITDylibSearchList
&>()));
577 /// Define all symbols provided by the materialization unit to be part of this
580 /// This overload always takes ownership of the MaterializationUnit. If any
581 /// errors occur, the MaterializationUnit consumed.
582 template <typename MaterializationUnitType
>
583 Error
define(std::unique_ptr
<MaterializationUnitType
> &&MU
);
585 /// Define all symbols provided by the materialization unit to be part of this
588 /// This overload only takes ownership of the MaterializationUnit no error is
589 /// generated. If an error occurs, ownership remains with the caller. This
590 /// may allow the caller to modify the MaterializationUnit to correct the
591 /// issue, then re-call define.
592 template <typename MaterializationUnitType
>
593 Error
define(std::unique_ptr
<MaterializationUnitType
> &MU
);
595 /// Tries to remove the given symbols.
597 /// If any symbols are not defined in this JITDylib this method will return
598 /// a SymbolsNotFound error covering the missing symbols.
600 /// If all symbols are found but some symbols are in the process of being
601 /// materialized this method will return a SymbolsCouldNotBeRemoved error.
603 /// On success, all symbols are removed. On failure, the JITDylib state is
604 /// left unmodified (no symbols are removed).
605 Error
remove(const SymbolNameSet
&Names
);
607 /// Search the given JITDylib for the symbols in Symbols. If found, store
608 /// the flags for each symbol in Flags. Returns any unresolved symbols.
609 Expected
<SymbolFlagsMap
> lookupFlags(const SymbolNameSet
&Names
);
611 /// Dump current JITDylib state to OS.
612 void dump(raw_ostream
&OS
);
614 /// FIXME: Remove this when we remove the old ORC layers.
615 /// Search the given JITDylibs in order for the symbols in Symbols. Results
616 /// (once they become available) will be returned via the given Query.
618 /// If any symbol is not found then the unresolved symbols will be returned,
619 /// and the query will not be applied. The Query is not failed and can be
620 /// re-used in a subsequent lookup once the symbols have been added, or
622 Expected
<SymbolNameSet
>
623 legacyLookup(std::shared_ptr
<AsynchronousSymbolQuery
> Q
, SymbolNameSet Names
);
626 using AsynchronousSymbolQueryList
=
627 std::vector
<std::shared_ptr
<AsynchronousSymbolQuery
>>;
629 struct UnmaterializedInfo
{
630 UnmaterializedInfo(std::unique_ptr
<MaterializationUnit
> MU
)
631 : MU(std::move(MU
)) {}
633 std::unique_ptr
<MaterializationUnit
> MU
;
636 using UnmaterializedInfosMap
=
637 DenseMap
<SymbolStringPtr
, std::shared_ptr
<UnmaterializedInfo
>>;
639 struct MaterializingInfo
{
640 SymbolDependenceMap Dependants
;
641 SymbolDependenceMap UnemittedDependencies
;
643 void addQuery(std::shared_ptr
<AsynchronousSymbolQuery
> Q
);
644 void removeQuery(const AsynchronousSymbolQuery
&Q
);
645 AsynchronousSymbolQueryList
takeQueriesMeeting(SymbolState RequiredState
);
646 AsynchronousSymbolQueryList
takeAllPendingQueries() {
647 return std::move(PendingQueries
);
649 bool hasQueriesPending() const { return !PendingQueries
.empty(); }
650 const AsynchronousSymbolQueryList
&pendingQueries() const {
651 return PendingQueries
;
654 AsynchronousSymbolQueryList PendingQueries
;
657 using MaterializingInfosMap
= DenseMap
<SymbolStringPtr
, MaterializingInfo
>;
659 class SymbolTableEntry
{
661 SymbolTableEntry() = default;
662 SymbolTableEntry(JITSymbolFlags Flags
)
663 : Flags(Flags
), State(static_cast<uint8_t>(SymbolState::NeverSearched
)),
664 MaterializerAttached(false), PendingRemoval(false) {}
666 JITTargetAddress
getAddress() const { return Addr
; }
667 JITSymbolFlags
getFlags() const { return Flags
; }
668 SymbolState
getState() const { return static_cast<SymbolState
>(State
); }
670 bool isInMaterializationPhase() const {
671 return getState() == SymbolState::Materializing
||
672 getState() == SymbolState::Resolved
;
675 bool hasMaterializerAttached() const { return MaterializerAttached
; }
676 bool isPendingRemoval() const { return PendingRemoval
; }
678 void setAddress(JITTargetAddress Addr
) { this->Addr
= Addr
; }
679 void setFlags(JITSymbolFlags Flags
) { this->Flags
= Flags
; }
680 void setState(SymbolState State
) {
681 assert(static_cast<uint8_t>(State
) < (1 << 6) &&
682 "State does not fit in bitfield");
683 this->State
= static_cast<uint8_t>(State
);
686 void setMaterializerAttached(bool MaterializerAttached
) {
687 this->MaterializerAttached
= MaterializerAttached
;
690 void setPendingRemoval(bool PendingRemoval
) {
691 this->PendingRemoval
= PendingRemoval
;
694 JITEvaluatedSymbol
getSymbol() const {
695 return JITEvaluatedSymbol(Addr
, Flags
);
699 JITTargetAddress Addr
= 0;
700 JITSymbolFlags Flags
;
702 uint8_t MaterializerAttached
: 1;
703 uint8_t PendingRemoval
: 1;
706 using SymbolTable
= DenseMap
<SymbolStringPtr
, SymbolTableEntry
>;
708 JITDylib(ExecutionSession
&ES
, std::string Name
);
710 Error
defineImpl(MaterializationUnit
&MU
);
712 Expected
<SymbolNameSet
> lookupFlagsImpl(SymbolFlagsMap
&Flags
,
713 const SymbolNameSet
&Names
);
715 Error
lodgeQuery(std::shared_ptr
<AsynchronousSymbolQuery
> &Q
,
716 SymbolNameSet
&Unresolved
, bool MatchNonExported
,
717 MaterializationUnitList
&MUs
);
719 Error
lodgeQueryImpl(std::shared_ptr
<AsynchronousSymbolQuery
> &Q
,
720 SymbolNameSet
&Unresolved
, bool MatchNonExported
,
721 MaterializationUnitList
&MUs
);
723 bool lookupImpl(std::shared_ptr
<AsynchronousSymbolQuery
> &Q
,
724 std::vector
<std::unique_ptr
<MaterializationUnit
>> &MUs
,
725 SymbolNameSet
&Unresolved
);
727 void detachQueryHelper(AsynchronousSymbolQuery
&Q
,
728 const SymbolNameSet
&QuerySymbols
);
730 void transferEmittedNodeDependencies(MaterializingInfo
&DependantMI
,
731 const SymbolStringPtr
&DependantName
,
732 MaterializingInfo
&EmittedMI
);
734 Error
defineMaterializing(const SymbolFlagsMap
&SymbolFlags
);
736 void replace(std::unique_ptr
<MaterializationUnit
> MU
);
738 SymbolNameSet
getRequestedSymbols(const SymbolFlagsMap
&SymbolFlags
) const;
740 void addDependencies(const SymbolStringPtr
&Name
,
741 const SymbolDependenceMap
&Dependants
);
743 Error
resolve(const SymbolMap
&Resolved
);
745 Error
emit(const SymbolFlagsMap
&Emitted
);
747 using FailedSymbolsWorklist
=
748 std::vector
<std::pair
<JITDylib
*, SymbolStringPtr
>>;
749 static void notifyFailed(FailedSymbolsWorklist FailedSymbols
);
751 ExecutionSession
&ES
;
752 std::string JITDylibName
;
754 UnmaterializedInfosMap UnmaterializedInfos
;
755 MaterializingInfosMap MaterializingInfos
;
756 std::vector
<std::unique_ptr
<DefinitionGenerator
>> DefGenerators
;
757 JITDylibSearchList SearchOrder
;
760 /// An ExecutionSession represents a running JIT program.
761 class ExecutionSession
{
762 // FIXME: Remove this when we remove the old ORC layers.
763 friend class JITDylib
;
766 /// For reporting errors.
767 using ErrorReporter
= std::function
<void(Error
)>;
769 /// For dispatching MaterializationUnit::materialize calls.
770 using DispatchMaterializationFunction
= std::function
<void(
771 JITDylib
&JD
, std::unique_ptr
<MaterializationUnit
> MU
)>;
773 /// Construct an ExecutionSession.
775 /// SymbolStringPools may be shared between ExecutionSessions.
776 ExecutionSession(std::shared_ptr
<SymbolStringPool
> SSP
= nullptr);
778 /// Add a symbol name to the SymbolStringPool and return a pointer to it.
779 SymbolStringPtr
intern(StringRef SymName
) { return SSP
->intern(SymName
); }
781 /// Returns a shared_ptr to the SymbolStringPool for this ExecutionSession.
782 std::shared_ptr
<SymbolStringPool
> getSymbolStringPool() const { return SSP
; }
784 /// Run the given lambda with the session mutex locked.
785 template <typename Func
> auto runSessionLocked(Func
&&F
) -> decltype(F()) {
786 std::lock_guard
<std::recursive_mutex
> Lock(SessionMutex
);
790 /// Get the "main" JITDylib, which is created automatically on construction of
791 /// the ExecutionSession.
792 JITDylib
&getMainJITDylib();
794 /// Return a pointer to the "name" JITDylib.
795 /// Ownership of JITDylib remains within Execution Session
796 JITDylib
*getJITDylibByName(StringRef Name
);
798 /// Add a new JITDylib to this ExecutionSession.
800 /// The JITDylib Name is required to be unique. Clients should verify that
801 /// names are not being re-used (e.g. by calling getJITDylibByName) if names
802 /// are based on user input.
803 JITDylib
&createJITDylib(std::string Name
,
804 bool AddToMainDylibSearchOrder
= true);
806 /// Allocate a module key for a new module to add to the JIT.
807 VModuleKey
allocateVModule() {
808 return runSessionLocked([this]() { return ++LastKey
; });
811 /// Return a module key to the ExecutionSession so that it can be
812 /// re-used. This should only be done once all resources associated
813 /// with the original key have been released.
814 void releaseVModule(VModuleKey Key
) { /* FIXME: Recycle keys */
817 /// Set the error reporter function.
818 ExecutionSession
&setErrorReporter(ErrorReporter ReportError
) {
819 this->ReportError
= std::move(ReportError
);
823 /// Report a error for this execution session.
825 /// Unhandled errors can be sent here to log them.
826 void reportError(Error Err
) { ReportError(std::move(Err
)); }
828 /// Set the materialization dispatch function.
829 ExecutionSession
&setDispatchMaterialization(
830 DispatchMaterializationFunction DispatchMaterialization
) {
831 this->DispatchMaterialization
= std::move(DispatchMaterialization
);
835 void legacyFailQuery(AsynchronousSymbolQuery
&Q
, Error Err
);
837 using LegacyAsyncLookupFunction
= std::function
<SymbolNameSet(
838 std::shared_ptr
<AsynchronousSymbolQuery
> Q
, SymbolNameSet Names
)>;
840 /// A legacy lookup function for JITSymbolResolverAdapter.
841 /// Do not use -- this will be removed soon.
843 legacyLookup(LegacyAsyncLookupFunction AsyncLookup
, SymbolNameSet Names
,
844 SymbolState RequiredState
,
845 RegisterDependenciesFunction RegisterDependencies
);
847 /// Search the given JITDylib list for the given symbols.
849 /// SearchOrder lists the JITDylibs to search. For each dylib, the associated
850 /// boolean indicates whether the search should match against non-exported
851 /// (hidden visibility) symbols in that dylib (true means match against
852 /// non-exported symbols, false means do not match).
854 /// The NotifyComplete callback will be called once all requested symbols
855 /// reach the required state.
857 /// If all symbols are found, the RegisterDependencies function will be called
858 /// while the session lock is held. This gives clients a chance to register
859 /// dependencies for on the queried symbols for any symbols they are
860 /// materializing (if a MaterializationResponsibility instance is present,
861 /// this can be implemented by calling
862 /// MaterializationResponsibility::addDependencies). If there are no
863 /// dependenant symbols for this query (e.g. it is being made by a top level
864 /// client to get an address to call) then the value NoDependenciesToRegister
866 void lookup(const JITDylibSearchList
&SearchOrder
, SymbolNameSet Symbols
,
867 SymbolState RequiredState
, SymbolsResolvedCallback NotifyComplete
,
868 RegisterDependenciesFunction RegisterDependencies
);
870 /// Blocking version of lookup above. Returns the resolved symbol map.
871 /// If WaitUntilReady is true (the default), will not return until all
872 /// requested symbols are ready (or an error occurs). If WaitUntilReady is
873 /// false, will return as soon as all requested symbols are resolved,
874 /// or an error occurs. If WaitUntilReady is false and an error occurs
875 /// after resolution, the function will return a success value, but the
876 /// error will be reported via reportErrors.
877 Expected
<SymbolMap
> lookup(const JITDylibSearchList
&SearchOrder
,
878 const SymbolNameSet
&Symbols
,
879 SymbolState RequiredState
= SymbolState::Ready
,
880 RegisterDependenciesFunction RegisterDependencies
=
881 NoDependenciesToRegister
);
883 /// Convenience version of blocking lookup.
884 /// Searches each of the JITDylibs in the search order in turn for the given
886 Expected
<JITEvaluatedSymbol
> lookup(const JITDylibSearchList
&SearchOrder
,
887 SymbolStringPtr Symbol
);
889 /// Convenience version of blocking lookup.
890 /// Searches each of the JITDylibs in the search order in turn for the given
891 /// symbol. The search will not find non-exported symbols.
892 Expected
<JITEvaluatedSymbol
> lookup(ArrayRef
<JITDylib
*> SearchOrder
,
893 SymbolStringPtr Symbol
);
895 /// Convenience version of blocking lookup.
896 /// Searches each of the JITDylibs in the search order in turn for the given
897 /// symbol. The search will not find non-exported symbols.
898 Expected
<JITEvaluatedSymbol
> lookup(ArrayRef
<JITDylib
*> SearchOrder
,
901 /// Materialize the given unit.
902 void dispatchMaterialization(JITDylib
&JD
,
903 std::unique_ptr
<MaterializationUnit
> MU
) {
905 runSessionLocked([&]() {
906 dbgs() << "Dispatching " << *MU
<< " for " << JD
.getName() << "\n";
909 DispatchMaterialization(JD
, std::move(MU
));
912 /// Dump the state of all the JITDylibs in this session.
913 void dump(raw_ostream
&OS
);
916 static void logErrorsToStdErr(Error Err
) {
917 logAllUnhandledErrors(std::move(Err
), errs(), "JIT session error: ");
921 materializeOnCurrentThread(JITDylib
&JD
,
922 std::unique_ptr
<MaterializationUnit
> MU
) {
923 MU
->doMaterialize(JD
);
926 void runOutstandingMUs();
928 mutable std::recursive_mutex SessionMutex
;
929 std::shared_ptr
<SymbolStringPool
> SSP
;
930 VModuleKey LastKey
= 0;
931 ErrorReporter ReportError
= logErrorsToStdErr
;
932 DispatchMaterializationFunction DispatchMaterialization
=
933 materializeOnCurrentThread
;
935 std::vector
<std::unique_ptr
<JITDylib
>> JDs
;
937 // FIXME: Remove this (and runOutstandingMUs) once the linking layer works
938 // with callbacks from asynchronous queries.
939 mutable std::recursive_mutex OutstandingMUsMutex
;
940 std::vector
<std::pair
<JITDylib
*, std::unique_ptr
<MaterializationUnit
>>>
944 template <typename GeneratorT
>
945 GeneratorT
&JITDylib::addGenerator(std::unique_ptr
<GeneratorT
> DefGenerator
) {
946 auto &G
= *DefGenerator
;
948 [&]() { DefGenerators
.push_back(std::move(DefGenerator
)); });
952 template <typename Func
>
953 auto JITDylib::withSearchOrderDo(Func
&&F
)
954 -> decltype(F(std::declval
<const JITDylibSearchList
&>())) {
955 return ES
.runSessionLocked([&]() { return F(SearchOrder
); });
958 template <typename MaterializationUnitType
>
959 Error
JITDylib::define(std::unique_ptr
<MaterializationUnitType
> &&MU
) {
960 assert(MU
&& "Can not define with a null MU");
961 return ES
.runSessionLocked([&, this]() -> Error
{
962 if (auto Err
= defineImpl(*MU
))
965 /// defineImpl succeeded.
966 auto UMI
= std::make_shared
<UnmaterializedInfo
>(std::move(MU
));
967 for (auto &KV
: UMI
->MU
->getSymbols())
968 UnmaterializedInfos
[KV
.first
] = UMI
;
970 return Error::success();
974 template <typename MaterializationUnitType
>
975 Error
JITDylib::define(std::unique_ptr
<MaterializationUnitType
> &MU
) {
976 assert(MU
&& "Can not define with a null MU");
978 return ES
.runSessionLocked([&, this]() -> Error
{
979 if (auto Err
= defineImpl(*MU
))
982 /// defineImpl succeeded.
983 auto UMI
= std::make_shared
<UnmaterializedInfo
>(std::move(MU
));
984 for (auto &KV
: UMI
->MU
->getSymbols())
985 UnmaterializedInfos
[KV
.first
] = UMI
;
987 return Error::success();
991 /// ReexportsGenerator can be used with JITDylib::setGenerator to automatically
992 /// re-export a subset of the source JITDylib's symbols in the target.
993 class ReexportsGenerator
: public JITDylib::DefinitionGenerator
{
995 using SymbolPredicate
= std::function
<bool(SymbolStringPtr
)>;
997 /// Create a reexports generator. If an Allow predicate is passed, only
998 /// symbols for which the predicate returns true will be reexported. If no
999 /// Allow predicate is passed, all symbols will be exported.
1000 ReexportsGenerator(JITDylib
&SourceJD
, bool MatchNonExported
= false,
1001 SymbolPredicate Allow
= SymbolPredicate());
1003 Expected
<SymbolNameSet
> tryToGenerate(JITDylib
&JD
,
1004 const SymbolNameSet
&Names
) override
;
1008 bool MatchNonExported
= false;
1009 SymbolPredicate Allow
;
1012 /// Mangles symbol names then uniques them in the context of an
1013 /// ExecutionSession.
1014 class MangleAndInterner
{
1016 MangleAndInterner(ExecutionSession
&ES
, const DataLayout
&DL
);
1017 SymbolStringPtr
operator()(StringRef Name
);
1020 ExecutionSession
&ES
;
1021 const DataLayout
&DL
;
1024 } // End namespace orc
1025 } // End namespace llvm
1027 #undef DEBUG_TYPE // "orc"
1029 #endif // LLVM_EXECUTIONENGINE_ORC_CORE_H