diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2019-08-20 20:50:12 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2019-08-20 20:50:12 +0000 |
commit | e6d1592492a3a379186bfb02bd0f4eda0669c0d5 (patch) | |
tree | 599ab169a01f1c86eda9adc774edaedde2f2db5b /include/llvm/ExecutionEngine/Orc/Core.h | |
parent | 1a56a5ead7a2e84bee8240f5f6b033b5f1707154 (diff) |
Diffstat (limited to 'include/llvm/ExecutionEngine/Orc/Core.h')
-rw-r--r-- | include/llvm/ExecutionEngine/Orc/Core.h | 228 |
1 files changed, 145 insertions, 83 deletions
diff --git a/include/llvm/ExecutionEngine/Orc/Core.h b/include/llvm/ExecutionEngine/Orc/Core.h index 39d306e0bd4c..94a5618233e4 100644 --- a/include/llvm/ExecutionEngine/Orc/Core.h +++ b/include/llvm/ExecutionEngine/Orc/Core.h @@ -1,9 +1,8 @@ //===------ Core.h -- Core ORC APIs (Layer, JITDylib, etc.) -----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -17,6 +16,7 @@ #include "llvm/ADT/BitmaskEnum.h" #include "llvm/ExecutionEngine/JITSymbol.h" #include "llvm/ExecutionEngine/Orc/SymbolStringPool.h" +#include "llvm/ExecutionEngine/OrcV1Deprecation.h" #include "llvm/IR/Module.h" #include "llvm/Support/Debug.h" @@ -34,6 +34,7 @@ class ExecutionSession; class MaterializationUnit; class MaterializationResponsibility; class JITDylib; +enum class SymbolState : uint8_t; /// VModuleKey provides a unique identifier (allocated and managed by /// ExecutionSessions) for a module added to the JIT. @@ -57,6 +58,18 @@ using SymbolDependenceMap = DenseMap<JITDylib *, SymbolNameSet>; /// A list of (JITDylib*, bool) pairs. using JITDylibSearchList = std::vector<std::pair<JITDylib *, bool>>; +struct SymbolAliasMapEntry { + SymbolAliasMapEntry() = default; + SymbolAliasMapEntry(SymbolStringPtr Aliasee, JITSymbolFlags AliasFlags) + : Aliasee(std::move(Aliasee)), AliasFlags(AliasFlags) {} + + SymbolStringPtr Aliasee; + JITSymbolFlags AliasFlags; +}; + +/// A map of Symbols to (Symbol, Flags) pairs. +using SymbolAliasMap = DenseMap<SymbolStringPtr, SymbolAliasMapEntry>; + /// Render a SymbolStringPtr. raw_ostream &operator<<(raw_ostream &OS, const SymbolStringPtr &Sym); @@ -88,12 +101,15 @@ raw_ostream &operator<<(raw_ostream &OS, const MaterializationUnit &MU); /// Render a JITDylibSearchList. raw_ostream &operator<<(raw_ostream &OS, const JITDylibSearchList &JDs); +/// Render a SymbolAliasMap. +raw_ostream &operator<<(raw_ostream &OS, const SymbolAliasMap &Aliases); + +/// Render a SymbolState. +raw_ostream &operator<<(raw_ostream &OS, const SymbolState &S); + /// Callback to notify client that symbols have been resolved. using SymbolsResolvedCallback = std::function<void(Expected<SymbolMap>)>; -/// Callback to notify client that symbols are ready for execution. -using SymbolsReadyCallback = std::function<void(Error)>; - /// Callback to register the dependencies for a given query. using RegisterDependenciesFunction = std::function<void(const SymbolDependenceMap &)>; @@ -175,7 +191,7 @@ public: /// Note: The returned flags may have transient flags (Lazy, Materializing) /// set. These should be stripped with JITSymbolFlags::stripTransientFlags /// before using. - const SymbolFlagsMap &getSymbols() { return SymbolFlags; } + const SymbolFlagsMap &getSymbols() const { return SymbolFlags; } /// Returns the names of any symbols covered by this /// MaterializationResponsibility object that have queries pending. This @@ -189,12 +205,12 @@ public: /// symbols must be ones covered by this MaterializationResponsibility /// instance. Individual calls to this method may resolve a subset of the /// symbols, but all symbols must have been resolved prior to calling emit. - void resolve(const SymbolMap &Symbols); + void notifyResolved(const SymbolMap &Symbols); /// Notifies the target JITDylib (and any pending queries on that JITDylib) /// that all symbols covered by this MaterializationResponsibility instance /// have been emitted. - void emit(); + void notifyEmitted(); /// Adds new symbols to the JITDylib and this responsibility instance. /// JITDylib entries start out in the materializing state. @@ -334,18 +350,6 @@ absoluteSymbols(SymbolMap Symbols, VModuleKey K = VModuleKey()) { std::move(Symbols), std::move(K)); } -struct SymbolAliasMapEntry { - SymbolAliasMapEntry() = default; - SymbolAliasMapEntry(SymbolStringPtr Aliasee, JITSymbolFlags AliasFlags) - : Aliasee(std::move(Aliasee)), AliasFlags(AliasFlags) {} - - SymbolStringPtr Aliasee; - JITSymbolFlags AliasFlags; -}; - -/// A map of Symbols to (Symbol, Flags) pairs. -using SymbolAliasMap = DenseMap<SymbolStringPtr, SymbolAliasMapEntry>; - /// A materialization unit for symbol aliases. Allows existing symbols to be /// aliased with alternate flags. class ReExportsMaterializationUnit : public MaterializationUnit { @@ -419,7 +423,7 @@ public: ReexportsGenerator(JITDylib &SourceJD, bool MatchNonExported = false, SymbolPredicate Allow = SymbolPredicate()); - SymbolNameSet operator()(JITDylib &JD, const SymbolNameSet &Names); + Expected<SymbolNameSet> operator()(JITDylib &JD, const SymbolNameSet &Names); private: JITDylib &SourceJD; @@ -427,6 +431,15 @@ private: SymbolPredicate Allow; }; +/// Represents the state that a symbol has reached during materialization. +enum class SymbolState : uint8_t { + Invalid, /// No symbol should be in this state. + NeverSearched, /// Added to the symbol table, never queried. + Materializing, /// Queried, materialization begun. + Resolved, /// Assigned address, still materializing. + Ready = 0x3f /// Ready and safe for clients to access. +}; + /// A symbol query that returns results via a callback when results are /// ready. /// @@ -437,38 +450,30 @@ class AsynchronousSymbolQuery { friend class JITSymbolResolverAdapter; public: - - /// Create a query for the given symbols, notify-resolved and - /// notify-ready callbacks. + /// Create a query for the given symbols. The NotifyComplete + /// callback will be called once all queried symbols reach the given + /// minimum state. AsynchronousSymbolQuery(const SymbolNameSet &Symbols, - SymbolsResolvedCallback NotifySymbolsResolved, - SymbolsReadyCallback NotifySymbolsReady); + SymbolState RequiredState, + SymbolsResolvedCallback NotifyComplete); - /// Set the resolved symbol information for the given symbol name. - void resolve(const SymbolStringPtr &Name, JITEvaluatedSymbol Sym); + /// Notify the query that a requested symbol has reached the required state. + void notifySymbolMetRequiredState(const SymbolStringPtr &Name, + JITEvaluatedSymbol Sym); /// Returns true if all symbols covered by this query have been /// resolved. - bool isFullyResolved() const { return NotYetResolvedCount == 0; } + bool isComplete() const { return OutstandingSymbolsCount == 0; } - /// Call the NotifySymbolsResolved callback. + /// Call the NotifyComplete callback. /// - /// This should only be called if all symbols covered by the query have been - /// resolved. - void handleFullyResolved(); - - /// Notify the query that a requested symbol is ready for execution. - void notifySymbolReady(); - - /// Returns true if all symbols covered by this query are ready. - bool isFullyReady() const { return NotYetReadyCount == 0; } - - /// Calls the NotifySymbolsReady callback. - /// - /// This should only be called if all symbols covered by this query are ready. - void handleFullyReady(); + /// This should only be called if all symbols covered by the query have + /// reached the specified state. + void handleComplete(); private: + SymbolState getRequiredState() { return RequiredState; } + void addQueryDependence(JITDylib &JD, SymbolStringPtr Name); void removeQueryDependence(JITDylib &JD, const SymbolStringPtr &Name); @@ -479,12 +484,11 @@ private: void detach(); - SymbolsResolvedCallback NotifySymbolsResolved; - SymbolsReadyCallback NotifySymbolsReady; + SymbolsResolvedCallback NotifyComplete; SymbolDependenceMap QueryRegistrations; SymbolMap ResolvedSymbols; - size_t NotYetResolvedCount; - size_t NotYetReadyCount; + size_t OutstandingSymbolsCount; + SymbolState RequiredState; }; /// A symbol table that supports asynchoronous symbol queries. @@ -498,7 +502,7 @@ class JITDylib { friend class ExecutionSession; friend class MaterializationResponsibility; public: - using GeneratorFunction = std::function<SymbolNameSet( + using GeneratorFunction = std::function<Expected<SymbolNameSet>( JITDylib &Parent, const SymbolNameSet &Names)>; using AsynchronousSymbolQuerySet = @@ -596,7 +600,7 @@ public: /// Search the given JITDylib for the symbols in Symbols. If found, store /// the flags for each symbol in Flags. Returns any unresolved symbols. - SymbolFlagsMap lookupFlags(const SymbolNameSet &Names); + Expected<SymbolFlagsMap> lookupFlags(const SymbolNameSet &Names); /// Dump current JITDylib state to OS. void dump(raw_ostream &OS); @@ -609,8 +613,8 @@ public: /// and the query will not be applied. The Query is not failed and can be /// re-used in a subsequent lookup once the symbols have been added, or /// manually failed. - SymbolNameSet legacyLookup(std::shared_ptr<AsynchronousSymbolQuery> Q, - SymbolNameSet Names); + Expected<SymbolNameSet> + legacyLookup(std::shared_ptr<AsynchronousSymbolQuery> Q, SymbolNameSet Names); private: using AsynchronousSymbolQueryList = @@ -627,40 +631,92 @@ private: DenseMap<SymbolStringPtr, std::shared_ptr<UnmaterializedInfo>>; struct MaterializingInfo { - AsynchronousSymbolQueryList PendingQueries; SymbolDependenceMap Dependants; SymbolDependenceMap UnemittedDependencies; bool IsEmitted = false; + + void addQuery(std::shared_ptr<AsynchronousSymbolQuery> Q); + void removeQuery(const AsynchronousSymbolQuery &Q); + AsynchronousSymbolQueryList takeQueriesMeeting(SymbolState RequiredState); + AsynchronousSymbolQueryList takeAllQueries(); + bool hasQueriesPending() const { return !PendingQueries.empty(); } + const AsynchronousSymbolQueryList &pendingQueries() const { + return PendingQueries; + } + + private: + AsynchronousSymbolQueryList PendingQueries; }; using MaterializingInfosMap = DenseMap<SymbolStringPtr, MaterializingInfo>; - using LookupImplActionFlags = enum { - None = 0, - NotifyFullyResolved = 1 << 0U, - NotifyFullyReady = 1 << 1U, - LLVM_MARK_AS_BITMASK_ENUM(NotifyFullyReady) + class SymbolTableEntry { + public: + SymbolTableEntry() = default; + SymbolTableEntry(JITSymbolFlags Flags) + : Flags(Flags), State(static_cast<uint8_t>(SymbolState::NeverSearched)), + MaterializerAttached(false), PendingRemoval(false) {} + + JITTargetAddress getAddress() const { return Addr; } + JITSymbolFlags getFlags() const { return Flags; } + SymbolState getState() const { return static_cast<SymbolState>(State); } + + bool isInMaterializationPhase() const { + return getState() == SymbolState::Materializing || + getState() == SymbolState::Resolved; + } + + bool hasMaterializerAttached() const { return MaterializerAttached; } + bool isPendingRemoval() const { return PendingRemoval; } + + void setAddress(JITTargetAddress Addr) { this->Addr = Addr; } + void setFlags(JITSymbolFlags Flags) { this->Flags = Flags; } + void setState(SymbolState State) { + assert(static_cast<uint8_t>(State) < (1 << 6) && + "State does not fit in bitfield"); + this->State = static_cast<uint8_t>(State); + } + + void setMaterializerAttached(bool MaterializerAttached) { + this->MaterializerAttached = MaterializerAttached; + } + + void setPendingRemoval(bool PendingRemoval) { + this->PendingRemoval = PendingRemoval; + } + + JITEvaluatedSymbol getSymbol() const { + return JITEvaluatedSymbol(Addr, Flags); + } + + private: + JITTargetAddress Addr = 0; + JITSymbolFlags Flags; + uint8_t State : 6; + uint8_t MaterializerAttached : 1; + uint8_t PendingRemoval : 1; }; + using SymbolTable = DenseMap<SymbolStringPtr, SymbolTableEntry>; + JITDylib(ExecutionSession &ES, std::string Name); Error defineImpl(MaterializationUnit &MU); - SymbolNameSet lookupFlagsImpl(SymbolFlagsMap &Flags, - const SymbolNameSet &Names); + Expected<SymbolNameSet> lookupFlagsImpl(SymbolFlagsMap &Flags, + const SymbolNameSet &Names); - void lodgeQuery(std::shared_ptr<AsynchronousSymbolQuery> &Q, - SymbolNameSet &Unresolved, bool MatchNonExported, - MaterializationUnitList &MUs); + Error lodgeQuery(std::shared_ptr<AsynchronousSymbolQuery> &Q, + SymbolNameSet &Unresolved, bool MatchNonExported, + MaterializationUnitList &MUs); void lodgeQueryImpl(std::shared_ptr<AsynchronousSymbolQuery> &Q, SymbolNameSet &Unresolved, bool MatchNonExported, MaterializationUnitList &MUs); - LookupImplActionFlags - lookupImpl(std::shared_ptr<AsynchronousSymbolQuery> &Q, - std::vector<std::unique_ptr<MaterializationUnit>> &MUs, - SymbolNameSet &Unresolved); + bool lookupImpl(std::shared_ptr<AsynchronousSymbolQuery> &Q, + std::vector<std::unique_ptr<MaterializationUnit>> &MUs, + SymbolNameSet &Unresolved); void detachQueryHelper(AsynchronousSymbolQuery &Q, const SymbolNameSet &QuerySymbols); @@ -686,7 +742,7 @@ private: ExecutionSession &ES; std::string JITDylibName; - SymbolMap Symbols; + SymbolTable Symbols; UnmaterializedInfosMap UnmaterializedInfos; MaterializingInfosMap MaterializingInfos; GeneratorFunction DefGenerator; @@ -727,7 +783,15 @@ public: /// the ExecutionSession. JITDylib &getMainJITDylib(); + /// Return a pointer to the "name" JITDylib. + /// Ownership of JITDylib remains within Execution Session + JITDylib *getJITDylibByName(StringRef Name); + /// Add a new JITDylib to this ExecutionSession. + /// + /// The JITDylib Name is required to be unique. Clients should verify that + /// names are not being re-used (e.g. by calling getJITDylibByName) if names + /// are based on user input. JITDylib &createJITDylib(std::string Name, bool AddToMainDylibSearchOrder = true); @@ -769,7 +833,7 @@ public: /// Do not use -- this will be removed soon. Expected<SymbolMap> legacyLookup(LegacyAsyncLookupFunction AsyncLookup, SymbolNameSet Names, - bool WaiUntilReady, + SymbolState RequiredState, RegisterDependenciesFunction RegisterDependencies); /// Search the given JITDylib list for the given symbols. @@ -779,11 +843,8 @@ public: /// (hidden visibility) symbols in that dylib (true means match against /// non-exported symbols, false means do not match). /// - /// The OnResolve callback will be called once all requested symbols are - /// resolved, or if an error occurs prior to resolution. - /// - /// The OnReady callback will be called once all requested symbols are ready, - /// or if an error occurs after resolution but before all symbols are ready. + /// The NotifyComplete callback will be called once all requested symbols + /// reach the required state. /// /// If all symbols are found, the RegisterDependencies function will be called /// while the session lock is held. This gives clients a chance to register @@ -795,7 +856,7 @@ public: /// client to get an address to call) then the value NoDependenciesToRegister /// can be used. void lookup(const JITDylibSearchList &SearchOrder, SymbolNameSet Symbols, - SymbolsResolvedCallback OnResolve, SymbolsReadyCallback OnReady, + SymbolState RequiredState, SymbolsResolvedCallback NotifyComplete, RegisterDependenciesFunction RegisterDependencies); /// Blocking version of lookup above. Returns the resolved symbol map. @@ -807,9 +868,9 @@ public: /// error will be reported via reportErrors. Expected<SymbolMap> lookup(const JITDylibSearchList &SearchOrder, const SymbolNameSet &Symbols, + SymbolState RequiredState = SymbolState::Ready, RegisterDependenciesFunction RegisterDependencies = - NoDependenciesToRegister, - bool WaitUntilReady = true); + NoDependenciesToRegister); /// Convenience version of blocking lookup. /// Searches each of the JITDylibs in the search order in turn for the given @@ -832,10 +893,11 @@ public: /// Materialize the given unit. void dispatchMaterialization(JITDylib &JD, std::unique_ptr<MaterializationUnit> MU) { - LLVM_DEBUG(runSessionLocked([&]() { - dbgs() << "Compiling, for " << JD.getName() << ", " << *MU - << "\n"; - });); + LLVM_DEBUG({ + runSessionLocked([&]() { + dbgs() << "Dispatching " << *MU << " for " << JD.getName() << "\n"; + }); + }); DispatchMaterialization(JD, std::move(MU)); } |