#pragma once #ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-parameter" #endif //===-- ObjectLinkingLayer.h - JITLink-based jit linking layer --*- 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 the definition for an JITLink-based, in-process object linking // layer. // //===----------------------------------------------------------------------===// #ifndef LLVM_EXECUTIONENGINE_ORC_OBJECTLINKINGLAYER_H #define LLVM_EXECUTIONENGINE_ORC_OBJECTLINKINGLAYER_H #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/ExecutionEngine/JITLink/JITLink.h" #include "llvm/ExecutionEngine/JITSymbol.h" #include "llvm/ExecutionEngine/Orc/Core.h" #include "llvm/ExecutionEngine/Orc/Layer.h" #include "llvm/Support/Error.h" #include #include #include #include #include #include #include #include namespace llvm { namespace jitlink { class EHFrameRegistrar; class LinkGraph; class Symbol; } // namespace jitlink namespace object { class ObjectFile; } // namespace object namespace orc { class ObjectLinkingLayerJITLinkContext; /// An ObjectLayer implementation built on JITLink. /// /// Clients can use this class to add relocatable object files to an /// ExecutionSession, and it typically serves as the base layer (underneath /// a compiling layer like IRCompileLayer) for the rest of the JIT. class ObjectLinkingLayer : public ObjectLayer, private ResourceManager { friend class ObjectLinkingLayerJITLinkContext; public: /// Plugin instances can be added to the ObjectLinkingLayer to receive /// callbacks when code is loaded or emitted, and when JITLink is being /// configured. class Plugin { public: using JITLinkSymbolVector = std::vector; using LocalDependenciesMap = DenseMap; virtual ~Plugin(); virtual void modifyPassConfig(MaterializationResponsibility &MR, const Triple &TT, jitlink::PassConfiguration &Config) {} virtual void notifyLoaded(MaterializationResponsibility &MR) {} virtual Error notifyEmitted(MaterializationResponsibility &MR) { return Error::success(); } virtual Error notifyFailed(MaterializationResponsibility &MR) = 0; virtual Error notifyRemovingResources(ResourceKey K) = 0; virtual void notifyTransferringResources(ResourceKey DstKey, ResourceKey SrcKey) = 0; /// Return any dependencies that synthetic symbols (e.g. init symbols) /// have on locally scoped jitlink::Symbols. This is used by the /// ObjectLinkingLayer to update the dependencies for the synthetic /// symbols. virtual LocalDependenciesMap getSyntheticSymbolLocalDependencies(MaterializationResponsibility &MR) { return LocalDependenciesMap(); } }; using ReturnObjectBufferFunction = std::function)>; /// Construct an ObjectLinkingLayer. ObjectLinkingLayer(ExecutionSession &ES, jitlink::JITLinkMemoryManager &MemMgr); /// Construct an ObjectLinkingLayer. Takes ownership of the given /// JITLinkMemoryManager. This method is a temporary hack to simplify /// co-existence with RTDyldObjectLinkingLayer (which also owns its /// allocators). ObjectLinkingLayer(ExecutionSession &ES, std::unique_ptr MemMgr); /// Destruct an ObjectLinkingLayer. ~ObjectLinkingLayer(); /// Set an object buffer return function. By default object buffers are /// deleted once the JIT has linked them. If a return function is set then /// it will be called to transfer ownership of the buffer instead. void setReturnObjectBuffer(ReturnObjectBufferFunction ReturnObjectBuffer) { this->ReturnObjectBuffer = std::move(ReturnObjectBuffer); } /// Add a pass-config modifier. ObjectLinkingLayer &addPlugin(std::unique_ptr P) { std::lock_guard Lock(LayerMutex); Plugins.push_back(std::move(P)); return *this; } /// Emit an object file. void emit(std::unique_ptr R, std::unique_ptr O) override; /// Emit a LinkGraph. void emit(std::unique_ptr R, std::unique_ptr G); /// Instructs this ObjectLinkingLayer instance to override the symbol flags /// found in the AtomGraph with the flags supplied by the /// MaterializationResponsibility instance. This is a workaround to support /// symbol visibility in COFF, which does not use the libObject's /// SF_Exported flag. Use only when generating / adding COFF object files. /// /// FIXME: We should be able to remove this if/when COFF properly tracks /// exported symbols. ObjectLinkingLayer & setOverrideObjectFlagsWithResponsibilityFlags(bool OverrideObjectFlags) { this->OverrideObjectFlags = OverrideObjectFlags; return *this; } /// If set, this ObjectLinkingLayer instance will claim responsibility /// for any symbols provided by a given object file that were not already in /// the MaterializationResponsibility instance. Setting this flag allows /// higher-level program representations (e.g. LLVM IR) to be added based on /// only a subset of the symbols they provide, without having to write /// intervening layers to scan and add the additional symbols. This trades /// diagnostic quality for convenience however: If all symbols are enumerated /// up-front then clashes can be detected and reported early (and usually /// deterministically). If this option is set, clashes for the additional /// symbols may not be detected until late, and detection may depend on /// the flow of control through JIT'd code. Use with care. ObjectLinkingLayer & setAutoClaimResponsibilityForObjectSymbols(bool AutoClaimObjectSymbols) { this->AutoClaimObjectSymbols = AutoClaimObjectSymbols; return *this; } private: using AllocPtr = std::unique_ptr; void modifyPassConfig(MaterializationResponsibility &MR, const Triple &TT, jitlink::PassConfiguration &PassConfig); void notifyLoaded(MaterializationResponsibility &MR); Error notifyEmitted(MaterializationResponsibility &MR, AllocPtr Alloc); Error handleRemoveResources(ResourceKey K) override; void handleTransferResources(ResourceKey DstKey, ResourceKey SrcKey) override; mutable std::mutex LayerMutex; jitlink::JITLinkMemoryManager &MemMgr; std::unique_ptr MemMgrOwnership; bool OverrideObjectFlags = false; bool AutoClaimObjectSymbols = false; ReturnObjectBufferFunction ReturnObjectBuffer; DenseMap> Allocs; std::vector> Plugins; }; class EHFrameRegistrationPlugin : public ObjectLinkingLayer::Plugin { public: EHFrameRegistrationPlugin( ExecutionSession &ES, std::unique_ptr Registrar); void modifyPassConfig(MaterializationResponsibility &MR, const Triple &TT, jitlink::PassConfiguration &PassConfig) override; Error notifyEmitted(MaterializationResponsibility &MR) override; Error notifyFailed(MaterializationResponsibility &MR) override; Error notifyRemovingResources(ResourceKey K) override; void notifyTransferringResources(ResourceKey DstKey, ResourceKey SrcKey) override; private: struct EHFrameRange { JITTargetAddress Addr = 0; size_t Size; }; std::mutex EHFramePluginMutex; ExecutionSession &ES; std::unique_ptr Registrar; DenseMap InProcessLinks; DenseMap> EHFrameRanges; }; } // end namespace orc } // end namespace llvm #endif // LLVM_EXECUTIONENGINE_ORC_OBJECTLINKINGLAYER_H #ifdef __GNUC__ #pragma GCC diagnostic pop #endif