diff options
Diffstat (limited to 'llvm/include')
-rw-r--r-- | llvm/include/llvm/ExecutionEngine/JITSymbol.h | 13 | ||||
-rw-r--r-- | llvm/include/llvm/ExecutionEngine/Orc/Core.h | 234 | ||||
-rw-r--r-- | llvm/include/llvm/ExecutionEngine/Orc/OrcError.h | 15 |
3 files changed, 260 insertions, 2 deletions
diff --git a/llvm/include/llvm/ExecutionEngine/JITSymbol.h b/llvm/include/llvm/ExecutionEngine/JITSymbol.h index 933b3ea8e13..daf8c0ac4c7 100644 --- a/llvm/include/llvm/ExecutionEngine/JITSymbol.h +++ b/llvm/include/llvm/ExecutionEngine/JITSymbol.h @@ -48,7 +48,9 @@ public: Weak = 1U << 1, Common = 1U << 2, Absolute = 1U << 3, - Exported = 1U << 4 + Exported = 1U << 4, + NotMaterialized = 1U << 5, + Materializing = 1U << 6 }; /// @brief Default-construct a JITSymbolFlags instance. @@ -67,6 +69,15 @@ public: return (Flags & HasError) == HasError; } + /// @brief Returns true if this symbol has been fully materialized (i.e. is + /// callable). + bool isMaterialized() const { return !(Flags & NotMaterialized); } + + /// @brief Returns true if this symbol is in the process of being + /// materialized. This is generally only of interest as an + /// implementation detail to JIT infrastructure. + bool isMaterializing() const { return Flags & Materializing; } + /// @brief Returns true if the Weak flag is set. bool isWeak() const { return (Flags & Weak) == Weak; diff --git a/llvm/include/llvm/ExecutionEngine/Orc/Core.h b/llvm/include/llvm/ExecutionEngine/Orc/Core.h new file mode 100644 index 00000000000..546ccc54a6d --- /dev/null +++ b/llvm/include/llvm/ExecutionEngine/Orc/Core.h @@ -0,0 +1,234 @@ +//===------ 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. +// +//===----------------------------------------------------------------------===// +// +// Contains core ORC APIs. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORC_CORE_H +#define LLVM_EXECUTIONENGINE_ORC_CORE_H + +#include "llvm/ExecutionEngine/JITSymbol.h" +#include "llvm/ExecutionEngine/Orc/SymbolStringPool.h" + +#include <deque> +#include <map> +#include <memory> +#include <set> +#include <vector> + +namespace llvm { +namespace orc { + +class VSO; + +/// @brief A set of symbol names (represented by SymbolStringPtrs for +// efficiency). +using SymbolNameSet = std::set<SymbolStringPtr>; + +/// @brief A map from symbol names (as SymbolStringPtrs) to JITSymbols +/// (address/flags pairs). +using SymbolMap = std::map<SymbolStringPtr, JITSymbol>; + +/// @brief A map from symbol names (as SymbolStringPtrs) to JITSymbolFlags. +using SymbolFlagsMap = std::map<SymbolStringPtr, JITSymbolFlags>; + +/// @brief A symbol query that returns results via a callback when results are +/// ready. +/// +/// makes a callback when all symbols are available. +class AsynchronousSymbolQuery { +public: + + /// @brief Callback to notify client that symbols have been resolved. + using SymbolsResolvedCallback = std::function<void(Expected<SymbolMap>)>; + + /// @brief Callback to notify client that symbols are ready for execution. + using SymbolsReadyCallback = std::function<void(Error)>; + + /// @brief Create a query for the given symbols, notify-resolved and + /// notify-ready callbacks. + AsynchronousSymbolQuery(const SymbolNameSet &Symbols, + SymbolsResolvedCallback NotifySymbolsResolved, + SymbolsReadyCallback NotifySymbolsReady); + + /// @brief Notify client that the query failed. + /// + /// If the notify-resolved callback has not been made yet, then it is called + /// with the given error, and the notify-finalized callback is never made. + /// + /// If the notify-resolved callback has already been made then then the + /// notify-finalized callback is called with the given error. + /// + /// It is illegal to call setFailed after both callbacks have been made. + void setFailed(Error Err); + + /// @brief Set the resolved symbol information for the given symbol name. + /// + /// If this symbol was the last one not resolved, this will trigger a call to + /// the notify-finalized callback passing the completed sybol map. + void setDefinition(SymbolStringPtr Name, JITSymbol Sym); + + /// @brief Notify the query that a requested symbol is ready for execution. + /// + /// This decrements the query's internal count of not-yet-ready symbols. If + /// this call to notifySymbolFinalized sets the counter to zero, it will call + /// the notify-finalized callback with Error::success as the value. + void notifySymbolFinalized(); +private: + SymbolMap Symbols; + size_t OutstandingResolutions = 0; + size_t OutstandingFinalizations = 0; + SymbolsResolvedCallback NotifySymbolsResolved; + SymbolsReadyCallback NotifySymbolsReady; +}; + +/// @brief Represents a source of symbol definitions which may be materialized +/// (turned into data / code through some materialization process) or +/// discarded (if the definition is overridden by a stronger one). +/// +/// SymbolSources are used when providing lazy definitions of symbols to VSOs. +/// The VSO will call materialize when the address of a symbol is requested via +/// the lookup method. The VSO will call discard if a stronger definition is +/// added or already present. +class SymbolSource { +public: + virtual ~SymbolSource() {} + + /// @brief Implementations of this method should materialize the given + /// symbols (plus any additional symbols required) by adding a + /// Materializer to the ExecutionSession's MaterializationQueue. + virtual Error materialize(VSO &V, SymbolNameSet Symbols) = 0; + + /// @brief Implementations of this method should discard the given symbol + /// from the source (e.g. if the source is an LLVM IR Module and the + /// symbol is a function, delete the function body or mark it available + /// externally). + virtual void discard(VSO &V, SymbolStringPtr Name) = 0; +private: + virtual void anchor(); +}; + +/// @brief Represents a dynamic linkage unit in a JIT process. +/// +/// VSO acts as a symbol table (symbol definitions can be set and the dylib +/// queried to find symbol addresses) and as a key for tracking resources +/// (since a VSO's address is fixed). +class VSO { + friend class ExecutionSession; +public: + + /// @brief + enum RelativeLinkageStrength { + NewDefinitionIsStronger, + DuplicateDefinition, + ExistingDefinitionIsStronger + }; + + using SetDefinitionsResult = + std::map<SymbolStringPtr, RelativeLinkageStrength>; + using SourceWorkMap = std::map<SymbolSource*, SymbolNameSet>; + + struct LookupResult { + SourceWorkMap MaterializationWork; + SymbolNameSet UnresolvedSymbols; + }; + + VSO() = default; + + VSO(const VSO&) = delete; + VSO& operator=(const VSO&) = delete; + VSO(VSO&&) = delete; + VSO& operator=(VSO&&) = delete; + + /// @brief Compare new linkage with existing linkage. + static RelativeLinkageStrength + compareLinkage(Optional<JITSymbolFlags> OldFlags, + JITSymbolFlags NewFlags); + + /// @brief Compare new linkage with an existing symbol's linkage. + RelativeLinkageStrength compareLinkage(SymbolStringPtr Name, + JITSymbolFlags NewFlags) const; + + /// @brief Adds the given symbols to the mapping as resolved, finalized + /// symbols. + /// + /// FIXME: We can take this by const-ref once symbol-based laziness is + /// removed. + Error define(SymbolMap NewSymbols); + + /// @brief Adds the given symbols to the mapping as lazy symbols. + Error defineLazy(const SymbolFlagsMap &NewSymbols, SymbolSource &Source); + + /// @brief Add the given symbol/address mappings to the dylib, but do not + /// mark the symbols as finalized yet. + void resolve(SymbolMap SymbolValues); + + /// @brief Finalize the given symbols. + void finalize(SymbolNameSet SymbolsToFinalize); + + /// @brief Apply the given query to the given symbols in this VSO. + /// + /// For symbols in this VSO that have already been materialized, their address + /// will be set in the query immediately. + /// + /// For symbols in this VSO that have not been materialized, the query will be + /// recorded and the source for those symbols (plus the set of symbols to be + /// materialized by that source) will be returned as the MaterializationWork + /// field of the LookupResult. + /// + /// Any symbols not found in this VSO will be returned in the + /// UnresolvedSymbols field of the LookupResult. + LookupResult lookup(AsynchronousSymbolQuery &Query, SymbolNameSet Symbols); + +private: + + class MaterializationInfo { + public: + MaterializationInfo(JITSymbolFlags Flags, AsynchronousSymbolQuery &Query); + JITSymbolFlags getFlags() const; + JITTargetAddress getAddress() const; + void query(SymbolStringPtr Name, AsynchronousSymbolQuery &Query); + void resolve(SymbolStringPtr Name, JITSymbol Sym); + void finalize(); + private: + JITSymbolFlags Flags; + JITTargetAddress Address = 0; + std::vector<AsynchronousSymbolQuery*> PendingResolution; + std::vector<AsynchronousSymbolQuery*> PendingFinalization; + }; + + class SymbolTableEntry { + public: + SymbolTableEntry(JITSymbolFlags Flags, SymbolSource &Source); + SymbolTableEntry(JITSymbol Sym); + SymbolTableEntry(SymbolTableEntry &&Other); + ~SymbolTableEntry(); + JITSymbolFlags getFlags() const; + void replaceWithSource(VSO &V, SymbolStringPtr Name, JITSymbolFlags Flags, + SymbolSource &NewSource); + SymbolSource* query(SymbolStringPtr Name, AsynchronousSymbolQuery &Query); + void resolve(VSO &V, SymbolStringPtr Name, JITSymbol Sym); + void finalize(); + private: + JITSymbolFlags Flags; + union { + JITTargetAddress Address; + SymbolSource *Source; + std::unique_ptr<MaterializationInfo> MatInfo; + }; + }; + + std::map<SymbolStringPtr, SymbolTableEntry> Symbols; +}; + +} // End namespace orc +} // End namespace llvm + +#endif // LLVM_EXECUTIONENGINE_ORC_CORE_H diff --git a/llvm/include/llvm/ExecutionEngine/Orc/OrcError.h b/llvm/include/llvm/ExecutionEngine/Orc/OrcError.h index e1ac87075ac..c2ff41e421e 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/OrcError.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/OrcError.h @@ -22,7 +22,8 @@ namespace orc { enum class OrcErrorCode : int { // RPC Errors - JITSymbolNotFound = 1, + DuplicateDefinition = 1, + JITSymbolNotFound, RemoteAllocatorDoesNotExist, RemoteAllocatorIdAlreadyInUse, RemoteMProtectAddrUnrecognized, @@ -39,6 +40,18 @@ enum class OrcErrorCode : int { std::error_code orcError(OrcErrorCode ErrCode); +class DuplicateDefinition : public ErrorInfo<DuplicateDefinition> { +public: + static char ID; + + DuplicateDefinition(std::string SymbolName); + std::error_code convertToErrorCode() const override; + void log(raw_ostream &OS) const override; + const std::string &getSymbolName() const; +private: + std::string SymbolName; +}; + class JITSymbolNotFound : public ErrorInfo<JITSymbolNotFound> { public: static char ID; |