//===------ Core.h -- Core ORC APIs (Layer, JITDylib, etc.) -----*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // Contains core ORC APIs. // //===----------------------------------------------------------------------===// #ifndef LLVM_EXECUTIONENGINE_ORC_CORE_H #define LLVM_EXECUTIONENGINE_ORC_CORE_H #include "llvm/ADT/BitmaskEnum.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/FunctionExtras.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ExecutionEngine/JITLink/JITLinkDylib.h" #include "llvm/ExecutionEngine/JITSymbol.h" #include "llvm/ExecutionEngine/Orc/ExecutorProcessControl.h" #include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h" #include "llvm/ExecutionEngine/Orc/Shared/ExecutorSymbolDef.h" #include "llvm/ExecutionEngine/Orc/Shared/WrapperFunctionUtils.h" #include "llvm/ExecutionEngine/Orc/TaskDispatch.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ExtensibleRTTI.h" #include <atomic> #include <deque> #include <future> #include <memory> #include <vector> namespace llvm { namespace orc { // Forward declare some classes. class AsynchronousSymbolQuery; class ExecutionSession; class MaterializationUnit; class MaterializationResponsibility; class JITDylib; class ResourceTracker; class InProgressLookupState; enum class SymbolState : uint8_t; ResourceTrackerSP; JITDylibSP; ResourceKey; /// API to remove / transfer ownership of JIT resources. class ResourceTracker : public ThreadSafeRefCountedBase<ResourceTracker> { … }; /// Listens for ResourceTracker operations. class ResourceManager { … }; /// A set of symbol names (represented by SymbolStringPtrs for // efficiency). SymbolNameSet; /// A vector of symbol names. SymbolNameVector; /// A map from symbol names (as SymbolStringPtrs) to JITSymbols /// (address/flags pairs). SymbolMap; /// A map from symbol names (as SymbolStringPtrs) to JITSymbolFlags. SymbolFlagsMap; /// A map from JITDylibs to sets of symbols. SymbolDependenceMap; /// Lookup flags that apply to each dylib in the search order for a lookup. /// /// If MatchHiddenSymbolsOnly is used (the default) for a given dylib, then /// only symbols in that Dylib's interface will be searched. If /// MatchHiddenSymbols is used then symbols with hidden visibility will match /// as well. enum class JITDylibLookupFlags { … }; /// Lookup flags that apply to each symbol in a lookup. /// /// If RequiredSymbol is used (the default) for a given symbol then that symbol /// must be found during the lookup or the lookup will fail returning a /// SymbolNotFound error. If WeaklyReferencedSymbol is used and the given /// symbol is not found then the query will continue, and no result for the /// missing symbol will be present in the result (assuming the rest of the /// lookup succeeds). enum class SymbolLookupFlags { … }; /// Describes the kind of lookup being performed. The lookup kind is passed to /// symbol generators (if they're invoked) to help them determine what /// definitions to generate. /// /// Static -- Lookup is being performed as-if at static link time (e.g. /// generators representing static archives should pull in new /// definitions). /// /// DLSym -- Lookup is being performed as-if at runtime (e.g. generators /// representing static archives should not pull in new definitions). enum class LookupKind { … }; /// A list of (JITDylib*, JITDylibLookupFlags) pairs to be used as a search /// order during symbol lookup. JITDylibSearchOrder; /// Convenience function for creating a search order from an ArrayRef of /// JITDylib*, all with the same flags. inline JITDylibSearchOrder makeJITDylibSearchOrder( ArrayRef<JITDylib *> JDs, JITDylibLookupFlags Flags = JITDylibLookupFlags::MatchExportedSymbolsOnly) { … } /// A set of symbols to look up, each associated with a SymbolLookupFlags /// value. /// /// This class is backed by a vector and optimized for fast insertion, /// deletion and iteration. It does not guarantee a stable order between /// operations, and will not automatically detect duplicate elements (they /// can be manually checked by calling the validate method). class SymbolLookupSet { … }; struct SymbolAliasMapEntry { … }; /// A map of Symbols to (Symbol, Flags) pairs. SymbolAliasMap; /// Callback to notify client that symbols have been resolved. SymbolsResolvedCallback; /// Callback to register the dependencies for a given query. RegisterDependenciesFunction; /// This can be used as the value for a RegisterDependenciesFunction if there /// are no dependants to register with. extern RegisterDependenciesFunction NoDependenciesToRegister; class ResourceTrackerDefunct : public ErrorInfo<ResourceTrackerDefunct> { … }; /// Used to notify a JITDylib that the given set of symbols failed to /// materialize. class FailedToMaterialize : public ErrorInfo<FailedToMaterialize> { … }; /// Used to report failure due to unsatisfiable symbol dependencies. class UnsatisfiedSymbolDependencies : public ErrorInfo<UnsatisfiedSymbolDependencies> { … }; /// Used to notify clients when symbols can not be found during a lookup. class SymbolsNotFound : public ErrorInfo<SymbolsNotFound> { … }; /// Used to notify clients that a set of symbols could not be removed. class SymbolsCouldNotBeRemoved : public ErrorInfo<SymbolsCouldNotBeRemoved> { … }; /// Errors of this type should be returned if a module fails to include /// definitions that are claimed by the module's associated /// MaterializationResponsibility. If this error is returned it is indicative of /// a broken transformation / compiler / object cache. class MissingSymbolDefinitions : public ErrorInfo<MissingSymbolDefinitions> { … }; /// Errors of this type should be returned if a module contains definitions for /// symbols that are not claimed by the module's associated /// MaterializationResponsibility. If this error is returned it is indicative of /// a broken transformation / compiler / object cache. class UnexpectedSymbolDefinitions : public ErrorInfo<UnexpectedSymbolDefinitions> { … }; /// A set of symbols and the their dependencies. Used to describe dependencies /// for the MaterializationResponsibility::notifyEmitted operation. struct SymbolDependenceGroup { … }; /// Tracks responsibility for materialization, and mediates interactions between /// MaterializationUnits and JDs. /// /// An instance of this class is passed to MaterializationUnits when their /// materialize method is called. It allows MaterializationUnits to resolve and /// emit symbols, or abandon materialization by notifying any unmaterialized /// symbols of an error. class MaterializationResponsibility { … }; /// A MaterializationUnit represents a set of symbol definitions that can /// be materialized as a group, or individually discarded (when /// overriding definitions are encountered). /// /// MaterializationUnits are used when providing lazy definitions of symbols to /// JITDylibs. The JITDylib will call materialize when the address of a symbol /// is requested via the lookup method. The JITDylib will call discard if a /// stronger definition is added or already present. class MaterializationUnit { … }; /// A MaterializationUnit implementation for pre-existing absolute symbols. /// /// All symbols will be resolved and marked ready as soon as the unit is /// materialized. class AbsoluteSymbolsMaterializationUnit : public MaterializationUnit { … }; /// Create an AbsoluteSymbolsMaterializationUnit with the given symbols. /// Useful for inserting absolute symbols into a JITDylib. E.g.: /// \code{.cpp} /// JITDylib &JD = ...; /// SymbolStringPtr Foo = ...; /// ExecutorSymbolDef FooSym = ...; /// if (auto Err = JD.define(absoluteSymbols({{Foo, FooSym}}))) /// return Err; /// \endcode /// inline std::unique_ptr<AbsoluteSymbolsMaterializationUnit> absoluteSymbols(SymbolMap Symbols) { … } /// A materialization unit for symbol aliases. Allows existing symbols to be /// aliased with alternate flags. class ReExportsMaterializationUnit : public MaterializationUnit { … }; /// Create a ReExportsMaterializationUnit with the given aliases. /// Useful for defining symbol aliases.: E.g., given a JITDylib JD containing /// symbols "foo" and "bar", we can define aliases "baz" (for "foo") and "qux" /// (for "bar") with: \code{.cpp} /// SymbolStringPtr Baz = ...; /// SymbolStringPtr Qux = ...; /// if (auto Err = JD.define(symbolAliases({ /// {Baz, { Foo, JITSymbolFlags::Exported }}, /// {Qux, { Bar, JITSymbolFlags::Weak }}})) /// return Err; /// \endcode inline std::unique_ptr<ReExportsMaterializationUnit> symbolAliases(SymbolAliasMap Aliases) { … } /// Create a materialization unit for re-exporting symbols from another JITDylib /// with alternative names/flags. /// SourceJD will be searched using the given JITDylibLookupFlags. inline std::unique_ptr<ReExportsMaterializationUnit> reexports(JITDylib &SourceJD, SymbolAliasMap Aliases, JITDylibLookupFlags SourceJDLookupFlags = JITDylibLookupFlags::MatchExportedSymbolsOnly) { … } /// Build a SymbolAliasMap for the common case where you want to re-export /// symbols from another JITDylib with the same linkage/flags. Expected<SymbolAliasMap> buildSimpleReexportsAliasMap(JITDylib &SourceJD, const SymbolNameSet &Symbols); /// Represents the state that a symbol has reached during materialization. enum class SymbolState : uint8_t { … }; /// A symbol query that returns results via a callback when results are /// ready. /// /// makes a callback when all symbols are available. class AsynchronousSymbolQuery { … }; /// Wraps state for a lookup-in-progress. /// DefinitionGenerators can optionally take ownership of a LookupState object /// to suspend a lookup-in-progress while they search for definitions. class LookupState { … }; /// Definition generators can be attached to JITDylibs to generate new /// definitions for otherwise unresolved symbols during lookup. class DefinitionGenerator { … }; /// Represents a JIT'd dynamic library. /// /// This class aims to mimic the behavior of a regular dylib or shared object, /// but without requiring the contained program representations to be compiled /// up-front. The JITDylib's content is defined by adding MaterializationUnits, /// and contained MaterializationUnits will typically rely on the JITDylib's /// links-against order to resolve external references (similar to a regular /// dylib). /// /// The JITDylib object is a thin wrapper that references state held by the /// ExecutionSession. JITDylibs can be removed, clearing this underlying state /// and leaving the JITDylib object in a defunct state. In this state the /// JITDylib's name is guaranteed to remain accessible. If the ExecutionSession /// is still alive then other operations are callable but will return an Error /// or null result (depending on the API). It is illegal to call any operation /// other than getName on a JITDylib after the ExecutionSession has been torn /// down. /// /// JITDylibs cannot be moved or copied. Their address is stable, and useful as /// a key in some JIT data structures. class JITDylib : public ThreadSafeRefCountedBase<JITDylib>, public jitlink::JITLinkDylib { … }; /// Platforms set up standard symbols and mediate interactions between dynamic /// initializers (e.g. C++ static constructors) and ExecutionSession state. /// Note that Platforms do not automatically run initializers: clients are still /// responsible for doing this. class Platform { … }; /// A materialization task. class MaterializationTask : public RTTIExtends<MaterializationTask, Task> { … }; /// Lookups are usually run on the current thread, but in some cases they may /// be run as tasks, e.g. if the lookup has been continued from a suspended /// state. class LookupTask : public RTTIExtends<LookupTask, Task> { … }; /// An ExecutionSession represents a running JIT program. class ExecutionSession { … }; template <typename Func> Error ResourceTracker::withResourceKeyDo(Func &&F) { … } inline ExecutionSession & MaterializationResponsibility::getExecutionSession() const { … } template <typename GeneratorT> GeneratorT &JITDylib::addGenerator(std::unique_ptr<GeneratorT> DefGenerator) { … } template <typename Func> auto JITDylib::withLinkOrderDo(Func &&F) -> decltype(F(std::declval<const JITDylibSearchOrder &>())) { … } template <typename MaterializationUnitType> Error JITDylib::define(std::unique_ptr<MaterializationUnitType> &&MU, ResourceTrackerSP RT) { … } template <typename MaterializationUnitType> Error JITDylib::define(std::unique_ptr<MaterializationUnitType> &MU, ResourceTrackerSP RT) { … } /// ReexportsGenerator can be used with JITDylib::addGenerator to automatically /// re-export a subset of the source JITDylib's symbols in the target. class ReexportsGenerator : public DefinitionGenerator { … }; // --------------- IMPLEMENTATION -------------- // Implementations for inline functions/methods. // --------------------------------------------- inline MaterializationResponsibility::~MaterializationResponsibility() { … } inline SymbolNameSet MaterializationResponsibility::getRequestedSymbols() const { … } inline Error MaterializationResponsibility::notifyResolved( const SymbolMap &Symbols) { … } inline Error MaterializationResponsibility::notifyEmitted( ArrayRef<SymbolDependenceGroup> EmittedDeps) { … } inline Error MaterializationResponsibility::defineMaterializing( SymbolFlagsMap SymbolFlags) { … } inline void MaterializationResponsibility::failMaterialization() { … } inline Error MaterializationResponsibility::replace( std::unique_ptr<MaterializationUnit> MU) { … } inline Expected<std::unique_ptr<MaterializationResponsibility>> MaterializationResponsibility::delegate(const SymbolNameSet &Symbols) { … } } // End namespace orc } // End namespace llvm #endif // LLVM_EXECUTIONENGINE_ORC_CORE_H