diff options
Diffstat (limited to 'contrib/llvm-project/llvm/include/llvm/ExecutionEngine')
52 files changed, 3473 insertions, 3459 deletions
diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/ExecutionEngine.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/ExecutionEngine.h index 2562da7cf60b..2e386518f0bf 100644 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/ExecutionEngine.h +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/ExecutionEngine.h @@ -142,11 +142,6 @@ protected: std::shared_ptr<LegacyJITSymbolResolver> SR, std::unique_ptr<TargetMachine> TM); - static ExecutionEngine *(*OrcMCJITReplacementCtor)( - std::string *ErrorStr, std::shared_ptr<MCJITMemoryManager> MM, - std::shared_ptr<LegacyJITSymbolResolver> SR, - std::unique_ptr<TargetMachine> TM); - static ExecutionEngine *(*InterpCtor)(std::unique_ptr<Module> M, std::string *ErrorStr); @@ -552,7 +547,6 @@ private: std::string MCPU; SmallVector<std::string, 4> MAttrs; bool VerifyModules; - bool UseOrcMCJITReplacement; bool EmulatedTLS = true; public: @@ -648,17 +642,6 @@ public: return *this; } - // Use OrcMCJITReplacement instead of MCJIT. Off by default. - LLVM_ATTRIBUTE_DEPRECATED( - inline void setUseOrcMCJITReplacement(bool UseOrcMCJITReplacement), - "ORCv1 utilities (including OrcMCJITReplacement) are deprecated. Please " - "use ORCv2/LLJIT instead (see docs/ORCv2.rst)"); - - void setUseOrcMCJITReplacement(ORCv1DeprecationAcknowledgement, - bool UseOrcMCJITReplacement) { - this->UseOrcMCJITReplacement = UseOrcMCJITReplacement; - } - void setEmulatedTLS(bool EmulatedTLS) { this->EmulatedTLS = EmulatedTLS; } @@ -679,10 +662,6 @@ public: ExecutionEngine *create(TargetMachine *TM); }; -void EngineBuilder::setUseOrcMCJITReplacement(bool UseOrcMCJITReplacement) { - this->UseOrcMCJITReplacement = UseOrcMCJITReplacement; -} - // Create wrappers for C Binding types (see CBindingWrapping.h). DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ExecutionEngine, LLVMExecutionEngineRef) diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITEventListener.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITEventListener.h index 606b6f7cc128..4eefd993de2b 100644 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITEventListener.h +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITEventListener.h @@ -20,7 +20,6 @@ #include "llvm/IR/DebugLoc.h" #include "llvm/Support/CBindingWrapping.h" #include <cstdint> -#include <vector> namespace llvm { diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/EHFrameSupport.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/EHFrameSupport.h index 72687682f606..ec78d9db40b6 100644 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/EHFrameSupport.h +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/EHFrameSupport.h @@ -21,14 +21,6 @@ namespace llvm { namespace jitlink { -/// Registers all FDEs in the given eh-frame section with the current process. -Error registerEHFrameSection(const void *EHFrameSectionAddr, - size_t EHFrameSectionSize); - -/// Deregisters all FDEs in the given eh-frame section with the current process. -Error deregisterEHFrameSection(const void *EHFrameSectionAddr, - size_t EHFrameSectionSize); - /// Supports registration/deregistration of EH-frames in a target process. class EHFrameRegistrar { public: @@ -42,32 +34,11 @@ public: /// Registers / Deregisters EH-frames in the current process. class InProcessEHFrameRegistrar final : public EHFrameRegistrar { public: - /// Get a reference to the InProcessEHFrameRegistrar singleton. - static InProcessEHFrameRegistrar &getInstance(); - - InProcessEHFrameRegistrar(const InProcessEHFrameRegistrar &) = delete; - InProcessEHFrameRegistrar & - operator=(const InProcessEHFrameRegistrar &) = delete; - - InProcessEHFrameRegistrar(InProcessEHFrameRegistrar &&) = delete; - InProcessEHFrameRegistrar &operator=(InProcessEHFrameRegistrar &&) = delete; - Error registerEHFrames(JITTargetAddress EHFrameSectionAddr, - size_t EHFrameSectionSize) override { - return registerEHFrameSection( - jitTargetAddressToPointer<void *>(EHFrameSectionAddr), - EHFrameSectionSize); - } + size_t EHFrameSectionSize) override; Error deregisterEHFrames(JITTargetAddress EHFrameSectionAddr, - size_t EHFrameSectionSize) override { - return deregisterEHFrameSection( - jitTargetAddressToPointer<void *>(EHFrameSectionAddr), - EHFrameSectionSize); - } - -private: - InProcessEHFrameRegistrar(); + size_t EHFrameSectionSize) override; }; using StoreFrameRangeFunction = diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/ELF.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/ELF.h index 9f6ea5271f4b..8912f3a2db45 100644 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/ELF.h +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/ELF.h @@ -19,11 +19,20 @@ namespace llvm { namespace jitlink { -/// jit-link the given ObjBuffer, which must be a ELF object file. +/// Create a LinkGraph from an ELF relocatable object. +/// +/// Note: The graph does not take ownership of the underlying buffer, nor copy +/// its contents. The caller is responsible for ensuring that the object buffer +/// outlives the graph. +Expected<std::unique_ptr<LinkGraph>> +createLinkGraphFromELFObject(MemoryBufferRef ObjectBuffer); + +/// Link the given graph. /// /// Uses conservative defaults for GOT and stub handling based on the target /// platform. -void jitLink_ELF(std::unique_ptr<JITLinkContext> Ctx); +void link_ELF(std::unique_ptr<LinkGraph> G, + std::unique_ptr<JITLinkContext> Ctx); } // end namespace jitlink } // end namespace llvm diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/ELF_x86_64.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/ELF_x86_64.h index 7860088f3569..1423b0c30b2a 100644 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/ELF_x86_64.h +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/ELF_x86_64.h @@ -44,8 +44,20 @@ enum ELFX86RelocationKind : Edge::Kind { } // end namespace ELF_x86_64_Edges +/// Create a LinkGraph from an ELF/x86-64 relocatable object. +/// +/// Note: The graph does not take ownership of the underlying buffer, nor copy +/// its contents. The caller is responsible for ensuring that the object buffer +/// outlives the graph. +Expected<std::unique_ptr<LinkGraph>> +createLinkGraphFromELFObject_x86_64(MemoryBufferRef ObjectBuffer); + /// jit-link the given object buffer, which must be a ELF x86-64 object file. -void jitLink_ELF_x86_64(std::unique_ptr<JITLinkContext> Ctx); +void link_ELF_x86_64(std::unique_ptr<LinkGraph> G, + std::unique_ptr<JITLinkContext> Ctx); + +/// Return the string name of the given ELF x86-64 edge kind. +StringRef getELFX86RelocationKindName(Edge::Kind R); } // end namespace jitlink } // end namespace llvm diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h index 76f9dea4160f..e8c0e28b83aa 100644 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h @@ -395,6 +395,10 @@ public: return Name; } + /// Rename this symbol. The client is responsible for updating scope and + /// linkage if this name-change requires it. + void setName(StringRef Name) { this->Name = Name; } + /// Returns true if this Symbol has content (potentially) defined within this /// object file (i.e. is anything but an external or absolute symbol). bool isDefined() const { @@ -782,21 +786,48 @@ public: Section::const_block_iterator, const Block *, getSectionConstBlocks>; - LinkGraph(std::string Name, unsigned PointerSize, + LinkGraph(std::string Name, const Triple &TT, unsigned PointerSize, support::endianness Endianness) - : Name(std::move(Name)), PointerSize(PointerSize), + : Name(std::move(Name)), TT(TT), PointerSize(PointerSize), Endianness(Endianness) {} /// Returns the name of this graph (usually the name of the original /// underlying MemoryBuffer). const std::string &getName() { return Name; } + /// Returns the target triple for this Graph. + const Triple &getTargetTriple() const { return TT; } + /// Returns the pointer size for use in this graph. unsigned getPointerSize() const { return PointerSize; } /// Returns the endianness of content in this graph. support::endianness getEndianness() const { return Endianness; } + /// Allocate a copy of the given string using the LinkGraph's allocator. + /// This can be useful when renaming symbols or adding new content to the + /// graph. + StringRef allocateString(StringRef Source) { + auto *AllocatedBuffer = Allocator.Allocate<char>(Source.size()); + llvm::copy(Source, AllocatedBuffer); + return StringRef(AllocatedBuffer, Source.size()); + } + + /// Allocate a copy of the given string using the LinkGraph's allocator. + /// This can be useful when renaming symbols or adding new content to the + /// graph. + /// + /// Note: This Twine-based overload requires an extra string copy and an + /// extra heap allocation for large strings. The StringRef overload should + /// be preferred where possible. + StringRef allocateString(Twine Source) { + SmallString<256> TmpBuffer; + auto SourceStr = Source.toStringRef(TmpBuffer); + auto *AllocatedBuffer = Allocator.Allocate<char>(SourceStr.size()); + llvm::copy(SourceStr, AllocatedBuffer); + return StringRef(AllocatedBuffer, SourceStr.size()); + } + /// Create a section with the given name, protection flags, and alignment. Section &createSection(StringRef Name, sys::Memory::ProtectionFlags Prot) { std::unique_ptr<Section> Sec(new Section(Name, Prot, Sections.size())); @@ -959,7 +990,7 @@ public: Section &Sec = Sym.getBlock().getSection(); Sec.removeSymbol(Sym); } - Sym.makeExternal(createAddressable(false)); + Sym.makeExternal(createAddressable(0, false)); ExternalSymbols.insert(&Sym); } @@ -1019,6 +1050,7 @@ private: BumpPtrAllocator Allocator; std::string Name; + Triple TT; unsigned PointerSize; support::endianness Endianness; SectionList Sections; @@ -1191,15 +1223,31 @@ struct PassConfiguration { /// Notable use cases: Building GOT, stub, and TLV symbols. LinkGraphPassList PostPrunePasses; + /// Post-allocation passes. + /// + /// These passes are called on the graph after memory has been allocated and + /// defined nodes have been assigned their final addresses, but before the + /// context has been notified of these addresses. At this point externals + /// have not been resolved, and symbol content has not yet been copied into + /// working memory. + /// + /// Notable use cases: Setting up data structures associated with addresses + /// of defined symbols (e.g. a mapping of __dso_handle to JITDylib* for the + /// JIT runtime) -- using a PostAllocationPass for this ensures that the + /// data structures are in-place before any query for resolved symbols + /// can complete. + LinkGraphPassList PostAllocationPasses; + /// Pre-fixup passes. /// /// These passes are called on the graph after memory has been allocated, - /// content copied into working memory, and nodes have been assigned their - /// final addresses. + /// content copied into working memory, and all nodes (including externals) + /// have been assigned their final addresses, but before any fixups have been + /// applied. /// /// Notable use cases: Late link-time optimizations like GOT and stub /// elimination. - LinkGraphPassList PostAllocationPasses; + LinkGraphPassList PreFixupPasses; /// Post-fixup passes. /// @@ -1255,16 +1303,18 @@ class JITLinkContext { public: using LookupMap = DenseMap<StringRef, SymbolLookupFlags>; + /// Create a JITLinkContext. + JITLinkContext(const JITLinkDylib *JD) : JD(JD) {} + /// Destroy a JITLinkContext. virtual ~JITLinkContext(); + /// Return the JITLinkDylib that this link is targeting, if any. + const JITLinkDylib *getJITLinkDylib() const { return JD; } + /// Return the MemoryManager to be used for this link. virtual JITLinkMemoryManager &getMemoryManager() = 0; - /// Returns a StringRef for the object buffer. - /// This method can not be called once takeObjectBuffer has been called. - virtual MemoryBufferRef getObjectBuffer() const = 0; - /// Notify this context that linking failed. /// Called by JITLink if linking cannot be completed. virtual void notifyFailed(Error Err) = 0; @@ -1279,7 +1329,11 @@ public: /// their final memory locations in the target process. At this point the /// LinkGraph can be inspected to build a symbol table, however the block /// content will not generally have been copied to the target location yet. - virtual void notifyResolved(LinkGraph &G) = 0; + /// + /// If the client detects an error in the LinkGraph state (e.g. unexpected or + /// missing symbols) they may return an error here. The error will be + /// propagated to notifyFailed and the linker will bail out. + virtual Error notifyResolved(LinkGraph &G) = 0; /// Called by JITLink to notify the context that the object has been /// finalized (i.e. emitted to memory and memory permissions set). If all of @@ -1305,16 +1359,25 @@ public: /// Called by JITLink to modify the pass pipeline prior to linking. /// The default version performs no modification. virtual Error modifyPassConfig(const Triple &TT, PassConfiguration &Config); + +private: + const JITLinkDylib *JD = nullptr; }; /// Marks all symbols in a graph live. This can be used as a default, /// conservative mark-live implementation. Error markAllSymbolsLive(LinkGraph &G); -/// Basic JITLink implementation. +/// Create a LinkGraph from the given object buffer. /// -/// This function will use sensible defaults for GOT and Stub handling. -void jitLink(std::unique_ptr<JITLinkContext> Ctx); +/// Note: The graph does not take ownership of the underlying buffer, nor copy +/// its contents. The caller is responsible for ensuring that the object buffer +/// outlives the graph. +Expected<std::unique_ptr<LinkGraph>> +createLinkGraphFromObject(MemoryBufferRef ObjectBuffer); + +/// Link the given graph. +void link(std::unique_ptr<LinkGraph> G, std::unique_ptr<JITLinkContext> Ctx); } // end namespace jitlink } // end namespace llvm diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/JITLinkDylib.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/JITLinkDylib.h new file mode 100644 index 000000000000..2aa88cb50074 --- /dev/null +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/JITLinkDylib.h @@ -0,0 +1,24 @@ +//===-- JITLinkDylib.h - JITLink Dylib type ---------------------*- 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 +// +//===----------------------------------------------------------------------===// +// +// Defines the JITLinkDylib API. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_JITLINK_JITLINKDYLIB_H +#define LLVM_EXECUTIONENGINE_JITLINK_JITLINKDYLIB_H + +namespace llvm { +namespace jitlink { + +class JITLinkDylib {}; + +} // end namespace jitlink +} // end namespace llvm + +#endif // LLVM_EXECUTIONENGINE_JITLINK_JITLINKDYLIB_H diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h index 0c8514a60a50..cee7d6b09c48 100644 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h @@ -14,10 +14,11 @@ #define LLVM_EXECUTIONENGINE_JITLINK_JITLINKMEMORYMANAGER_H #include "llvm/ADT/DenseMap.h" +#include "llvm/ExecutionEngine/JITLink/JITLinkDylib.h" #include "llvm/ExecutionEngine/JITSymbol.h" #include "llvm/Support/Error.h" -#include "llvm/Support/Memory.h" #include "llvm/Support/MSVCErrorWorkarounds.h" +#include "llvm/Support/Memory.h" #include <cstdint> #include <future> @@ -93,18 +94,28 @@ public: virtual ~JITLinkMemoryManager(); /// Create an Allocation object. + /// + /// The JD argument represents the target JITLinkDylib, and can be used by + /// JITLinkMemoryManager implementers to manage per-dylib allocation pools + /// (e.g. one pre-reserved address space slab per dylib to ensure that all + /// allocations for the dylib are within a certain range). The JD argument + /// may be null (representing an allocation not associated with any + /// JITDylib. + /// + /// The request argument describes the segment sizes and permisssions being + /// requested. virtual Expected<std::unique_ptr<Allocation>> - allocate(const SegmentsRequestMap &Request) = 0; + allocate(const JITLinkDylib *JD, const SegmentsRequestMap &Request) = 0; }; /// A JITLinkMemoryManager that allocates in-process memory. class InProcessMemoryManager : public JITLinkMemoryManager { public: Expected<std::unique_ptr<Allocation>> - allocate(const SegmentsRequestMap &Request) override; + allocate(const JITLinkDylib *JD, const SegmentsRequestMap &Request) override; }; } // end namespace jitlink } // end namespace llvm -#endif // LLVM_EXECUTIONENGINE_JITLINK_JITLINK_H +#endif // LLVM_EXECUTIONENGINE_JITLINK_JITLINKMEMORYMANAGER_H diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/MachO.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/MachO.h index 7facb657a51c..b8432c4d26c6 100644 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/MachO.h +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/MachO.h @@ -18,11 +18,20 @@ namespace llvm { namespace jitlink { +/// Create a LinkGraph from a MachO relocatable object. +/// +/// Note: The graph does not take ownership of the underlying buffer, nor copy +/// its contents. The caller is responsible for ensuring that the object buffer +/// outlives the graph. +Expected<std::unique_ptr<LinkGraph>> +createLinkGraphFromMachOObject(MemoryBufferRef ObjectBuffer); + /// jit-link the given ObjBuffer, which must be a MachO object file. /// /// Uses conservative defaults for GOT and stub handling based on the target /// platform. -void jitLink_MachO(std::unique_ptr<JITLinkContext> Ctx); +void link_MachO(std::unique_ptr<LinkGraph> G, + std::unique_ptr<JITLinkContext> Ctx); } // end namespace jitlink } // end namespace llvm diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/MachO_arm64.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/MachO_arm64.h index d70b545fff86..c6aed2b60eac 100644 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/MachO_arm64.h +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/MachO_arm64.h @@ -40,6 +40,14 @@ enum MachOARM64RelocationKind : Edge::Kind { } // namespace MachO_arm64_Edges +/// Create a LinkGraph from a MachO/arm64 relocatable object. +/// +/// Note: The graph does not take ownership of the underlying buffer, nor copy +/// its contents. The caller is responsible for ensuring that the object buffer +/// outlives the graph. +Expected<std::unique_ptr<LinkGraph>> +createLinkGraphFromMachOObject_arm64(MemoryBufferRef ObjectBuffer); + /// jit-link the given object buffer, which must be a MachO arm64 object file. /// /// If PrePrunePasses is empty then a default mark-live pass will be inserted @@ -49,7 +57,8 @@ enum MachOARM64RelocationKind : Edge::Kind { /// If PostPrunePasses is empty then a default GOT-and-stubs insertion pass will /// be inserted. If PostPrunePasses is not empty then the caller is responsible /// for including a pass to insert GOT and stub edges. -void jitLink_MachO_arm64(std::unique_ptr<JITLinkContext> Ctx); +void link_MachO_arm64(std::unique_ptr<LinkGraph> G, + std::unique_ptr<JITLinkContext> Ctx); /// Return the string name of the given MachO arm64 edge kind. StringRef getMachOARM64RelocationKindName(Edge::Kind R); diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/MachO_x86_64.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/MachO_x86_64.h index 27fcdf4fa990..66c53d8c8291 100644 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/MachO_x86_64.h +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITLink/MachO_x86_64.h @@ -45,7 +45,15 @@ enum MachOX86RelocationKind : Edge::Kind { } // namespace MachO_x86_64_Edges -/// jit-link the given object buffer, which must be a MachO x86-64 object file. +/// Create a LinkGraph from a MachO/x86-64 relocatable object. +/// +/// Note: The graph does not take ownership of the underlying buffer, nor copy +/// its contents. The caller is responsible for ensuring that the object buffer +/// outlives the graph. +Expected<std::unique_ptr<LinkGraph>> +createLinkGraphFromMachOObject_x86_64(MemoryBufferRef ObjectBuffer); + +/// jit-link the given LinkGraph. /// /// If PrePrunePasses is empty then a default mark-live pass will be inserted /// that will mark all exported atoms live. If PrePrunePasses is not empty, the @@ -54,7 +62,8 @@ enum MachOX86RelocationKind : Edge::Kind { /// If PostPrunePasses is empty then a default GOT-and-stubs insertion pass will /// be inserted. If PostPrunePasses is not empty then the caller is responsible /// for including a pass to insert GOT and stub edges. -void jitLink_MachO_x86_64(std::unique_ptr<JITLinkContext> Ctx); +void link_MachO_x86_64(std::unique_ptr<LinkGraph> G, + std::unique_ptr<JITLinkContext> Ctx); /// Return the string name of the given MachO x86-64 edge kind. StringRef getMachOX86RelocationKindName(Edge::Kind R); diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITSymbol.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITSymbol.h index 6f0030a18f47..9bbdd21f77de 100644 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITSymbol.h +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/JITSymbol.h @@ -429,7 +429,7 @@ public: virtual JITSymbol findSymbol(const std::string &Name) = 0; private: - virtual void anchor(); + void anchor() override; }; } // end namespace llvm diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h index 9ecc0464dec1..91b12fd2277a 100644 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h @@ -20,12 +20,10 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ExecutionEngine/JITSymbol.h" #include "llvm/ExecutionEngine/Orc/IndirectionUtils.h" -#include "llvm/ExecutionEngine/Orc/LambdaResolver.h" #include "llvm/ExecutionEngine/Orc/Layer.h" #include "llvm/ExecutionEngine/Orc/LazyReexports.h" -#include "llvm/ExecutionEngine/Orc/Legacy.h" -#include "llvm/ExecutionEngine/Orc/OrcError.h" #include "llvm/ExecutionEngine/Orc/Speculation.h" +#include "llvm/ExecutionEngine/Orc/Shared/OrcError.h" #include "llvm/ExecutionEngine/RuntimeDyld.h" #include "llvm/IR/Attributes.h" #include "llvm/IR/Constant.h" @@ -96,7 +94,8 @@ public: /// Emits the given module. This should not be called by clients: it will be /// called by the JIT when a definition added via the add method is requested. - void emit(MaterializationResponsibility R, ThreadSafeModule TSM) override; + void emit(std::unique_ptr<MaterializationResponsibility> R, + ThreadSafeModule TSM) override; private: struct PerDylibResources { @@ -120,7 +119,8 @@ private: void expandPartition(GlobalValueSet &Partition); - void emitPartition(MaterializationResponsibility R, ThreadSafeModule TSM, + void emitPartition(std::unique_ptr<MaterializationResponsibility> R, + ThreadSafeModule TSM, IRMaterializationUnit::SymbolNameToDefinitionMap Defs); mutable std::mutex CODLayerMutex; @@ -134,635 +134,6 @@ private: ImplSymbolMap *AliaseeImpls = nullptr; }; -/// Compile-on-demand layer. -/// -/// When a module is added to this layer a stub is created for each of its -/// function definitions. The stubs and other global values are immediately -/// added to the layer below. When a stub is called it triggers the extraction -/// of the function body from the original module. The extracted body is then -/// compiled and executed. -template <typename BaseLayerT, - typename CompileCallbackMgrT = JITCompileCallbackManager, - typename IndirectStubsMgrT = IndirectStubsManager> -class LegacyCompileOnDemandLayer { -private: - template <typename MaterializerFtor> - class LambdaMaterializer final : public ValueMaterializer { - public: - LambdaMaterializer(MaterializerFtor M) : M(std::move(M)) {} - - Value *materialize(Value *V) final { return M(V); } - - private: - MaterializerFtor M; - }; - - template <typename MaterializerFtor> - LambdaMaterializer<MaterializerFtor> - createLambdaMaterializer(MaterializerFtor M) { - return LambdaMaterializer<MaterializerFtor>(std::move(M)); - } - - // Provide type-erasure for the Modules and MemoryManagers. - template <typename ResourceT> - class ResourceOwner { - public: - ResourceOwner() = default; - ResourceOwner(const ResourceOwner &) = delete; - ResourceOwner &operator=(const ResourceOwner &) = delete; - virtual ~ResourceOwner() = default; - - virtual ResourceT& getResource() const = 0; - }; - - template <typename ResourceT, typename ResourcePtrT> - class ResourceOwnerImpl : public ResourceOwner<ResourceT> { - public: - ResourceOwnerImpl(ResourcePtrT ResourcePtr) - : ResourcePtr(std::move(ResourcePtr)) {} - - ResourceT& getResource() const override { return *ResourcePtr; } - - private: - ResourcePtrT ResourcePtr; - }; - - template <typename ResourceT, typename ResourcePtrT> - std::unique_ptr<ResourceOwner<ResourceT>> - wrapOwnership(ResourcePtrT ResourcePtr) { - using RO = ResourceOwnerImpl<ResourceT, ResourcePtrT>; - return std::make_unique<RO>(std::move(ResourcePtr)); - } - - struct LogicalDylib { - struct SourceModuleEntry { - std::unique_ptr<Module> SourceMod; - std::set<Function*> StubsToClone; - }; - - using SourceModulesList = std::vector<SourceModuleEntry>; - using SourceModuleHandle = typename SourceModulesList::size_type; - - LogicalDylib() = default; - - LogicalDylib(VModuleKey K, std::shared_ptr<SymbolResolver> BackingResolver, - std::unique_ptr<IndirectStubsMgrT> StubsMgr) - : K(std::move(K)), BackingResolver(std::move(BackingResolver)), - StubsMgr(std::move(StubsMgr)) {} - - SourceModuleHandle addSourceModule(std::unique_ptr<Module> M) { - SourceModuleHandle H = SourceModules.size(); - SourceModules.push_back(SourceModuleEntry()); - SourceModules.back().SourceMod = std::move(M); - return H; - } - - Module& getSourceModule(SourceModuleHandle H) { - return *SourceModules[H].SourceMod; - } - - std::set<Function*>& getStubsToClone(SourceModuleHandle H) { - return SourceModules[H].StubsToClone; - } - - JITSymbol findSymbol(BaseLayerT &BaseLayer, const std::string &Name, - bool ExportedSymbolsOnly) { - if (auto Sym = StubsMgr->findStub(Name, ExportedSymbolsOnly)) - return Sym; - for (auto BLK : BaseLayerVModuleKeys) - if (auto Sym = BaseLayer.findSymbolIn(BLK, Name, ExportedSymbolsOnly)) - return Sym; - else if (auto Err = Sym.takeError()) - return std::move(Err); - return nullptr; - } - - Error removeModulesFromBaseLayer(BaseLayerT &BaseLayer) { - for (auto &BLK : BaseLayerVModuleKeys) - if (auto Err = BaseLayer.removeModule(BLK)) - return Err; - return Error::success(); - } - - VModuleKey K; - std::shared_ptr<SymbolResolver> BackingResolver; - std::unique_ptr<IndirectStubsMgrT> StubsMgr; - SymbolLinkagePromoter PromoteSymbols; - SourceModulesList SourceModules; - std::vector<VModuleKey> BaseLayerVModuleKeys; - }; - -public: - - /// Module partitioning functor. - using PartitioningFtor = std::function<std::set<Function*>(Function&)>; - - /// Builder for IndirectStubsManagers. - using IndirectStubsManagerBuilderT = - std::function<std::unique_ptr<IndirectStubsMgrT>()>; - - using SymbolResolverGetter = - std::function<std::shared_ptr<SymbolResolver>(VModuleKey K)>; - - using SymbolResolverSetter = - std::function<void(VModuleKey K, std::shared_ptr<SymbolResolver> R)>; - - /// Construct a compile-on-demand layer instance. - LLVM_ATTRIBUTE_DEPRECATED( - LegacyCompileOnDemandLayer( - ExecutionSession &ES, BaseLayerT &BaseLayer, - SymbolResolverGetter GetSymbolResolver, - SymbolResolverSetter SetSymbolResolver, PartitioningFtor Partition, - CompileCallbackMgrT &CallbackMgr, - IndirectStubsManagerBuilderT CreateIndirectStubsManager, - bool CloneStubsIntoPartitions = true), - "ORCv1 layers (layers with the 'Legacy' prefix) are deprecated. Please " - "use " - "the ORCv2 LegacyCompileOnDemandLayer instead"); - - /// Legacy layer constructor with deprecation acknowledgement. - LegacyCompileOnDemandLayer( - ORCv1DeprecationAcknowledgement, ExecutionSession &ES, - BaseLayerT &BaseLayer, SymbolResolverGetter GetSymbolResolver, - SymbolResolverSetter SetSymbolResolver, PartitioningFtor Partition, - CompileCallbackMgrT &CallbackMgr, - IndirectStubsManagerBuilderT CreateIndirectStubsManager, - bool CloneStubsIntoPartitions = true) - : ES(ES), BaseLayer(BaseLayer), - GetSymbolResolver(std::move(GetSymbolResolver)), - SetSymbolResolver(std::move(SetSymbolResolver)), - Partition(std::move(Partition)), CompileCallbackMgr(CallbackMgr), - CreateIndirectStubsManager(std::move(CreateIndirectStubsManager)), - CloneStubsIntoPartitions(CloneStubsIntoPartitions) {} - - ~LegacyCompileOnDemandLayer() { - // FIXME: Report error on log. - while (!LogicalDylibs.empty()) - consumeError(removeModule(LogicalDylibs.begin()->first)); - } - - /// Add a module to the compile-on-demand layer. - Error addModule(VModuleKey K, std::unique_ptr<Module> M) { - - assert(!LogicalDylibs.count(K) && "VModuleKey K already in use"); - auto I = LogicalDylibs.insert( - LogicalDylibs.end(), - std::make_pair(K, LogicalDylib(K, GetSymbolResolver(K), - CreateIndirectStubsManager()))); - - return addLogicalModule(I->second, std::move(M)); - } - - /// Add extra modules to an existing logical module. - Error addExtraModule(VModuleKey K, std::unique_ptr<Module> M) { - return addLogicalModule(LogicalDylibs[K], std::move(M)); - } - - /// Remove the module represented by the given key. - /// - /// This will remove all modules in the layers below that were derived from - /// the module represented by K. - Error removeModule(VModuleKey K) { - auto I = LogicalDylibs.find(K); - assert(I != LogicalDylibs.end() && "VModuleKey K not valid here"); - auto Err = I->second.removeModulesFromBaseLayer(BaseLayer); - LogicalDylibs.erase(I); - return Err; - } - - /// Search for the given named symbol. - /// @param Name The name of the symbol to search for. - /// @param ExportedSymbolsOnly If true, search only for exported symbols. - /// @return A handle for the given named symbol, if it exists. - JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly) { - for (auto &KV : LogicalDylibs) { - if (auto Sym = KV.second.StubsMgr->findStub(Name, ExportedSymbolsOnly)) - return Sym; - if (auto Sym = - findSymbolIn(KV.first, std::string(Name), ExportedSymbolsOnly)) - return Sym; - else if (auto Err = Sym.takeError()) - return std::move(Err); - } - return BaseLayer.findSymbol(std::string(Name), ExportedSymbolsOnly); - } - - /// Get the address of a symbol provided by this layer, or some layer - /// below this one. - JITSymbol findSymbolIn(VModuleKey K, const std::string &Name, - bool ExportedSymbolsOnly) { - assert(LogicalDylibs.count(K) && "VModuleKey K is not valid here"); - return LogicalDylibs[K].findSymbol(BaseLayer, Name, ExportedSymbolsOnly); - } - - /// Update the stub for the given function to point at FnBodyAddr. - /// This can be used to support re-optimization. - /// @return true if the function exists and the stub is updated, false - /// otherwise. - // - // FIXME: We should track and free associated resources (unused compile - // callbacks, uncompiled IR, and no-longer-needed/reachable function - // implementations). - Error updatePointer(std::string FuncName, JITTargetAddress FnBodyAddr) { - //Find out which logical dylib contains our symbol - auto LDI = LogicalDylibs.begin(); - for (auto LDE = LogicalDylibs.end(); LDI != LDE; ++LDI) { - if (auto LMResources = - LDI->getLogicalModuleResourcesForSymbol(FuncName, false)) { - Module &SrcM = LMResources->SourceModule->getResource(); - std::string CalledFnName = mangle(FuncName, SrcM.getDataLayout()); - if (auto Err = LMResources->StubsMgr->updatePointer(CalledFnName, - FnBodyAddr)) - return Err; - return Error::success(); - } - } - return make_error<JITSymbolNotFound>(FuncName); - } - -private: - Error addLogicalModule(LogicalDylib &LD, std::unique_ptr<Module> SrcMPtr) { - - // Rename anonymous globals and promote linkage to ensure that everything - // will resolve properly after we partition SrcM. - LD.PromoteSymbols(*SrcMPtr); - - // Create a logical module handle for SrcM within the logical dylib. - Module &SrcM = *SrcMPtr; - auto LMId = LD.addSourceModule(std::move(SrcMPtr)); - - // Create stub functions. - const DataLayout &DL = SrcM.getDataLayout(); - - typename IndirectStubsMgrT::StubInitsMap StubInits; - for (auto &F : SrcM) { - // Skip declarations. - if (F.isDeclaration()) - continue; - - // Skip weak functions for which we already have definitions. - auto MangledName = mangle(F.getName(), DL); - if (F.hasWeakLinkage() || F.hasLinkOnceLinkage()) { - if (auto Sym = LD.findSymbol(BaseLayer, MangledName, false)) - continue; - else if (auto Err = Sym.takeError()) - return Err; - } - - // Record all functions defined by this module. - if (CloneStubsIntoPartitions) - LD.getStubsToClone(LMId).insert(&F); - - // Create a callback, associate it with the stub for the function, - // and set the compile action to compile the partition containing the - // function. - auto CompileAction = [this, &LD, LMId, &F]() -> JITTargetAddress { - if (auto FnImplAddrOrErr = this->extractAndCompile(LD, LMId, F)) - return *FnImplAddrOrErr; - else { - // FIXME: Report error, return to 'abort' or something similar. - consumeError(FnImplAddrOrErr.takeError()); - return 0; - } - }; - if (auto CCAddr = - CompileCallbackMgr.getCompileCallback(std::move(CompileAction))) - StubInits[MangledName] = - std::make_pair(*CCAddr, JITSymbolFlags::fromGlobalValue(F)); - else - return CCAddr.takeError(); - } - - if (auto Err = LD.StubsMgr->createStubs(StubInits)) - return Err; - - // If this module doesn't contain any globals, aliases, or module flags then - // we can bail out early and avoid the overhead of creating and managing an - // empty globals module. - if (SrcM.global_empty() && SrcM.alias_empty() && - !SrcM.getModuleFlagsMetadata()) - return Error::success(); - - // Create the GlobalValues module. - auto GVsM = std::make_unique<Module>((SrcM.getName() + ".globals").str(), - SrcM.getContext()); - GVsM->setDataLayout(DL); - - ValueToValueMapTy VMap; - - // Clone global variable decls. - for (auto &GV : SrcM.globals()) - if (!GV.isDeclaration() && !VMap.count(&GV)) - cloneGlobalVariableDecl(*GVsM, GV, &VMap); - - // And the aliases. - for (auto &A : SrcM.aliases()) - if (!VMap.count(&A)) - cloneGlobalAliasDecl(*GVsM, A, VMap); - - // Clone the module flags. - cloneModuleFlagsMetadata(*GVsM, SrcM, VMap); - - // Now we need to clone the GV and alias initializers. - - // Initializers may refer to functions declared (but not defined) in this - // module. Build a materializer to clone decls on demand. - auto Materializer = createLambdaMaterializer( - [&LD, &GVsM](Value *V) -> Value* { - if (auto *F = dyn_cast<Function>(V)) { - // Decls in the original module just get cloned. - if (F->isDeclaration()) - return cloneFunctionDecl(*GVsM, *F); - - // Definitions in the original module (which we have emitted stubs - // for at this point) get turned into a constant alias to the stub - // instead. - const DataLayout &DL = GVsM->getDataLayout(); - std::string FName = mangle(F->getName(), DL); - unsigned PtrBitWidth = DL.getPointerTypeSizeInBits(F->getType()); - JITTargetAddress StubAddr = - LD.StubsMgr->findStub(FName, false).getAddress(); - - ConstantInt *StubAddrCI = - ConstantInt::get(GVsM->getContext(), APInt(PtrBitWidth, StubAddr)); - Constant *Init = ConstantExpr::getCast(Instruction::IntToPtr, - StubAddrCI, F->getType()); - return GlobalAlias::create(F->getFunctionType(), - F->getType()->getAddressSpace(), - F->getLinkage(), F->getName(), - Init, GVsM.get()); - } - // else.... - return nullptr; - }); - - // Clone the global variable initializers. - for (auto &GV : SrcM.globals()) - if (!GV.isDeclaration()) - moveGlobalVariableInitializer(GV, VMap, &Materializer); - - // Clone the global alias initializers. - for (auto &A : SrcM.aliases()) { - auto *NewA = cast<GlobalAlias>(VMap[&A]); - assert(NewA && "Alias not cloned?"); - Value *Init = MapValue(A.getAliasee(), VMap, RF_None, nullptr, - &Materializer); - NewA->setAliasee(cast<Constant>(Init)); - } - - // Build a resolver for the globals module and add it to the base layer. - auto LegacyLookup = [this, &LD](StringRef Name) -> JITSymbol { - if (auto Sym = LD.StubsMgr->findStub(Name, false)) - return Sym; - - if (auto Sym = LD.findSymbol(BaseLayer, std::string(Name), false)) - return Sym; - else if (auto Err = Sym.takeError()) - return std::move(Err); - - return nullptr; - }; - - auto GVsResolver = createSymbolResolver( - [&LD, LegacyLookup](const SymbolNameSet &Symbols) { - auto RS = getResponsibilitySetWithLegacyFn(Symbols, LegacyLookup); - - if (!RS) { - logAllUnhandledErrors( - RS.takeError(), errs(), - "CODLayer/GVsResolver responsibility set lookup failed: "); - return SymbolNameSet(); - } - - if (RS->size() == Symbols.size()) - return *RS; - - SymbolNameSet NotFoundViaLegacyLookup; - for (auto &S : Symbols) - if (!RS->count(S)) - NotFoundViaLegacyLookup.insert(S); - auto RS2 = - LD.BackingResolver->getResponsibilitySet(NotFoundViaLegacyLookup); - - for (auto &S : RS2) - (*RS).insert(S); - - return *RS; - }, - [this, &LD, - LegacyLookup](std::shared_ptr<AsynchronousSymbolQuery> Query, - SymbolNameSet Symbols) { - auto NotFoundViaLegacyLookup = - lookupWithLegacyFn(ES, *Query, Symbols, LegacyLookup); - return LD.BackingResolver->lookup(Query, NotFoundViaLegacyLookup); - }); - - SetSymbolResolver(LD.K, std::move(GVsResolver)); - - if (auto Err = BaseLayer.addModule(LD.K, std::move(GVsM))) - return Err; - - LD.BaseLayerVModuleKeys.push_back(LD.K); - - return Error::success(); - } - - static std::string mangle(StringRef Name, const DataLayout &DL) { - std::string MangledName; - { - raw_string_ostream MangledNameStream(MangledName); - Mangler::getNameWithPrefix(MangledNameStream, Name, DL); - } - return MangledName; - } - - Expected<JITTargetAddress> - extractAndCompile(LogicalDylib &LD, - typename LogicalDylib::SourceModuleHandle LMId, - Function &F) { - Module &SrcM = LD.getSourceModule(LMId); - - // If F is a declaration we must already have compiled it. - if (F.isDeclaration()) - return 0; - - // Grab the name of the function being called here. - std::string CalledFnName = mangle(F.getName(), SrcM.getDataLayout()); - - JITTargetAddress CalledAddr = 0; - auto Part = Partition(F); - if (auto PartKeyOrErr = emitPartition(LD, LMId, Part)) { - auto &PartKey = *PartKeyOrErr; - for (auto *SubF : Part) { - std::string FnName = mangle(SubF->getName(), SrcM.getDataLayout()); - if (auto FnBodySym = BaseLayer.findSymbolIn(PartKey, FnName, false)) { - if (auto FnBodyAddrOrErr = FnBodySym.getAddress()) { - JITTargetAddress FnBodyAddr = *FnBodyAddrOrErr; - - // If this is the function we're calling record the address so we can - // return it from this function. - if (SubF == &F) - CalledAddr = FnBodyAddr; - - // Update the function body pointer for the stub. - if (auto EC = LD.StubsMgr->updatePointer(FnName, FnBodyAddr)) - return 0; - - } else - return FnBodyAddrOrErr.takeError(); - } else if (auto Err = FnBodySym.takeError()) - return std::move(Err); - else - llvm_unreachable("Function not emitted for partition"); - } - - LD.BaseLayerVModuleKeys.push_back(PartKey); - } else - return PartKeyOrErr.takeError(); - - return CalledAddr; - } - - template <typename PartitionT> - Expected<VModuleKey> - emitPartition(LogicalDylib &LD, - typename LogicalDylib::SourceModuleHandle LMId, - const PartitionT &Part) { - Module &SrcM = LD.getSourceModule(LMId); - - // Create the module. - std::string NewName(SrcM.getName()); - for (auto *F : Part) { - NewName += "."; - NewName += F->getName(); - } - - auto M = std::make_unique<Module>(NewName, SrcM.getContext()); - M->setDataLayout(SrcM.getDataLayout()); - ValueToValueMapTy VMap; - - auto Materializer = createLambdaMaterializer([&LD, &LMId, - &M](Value *V) -> Value * { - if (auto *GV = dyn_cast<GlobalVariable>(V)) - return cloneGlobalVariableDecl(*M, *GV); - - if (auto *F = dyn_cast<Function>(V)) { - // Check whether we want to clone an available_externally definition. - if (!LD.getStubsToClone(LMId).count(F)) - return cloneFunctionDecl(*M, *F); - - // Ok - we want an inlinable stub. For that to work we need a decl - // for the stub pointer. - auto *StubPtr = createImplPointer(*F->getType(), *M, - F->getName() + "$stub_ptr", nullptr); - auto *ClonedF = cloneFunctionDecl(*M, *F); - makeStub(*ClonedF, *StubPtr); - ClonedF->setLinkage(GlobalValue::AvailableExternallyLinkage); - ClonedF->addFnAttr(Attribute::AlwaysInline); - return ClonedF; - } - - if (auto *A = dyn_cast<GlobalAlias>(V)) { - auto *Ty = A->getValueType(); - if (Ty->isFunctionTy()) - return Function::Create(cast<FunctionType>(Ty), - GlobalValue::ExternalLinkage, A->getName(), - M.get()); - - return new GlobalVariable(*M, Ty, false, GlobalValue::ExternalLinkage, - nullptr, A->getName(), nullptr, - GlobalValue::NotThreadLocal, - A->getType()->getAddressSpace()); - } - - return nullptr; - }); - - // Create decls in the new module. - for (auto *F : Part) - cloneFunctionDecl(*M, *F, &VMap); - - // Move the function bodies. - for (auto *F : Part) - moveFunctionBody(*F, VMap, &Materializer); - - auto K = ES.allocateVModule(); - - auto LegacyLookup = [this, &LD](StringRef Name) -> JITSymbol { - return LD.findSymbol(BaseLayer, std::string(Name), false); - }; - - // Create memory manager and symbol resolver. - auto Resolver = createSymbolResolver( - [&LD, LegacyLookup](const SymbolNameSet &Symbols) { - auto RS = getResponsibilitySetWithLegacyFn(Symbols, LegacyLookup); - if (!RS) { - logAllUnhandledErrors( - RS.takeError(), errs(), - "CODLayer/SubResolver responsibility set lookup failed: "); - return SymbolNameSet(); - } - - if (RS->size() == Symbols.size()) - return *RS; - - SymbolNameSet NotFoundViaLegacyLookup; - for (auto &S : Symbols) - if (!RS->count(S)) - NotFoundViaLegacyLookup.insert(S); - - auto RS2 = - LD.BackingResolver->getResponsibilitySet(NotFoundViaLegacyLookup); - - for (auto &S : RS2) - (*RS).insert(S); - - return *RS; - }, - [this, &LD, LegacyLookup](std::shared_ptr<AsynchronousSymbolQuery> Q, - SymbolNameSet Symbols) { - auto NotFoundViaLegacyLookup = - lookupWithLegacyFn(ES, *Q, Symbols, LegacyLookup); - return LD.BackingResolver->lookup(Q, - std::move(NotFoundViaLegacyLookup)); - }); - SetSymbolResolver(K, std::move(Resolver)); - - if (auto Err = BaseLayer.addModule(std::move(K), std::move(M))) - return std::move(Err); - - return K; - } - - ExecutionSession &ES; - BaseLayerT &BaseLayer; - SymbolResolverGetter GetSymbolResolver; - SymbolResolverSetter SetSymbolResolver; - PartitioningFtor Partition; - CompileCallbackMgrT &CompileCallbackMgr; - IndirectStubsManagerBuilderT CreateIndirectStubsManager; - - std::map<VModuleKey, LogicalDylib> LogicalDylibs; - bool CloneStubsIntoPartitions; -}; - -template <typename BaseLayerT, typename CompileCallbackMgrT, - typename IndirectStubsMgrT> -LegacyCompileOnDemandLayer<BaseLayerT, CompileCallbackMgrT, IndirectStubsMgrT>:: - LegacyCompileOnDemandLayer( - ExecutionSession &ES, BaseLayerT &BaseLayer, - SymbolResolverGetter GetSymbolResolver, - SymbolResolverSetter SetSymbolResolver, PartitioningFtor Partition, - CompileCallbackMgrT &CallbackMgr, - IndirectStubsManagerBuilderT CreateIndirectStubsManager, - bool CloneStubsIntoPartitions) - : ES(ES), BaseLayer(BaseLayer), - GetSymbolResolver(std::move(GetSymbolResolver)), - SetSymbolResolver(std::move(SetSymbolResolver)), - Partition(std::move(Partition)), CompileCallbackMgr(CallbackMgr), - CreateIndirectStubsManager(std::move(CreateIndirectStubsManager)), - CloneStubsIntoPartitions(CloneStubsIntoPartitions) {} - } // end namespace orc } // end namespace llvm diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/CompileUtils.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/CompileUtils.h index 8376d163d57a..c7ba57228ab7 100644 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/CompileUtils.h +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/CompileUtils.h @@ -28,8 +28,6 @@ class TargetMachine; namespace orc { -class JITTargetMachineBuilder; - IRSymbolMapper::ManglingOptions irManglingOptionsFromTargetOptions(const TargetOptions &Opts); diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/Core.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/Core.h index a117acefd2d3..4a4b58ed32e3 100644 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/Core.h +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/Core.h @@ -16,11 +16,14 @@ #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/SymbolStringPool.h" #include "llvm/ExecutionEngine/OrcV1Deprecation.h" #include "llvm/Support/Debug.h" +#include <atomic> #include <memory> #include <vector> @@ -33,11 +36,67 @@ class ExecutionSession; class MaterializationUnit; class MaterializationResponsibility; class JITDylib; +class ResourceTracker; +class InProgressLookupState; + enum class SymbolState : uint8_t; -/// VModuleKey provides a unique identifier (allocated and managed by -/// ExecutionSessions) for a module added to the JIT. -using VModuleKey = uint64_t; +using ResourceTrackerSP = IntrusiveRefCntPtr<ResourceTracker>; +using JITDylibSP = IntrusiveRefCntPtr<JITDylib>; + +using ResourceKey = uintptr_t; + +/// API to remove / transfer ownership of JIT resources. +class ResourceTracker : public ThreadSafeRefCountedBase<ResourceTracker> { +private: + friend class ExecutionSession; + friend class JITDylib; + friend class MaterializationResponsibility; + +public: + ResourceTracker(const ResourceTracker &) = delete; + ResourceTracker &operator=(const ResourceTracker &) = delete; + ResourceTracker(ResourceTracker &&) = delete; + ResourceTracker &operator=(ResourceTracker &&) = delete; + + ~ResourceTracker(); + + /// Return the JITDylib targeted by this tracker. + JITDylib &getJITDylib() const { + return *reinterpret_cast<JITDylib *>(JDAndFlag.load() & + ~static_cast<uintptr_t>(1)); + } + + /// Remove all resources associated with this key. + Error remove(); + + /// Transfer all resources associated with this key to the given + /// tracker, which must target the same JITDylib as this one. + void transferTo(ResourceTracker &DstRT); + + /// Return true if this tracker has become defunct. + bool isDefunct() const { return JDAndFlag.load() & 0x1; } + + /// Returns the key associated with this tracker. + /// This method should not be used except for debug logging: there is no + /// guarantee that the returned value will remain valid. + ResourceKey getKeyUnsafe() const { return reinterpret_cast<uintptr_t>(this); } + +private: + ResourceTracker(JITDylibSP JD); + + void makeDefunct(); + + std::atomic_uintptr_t JDAndFlag; +}; + +/// Listens for ResourceTracker operations. +class ResourceManager { +public: + virtual ~ResourceManager(); + virtual Error handleRemoveResources(ResourceKey K) = 0; + virtual void handleTransferResources(ResourceKey DstK, ResourceKey SrcK) = 0; +}; /// A set of symbol names (represented by SymbolStringPtrs for // efficiency). @@ -158,9 +217,19 @@ public: /// Add an element to the set. The client is responsible for checking that /// duplicates are not added. - void add(SymbolStringPtr Name, - SymbolLookupFlags Flags = SymbolLookupFlags::RequiredSymbol) { + SymbolLookupSet & + add(SymbolStringPtr Name, + SymbolLookupFlags Flags = SymbolLookupFlags::RequiredSymbol) { Symbols.push_back(std::make_pair(std::move(Name), Flags)); + return *this; + } + + /// Quickly append one lookup set to another. + SymbolLookupSet &append(SymbolLookupSet Other) { + Symbols.reserve(Symbols.size() + Other.size()); + for (auto &KV : Other) + Symbols.push_back(std::move(KV)); + return *this; } bool empty() const { return Symbols.empty(); } @@ -287,7 +356,7 @@ public: for (UnderlyingVector::size_type I = 1; I != Symbols.size(); ++I) if (Symbols[I].first == Symbols[I - 1].first) return true; - return true; + return false; } #endif @@ -318,6 +387,18 @@ using RegisterDependenciesFunction = /// are no dependants to register with. extern RegisterDependenciesFunction NoDependenciesToRegister; +class ResourceTrackerDefunct : public ErrorInfo<ResourceTrackerDefunct> { +public: + static char ID; + + ResourceTrackerDefunct(ResourceTrackerSP RT); + std::error_code convertToErrorCode() const override; + void log(raw_ostream &OS) const override; + +private: + ResourceTrackerSP RT; +}; + /// Used to notify a JITDylib that the given set of symbols failed to /// materialize. class FailedToMaterialize : public ErrorInfo<FailedToMaterialize> { @@ -408,9 +489,10 @@ private: /// emit symbols, or abandon materialization by notifying any unmaterialized /// symbols of an error. class MaterializationResponsibility { - friend class MaterializationUnit; + friend class ExecutionSession; + public: - MaterializationResponsibility(MaterializationResponsibility &&) = default; + MaterializationResponsibility(MaterializationResponsibility &&) = delete; MaterializationResponsibility & operator=(MaterializationResponsibility &&) = delete; @@ -419,12 +501,15 @@ public: /// emitted or notified of an error. ~MaterializationResponsibility(); + /// Returns the ResourceTracker for this instance. + template <typename Func> Error withResourceKeyDo(Func &&F) const; + /// Returns the target JITDylib that these symbols are being materialized /// into. JITDylib &getTargetJITDylib() const { return *JD; } - /// Returns the VModuleKey for this instance. - VModuleKey getVModuleKey() const { return K; } + /// Returns the ExecutionSession for this instance. + ExecutionSession &getExecutionSession(); /// Returns the symbol flags map for this responsibility instance. /// Note: The returned flags may have transient flags (Lazy, Materializing) @@ -509,13 +594,13 @@ public: /// materializers to break up work based on run-time information (e.g. /// by introspecting which symbols have actually been looked up and /// materializing only those). - void replace(std::unique_ptr<MaterializationUnit> MU); + Error replace(std::unique_ptr<MaterializationUnit> MU); /// Delegates responsibility for the given symbols to the returned /// materialization responsibility. Useful for breaking up work between /// threads, or different kinds of materialization processes. - MaterializationResponsibility delegate(const SymbolNameSet &Symbols, - VModuleKey NewKey = VModuleKey()); + Expected<std::unique_ptr<MaterializationResponsibility>> + delegate(const SymbolNameSet &Symbols); void addDependencies(const SymbolStringPtr &Name, const SymbolDependenceMap &Dependencies); @@ -526,19 +611,17 @@ public: private: /// Create a MaterializationResponsibility for the given JITDylib and /// initial symbols. - MaterializationResponsibility(std::shared_ptr<JITDylib> JD, - SymbolFlagsMap SymbolFlags, - SymbolStringPtr InitSymbol, VModuleKey K) + MaterializationResponsibility(JITDylibSP JD, SymbolFlagsMap SymbolFlags, + SymbolStringPtr InitSymbol) : JD(std::move(JD)), SymbolFlags(std::move(SymbolFlags)), - InitSymbol(std::move(InitSymbol)), K(std::move(K)) { - assert(this->JD && "Cannot initialize with null JD"); + InitSymbol(std::move(InitSymbol)) { + assert(this->JD && "Cannot initialize with null JITDylib"); assert(!this->SymbolFlags.empty() && "Materializing nothing?"); } - std::shared_ptr<JITDylib> JD; + JITDylibSP JD; SymbolFlagsMap SymbolFlags; SymbolStringPtr InitSymbol; - VModuleKey K; }; /// A MaterializationUnit represents a set of symbol definitions that can @@ -555,9 +638,9 @@ class MaterializationUnit { public: MaterializationUnit(SymbolFlagsMap InitalSymbolFlags, - SymbolStringPtr InitSymbol, VModuleKey K) + SymbolStringPtr InitSymbol) : SymbolFlags(std::move(InitalSymbolFlags)), - InitSymbol(std::move(InitSymbol)), K(std::move(K)) { + InitSymbol(std::move(InitSymbol)) { assert((!this->InitSymbol || this->SymbolFlags.count(this->InitSymbol)) && "If set, InitSymbol should appear in InitialSymbolFlags map"); } @@ -577,7 +660,8 @@ public: /// Implementations of this method should materialize all symbols /// in the materialzation unit, except for those that have been /// previously discarded. - virtual void materialize(MaterializationResponsibility R) = 0; + virtual void + materialize(std::unique_ptr<MaterializationResponsibility> R) = 0; /// Called by JITDylibs to notify MaterializationUnits that the given symbol /// has been overridden. @@ -589,17 +673,10 @@ public: protected: SymbolFlagsMap SymbolFlags; SymbolStringPtr InitSymbol; - VModuleKey K; private: virtual void anchor(); - MaterializationResponsibility - createMaterializationResponsibility(std::shared_ptr<JITDylib> JD) { - return MaterializationResponsibility(std::move(JD), std::move(SymbolFlags), - std::move(InitSymbol), K); - } - /// 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 @@ -607,21 +684,18 @@ private: virtual void discard(const JITDylib &JD, const SymbolStringPtr &Name) = 0; }; -using MaterializationUnitList = - std::vector<std::unique_ptr<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 { public: - AbsoluteSymbolsMaterializationUnit(SymbolMap Symbols, VModuleKey K); + AbsoluteSymbolsMaterializationUnit(SymbolMap Symbols); StringRef getName() const override; private: - void materialize(MaterializationResponsibility R) override; + void materialize(std::unique_ptr<MaterializationResponsibility> R) override; void discard(const JITDylib &JD, const SymbolStringPtr &Name) override; static SymbolFlagsMap extractFlags(const SymbolMap &Symbols); @@ -639,9 +713,9 @@ private: /// \endcode /// inline std::unique_ptr<AbsoluteSymbolsMaterializationUnit> -absoluteSymbols(SymbolMap Symbols, VModuleKey K = VModuleKey()) { +absoluteSymbols(SymbolMap Symbols) { return std::make_unique<AbsoluteSymbolsMaterializationUnit>( - std::move(Symbols), std::move(K)); + std::move(Symbols)); } /// A materialization unit for symbol aliases. Allows existing symbols to be @@ -658,12 +732,12 @@ public: /// resolved. ReExportsMaterializationUnit(JITDylib *SourceJD, JITDylibLookupFlags SourceJDLookupFlags, - SymbolAliasMap Aliases, VModuleKey K); + SymbolAliasMap Aliases); StringRef getName() const override; private: - void materialize(MaterializationResponsibility R) override; + void materialize(std::unique_ptr<MaterializationResponsibility> R) override; void discard(const JITDylib &JD, const SymbolStringPtr &Name) override; static SymbolFlagsMap extractFlags(const SymbolAliasMap &Aliases); @@ -684,10 +758,9 @@ private: /// return Err; /// \endcode inline std::unique_ptr<ReExportsMaterializationUnit> -symbolAliases(SymbolAliasMap Aliases, VModuleKey K = VModuleKey()) { +symbolAliases(SymbolAliasMap Aliases) { return std::make_unique<ReExportsMaterializationUnit>( - nullptr, JITDylibLookupFlags::MatchAllSymbols, std::move(Aliases), - std::move(K)); + nullptr, JITDylibLookupFlags::MatchAllSymbols, std::move(Aliases)); } /// Create a materialization unit for re-exporting symbols from another JITDylib @@ -696,10 +769,9 @@ symbolAliases(SymbolAliasMap Aliases, VModuleKey K = VModuleKey()) { inline std::unique_ptr<ReExportsMaterializationUnit> reexports(JITDylib &SourceJD, SymbolAliasMap Aliases, JITDylibLookupFlags SourceJDLookupFlags = - JITDylibLookupFlags::MatchExportedSymbolsOnly, - VModuleKey K = VModuleKey()) { + JITDylibLookupFlags::MatchExportedSymbolsOnly) { return std::make_unique<ReExportsMaterializationUnit>( - &SourceJD, SourceJDLookupFlags, std::move(Aliases), std::move(K)); + &SourceJD, SourceJDLookupFlags, std::move(Aliases)); } /// Build a SymbolAliasMap for the common case where you want to re-export @@ -723,8 +795,10 @@ enum class SymbolState : uint8_t { /// makes a callback when all symbols are available. class AsynchronousSymbolQuery { friend class ExecutionSession; + friend class InProgressFullLookupState; friend class JITDylib; friend class JITSymbolResolverAdapter; + friend class MaterializationResponsibility; public: /// Create a query for the given symbols. The NotifyComplete @@ -757,8 +831,6 @@ private: void dropSymbol(const SymbolStringPtr &Name); - bool canStillFail(); - void handleFailed(Error Err); void detach(); @@ -770,34 +842,62 @@ private: SymbolState RequiredState; }; +/// 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 { + friend class OrcV2CAPIHelper; + friend class ExecutionSession; + +public: + LookupState(); + LookupState(LookupState &&); + LookupState &operator=(LookupState &&); + ~LookupState(); + + /// Continue the lookup. This can be called by DefinitionGenerators + /// to re-start a captured query-application operation. + void continueLookup(Error Err); + +private: + LookupState(std::unique_ptr<InProgressLookupState> IPLS); + + // For C API. + void reset(InProgressLookupState *IPLS); + + std::unique_ptr<InProgressLookupState> IPLS; +}; + +/// Definition generators can be attached to JITDylibs to generate new +/// definitions for otherwise unresolved symbols during lookup. +class DefinitionGenerator { +public: + virtual ~DefinitionGenerator(); + + /// DefinitionGenerators should override this method to insert new + /// definitions into the parent JITDylib. K specifies the kind of this + /// lookup. JD specifies the target JITDylib being searched, and + /// JDLookupFlags specifies whether the search should match against + /// hidden symbols. Finally, Symbols describes the set of unresolved + /// symbols and their associated lookup flags. + virtual Error tryToGenerate(LookupState &LS, LookupKind K, JITDylib &JD, + JITDylibLookupFlags JDLookupFlags, + const SymbolLookupSet &LookupSet) = 0; +}; + /// A symbol table that supports asynchoronous symbol queries. /// /// Represents a virtual shared object. Instances can not be copied or moved, so /// their addresses may be used as keys for resource management. /// JITDylib state changes must be made via an ExecutionSession to guarantee /// that they are synchronized with respect to other JITDylib operations. -class JITDylib : public std::enable_shared_from_this<JITDylib> { +class JITDylib : public ThreadSafeRefCountedBase<JITDylib>, + public jitlink::JITLinkDylib { friend class AsynchronousSymbolQuery; friend class ExecutionSession; friend class Platform; friend class MaterializationResponsibility; public: - /// Definition generators can be attached to JITDylibs to generate new - /// definitions for otherwise unresolved symbols during lookup. - class DefinitionGenerator { - public: - virtual ~DefinitionGenerator(); - - /// DefinitionGenerators should override this method to insert new - /// definitions into the parent JITDylib. K specifies the kind of this - /// lookup. JD specifies the target JITDylib being searched, and - /// JDLookupFlags specifies whether the search should match against - /// hidden symbols. Finally, Symbols describes the set of unresolved - /// symbols and their associated lookup flags. - virtual Error tryToGenerate(LookupKind K, JITDylib &JD, - JITDylibLookupFlags JDLookupFlags, - const SymbolLookupSet &LookupSet) = 0; - }; using AsynchronousSymbolQuerySet = std::set<std::shared_ptr<AsynchronousSymbolQuery>>; @@ -813,6 +913,21 @@ public: /// Get a reference to the ExecutionSession for this JITDylib. ExecutionSession &getExecutionSession() const { return ES; } + /// Calls remove on all trackers currently associated with this JITDylib. + /// Does not run static deinits. + /// + /// Note that removal happens outside the session lock, so new code may be + /// added concurrently while the clear is underway, and the newly added + /// code will *not* be cleared. Adding new code concurrently with a clear + /// is usually a bug and should be avoided. + Error clear(); + + /// Get the default resource tracker for this JITDylib. + ResourceTrackerSP getDefaultResourceTracker(); + + /// Create a resource tracker for this JITDylib. + ResourceTrackerSP createResourceTracker(); + /// Adds a definition generator to this JITDylib and returns a referenece to /// it. /// @@ -873,10 +988,13 @@ public: /// Define all symbols provided by the materialization unit to be part of this /// JITDylib. /// + /// If RT is not specified then the default resource tracker will be used. + /// /// This overload always takes ownership of the MaterializationUnit. If any /// errors occur, the MaterializationUnit consumed. template <typename MaterializationUnitType> - Error define(std::unique_ptr<MaterializationUnitType> &&MU); + Error define(std::unique_ptr<MaterializationUnitType> &&MU, + ResourceTrackerSP RT = nullptr); /// Define all symbols provided by the materialization unit to be part of this /// JITDylib. @@ -886,7 +1004,8 @@ public: /// may allow the caller to modify the MaterializationUnit to correct the /// issue, then re-call define. template <typename MaterializationUnitType> - Error define(std::unique_ptr<MaterializationUnitType> &MU); + Error define(std::unique_ptr<MaterializationUnitType> &MU, + ResourceTrackerSP RT = nullptr); /// Tries to remove the given symbols. /// @@ -900,41 +1019,47 @@ public: /// left unmodified (no symbols are removed). Error remove(const SymbolNameSet &Names); - /// Search the given JITDylib for the symbols in Symbols. If found, store - /// the flags for each symbol in Flags. If any required symbols are not found - /// then an error will be returned. - Expected<SymbolFlagsMap> lookupFlags(LookupKind K, - JITDylibLookupFlags JDLookupFlags, - SymbolLookupSet LookupSet); - /// Dump current JITDylib state to OS. void dump(raw_ostream &OS); - /// FIXME: Remove this when we remove the old ORC layers. - /// Search the given JITDylibs in order for the symbols in Symbols. Results - /// (once they become available) will be returned via the given Query. - /// - /// If any symbol is not found then the unresolved symbols will be returned, - /// 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. - Expected<SymbolNameSet> - legacyLookup(std::shared_ptr<AsynchronousSymbolQuery> Q, SymbolNameSet Names); + /// Returns the given JITDylibs and all of their transitive dependencies in + /// DFS order (based on linkage relationships). Each JITDylib will appear + /// only once. + static std::vector<JITDylibSP> getDFSLinkOrder(ArrayRef<JITDylibSP> JDs); + + /// Returns the given JITDylibs and all of their transitive dependensies in + /// reverse DFS order (based on linkage relationships). Each JITDylib will + /// appear only once. + static std::vector<JITDylibSP> + getReverseDFSLinkOrder(ArrayRef<JITDylibSP> JDs); + + /// Return this JITDylib and its transitive dependencies in DFS order + /// based on linkage relationships. + std::vector<JITDylibSP> getDFSLinkOrder(); + + /// Rteurn this JITDylib and its transitive dependencies in reverse DFS order + /// based on linkage relationships. + std::vector<JITDylibSP> getReverseDFSLinkOrder(); private: using AsynchronousSymbolQueryList = std::vector<std::shared_ptr<AsynchronousSymbolQuery>>; struct UnmaterializedInfo { - UnmaterializedInfo(std::unique_ptr<MaterializationUnit> MU) - : MU(std::move(MU)) {} + UnmaterializedInfo(std::unique_ptr<MaterializationUnit> MU, + ResourceTracker *RT) + : MU(std::move(MU)), RT(RT) {} std::unique_ptr<MaterializationUnit> MU; + ResourceTracker *RT; }; using UnmaterializedInfosMap = DenseMap<SymbolStringPtr, std::shared_ptr<UnmaterializedInfo>>; + using UnmaterializedInfosList = + std::vector<std::shared_ptr<UnmaterializedInfo>>; + struct MaterializingInfo { SymbolDependenceMap Dependants; SymbolDependenceMap UnemittedDependencies; @@ -1001,25 +1126,16 @@ private: JITDylib(ExecutionSession &ES, std::string Name); - Error defineImpl(MaterializationUnit &MU); - - void lookupFlagsImpl(SymbolFlagsMap &Result, LookupKind K, - JITDylibLookupFlags JDLookupFlags, - SymbolLookupSet &Unresolved); + ResourceTrackerSP getTracker(MaterializationResponsibility &MR); + std::pair<AsynchronousSymbolQuerySet, std::shared_ptr<SymbolDependenceMap>> + removeTracker(ResourceTracker &RT); - Error lodgeQuery(MaterializationUnitList &MUs, - std::shared_ptr<AsynchronousSymbolQuery> &Q, LookupKind K, - JITDylibLookupFlags JDLookupFlags, - SymbolLookupSet &Unresolved); + void transferTracker(ResourceTracker &DstRT, ResourceTracker &SrcRT); - Error lodgeQueryImpl(MaterializationUnitList &MUs, - std::shared_ptr<AsynchronousSymbolQuery> &Q, - LookupKind K, JITDylibLookupFlags JDLookupFlags, - SymbolLookupSet &Unresolved); + Error defineImpl(MaterializationUnit &MU); - bool lookupImpl(std::shared_ptr<AsynchronousSymbolQuery> &Q, - std::vector<std::unique_ptr<MaterializationUnit>> &MUs, - SymbolLookupSet &Unresolved); + void installMaterializationUnit(std::unique_ptr<MaterializationUnit> MU, + ResourceTracker &RT); void detachQueryHelper(AsynchronousSymbolQuery &Q, const SymbolNameSet &QuerySymbols); @@ -1030,29 +1146,45 @@ private: Expected<SymbolFlagsMap> defineMaterializing(SymbolFlagsMap SymbolFlags); - void replace(std::unique_ptr<MaterializationUnit> MU); + Error replace(MaterializationResponsibility &FromMR, + std::unique_ptr<MaterializationUnit> MU); + + Expected<std::unique_ptr<MaterializationResponsibility>> + delegate(MaterializationResponsibility &FromMR, SymbolFlagsMap SymbolFlags, + SymbolStringPtr InitSymbol); SymbolNameSet getRequestedSymbols(const SymbolFlagsMap &SymbolFlags) const; void addDependencies(const SymbolStringPtr &Name, const SymbolDependenceMap &Dependants); - Error resolve(const SymbolMap &Resolved); + Error resolve(MaterializationResponsibility &MR, const SymbolMap &Resolved); + + Error emit(MaterializationResponsibility &MR, const SymbolFlagsMap &Emitted); - Error emit(const SymbolFlagsMap &Emitted); + void unlinkMaterializationResponsibility(MaterializationResponsibility &MR); using FailedSymbolsWorklist = std::vector<std::pair<JITDylib *, SymbolStringPtr>>; - static void notifyFailed(FailedSymbolsWorklist FailedSymbols); + + static std::pair<AsynchronousSymbolQuerySet, + std::shared_ptr<SymbolDependenceMap>> + failSymbols(FailedSymbolsWorklist); ExecutionSession &ES; std::string JITDylibName; + std::mutex GeneratorsMutex; bool Open = true; SymbolTable Symbols; UnmaterializedInfosMap UnmaterializedInfos; MaterializingInfosMap MaterializingInfos; - std::vector<std::unique_ptr<DefinitionGenerator>> DefGenerators; + std::vector<std::shared_ptr<DefinitionGenerator>> DefGenerators; JITDylibSearchOrder LinkOrder; + ResourceTrackerSP DefaultTracker; + + // Map trackers to sets of symbols tracked. + DenseMap<ResourceTracker *, SymbolNameVector> TrackerSymbols; + DenseMap<MaterializationResponsibility *, ResourceTracker *> MRTrackers; }; /// Platforms set up standard symbols and mediate interactions between dynamic @@ -1071,11 +1203,12 @@ public: /// This method will be called under the ExecutionSession lock each time a /// MaterializationUnit is added to a JITDylib. - virtual Error notifyAdding(JITDylib &JD, const MaterializationUnit &MU) = 0; + virtual Error notifyAdding(ResourceTracker &RT, + const MaterializationUnit &MU) = 0; /// This method will be called under the ExecutionSession lock when a - /// VModuleKey is removed. - virtual Error notifyRemoving(JITDylib &JD, VModuleKey K) = 0; + /// ResourceTracker is removed. + virtual Error notifyRemoving(ResourceTracker &RT) = 0; /// A utility function for looking up initializer symbols. Performs a blocking /// lookup for the given symbols in each of the given JITDylibs. @@ -1086,8 +1219,12 @@ public: /// An ExecutionSession represents a running JIT program. class ExecutionSession { - // FIXME: Remove this when we remove the old ORC layers. + friend class InProgressLookupFlagsState; + friend class InProgressFullLookupState; friend class JITDylib; + friend class LookupState; + friend class MaterializationResponsibility; + friend class ResourceTracker; public: /// For reporting errors. @@ -1096,13 +1233,16 @@ public: /// For dispatching MaterializationUnit::materialize calls. using DispatchMaterializationFunction = std::function<void(std::unique_ptr<MaterializationUnit> MU, - MaterializationResponsibility MR)>; + std::unique_ptr<MaterializationResponsibility> MR)>; /// Construct an ExecutionSession. /// /// SymbolStringPools may be shared between ExecutionSessions. ExecutionSession(std::shared_ptr<SymbolStringPool> SSP = nullptr); + /// End the session. Closes all JITDylibs. + Error endSession(); + /// Add a symbol name to the SymbolStringPool and return a pointer to it. SymbolStringPtr intern(StringRef SymName) { return SSP->intern(SymName); } @@ -1122,6 +1262,14 @@ public: return F(); } + /// Register the given ResourceManager with this ExecutionSession. + /// Managers will be notified of events in reverse order of registration. + void registerResourceManager(ResourceManager &RM); + + /// Deregister the given ResourceManager with this ExecutionSession. + /// Manager must have been previously registered. + void deregisterResourceManager(ResourceManager &RM); + /// Return a pointer to the "name" JITDylib. /// Ownership of JITDylib remains within Execution Session JITDylib *getJITDylibByName(StringRef Name); @@ -1147,17 +1295,6 @@ public: /// If no Platform is attached this call is equivalent to createBareJITDylib. Expected<JITDylib &> createJITDylib(std::string Name); - /// Allocate a module key for a new module to add to the JIT. - VModuleKey allocateVModule() { - return runSessionLocked([this]() { return ++LastKey; }); - } - - /// Return a module key to the ExecutionSession so that it can be - /// re-used. This should only be done once all resources associated - /// with the original key have been released. - void releaseVModule(VModuleKey Key) { /* FIXME: Recycle keys */ - } - /// Set the error reporter function. ExecutionSession &setErrorReporter(ErrorReporter ReportError) { this->ReportError = std::move(ReportError); @@ -1176,19 +1313,18 @@ public: return *this; } - void legacyFailQuery(AsynchronousSymbolQuery &Q, Error Err); + /// Search the given JITDylibs to find the flags associated with each of the + /// given symbols. + void lookupFlags(LookupKind K, JITDylibSearchOrder SearchOrder, + SymbolLookupSet Symbols, + unique_function<void(Expected<SymbolFlagsMap>)> OnComplete); - using LegacyAsyncLookupFunction = std::function<SymbolNameSet( - std::shared_ptr<AsynchronousSymbolQuery> Q, SymbolNameSet Names)>; - - /// A legacy lookup function for JITSymbolResolverAdapter. - /// Do not use -- this will be removed soon. - Expected<SymbolMap> - legacyLookup(LegacyAsyncLookupFunction AsyncLookup, SymbolNameSet Names, - SymbolState RequiredState, - RegisterDependenciesFunction RegisterDependencies); + /// Blocking version of lookupFlags. + Expected<SymbolFlagsMap> lookupFlags(LookupKind K, + JITDylibSearchOrder SearchOrder, + SymbolLookupSet Symbols); - /// Search the given JITDylib list for the given symbols. + /// Search the given JITDylibs for the given symbols. /// /// SearchOrder lists the JITDylibs to search. For each dylib, the associated /// boolean indicates whether the search should match against non-exported @@ -1248,10 +1384,11 @@ public: SymbolState RequiredState = SymbolState::Ready); /// Materialize the given unit. - void dispatchMaterialization(std::unique_ptr<MaterializationUnit> MU, - MaterializationResponsibility MR) { + void + dispatchMaterialization(std::unique_ptr<MaterializationUnit> MU, + std::unique_ptr<MaterializationResponsibility> MR) { assert(MU && "MU must be non-null"); - DEBUG_WITH_TYPE("orc", dumpDispatchInfo(MR.getTargetJITDylib(), *MU)); + DEBUG_WITH_TYPE("orc", dumpDispatchInfo(MR->getTargetJITDylib(), *MU)); DispatchMaterialization(std::move(MU), std::move(MR)); } @@ -1263,41 +1400,124 @@ private: logAllUnhandledErrors(std::move(Err), errs(), "JIT session error: "); } - static void - materializeOnCurrentThread(std::unique_ptr<MaterializationUnit> MU, - MaterializationResponsibility MR) { + static void materializeOnCurrentThread( + std::unique_ptr<MaterializationUnit> MU, + std::unique_ptr<MaterializationResponsibility> MR) { MU->materialize(std::move(MR)); } - void runOutstandingMUs(); + void dispatchOutstandingMUs(); + + static std::unique_ptr<MaterializationResponsibility> + createMaterializationResponsibility(ResourceTracker &RT, + SymbolFlagsMap Symbols, + SymbolStringPtr InitSymbol) { + auto &JD = RT.getJITDylib(); + std::unique_ptr<MaterializationResponsibility> MR( + new MaterializationResponsibility(&JD, std::move(Symbols), + std::move(InitSymbol))); + JD.MRTrackers[MR.get()] = &RT; + return MR; + } + + Error removeResourceTracker(ResourceTracker &RT); + void transferResourceTracker(ResourceTracker &DstRT, ResourceTracker &SrcRT); + void destroyResourceTracker(ResourceTracker &RT); + + // State machine functions for query application.. + + /// IL_updateCandidatesFor is called to remove already-defined symbols that + /// match a given query from the set of candidate symbols to generate + /// definitions for (no need to generate a definition if one already exists). + Error IL_updateCandidatesFor(JITDylib &JD, JITDylibLookupFlags JDLookupFlags, + SymbolLookupSet &Candidates, + SymbolLookupSet *NonCandidates); + + /// OL_applyQueryPhase1 is an optionally re-startable loop for triggering + /// definition generation. It is called when a lookup is performed, and again + /// each time that LookupState::continueLookup is called. + void OL_applyQueryPhase1(std::unique_ptr<InProgressLookupState> IPLS, + Error Err); + + /// OL_completeLookup is run once phase 1 successfully completes for a lookup + /// call. It attempts to attach the symbol to all symbol table entries and + /// collect all MaterializationUnits to dispatch. If this method fails then + /// all MaterializationUnits will be left un-materialized. + void OL_completeLookup(std::unique_ptr<InProgressLookupState> IPLS, + std::shared_ptr<AsynchronousSymbolQuery> Q, + RegisterDependenciesFunction RegisterDependencies); + + /// OL_completeLookupFlags is run once phase 1 successfully completes for a + /// lookupFlags call. + void OL_completeLookupFlags( + std::unique_ptr<InProgressLookupState> IPLS, + unique_function<void(Expected<SymbolFlagsMap>)> OnComplete); + + // State machine functions for MaterializationResponsibility. + void OL_destroyMaterializationResponsibility( + MaterializationResponsibility &MR); + SymbolNameSet OL_getRequestedSymbols(const MaterializationResponsibility &MR); + Error OL_notifyResolved(MaterializationResponsibility &MR, + const SymbolMap &Symbols); + Error OL_notifyEmitted(MaterializationResponsibility &MR); + Error OL_defineMaterializing(MaterializationResponsibility &MR, + SymbolFlagsMap SymbolFlags); + void OL_notifyFailed(MaterializationResponsibility &MR); + Error OL_replace(MaterializationResponsibility &MR, + std::unique_ptr<MaterializationUnit> MU); + Expected<std::unique_ptr<MaterializationResponsibility>> + OL_delegate(MaterializationResponsibility &MR, const SymbolNameSet &Symbols); + void OL_addDependencies(MaterializationResponsibility &MR, + const SymbolStringPtr &Name, + const SymbolDependenceMap &Dependencies); + void OL_addDependenciesForAll(MaterializationResponsibility &MR, + const SymbolDependenceMap &Dependencies); #ifndef NDEBUG void dumpDispatchInfo(JITDylib &JD, MaterializationUnit &MU); #endif // NDEBUG mutable std::recursive_mutex SessionMutex; + bool SessionOpen = true; std::shared_ptr<SymbolStringPool> SSP; std::unique_ptr<Platform> P; - VModuleKey LastKey = 0; ErrorReporter ReportError = logErrorsToStdErr; DispatchMaterializationFunction DispatchMaterialization = materializeOnCurrentThread; - std::vector<std::shared_ptr<JITDylib>> JDs; + std::vector<ResourceManager *> ResourceManagers; + + std::vector<JITDylibSP> JDs; // FIXME: Remove this (and runOutstandingMUs) once the linking layer works // with callbacks from asynchronous queries. mutable std::recursive_mutex OutstandingMUsMutex; std::vector<std::pair<std::unique_ptr<MaterializationUnit>, - MaterializationResponsibility>> + std::unique_ptr<MaterializationResponsibility>>> OutstandingMUs; }; +inline ExecutionSession &MaterializationResponsibility::getExecutionSession() { + return JD->getExecutionSession(); +} + +template <typename Func> +Error MaterializationResponsibility::withResourceKeyDo(Func &&F) const { + return JD->getExecutionSession().runSessionLocked([&]() -> Error { + auto I = JD->MRTrackers.find(this); + assert(I != JD->MRTrackers.end() && "No tracker for this MR"); + if (I->second->isDefunct()) + return make_error<ResourceTrackerDefunct>(I->second); + F(I->second->getKeyUnsafe()); + return Error::success(); + }); +} + template <typename GeneratorT> GeneratorT &JITDylib::addGenerator(std::unique_ptr<GeneratorT> DefGenerator) { auto &G = *DefGenerator; - ES.runSessionLocked( - [&]() { DefGenerators.push_back(std::move(DefGenerator)); }); + std::lock_guard<std::mutex> Lock(GeneratorsMutex); + DefGenerators.push_back(std::move(DefGenerator)); return G; } @@ -1308,7 +1528,8 @@ auto JITDylib::withLinkOrderDo(Func &&F) } template <typename MaterializationUnitType> -Error JITDylib::define(std::unique_ptr<MaterializationUnitType> &&MU) { +Error JITDylib::define(std::unique_ptr<MaterializationUnitType> &&MU, + ResourceTrackerSP RT) { assert(MU && "Can not define with a null MU"); if (MU->getSymbols().empty()) { @@ -1320,29 +1541,36 @@ Error JITDylib::define(std::unique_ptr<MaterializationUnitType> &&MU) { return Error::success(); } else DEBUG_WITH_TYPE("orc", { - dbgs() << "Defining MU " << MU->getName() << " for " << getName() << "\n"; + dbgs() << "Defining MU " << MU->getName() << " for " << getName() + << " (tracker: "; + if (RT == getDefaultResourceTracker()) + dbgs() << "default)"; + else if (RT) + dbgs() << RT.get() << ")\n"; + else + dbgs() << "0x0, default will be used)\n"; }); return ES.runSessionLocked([&, this]() -> Error { if (auto Err = defineImpl(*MU)) return Err; + if (!RT) + RT = getDefaultResourceTracker(); + if (auto *P = ES.getPlatform()) { - if (auto Err = P->notifyAdding(*this, *MU)) + if (auto Err = P->notifyAdding(*RT, *MU)) return Err; } - /// defineImpl succeeded. - auto UMI = std::make_shared<UnmaterializedInfo>(std::move(MU)); - for (auto &KV : UMI->MU->getSymbols()) - UnmaterializedInfos[KV.first] = UMI; - + installMaterializationUnit(std::move(MU), *RT); return Error::success(); }); } template <typename MaterializationUnitType> -Error JITDylib::define(std::unique_ptr<MaterializationUnitType> &MU) { +Error JITDylib::define(std::unique_ptr<MaterializationUnitType> &MU, + ResourceTrackerSP RT) { assert(MU && "Can not define with a null MU"); if (MU->getSymbols().empty()) { @@ -1354,30 +1582,36 @@ Error JITDylib::define(std::unique_ptr<MaterializationUnitType> &MU) { return Error::success(); } else DEBUG_WITH_TYPE("orc", { - dbgs() << "Defining MU " << MU->getName() << " for " << getName() << "\n"; + dbgs() << "Defining MU " << MU->getName() << " for " << getName() + << " (tracker: "; + if (RT == getDefaultResourceTracker()) + dbgs() << "default)"; + else if (RT) + dbgs() << RT.get() << ")\n"; + else + dbgs() << "0x0, default will be used)\n"; }); return ES.runSessionLocked([&, this]() -> Error { if (auto Err = defineImpl(*MU)) return Err; + if (!RT) + RT = getDefaultResourceTracker(); + if (auto *P = ES.getPlatform()) { - if (auto Err = P->notifyAdding(*this, *MU)) + if (auto Err = P->notifyAdding(*RT, *MU)) return Err; } - /// defineImpl succeeded. - auto UMI = std::make_shared<UnmaterializedInfo>(std::move(MU)); - for (auto &KV : UMI->MU->getSymbols()) - UnmaterializedInfos[KV.first] = UMI; - + installMaterializationUnit(std::move(MU), *RT); return Error::success(); }); } /// 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 JITDylib::DefinitionGenerator { +class ReexportsGenerator : public DefinitionGenerator { public: using SymbolPredicate = std::function<bool(SymbolStringPtr)>; @@ -1388,7 +1622,7 @@ public: JITDylibLookupFlags SourceJDLookupFlags, SymbolPredicate Allow = SymbolPredicate()); - Error tryToGenerate(LookupKind K, JITDylib &JD, + Error tryToGenerate(LookupState &LS, LookupKind K, JITDylib &JD, JITDylibLookupFlags JDLookupFlags, const SymbolLookupSet &LookupSet) override; @@ -1398,6 +1632,57 @@ private: SymbolPredicate Allow; }; +// --------------- IMPLEMENTATION -------------- +// Implementations for inline functions/methods. +// --------------------------------------------- + +inline MaterializationResponsibility::~MaterializationResponsibility() { + JD->getExecutionSession().OL_destroyMaterializationResponsibility(*this); +} + +inline SymbolNameSet MaterializationResponsibility::getRequestedSymbols() const { + return JD->getExecutionSession().OL_getRequestedSymbols(*this); +} + +inline Error MaterializationResponsibility::notifyResolved( + const SymbolMap &Symbols) { + return JD->getExecutionSession().OL_notifyResolved(*this, Symbols); +} + +inline Error MaterializationResponsibility::notifyEmitted() { + return JD->getExecutionSession().OL_notifyEmitted(*this); +} + +inline Error MaterializationResponsibility::defineMaterializing( + SymbolFlagsMap SymbolFlags) { + return JD->getExecutionSession().OL_defineMaterializing( + *this, std::move(SymbolFlags)); +} + +inline void MaterializationResponsibility::failMaterialization() { + JD->getExecutionSession().OL_notifyFailed(*this); +} + +inline Error MaterializationResponsibility::replace( + std::unique_ptr<MaterializationUnit> MU) { + return JD->getExecutionSession().OL_replace(*this, std::move(MU)); +} + +inline Expected<std::unique_ptr<MaterializationResponsibility>> +MaterializationResponsibility::delegate(const SymbolNameSet &Symbols) { + return JD->getExecutionSession().OL_delegate(*this, Symbols); +} + +inline void MaterializationResponsibility::addDependencies( + const SymbolStringPtr &Name, const SymbolDependenceMap &Dependencies) { + JD->getExecutionSession().OL_addDependencies(*this, Name, Dependencies); +} + +inline void MaterializationResponsibility::addDependenciesForAll( + const SymbolDependenceMap &Dependencies) { + JD->getExecutionSession().OL_addDependenciesForAll(*this, Dependencies); +} + } // End namespace orc } // End namespace llvm diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h index 3b824b83b052..fdddc9694d0b 100644 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h @@ -18,7 +18,7 @@ #include "llvm/ExecutionEngine/JITSymbol.h" #include "llvm/ExecutionEngine/Orc/Core.h" #include "llvm/ExecutionEngine/Orc/Mangling.h" -#include "llvm/ExecutionEngine/Orc/OrcError.h" +#include "llvm/ExecutionEngine/Orc/Shared/OrcError.h" #include "llvm/ExecutionEngine/RuntimeDyld.h" #include "llvm/Object/Archive.h" #include "llvm/Support/DynamicLibrary.h" @@ -41,17 +41,6 @@ namespace orc { class ObjectLayer; -/// Run a main function, returning the result. -/// -/// If the optional ProgramName argument is given then it will be inserted -/// before the strings in Args as the first argument to the called function. -/// -/// It is legal to have an empty argument list and no program name, however -/// many main functions will expect a name argument at least, and will fail -/// if none is provided. -int runAsMain(int (*Main)(int, char *[]), ArrayRef<std::string> Args, - Optional<StringRef> ProgramName = None); - /// This iterator provides a convenient way to iterate over the elements /// of an llvm.global_ctors/llvm.global_dtors instance. /// @@ -152,56 +141,6 @@ inline iterator_range<StaticInitGVIterator> getStaticInitGVs(Module &M) { return make_range(StaticInitGVIterator(M), StaticInitGVIterator()); } -/// Convenience class for recording constructor/destructor names for -/// later execution. -template <typename JITLayerT> -class LegacyCtorDtorRunner { -public: - /// Construct a CtorDtorRunner for the given range using the given - /// name mangling function. - LLVM_ATTRIBUTE_DEPRECATED( - LegacyCtorDtorRunner(std::vector<std::string> CtorDtorNames, - VModuleKey K), - "ORCv1 utilities (utilities with the 'Legacy' prefix) are deprecated. " - "Please use the ORCv2 CtorDtorRunner utility instead"); - - LegacyCtorDtorRunner(ORCv1DeprecationAcknowledgement, - std::vector<std::string> CtorDtorNames, VModuleKey K) - : CtorDtorNames(std::move(CtorDtorNames)), K(K) {} - - /// Run the recorded constructors/destructors through the given JIT - /// layer. - Error runViaLayer(JITLayerT &JITLayer) const { - using CtorDtorTy = void (*)(); - - for (const auto &CtorDtorName : CtorDtorNames) { - if (auto CtorDtorSym = JITLayer.findSymbolIn(K, CtorDtorName, false)) { - if (auto AddrOrErr = CtorDtorSym.getAddress()) { - CtorDtorTy CtorDtor = - reinterpret_cast<CtorDtorTy>(static_cast<uintptr_t>(*AddrOrErr)); - CtorDtor(); - } else - return AddrOrErr.takeError(); - } else { - if (auto Err = CtorDtorSym.takeError()) - return Err; - else - return make_error<JITSymbolNotFound>(CtorDtorName); - } - } - return Error::success(); - } - -private: - std::vector<std::string> CtorDtorNames; - orc::VModuleKey K; -}; - -template <typename JITLayerT> -LegacyCtorDtorRunner<JITLayerT>::LegacyCtorDtorRunner( - std::vector<std::string> CtorDtorNames, VModuleKey K) - : CtorDtorNames(std::move(CtorDtorNames)), K(K) {} - class CtorDtorRunner { public: CtorDtorRunner(JITDylib &JD) : JD(JD) {} @@ -250,45 +189,6 @@ protected: void *DSOHandle); }; -class LegacyLocalCXXRuntimeOverrides : public LocalCXXRuntimeOverridesBase { -public: - /// Create a runtime-overrides class. - template <typename MangleFtorT> - LLVM_ATTRIBUTE_DEPRECATED( - LegacyLocalCXXRuntimeOverrides(const MangleFtorT &Mangle), - "ORCv1 utilities (utilities with the 'Legacy' prefix) are deprecated. " - "Please use the ORCv2 LocalCXXRuntimeOverrides utility instead"); - - template <typename MangleFtorT> - LegacyLocalCXXRuntimeOverrides(ORCv1DeprecationAcknowledgement, - const MangleFtorT &Mangle) { - addOverride(Mangle("__dso_handle"), toTargetAddress(&DSOHandleOverride)); - addOverride(Mangle("__cxa_atexit"), toTargetAddress(&CXAAtExitOverride)); - } - - /// Search overrided symbols. - JITEvaluatedSymbol searchOverrides(const std::string &Name) { - auto I = CXXRuntimeOverrides.find(Name); - if (I != CXXRuntimeOverrides.end()) - return JITEvaluatedSymbol(I->second, JITSymbolFlags::Exported); - return nullptr; - } - -private: - void addOverride(const std::string &Name, JITTargetAddress Addr) { - CXXRuntimeOverrides.insert(std::make_pair(Name, Addr)); - } - - StringMap<JITTargetAddress> CXXRuntimeOverrides; -}; - -template <typename MangleFtorT> -LegacyLocalCXXRuntimeOverrides::LegacyLocalCXXRuntimeOverrides( - const MangleFtorT &Mangle) { - addOverride(Mangle("__dso_handle"), toTargetAddress(&DSOHandleOverride)); - addOverride(Mangle("__cxa_atexit"), toTargetAddress(&CXAAtExitOverride)); -} - class LocalCXXRuntimeOverrides : public LocalCXXRuntimeOverridesBase { public: Error enable(JITDylib &JD, MangleAndInterner &Mangler); @@ -315,7 +215,7 @@ private: /// If an instance of this class is attached to a JITDylib as a fallback /// definition generator, then any symbol found in the given DynamicLibrary that /// passes the 'Allow' predicate will be added to the JITDylib. -class DynamicLibrarySearchGenerator : public JITDylib::DefinitionGenerator { +class DynamicLibrarySearchGenerator : public DefinitionGenerator { public: using SymbolPredicate = std::function<bool(const SymbolStringPtr &)>; @@ -343,7 +243,7 @@ public: return Load(nullptr, GlobalPrefix, std::move(Allow)); } - Error tryToGenerate(LookupKind K, JITDylib &JD, + Error tryToGenerate(LookupState &LS, LookupKind K, JITDylib &JD, JITDylibLookupFlags JDLookupFlags, const SymbolLookupSet &Symbols) override; @@ -358,7 +258,7 @@ private: /// If an instance of this class is attached to a JITDylib as a fallback /// definition generator, then any symbol found in the archive will result in /// the containing object being added to the JITDylib. -class StaticLibraryDefinitionGenerator : public JITDylib::DefinitionGenerator { +class StaticLibraryDefinitionGenerator : public DefinitionGenerator { public: /// Try to create a StaticLibraryDefinitionGenerator from the given path. /// @@ -381,7 +281,7 @@ public: static Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>> Create(ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer); - Error tryToGenerate(LookupKind K, JITDylib &JD, + Error tryToGenerate(LookupState &LS, LookupKind K, JITDylib &JD, JITDylibLookupFlags JDLookupFlags, const SymbolLookupSet &Symbols) override; diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/GlobalMappingLayer.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/GlobalMappingLayer.h deleted file mode 100644 index a4e43d4e1c9c..000000000000 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/GlobalMappingLayer.h +++ /dev/null @@ -1,111 +0,0 @@ -//===- GlobalMappingLayer.h - Run all IR through a functor ------*- 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 -// -//===----------------------------------------------------------------------===// -// -// Convenience layer for injecting symbols that will appear in calls to -// findSymbol. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_EXECUTIONENGINE_ORC_GLOBALMAPPINGLAYER_H -#define LLVM_EXECUTIONENGINE_ORC_GLOBALMAPPINGLAYER_H - -#include "llvm/ExecutionEngine/JITSymbol.h" -#include <map> -#include <memory> -#include <string> - -namespace llvm { - -class Module; -class JITSymbolResolver; - -namespace orc { - -/// Global mapping layer. -/// -/// This layer overrides the findSymbol method to first search a local symbol -/// table that the client can define. It can be used to inject new symbol -/// mappings into the JIT. Beware, however: symbols within a single IR module or -/// object file will still resolve locally (via RuntimeDyld's symbol table) - -/// such internal references cannot be overriden via this layer. -template <typename BaseLayerT> -class GlobalMappingLayer { -public: - - /// Handle to an added module. - using ModuleHandleT = typename BaseLayerT::ModuleHandleT; - - /// Construct an GlobalMappingLayer with the given BaseLayer - GlobalMappingLayer(BaseLayerT &BaseLayer) : BaseLayer(BaseLayer) {} - - /// Add the given module to the JIT. - /// @return A handle for the added modules. - Expected<ModuleHandleT> - addModule(std::shared_ptr<Module> M, - std::shared_ptr<JITSymbolResolver> Resolver) { - return BaseLayer.addModule(std::move(M), std::move(Resolver)); - } - - /// Remove the module set associated with the handle H. - Error removeModule(ModuleHandleT H) { return BaseLayer.removeModule(H); } - - /// Manually set the address to return for the given symbol. - void setGlobalMapping(const std::string &Name, JITTargetAddress Addr) { - SymbolTable[Name] = Addr; - } - - /// Remove the given symbol from the global mapping. - void eraseGlobalMapping(const std::string &Name) { - SymbolTable.erase(Name); - } - - /// Search for the given named symbol. - /// - /// This method will first search the local symbol table, returning - /// any symbol found there. If the symbol is not found in the local - /// table then this call will be passed through to the base layer. - /// - /// @param Name The name of the symbol to search for. - /// @param ExportedSymbolsOnly If true, search only for exported symbols. - /// @return A handle for the given named symbol, if it exists. - JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) { - auto I = SymbolTable.find(Name); - if (I != SymbolTable.end()) - return JITSymbol(I->second, JITSymbolFlags::Exported); - return BaseLayer.findSymbol(Name, ExportedSymbolsOnly); - } - - /// Get the address of the given symbol in the context of the of the - /// module represented by the handle H. This call is forwarded to the - /// base layer's implementation. - /// @param H The handle for the module to search in. - /// @param Name The name of the symbol to search for. - /// @param ExportedSymbolsOnly If true, search only for exported symbols. - /// @return A handle for the given named symbol, if it is found in the - /// given module. - JITSymbol findSymbolIn(ModuleHandleT H, const std::string &Name, - bool ExportedSymbolsOnly) { - return BaseLayer.findSymbolIn(H, Name, ExportedSymbolsOnly); - } - - /// Immediately emit and finalize the module set represented by the - /// given handle. - /// @param H Handle for module set to emit/finalize. - Error emitAndFinalize(ModuleHandleT H) { - return BaseLayer.emitAndFinalize(H); - } - -private: - BaseLayerT &BaseLayer; - std::map<std::string, JITTargetAddress> SymbolTable; -}; - -} // end namespace orc -} // end namespace llvm - -#endif // LLVM_EXECUTIONENGINE_ORC_GLOBALMAPPINGLAYER_H diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h index eb74d283f043..f8fdb171bbf9 100644 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h @@ -45,8 +45,8 @@ public: IRSymbolMapper::ManglingOptions MO; }; - using NotifyCompiledFunction = - std::function<void(VModuleKey K, ThreadSafeModule TSM)>; + using NotifyCompiledFunction = std::function<void( + MaterializationResponsibility &R, ThreadSafeModule TSM)>; IRCompileLayer(ExecutionSession &ES, ObjectLayer &BaseLayer, std::unique_ptr<IRCompiler> Compile); @@ -55,7 +55,8 @@ public: void setNotifyCompiled(NotifyCompiledFunction NotifyCompiled); - void emit(MaterializationResponsibility R, ThreadSafeModule TSM) override; + void emit(std::unique_ptr<MaterializationResponsibility> R, + ThreadSafeModule TSM) override; private: mutable std::mutex IRLayerMutex; @@ -65,99 +66,6 @@ private: NotifyCompiledFunction NotifyCompiled = NotifyCompiledFunction(); }; -/// Eager IR compiling layer. -/// -/// This layer immediately compiles each IR module added via addModule to an -/// object file and adds this module file to the layer below, which must -/// implement the object layer concept. -template <typename BaseLayerT, typename CompileFtor> -class LegacyIRCompileLayer { -public: - /// Callback type for notifications when modules are compiled. - using NotifyCompiledCallback = - std::function<void(VModuleKey K, std::unique_ptr<Module>)>; - - /// Construct an LegacyIRCompileLayer with the given BaseLayer, which must - /// implement the ObjectLayer concept. - LLVM_ATTRIBUTE_DEPRECATED( - LegacyIRCompileLayer( - BaseLayerT &BaseLayer, CompileFtor Compile, - NotifyCompiledCallback NotifyCompiled = NotifyCompiledCallback()), - "ORCv1 layers (layers with the 'Legacy' prefix) are deprecated. Please " - "use " - "the ORCv2 IRCompileLayer instead"); - - /// Legacy layer constructor with deprecation acknowledgement. - LegacyIRCompileLayer( - ORCv1DeprecationAcknowledgement, BaseLayerT &BaseLayer, - CompileFtor Compile, - NotifyCompiledCallback NotifyCompiled = NotifyCompiledCallback()) - : BaseLayer(BaseLayer), Compile(std::move(Compile)), - NotifyCompiled(std::move(NotifyCompiled)) {} - - /// Get a reference to the compiler functor. - CompileFtor& getCompiler() { return Compile; } - - /// (Re)set the NotifyCompiled callback. - void setNotifyCompiled(NotifyCompiledCallback NotifyCompiled) { - this->NotifyCompiled = std::move(NotifyCompiled); - } - - /// Compile the module, and add the resulting object to the base layer - /// along with the given memory manager and symbol resolver. - Error addModule(VModuleKey K, std::unique_ptr<Module> M) { - auto Obj = Compile(*M); - if (!Obj) - return Obj.takeError(); - if (auto Err = BaseLayer.addObject(std::move(K), std::move(*Obj))) - return Err; - if (NotifyCompiled) - NotifyCompiled(std::move(K), std::move(M)); - return Error::success(); - } - - /// Remove the module associated with the VModuleKey K. - Error removeModule(VModuleKey K) { return BaseLayer.removeObject(K); } - - /// Search for the given named symbol. - /// @param Name The name of the symbol to search for. - /// @param ExportedSymbolsOnly If true, search only for exported symbols. - /// @return A handle for the given named symbol, if it exists. - JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) { - return BaseLayer.findSymbol(Name, ExportedSymbolsOnly); - } - - /// Get the address of the given symbol in compiled module represented - /// by the handle H. This call is forwarded to the base layer's - /// implementation. - /// @param K The VModuleKey for the module to search in. - /// @param Name The name of the symbol to search for. - /// @param ExportedSymbolsOnly If true, search only for exported symbols. - /// @return A handle for the given named symbol, if it is found in the - /// given module. - JITSymbol findSymbolIn(VModuleKey K, const std::string &Name, - bool ExportedSymbolsOnly) { - return BaseLayer.findSymbolIn(K, Name, ExportedSymbolsOnly); - } - - /// Immediately emit and finalize the module represented by the given - /// handle. - /// @param K The VModuleKey for the module to emit/finalize. - Error emitAndFinalize(VModuleKey K) { return BaseLayer.emitAndFinalize(K); } - -private: - BaseLayerT &BaseLayer; - CompileFtor Compile; - NotifyCompiledCallback NotifyCompiled; -}; - -template <typename BaseLayerT, typename CompileFtor> -LegacyIRCompileLayer<BaseLayerT, CompileFtor>::LegacyIRCompileLayer( - BaseLayerT &BaseLayer, CompileFtor Compile, - NotifyCompiledCallback NotifyCompiled) - : BaseLayer(BaseLayer), Compile(std::move(Compile)), - NotifyCompiled(std::move(NotifyCompiled)) {} - } // end namespace orc } // end namespace llvm diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h index 296d74ae6b86..66966a0f8762 100644 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h @@ -13,6 +13,7 @@ #ifndef LLVM_EXECUTIONENGINE_ORC_IRTRANSFORMLAYER_H #define LLVM_EXECUTIONENGINE_ORC_IRTRANSFORMLAYER_H +#include "llvm/ADT/FunctionExtras.h" #include "llvm/ExecutionEngine/JITSymbol.h" #include "llvm/ExecutionEngine/Orc/Layer.h" #include <memory> @@ -27,7 +28,7 @@ namespace orc { /// before operating on the module. class IRTransformLayer : public IRLayer { public: - using TransformFunction = std::function<Expected<ThreadSafeModule>( + using TransformFunction = unique_function<Expected<ThreadSafeModule>( ThreadSafeModule, MaterializationResponsibility &R)>; IRTransformLayer(ExecutionSession &ES, IRLayer &BaseLayer, @@ -37,7 +38,8 @@ public: this->Transform = std::move(Transform); } - void emit(MaterializationResponsibility R, ThreadSafeModule TSM) override; + void emit(std::unique_ptr<MaterializationResponsibility> R, + ThreadSafeModule TSM) override; static ThreadSafeModule identityTransform(ThreadSafeModule TSM, MaterializationResponsibility &R) { @@ -49,80 +51,6 @@ private: TransformFunction Transform; }; -/// IR mutating layer. -/// -/// This layer applies a user supplied transform to each module that is added, -/// then adds the transformed module to the layer below. -template <typename BaseLayerT, typename TransformFtor> -class LegacyIRTransformLayer { -public: - - /// Construct an LegacyIRTransformLayer with the given BaseLayer - LLVM_ATTRIBUTE_DEPRECATED( - LegacyIRTransformLayer(BaseLayerT &BaseLayer, - TransformFtor Transform = TransformFtor()), - "ORCv1 layers (layers with the 'Legacy' prefix) are deprecated. Please " - "use " - "the ORCv2 IRTransformLayer instead"); - - /// Legacy layer constructor with deprecation acknowledgement. - LegacyIRTransformLayer(ORCv1DeprecationAcknowledgement, BaseLayerT &BaseLayer, - TransformFtor Transform = TransformFtor()) - : BaseLayer(BaseLayer), Transform(std::move(Transform)) {} - - /// Apply the transform functor to the module, then add the module to - /// the layer below, along with the memory manager and symbol resolver. - /// - /// @return A handle for the added modules. - Error addModule(VModuleKey K, std::unique_ptr<Module> M) { - return BaseLayer.addModule(std::move(K), Transform(std::move(M))); - } - - /// Remove the module associated with the VModuleKey K. - Error removeModule(VModuleKey K) { return BaseLayer.removeModule(K); } - - /// Search for the given named symbol. - /// @param Name The name of the symbol to search for. - /// @param ExportedSymbolsOnly If true, search only for exported symbols. - /// @return A handle for the given named symbol, if it exists. - JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) { - return BaseLayer.findSymbol(Name, ExportedSymbolsOnly); - } - - /// Get the address of the given symbol in the context of the module - /// represented by the VModuleKey K. This call is forwarded to the base - /// layer's implementation. - /// @param K The VModuleKey for the module to search in. - /// @param Name The name of the symbol to search for. - /// @param ExportedSymbolsOnly If true, search only for exported symbols. - /// @return A handle for the given named symbol, if it is found in the - /// given module. - JITSymbol findSymbolIn(VModuleKey K, const std::string &Name, - bool ExportedSymbolsOnly) { - return BaseLayer.findSymbolIn(K, Name, ExportedSymbolsOnly); - } - - /// Immediately emit and finalize the module represented by the given - /// VModuleKey. - /// @param K The VModuleKey for the module to emit/finalize. - Error emitAndFinalize(VModuleKey K) { return BaseLayer.emitAndFinalize(K); } - - /// Access the transform functor directly. - TransformFtor& getTransform() { return Transform; } - - /// Access the mumate functor directly. - const TransformFtor& getTransform() const { return Transform; } - -private: - BaseLayerT &BaseLayer; - TransformFtor Transform; -}; - -template <typename BaseLayerT, typename TransformFtor> -LegacyIRTransformLayer<BaseLayerT, TransformFtor>::LegacyIRTransformLayer( - BaseLayerT &BaseLayer, TransformFtor Transform) - : BaseLayer(BaseLayer), Transform(std::move(Transform)) {} - } // end namespace orc } // end namespace llvm diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h index e0cfd8bf2409..78e3ceef50e2 100644 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h @@ -62,14 +62,33 @@ public: JITTargetAddress TrampolineAddr, NotifyLandingResolvedFunction OnLandingResolved) const>; - virtual ~TrampolinePool() {} + virtual ~TrampolinePool(); /// Get an available trampoline address. /// Returns an error if no trampoline can be created. - virtual Expected<JITTargetAddress> getTrampoline() = 0; + Expected<JITTargetAddress> getTrampoline() { + std::lock_guard<std::mutex> Lock(TPMutex); + if (AvailableTrampolines.empty()) { + if (auto Err = grow()) + return std::move(Err); + } + assert(!AvailableTrampolines.empty() && "Failed to grow trampoline pool"); + auto TrampolineAddr = AvailableTrampolines.back(); + AvailableTrampolines.pop_back(); + return TrampolineAddr; + } -private: - virtual void anchor(); + /// Returns the given trampoline to the pool for re-use. + void releaseTrampoline(JITTargetAddress TrampolineAddr) { + std::lock_guard<std::mutex> Lock(TPMutex); + AvailableTrampolines.push_back(TrampolineAddr); + } + +protected: + virtual Error grow() = 0; + + std::mutex TPMutex; + std::vector<JITTargetAddress> AvailableTrampolines; }; /// A trampoline pool for trampolines within the current process. @@ -90,26 +109,6 @@ public: return std::move(LTP); } - /// Get a free trampoline. Returns an error if one can not be provided (e.g. - /// because the pool is empty and can not be grown). - Expected<JITTargetAddress> getTrampoline() override { - std::lock_guard<std::mutex> Lock(LTPMutex); - if (AvailableTrampolines.empty()) { - if (auto Err = grow()) - return std::move(Err); - } - assert(!AvailableTrampolines.empty() && "Failed to grow trampoline pool"); - auto TrampolineAddr = AvailableTrampolines.back(); - AvailableTrampolines.pop_back(); - return TrampolineAddr; - } - - /// Returns the given trampoline to the pool for re-use. - void releaseTrampoline(JITTargetAddress TrampolineAddr) { - std::lock_guard<std::mutex> Lock(LTPMutex); - AvailableTrampolines.push_back(TrampolineAddr); - } - private: static JITTargetAddress reenter(void *TrampolinePoolPtr, void *TrampolineId) { LocalTrampolinePool<ORCABI> *TrampolinePool = @@ -154,8 +153,8 @@ private: } } - Error grow() { - assert(this->AvailableTrampolines.empty() && "Growing prematurely?"); + Error grow() override { + assert(AvailableTrampolines.empty() && "Growing prematurely?"); std::error_code EC; auto TrampolineBlock = @@ -175,7 +174,7 @@ private: pointerToJITTargetAddress(ResolverBlock.base()), NumTrampolines); for (unsigned I = 0; I < NumTrampolines; ++I) - this->AvailableTrampolines.push_back(pointerToJITTargetAddress( + AvailableTrampolines.push_back(pointerToJITTargetAddress( TrampolineMem + (I * ORCABI::TrampolineSize))); if (auto EC = sys::Memory::protectMappedMemory( @@ -189,10 +188,8 @@ private: ResolveLandingFunction ResolveLanding; - std::mutex LTPMutex; sys::OwningMemoryBlock ResolverBlock; std::vector<sys::OwningMemoryBlock> TrampolineBlocks; - std::vector<JITTargetAddress> AvailableTrampolines; }; /// Target-independent base class for compile callback management. diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/LLJIT.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/LLJIT.h index 96f8e169e7dc..ff0aa0238523 100644 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/LLJIT.h +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/LLJIT.h @@ -19,7 +19,6 @@ #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" #include "llvm/ExecutionEngine/Orc/IRTransformLayer.h" #include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h" -#include "llvm/ExecutionEngine/Orc/ObjectTransformLayer.h" #include "llvm/ExecutionEngine/Orc/ThreadSafeModule.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ThreadPool.h" @@ -29,6 +28,8 @@ namespace orc { class LLJITBuilderState; class LLLazyJITBuilderState; +class ObjectTransformLayer; +class TargetProcessControl; /// A pre-fabricated ORC JIT stack that can serve as an alternative to MCJIT. /// @@ -85,21 +86,8 @@ public: return ES->createJITDylib(std::move(Name)); } - /// A convenience method for defining MUs in LLJIT's Main JITDylib. This can - /// be useful for succinctly defining absolute symbols, aliases and - /// re-exports. - template <typename MUType> - Error define(std::unique_ptr<MUType> &&MU) { - return Main->define(std::move(MU)); - } - - /// A convenience method for defining MUs in LLJIT's Main JITDylib. This can - /// be usedful for succinctly defining absolute symbols, aliases and - /// re-exports. - template <typename MUType> - Error define(std::unique_ptr<MUType> &MU) { - return Main->define(MU); - } + /// Adds an IR module with the given ResourceTracker. + Error addIRModule(ResourceTrackerSP RT, ThreadSafeModule TSM); /// Adds an IR module to the given JITDylib. Error addIRModule(JITDylib &JD, ThreadSafeModule TSM); @@ -110,6 +98,9 @@ public: } /// Adds an object file to the given JITDylib. + Error addObjectFile(ResourceTrackerSP RT, std::unique_ptr<MemoryBuffer> Obj); + + /// Adds an object file to the given JITDylib. Error addObjectFile(JITDylib &JD, std::unique_ptr<MemoryBuffer> Obj); /// Adds an object file to the given JITDylib. @@ -178,7 +169,7 @@ public: ObjectLayer &getObjLinkingLayer() { return *ObjLinkingLayer; } /// Returns a reference to the object transform layer. - ObjectTransformLayer &getObjTransformLayer() { return ObjTransformLayer; } + ObjectTransformLayer &getObjTransformLayer() { return *ObjTransformLayer; } /// Returns a reference to the IR transform layer. IRTransformLayer &getIRTransformLayer() { return *TransformLayer; } @@ -195,7 +186,7 @@ public: } protected: - static std::unique_ptr<ObjectLayer> + static Expected<std::unique_ptr<ObjectLayer>> createObjectLinkingLayer(LLJITBuilderState &S, ExecutionSession &ES); static Expected<std::unique_ptr<IRCompileLayer::IRCompiler>> @@ -218,7 +209,7 @@ protected: std::unique_ptr<ThreadPool> CompileThreads; std::unique_ptr<ObjectLayer> ObjLinkingLayer; - ObjectTransformLayer ObjTransformLayer; + std::unique_ptr<ObjectTransformLayer> ObjTransformLayer; std::unique_ptr<IRCompileLayer> CompileLayer; std::unique_ptr<IRTransformLayer> TransformLayer; std::unique_ptr<IRTransformLayer> InitHelperTransformLayer; @@ -237,6 +228,9 @@ public: CODLayer->setPartitionFunction(std::move(Partition)); } + /// Returns a reference to the on-demand layer. + CompileOnDemandLayer &getCompileOnDemandLayer() { return *CODLayer; } + /// Add a module to be lazily compiled to JITDylib JD. Error addLazyIRModule(JITDylib &JD, ThreadSafeModule M); @@ -256,8 +250,9 @@ private: class LLJITBuilderState { public: - using ObjectLinkingLayerCreator = std::function<std::unique_ptr<ObjectLayer>( - ExecutionSession &, const Triple &TT)>; + using ObjectLinkingLayerCreator = + std::function<Expected<std::unique_ptr<ObjectLayer>>(ExecutionSession &, + const Triple &)>; using CompileFunctionCreator = std::function<Expected<std::unique_ptr<IRCompileLayer::IRCompiler>>( @@ -272,6 +267,7 @@ public: CompileFunctionCreator CreateCompileFunction; PlatformSetupFunction SetUpPlatform; unsigned NumCompileThreads = 0; + TargetProcessControl *TPC = nullptr; /// Called prior to JIT class construcion to fix up defaults. Error prepareForConstruction(); @@ -354,6 +350,17 @@ public: return impl(); } + /// Set a TargetProcessControl object. + /// + /// If the platform uses ObjectLinkingLayer by default and no + /// ObjectLinkingLayerCreator has been set then the TargetProcessControl + /// object will be used to supply the memory manager for the + /// ObjectLinkingLayer. + SetterImpl &setTargetProcessControl(TargetProcessControl &TPC) { + impl().TPC = &TPC; + return impl(); + } + /// Create an instance of the JIT. Expected<std::unique_ptr<JITType>> create() { if (auto Err = impl().prepareForConstruction()) diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/LambdaResolver.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/LambdaResolver.h deleted file mode 100644 index b31914f12a0d..000000000000 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/LambdaResolver.h +++ /dev/null @@ -1,84 +0,0 @@ -//===- LambdaResolverMM - Redirect symbol lookup via a functor --*- 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 -// -//===----------------------------------------------------------------------===// -// -// Defines a RuntimeDyld::SymbolResolver subclass that uses a user-supplied -// functor for symbol resolution. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_EXECUTIONENGINE_ORC_LAMBDARESOLVER_H -#define LLVM_EXECUTIONENGINE_ORC_LAMBDARESOLVER_H - -#include "llvm/ADT/STLExtras.h" -#include "llvm/ExecutionEngine/JITSymbol.h" -#include "llvm/ExecutionEngine/OrcV1Deprecation.h" -#include <memory> - -namespace llvm { -namespace orc { - -template <typename DylibLookupFtorT, typename ExternalLookupFtorT> -class LambdaResolver : public LegacyJITSymbolResolver { -public: - LLVM_ATTRIBUTE_DEPRECATED( - LambdaResolver(DylibLookupFtorT DylibLookupFtor, - ExternalLookupFtorT ExternalLookupFtor), - "ORCv1 utilities (including resolvers) are deprecated and will be " - "removed " - "in the next release. Please use ORCv2 (see docs/ORCv2.rst)"); - - LambdaResolver(ORCv1DeprecationAcknowledgement, - DylibLookupFtorT DylibLookupFtor, - ExternalLookupFtorT ExternalLookupFtor) - : DylibLookupFtor(DylibLookupFtor), - ExternalLookupFtor(ExternalLookupFtor) {} - - JITSymbol findSymbolInLogicalDylib(const std::string &Name) final { - return DylibLookupFtor(Name); - } - - JITSymbol findSymbol(const std::string &Name) final { - return ExternalLookupFtor(Name); - } - -private: - DylibLookupFtorT DylibLookupFtor; - ExternalLookupFtorT ExternalLookupFtor; -}; - -template <typename DylibLookupFtorT, typename ExternalLookupFtorT> -LambdaResolver<DylibLookupFtorT, ExternalLookupFtorT>::LambdaResolver( - DylibLookupFtorT DylibLookupFtor, ExternalLookupFtorT ExternalLookupFtor) - : DylibLookupFtor(DylibLookupFtor), ExternalLookupFtor(ExternalLookupFtor) { -} - -template <typename DylibLookupFtorT, - typename ExternalLookupFtorT> -std::shared_ptr<LambdaResolver<DylibLookupFtorT, ExternalLookupFtorT>> -createLambdaResolver(DylibLookupFtorT DylibLookupFtor, - ExternalLookupFtorT ExternalLookupFtor) { - using LR = LambdaResolver<DylibLookupFtorT, ExternalLookupFtorT>; - return std::make_unique<LR>(std::move(DylibLookupFtor), - std::move(ExternalLookupFtor)); -} - -template <typename DylibLookupFtorT, typename ExternalLookupFtorT> -std::shared_ptr<LambdaResolver<DylibLookupFtorT, ExternalLookupFtorT>> -createLambdaResolver(ORCv1DeprecationAcknowledgement, - DylibLookupFtorT DylibLookupFtor, - ExternalLookupFtorT ExternalLookupFtor) { - using LR = LambdaResolver<DylibLookupFtorT, ExternalLookupFtorT>; - return std::make_unique<LR>(AcknowledgeORCv1Deprecation, - std::move(DylibLookupFtor), - std::move(ExternalLookupFtor)); -} - -} // end namespace orc -} // end namespace llvm - -#endif // LLVM_EXECUTIONENGINE_ORC_LAMBDARESOLVER_H diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/Layer.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/Layer.h index e843d0f56245..f9cc15583b42 100644 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/Layer.h +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/Layer.h @@ -34,15 +34,15 @@ public: /// SymbolFlags and SymbolToDefinition maps. IRMaterializationUnit(ExecutionSession &ES, const IRSymbolMapper::ManglingOptions &MO, - ThreadSafeModule TSM, VModuleKey K); + ThreadSafeModule TSM); /// Create an IRMaterializationLayer from a module, and pre-existing /// SymbolFlags and SymbolToDefinition maps. The maps must provide /// entries for each definition in M. /// This constructor is useful for delegating work from one /// IRMaterializationUnit to another. - IRMaterializationUnit(ThreadSafeModule TSM, VModuleKey K, - SymbolFlagsMap SymbolFlags, SymbolStringPtr InitSymbol, + IRMaterializationUnit(ThreadSafeModule TSM, SymbolFlagsMap SymbolFlags, + SymbolStringPtr InitSymbol, SymbolNameToDefinitionMap SymbolToDefinition); /// Return the ModuleIdentifier as the name for this MaterializationUnit. @@ -94,13 +94,19 @@ public: /// Returns the current value of the CloneToNewContextOnEmit flag. bool getCloneToNewContextOnEmit() const { return CloneToNewContextOnEmit; } + /// Add a MaterializatinoUnit representing the given IR to the JITDylib + /// targeted by the given tracker. + virtual Error add(ResourceTrackerSP RT, ThreadSafeModule TSM); + /// Adds a MaterializationUnit representing the given IR to the given - /// JITDylib. - virtual Error add(JITDylib &JD, ThreadSafeModule TSM, - VModuleKey K = VModuleKey()); + /// JITDylib. If RT is not specif + Error add(JITDylib &JD, ThreadSafeModule TSM) { + return add(JD.getDefaultResourceTracker(), std::move(TSM)); + } /// Emit should materialize the given IR. - virtual void emit(MaterializationResponsibility R, ThreadSafeModule TSM) = 0; + virtual void emit(std::unique_ptr<MaterializationResponsibility> R, + ThreadSafeModule TSM) = 0; private: bool CloneToNewContextOnEmit = false; @@ -114,14 +120,12 @@ class BasicIRLayerMaterializationUnit : public IRMaterializationUnit { public: BasicIRLayerMaterializationUnit(IRLayer &L, const IRSymbolMapper::ManglingOptions &MO, - ThreadSafeModule TSM, VModuleKey K); + ThreadSafeModule TSM); private: - - void materialize(MaterializationResponsibility R) override; + void materialize(std::unique_ptr<MaterializationResponsibility> R) override; IRLayer &L; - VModuleKey K; }; /// Interface for Layers that accept object files. @@ -135,11 +139,14 @@ public: /// Adds a MaterializationUnit representing the given IR to the given /// JITDylib. - virtual Error add(JITDylib &JD, std::unique_ptr<MemoryBuffer> O, - VModuleKey K = VModuleKey()); + virtual Error add(ResourceTrackerSP RT, std::unique_ptr<MemoryBuffer> O); + + Error add(JITDylib &JD, std::unique_ptr<MemoryBuffer> O) { + return add(JD.getDefaultResourceTracker(), std::move(O)); + } /// Emit should materialize the given IR. - virtual void emit(MaterializationResponsibility R, + virtual void emit(std::unique_ptr<MaterializationResponsibility> R, std::unique_ptr<MemoryBuffer> O) = 0; private: @@ -151,9 +158,9 @@ private: class BasicObjectLayerMaterializationUnit : public MaterializationUnit { public: static Expected<std::unique_ptr<BasicObjectLayerMaterializationUnit>> - Create(ObjectLayer &L, VModuleKey K, std::unique_ptr<MemoryBuffer> O); + Create(ObjectLayer &L, std::unique_ptr<MemoryBuffer> O); - BasicObjectLayerMaterializationUnit(ObjectLayer &L, VModuleKey K, + BasicObjectLayerMaterializationUnit(ObjectLayer &L, std::unique_ptr<MemoryBuffer> O, SymbolFlagsMap SymbolFlags, SymbolStringPtr InitSymbol); @@ -162,8 +169,7 @@ public: StringRef getName() const override; private: - - void materialize(MaterializationResponsibility R) override; + void materialize(std::unique_ptr<MaterializationResponsibility> R) override; void discard(const JITDylib &JD, const SymbolStringPtr &Name) override; ObjectLayer &L; diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h deleted file mode 100644 index 84f5e0350c2e..000000000000 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h +++ /dev/null @@ -1,267 +0,0 @@ -//===- LazyEmittingLayer.h - Lazily emit IR to lower JIT layers -*- 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 a lazy-emitting layer for the JIT. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_EXECUTIONENGINE_ORC_LAZYEMITTINGLAYER_H -#define LLVM_EXECUTIONENGINE_ORC_LAZYEMITTINGLAYER_H - -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/StringMap.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ExecutionEngine/JITSymbol.h" -#include "llvm/ExecutionEngine/Orc/Core.h" -#include "llvm/IR/GlobalValue.h" -#include "llvm/IR/Mangler.h" -#include "llvm/IR/Module.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/raw_ostream.h" -#include <algorithm> -#include <cassert> -#include <list> -#include <memory> -#include <string> - -namespace llvm { -namespace orc { - -/// Lazy-emitting IR layer. -/// -/// This layer accepts LLVM IR Modules (via addModule) but does not -/// immediately emit them the layer below. Instead, emission to the base layer -/// is deferred until the first time the client requests the address (via -/// JITSymbol::getAddress) for a symbol contained in this layer. -template <typename BaseLayerT> class LazyEmittingLayer { -private: - class EmissionDeferredModule { - public: - EmissionDeferredModule(VModuleKey K, std::unique_ptr<Module> M) - : K(std::move(K)), M(std::move(M)) {} - - JITSymbol find(StringRef Name, bool ExportedSymbolsOnly, BaseLayerT &B) { - switch (EmitState) { - case NotEmitted: - if (auto GV = searchGVs(Name, ExportedSymbolsOnly)) { - JITSymbolFlags Flags = JITSymbolFlags::fromGlobalValue(*GV); - auto GetAddress = [this, ExportedSymbolsOnly, Name = Name.str(), - &B]() -> Expected<JITTargetAddress> { - if (this->EmitState == Emitting) - return 0; - else if (this->EmitState == NotEmitted) { - this->EmitState = Emitting; - if (auto Err = this->emitToBaseLayer(B)) - return std::move(Err); - this->EmitState = Emitted; - } - if (auto Sym = B.findSymbolIn(K, Name, ExportedSymbolsOnly)) - return Sym.getAddress(); - else if (auto Err = Sym.takeError()) - return std::move(Err); - else - llvm_unreachable("Successful symbol lookup should return " - "definition address here"); - }; - return JITSymbol(std::move(GetAddress), Flags); - } else - return nullptr; - case Emitting: - // Calling "emit" can trigger a recursive call to 'find' (e.g. to check - // for pre-existing definitions of common-symbol), but any symbol in - // this module would already have been found internally (in the - // RuntimeDyld that did the lookup), so just return a nullptr here. - return nullptr; - case Emitted: - return B.findSymbolIn(K, std::string(Name), ExportedSymbolsOnly); - } - llvm_unreachable("Invalid emit-state."); - } - - Error removeModuleFromBaseLayer(BaseLayerT& BaseLayer) { - return EmitState != NotEmitted ? BaseLayer.removeModule(K) - : Error::success(); - } - - void emitAndFinalize(BaseLayerT &BaseLayer) { - assert(EmitState != Emitting && - "Cannot emitAndFinalize while already emitting"); - if (EmitState == NotEmitted) { - EmitState = Emitting; - emitToBaseLayer(BaseLayer); - EmitState = Emitted; - } - BaseLayer.emitAndFinalize(K); - } - - private: - - const GlobalValue* searchGVs(StringRef Name, - bool ExportedSymbolsOnly) const { - // FIXME: We could clean all this up if we had a way to reliably demangle - // names: We could just demangle name and search, rather than - // mangling everything else. - - // If we have already built the mangled name set then just search it. - if (MangledSymbols) { - auto VI = MangledSymbols->find(Name); - if (VI == MangledSymbols->end()) - return nullptr; - auto GV = VI->second; - if (!ExportedSymbolsOnly || GV->hasDefaultVisibility()) - return GV; - return nullptr; - } - - // If we haven't built the mangled name set yet, try to build it. As an - // optimization this will leave MangledNames set to nullptr if we find - // Name in the process of building the set. - return buildMangledSymbols(Name, ExportedSymbolsOnly); - } - - Error emitToBaseLayer(BaseLayerT &BaseLayer) { - // We don't need the mangled names set any more: Once we've emitted this - // to the base layer we'll just look for symbols there. - MangledSymbols.reset(); - return BaseLayer.addModule(std::move(K), std::move(M)); - } - - // If the mangled name of the given GlobalValue matches the given search - // name (and its visibility conforms to the ExportedSymbolsOnly flag) then - // return the symbol. Otherwise, add the mangled name to the Names map and - // return nullptr. - const GlobalValue* addGlobalValue(StringMap<const GlobalValue*> &Names, - const GlobalValue &GV, - const Mangler &Mang, StringRef SearchName, - bool ExportedSymbolsOnly) const { - // Modules don't "provide" decls or common symbols. - if (GV.isDeclaration() || GV.hasCommonLinkage()) - return nullptr; - - // Mangle the GV name. - std::string MangledName; - { - raw_string_ostream MangledNameStream(MangledName); - Mang.getNameWithPrefix(MangledNameStream, &GV, false); - } - - // Check whether this is the name we were searching for, and if it is then - // bail out early. - if (MangledName == SearchName) - if (!ExportedSymbolsOnly || GV.hasDefaultVisibility()) - return &GV; - - // Otherwise add this to the map for later. - Names[MangledName] = &GV; - return nullptr; - } - - // Build the MangledSymbols map. Bails out early (with MangledSymbols left set - // to nullptr) if the given SearchName is found while building the map. - const GlobalValue* buildMangledSymbols(StringRef SearchName, - bool ExportedSymbolsOnly) const { - assert(!MangledSymbols && "Mangled symbols map already exists?"); - - auto Symbols = std::make_unique<StringMap<const GlobalValue*>>(); - - Mangler Mang; - - for (const auto &GO : M->global_objects()) - if (auto GV = addGlobalValue(*Symbols, GO, Mang, SearchName, - ExportedSymbolsOnly)) - return GV; - - MangledSymbols = std::move(Symbols); - return nullptr; - } - - enum { NotEmitted, Emitting, Emitted } EmitState = NotEmitted; - VModuleKey K; - std::unique_ptr<Module> M; - mutable std::unique_ptr<StringMap<const GlobalValue*>> MangledSymbols; - }; - - BaseLayerT &BaseLayer; - std::map<VModuleKey, std::unique_ptr<EmissionDeferredModule>> ModuleMap; - -public: - - /// Construct a lazy emitting layer. - LLVM_ATTRIBUTE_DEPRECATED( - LazyEmittingLayer(BaseLayerT &BaseLayer), - "ORCv1 layers (including LazyEmittingLayer) are deprecated. Please use " - "ORCv2, where lazy emission is the default"); - - /// Construct a lazy emitting layer. - LazyEmittingLayer(ORCv1DeprecationAcknowledgement, BaseLayerT &BaseLayer) - : BaseLayer(BaseLayer) {} - - /// Add the given module to the lazy emitting layer. - Error addModule(VModuleKey K, std::unique_ptr<Module> M) { - assert(!ModuleMap.count(K) && "VModuleKey K already in use"); - ModuleMap[K] = - std::make_unique<EmissionDeferredModule>(std::move(K), std::move(M)); - return Error::success(); - } - - /// Remove the module represented by the given handle. - /// - /// This method will free the memory associated with the given module, both - /// in this layer, and the base layer. - Error removeModule(VModuleKey K) { - auto I = ModuleMap.find(K); - assert(I != ModuleMap.end() && "VModuleKey K not valid here"); - auto EDM = std::move(I.second); - ModuleMap.erase(I); - return EDM->removeModuleFromBaseLayer(BaseLayer); - } - - /// Search for the given named symbol. - /// @param Name The name of the symbol to search for. - /// @param ExportedSymbolsOnly If true, search only for exported symbols. - /// @return A handle for the given named symbol, if it exists. - JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) { - // Look for the symbol among existing definitions. - if (auto Symbol = BaseLayer.findSymbol(Name, ExportedSymbolsOnly)) - return Symbol; - - // If not found then search the deferred modules. If any of these contain a - // definition of 'Name' then they will return a JITSymbol that will emit - // the corresponding module when the symbol address is requested. - for (auto &KV : ModuleMap) - if (auto Symbol = KV.second->find(Name, ExportedSymbolsOnly, BaseLayer)) - return Symbol; - - // If no definition found anywhere return a null symbol. - return nullptr; - } - - /// Get the address of the given symbol in the context of the of - /// compiled modules represented by the key K. - JITSymbol findSymbolIn(VModuleKey K, const std::string &Name, - bool ExportedSymbolsOnly) { - assert(ModuleMap.count(K) && "VModuleKey K not valid here"); - return ModuleMap[K]->find(Name, ExportedSymbolsOnly, BaseLayer); - } - - /// Immediately emit and finalize the module represented by the given - /// key. - Error emitAndFinalize(VModuleKey K) { - assert(ModuleMap.count(K) && "VModuleKey K not valid here"); - return ModuleMap[K]->emitAndFinalize(BaseLayer); - } -}; - -template <typename BaseLayerT> -LazyEmittingLayer<BaseLayerT>::LazyEmittingLayer(BaseLayerT &BaseLayer) - : BaseLayer(BaseLayer) {} - -} // end namespace orc -} // end namespace llvm - -#endif // LLVM_EXECUTIONENGINE_ORC_LAZYEMITTINGLAYER_H diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/LazyReexports.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/LazyReexports.h index 0d3ccecdf121..e6a9d8945285 100644 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/LazyReexports.h +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/LazyReexports.h @@ -40,6 +40,9 @@ public: using NotifyResolvedFunction = unique_function<Error(JITTargetAddress ResolvedAddr)>; + LazyCallThroughManager(ExecutionSession &ES, + JITTargetAddress ErrorHandlerAddr, TrampolinePool *TP); + // Return a free call-through trampoline and bind it to look up and call // through to the given symbol. Expected<JITTargetAddress> @@ -56,9 +59,6 @@ protected: using NotifyLandingResolvedFunction = TrampolinePool::NotifyLandingResolvedFunction; - LazyCallThroughManager(ExecutionSession &ES, - JITTargetAddress ErrorHandlerAddr, TrampolinePool *TP); - struct ReexportsEntry { JITDylib *SourceJD; SymbolStringPtr SymbolName; @@ -144,12 +144,12 @@ public: IndirectStubsManager &ISManager, JITDylib &SourceJD, SymbolAliasMap CallableAliases, - ImplSymbolMap *SrcJDLoc, VModuleKey K); + ImplSymbolMap *SrcJDLoc); StringRef getName() const override; private: - void materialize(MaterializationResponsibility R) override; + void materialize(std::unique_ptr<MaterializationResponsibility> R) override; void discard(const JITDylib &JD, const SymbolStringPtr &Name) override; static SymbolFlagsMap extractFlags(const SymbolAliasMap &Aliases); @@ -166,11 +166,10 @@ private: inline std::unique_ptr<LazyReexportsMaterializationUnit> lazyReexports(LazyCallThroughManager &LCTManager, IndirectStubsManager &ISManager, JITDylib &SourceJD, - SymbolAliasMap CallableAliases, ImplSymbolMap *SrcJDLoc = nullptr, - VModuleKey K = VModuleKey()) { + SymbolAliasMap CallableAliases, + ImplSymbolMap *SrcJDLoc = nullptr) { return std::make_unique<LazyReexportsMaterializationUnit>( - LCTManager, ISManager, SourceJD, std::move(CallableAliases), SrcJDLoc, - std::move(K)); + LCTManager, ISManager, SourceJD, std::move(CallableAliases), SrcJDLoc); } } // End namespace orc diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/Legacy.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/Legacy.h deleted file mode 100644 index b20202a49ef6..000000000000 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/Legacy.h +++ /dev/null @@ -1,211 +0,0 @@ -//===--- Legacy.h -- Adapters for ExecutionEngine API interop ---*- 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_LEGACY_H -#define LLVM_EXECUTIONENGINE_ORC_LEGACY_H - -#include "llvm/ExecutionEngine/JITSymbol.h" -#include "llvm/ExecutionEngine/Orc/Core.h" - -namespace llvm { -namespace orc { - -/// SymbolResolver is a composable interface for looking up symbol flags -/// and addresses using the AsynchronousSymbolQuery type. It will -/// eventually replace the LegacyJITSymbolResolver interface as the -/// stardard ORC symbol resolver type. -/// -/// FIXME: SymbolResolvers should go away and be replaced with VSOs with -/// defenition generators. -class SymbolResolver { -public: - virtual ~SymbolResolver() = default; - - /// Returns the subset of the given symbols that the caller is responsible for - /// materializing. - virtual SymbolNameSet getResponsibilitySet(const SymbolNameSet &Symbols) = 0; - - /// For each symbol in Symbols that can be found, assigns that symbols - /// value in Query. Returns the set of symbols that could not be found. - virtual SymbolNameSet lookup(std::shared_ptr<AsynchronousSymbolQuery> Query, - SymbolNameSet Symbols) = 0; - -private: - virtual void anchor(); -}; - -/// Implements SymbolResolver with a pair of supplied function objects -/// for convenience. See createSymbolResolver. -template <typename GetResponsibilitySetFn, typename LookupFn> -class LambdaSymbolResolver final : public SymbolResolver { -public: - template <typename GetResponsibilitySetFnRef, typename LookupFnRef> - LambdaSymbolResolver(GetResponsibilitySetFnRef &&GetResponsibilitySet, - LookupFnRef &&Lookup) - : GetResponsibilitySet( - std::forward<GetResponsibilitySetFnRef>(GetResponsibilitySet)), - Lookup(std::forward<LookupFnRef>(Lookup)) {} - - SymbolNameSet getResponsibilitySet(const SymbolNameSet &Symbols) final { - return GetResponsibilitySet(Symbols); - } - - SymbolNameSet lookup(std::shared_ptr<AsynchronousSymbolQuery> Query, - SymbolNameSet Symbols) final { - return Lookup(std::move(Query), std::move(Symbols)); - } - -private: - GetResponsibilitySetFn GetResponsibilitySet; - LookupFn Lookup; -}; - -/// Creates a SymbolResolver implementation from the pair of supplied -/// function objects. -template <typename GetResponsibilitySetFn, typename LookupFn> -std::unique_ptr<LambdaSymbolResolver< - std::remove_cv_t<std::remove_reference_t<GetResponsibilitySetFn>>, - std::remove_cv_t<std::remove_reference_t<LookupFn>>>> -createSymbolResolver(GetResponsibilitySetFn &&GetResponsibilitySet, - LookupFn &&Lookup) { - using LambdaSymbolResolverImpl = LambdaSymbolResolver< - std::remove_cv_t<std::remove_reference_t<GetResponsibilitySetFn>>, - std::remove_cv_t<std::remove_reference_t<LookupFn>>>; - return std::make_unique<LambdaSymbolResolverImpl>( - std::forward<GetResponsibilitySetFn>(GetResponsibilitySet), - std::forward<LookupFn>(Lookup)); -} - -/// Legacy adapter. Remove once we kill off the old ORC layers. -class JITSymbolResolverAdapter : public JITSymbolResolver { -public: - JITSymbolResolverAdapter(ExecutionSession &ES, SymbolResolver &R, - MaterializationResponsibility *MR); - Expected<LookupSet> getResponsibilitySet(const LookupSet &Symbols) override; - void lookup(const LookupSet &Symbols, OnResolvedFunction OnResolved) override; - -private: - ExecutionSession &ES; - std::set<SymbolStringPtr> ResolvedStrings; - SymbolResolver &R; - MaterializationResponsibility *MR; -}; - -/// Use the given legacy-style FindSymbol function (i.e. a function that takes -/// a const std::string& or StringRef and returns a JITSymbol) to get the -/// subset of symbols that the caller is responsible for materializing. If any -/// JITSymbol returned by FindSymbol is in an error state the function returns -/// immediately with that error. -/// -/// Useful for implementing getResponsibilitySet bodies that query legacy -/// resolvers. -template <typename FindSymbolFn> -Expected<SymbolNameSet> -getResponsibilitySetWithLegacyFn(const SymbolNameSet &Symbols, - FindSymbolFn FindSymbol) { - SymbolNameSet Result; - - for (auto &S : Symbols) { - if (JITSymbol Sym = FindSymbol(*S)) { - if (!Sym.getFlags().isStrong()) - Result.insert(S); - } else if (auto Err = Sym.takeError()) - return std::move(Err); - } - - return Result; -} - -/// Use the given legacy-style FindSymbol function (i.e. a function that -/// takes a const std::string& or StringRef and returns a JITSymbol) to -/// find the address and flags for each symbol in Symbols and store the -/// result in Query. If any JITSymbol returned by FindSymbol is in an -/// error then Query.notifyFailed(...) is called with that error and the -/// function returns immediately. On success, returns the set of symbols -/// not found. -/// -/// Useful for implementing lookup bodies that query legacy resolvers. -template <typename FindSymbolFn> -SymbolNameSet -lookupWithLegacyFn(ExecutionSession &ES, AsynchronousSymbolQuery &Query, - const SymbolNameSet &Symbols, FindSymbolFn FindSymbol) { - SymbolNameSet SymbolsNotFound; - bool NewSymbolsResolved = false; - - for (auto &S : Symbols) { - if (JITSymbol Sym = FindSymbol(*S)) { - if (auto Addr = Sym.getAddress()) { - Query.notifySymbolMetRequiredState( - S, JITEvaluatedSymbol(*Addr, Sym.getFlags())); - NewSymbolsResolved = true; - } else { - ES.legacyFailQuery(Query, Addr.takeError()); - return SymbolNameSet(); - } - } else if (auto Err = Sym.takeError()) { - ES.legacyFailQuery(Query, std::move(Err)); - return SymbolNameSet(); - } else - SymbolsNotFound.insert(S); - } - - if (NewSymbolsResolved && Query.isComplete()) - Query.handleComplete(); - - return SymbolsNotFound; -} - -/// An ORC SymbolResolver implementation that uses a legacy -/// findSymbol-like function to perform lookup; -template <typename LegacyLookupFn> -class LegacyLookupFnResolver final : public SymbolResolver { -public: - using ErrorReporter = std::function<void(Error)>; - - LegacyLookupFnResolver(ExecutionSession &ES, LegacyLookupFn LegacyLookup, - ErrorReporter ReportError) - : ES(ES), LegacyLookup(std::move(LegacyLookup)), - ReportError(std::move(ReportError)) {} - - SymbolNameSet getResponsibilitySet(const SymbolNameSet &Symbols) final { - if (auto ResponsibilitySet = - getResponsibilitySetWithLegacyFn(Symbols, LegacyLookup)) - return std::move(*ResponsibilitySet); - else { - ReportError(ResponsibilitySet.takeError()); - return SymbolNameSet(); - } - } - - SymbolNameSet lookup(std::shared_ptr<AsynchronousSymbolQuery> Query, - SymbolNameSet Symbols) final { - return lookupWithLegacyFn(ES, *Query, Symbols, LegacyLookup); - } - -private: - ExecutionSession &ES; - LegacyLookupFn LegacyLookup; - ErrorReporter ReportError; -}; - -template <typename LegacyLookupFn> -std::shared_ptr<LegacyLookupFnResolver<LegacyLookupFn>> -createLegacyLookupResolver(ExecutionSession &ES, LegacyLookupFn LegacyLookup, - std::function<void(Error)> ErrorReporter) { - return std::make_shared<LegacyLookupFnResolver<LegacyLookupFn>>( - ES, std::move(LegacyLookup), std::move(ErrorReporter)); -} - -} // End namespace orc -} // End namespace llvm - -#endif // LLVM_EXECUTIONENGINE_ORC_LEGACY_H diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/MachOPlatform.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/MachOPlatform.h index 15fe079eccaf..90e1d4704f34 100644 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/MachOPlatform.h +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/MachOPlatform.h @@ -98,8 +98,9 @@ public: ExecutionSession &getExecutionSession() const { return ES; } Error setupJITDylib(JITDylib &JD) override; - Error notifyAdding(JITDylib &JD, const MaterializationUnit &MU) override; - Error notifyRemoving(JITDylib &JD, VModuleKey K) override; + Error notifyAdding(ResourceTracker &RT, + const MaterializationUnit &MU) override; + Error notifyRemoving(ResourceTracker &RT) override; Expected<InitializerSequence> getInitializerSequence(JITDylib &JD); @@ -119,6 +120,19 @@ private: LocalDependenciesMap getSyntheticSymbolLocalDependencies( MaterializationResponsibility &MR) override; + // FIXME: We should be tentatively tracking scraped sections and discarding + // if the MR fails. + Error notifyFailed(MaterializationResponsibility &MR) override { + return Error::success(); + } + + Error notifyRemovingResources(ResourceKey K) override { + return Error::success(); + } + + void notifyTransferringResources(ResourceKey DstKey, + ResourceKey SrcKey) override {} + private: using InitSymbolDepMap = DenseMap<MaterializationResponsibility *, JITLinkSymbolVector>; @@ -136,8 +150,6 @@ private: InitSymbolDepMap InitSymbolDeps; }; - static std::vector<JITDylib *> getDFSLinkOrder(JITDylib &JD); - void registerInitInfo(JITDylib &JD, JITTargetAddress ObjCImageInfoAddr, MachOJITDylibInitializers::SectionExtent ModInits, MachOJITDylibInitializers::SectionExtent ObjCSelRefs, diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/NullResolver.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/NullResolver.h deleted file mode 100644 index ffa37a13d064..000000000000 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/NullResolver.h +++ /dev/null @@ -1,43 +0,0 @@ -//===------ NullResolver.h - Reject symbol lookup requests ------*- 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 -// -//===----------------------------------------------------------------------===// -// -// Defines a RuntimeDyld::SymbolResolver subclass that rejects all symbol -// resolution requests, for clients that have no cross-object fixups. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_EXECUTIONENGINE_ORC_NULLRESOLVER_H -#define LLVM_EXECUTIONENGINE_ORC_NULLRESOLVER_H - -#include "llvm/ExecutionEngine/Orc/Legacy.h" -#include "llvm/ExecutionEngine/RuntimeDyld.h" - -namespace llvm { -namespace orc { - -class NullResolver : public SymbolResolver { -public: - SymbolNameSet getResponsibilitySet(const SymbolNameSet &Symbols) final; - - SymbolNameSet lookup(std::shared_ptr<AsynchronousSymbolQuery> Query, - SymbolNameSet Symbols) final; -}; - -/// SymbolResolver impliementation that rejects all resolution requests. -/// Useful for clients that have no cross-object fixups. -class NullLegacyResolver : public LegacyJITSymbolResolver { -public: - JITSymbol findSymbol(const std::string &Name) final; - - JITSymbol findSymbolInLogicalDylib(const std::string &Name) final; -}; - -} // End namespace orc. -} // End namespace llvm. - -#endif // LLVM_EXECUTIONENGINE_ORC_NULLRESOLVER_H diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h index 2bfe3b001709..f2975e29fcd6 100644 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h @@ -35,6 +35,7 @@ namespace llvm { namespace jitlink { class EHFrameRegistrar; +class LinkGraph; class Symbol; } // namespace jitlink @@ -51,7 +52,7 @@ class ObjectLinkingLayerJITLinkContext; /// 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 { +class ObjectLinkingLayer : public ObjectLayer, private ResourceManager { friend class ObjectLinkingLayerJITLinkContext; public: @@ -72,10 +73,10 @@ public: virtual Error notifyEmitted(MaterializationResponsibility &MR) { return Error::success(); } - virtual Error notifyRemovingModule(VModuleKey K) { - return Error::success(); - } - virtual Error notifyRemovingAllModules() { 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 @@ -90,8 +91,14 @@ public: using ReturnObjectBufferFunction = std::function<void(std::unique_ptr<MemoryBuffer>)>; - /// Construct an ObjectLinkingLayer with the given NotifyLoaded, - /// and NotifyEmitted functors. + /// 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<jitlink::JITLinkMemoryManager> MemMgr); @@ -112,10 +119,14 @@ public: return *this; } - /// Emit the object. - void emit(MaterializationResponsibility R, + /// Emit an object file. + void emit(std::unique_ptr<MaterializationResponsibility> R, std::unique_ptr<MemoryBuffer> O) override; + /// Emit a LinkGraph. + void emit(std::unique_ptr<MaterializationResponsibility> R, + std::unique_ptr<jitlink::LinkGraph> 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 @@ -155,27 +166,31 @@ private: void notifyLoaded(MaterializationResponsibility &MR); Error notifyEmitted(MaterializationResponsibility &MR, AllocPtr Alloc); - Error removeModule(VModuleKey K); - Error removeAllModules(); + Error handleRemoveResources(ResourceKey K) override; + void handleTransferResources(ResourceKey DstKey, ResourceKey SrcKey) override; mutable std::mutex LayerMutex; - std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr; + jitlink::JITLinkMemoryManager &MemMgr; + std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgrOwnership; bool OverrideObjectFlags = false; bool AutoClaimObjectSymbols = false; ReturnObjectBufferFunction ReturnObjectBuffer; - DenseMap<VModuleKey, AllocPtr> TrackedAllocs; - std::vector<AllocPtr> UntrackedAllocs; + DenseMap<ResourceKey, std::vector<AllocPtr>> Allocs; std::vector<std::unique_ptr<Plugin>> Plugins; }; class EHFrameRegistrationPlugin : public ObjectLinkingLayer::Plugin { public: - EHFrameRegistrationPlugin(jitlink::EHFrameRegistrar &Registrar); - Error notifyEmitted(MaterializationResponsibility &MR) override; + EHFrameRegistrationPlugin( + ExecutionSession &ES, + std::unique_ptr<jitlink::EHFrameRegistrar> Registrar); void modifyPassConfig(MaterializationResponsibility &MR, const Triple &TT, jitlink::PassConfiguration &PassConfig) override; - Error notifyRemovingModule(VModuleKey K) override; - Error notifyRemovingAllModules() override; + Error notifyEmitted(MaterializationResponsibility &MR) override; + Error notifyFailed(MaterializationResponsibility &MR) override; + Error notifyRemovingResources(ResourceKey K) override; + void notifyTransferringResources(ResourceKey DstKey, + ResourceKey SrcKey) override; private: @@ -185,10 +200,10 @@ private: }; std::mutex EHFramePluginMutex; - jitlink::EHFrameRegistrar &Registrar; + ExecutionSession &ES; + std::unique_ptr<jitlink::EHFrameRegistrar> Registrar; DenseMap<MaterializationResponsibility *, EHFrameRange> InProcessLinks; - DenseMap<VModuleKey, EHFrameRange> TrackedEHFrameRanges; - std::vector<EHFrameRange> UntrackedEHFrameRanges; + DenseMap<ResourceKey, std::vector<EHFrameRange>> EHFrameRanges; }; } // end namespace orc diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/ObjectTransformLayer.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/ObjectTransformLayer.h index bf989cc8677c..d8395ab34e47 100644 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/ObjectTransformLayer.h +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/ObjectTransformLayer.h @@ -31,7 +31,7 @@ public: ObjectTransformLayer(ExecutionSession &ES, ObjectLayer &BaseLayer, TransformFunction Transform = TransformFunction()); - void emit(MaterializationResponsibility R, + void emit(std::unique_ptr<MaterializationResponsibility> R, std::unique_ptr<MemoryBuffer> O) override; void setTransform(TransformFunction Transform) { @@ -43,88 +43,6 @@ private: TransformFunction Transform; }; -/// Object mutating layer. -/// -/// This layer accepts sets of ObjectFiles (via addObject). It -/// immediately applies the user supplied functor to each object, then adds -/// the set of transformed objects to the layer below. -template <typename BaseLayerT, typename TransformFtor> -class LegacyObjectTransformLayer { -public: - /// Construct an ObjectTransformLayer with the given BaseLayer - LLVM_ATTRIBUTE_DEPRECATED( - LegacyObjectTransformLayer(BaseLayerT &BaseLayer, - TransformFtor Transform = TransformFtor()), - "ORCv1 layers (layers with the 'Legacy' prefix) are deprecated. Please " - "use " - "the ORCv2 ObjectTransformLayer instead"); - - /// Legacy layer constructor with deprecation acknowledgement. - LegacyObjectTransformLayer(ORCv1DeprecationAcknowledgement, - BaseLayerT &BaseLayer, - TransformFtor Transform = TransformFtor()) - : BaseLayer(BaseLayer), Transform(std::move(Transform)) {} - - /// Apply the transform functor to each object in the object set, then - /// add the resulting set of objects to the base layer, along with the - /// memory manager and symbol resolver. - /// - /// @return A handle for the added objects. - template <typename ObjectPtr> Error addObject(VModuleKey K, ObjectPtr Obj) { - return BaseLayer.addObject(std::move(K), Transform(std::move(Obj))); - } - - /// Remove the object set associated with the VModuleKey K. - Error removeObject(VModuleKey K) { return BaseLayer.removeObject(K); } - - /// Search for the given named symbol. - /// @param Name The name of the symbol to search for. - /// @param ExportedSymbolsOnly If true, search only for exported symbols. - /// @return A handle for the given named symbol, if it exists. - JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) { - return BaseLayer.findSymbol(Name, ExportedSymbolsOnly); - } - - /// Get the address of the given symbol in the context of the set of - /// objects represented by the VModuleKey K. This call is forwarded to - /// the base layer's implementation. - /// @param K The VModuleKey associated with the object set to search in. - /// @param Name The name of the symbol to search for. - /// @param ExportedSymbolsOnly If true, search only for exported symbols. - /// @return A handle for the given named symbol, if it is found in the - /// given object set. - JITSymbol findSymbolIn(VModuleKey K, const std::string &Name, - bool ExportedSymbolsOnly) { - return BaseLayer.findSymbolIn(K, Name, ExportedSymbolsOnly); - } - - /// Immediately emit and finalize the object set represented by the - /// given VModuleKey K. - Error emitAndFinalize(VModuleKey K) { return BaseLayer.emitAndFinalize(K); } - - /// Map section addresses for the objects associated with the - /// VModuleKey K. - void mapSectionAddress(VModuleKey K, const void *LocalAddress, - JITTargetAddress TargetAddr) { - BaseLayer.mapSectionAddress(K, LocalAddress, TargetAddr); - } - - /// Access the transform functor directly. - TransformFtor &getTransform() { return Transform; } - - /// Access the mumate functor directly. - const TransformFtor &getTransform() const { return Transform; } - -private: - BaseLayerT &BaseLayer; - TransformFtor Transform; -}; - -template <typename BaseLayerT, typename TransformFtor> -LegacyObjectTransformLayer<BaseLayerT, TransformFtor>:: - LegacyObjectTransformLayer(BaseLayerT &BaseLayer, TransformFtor Transform) - : BaseLayer(BaseLayer), Transform(std::move(Transform)) {} - } // end namespace orc } // end namespace llvm diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/OrcRPCTargetProcessControl.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/OrcRPCTargetProcessControl.h new file mode 100644 index 000000000000..a8aa42799115 --- /dev/null +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/OrcRPCTargetProcessControl.h @@ -0,0 +1,415 @@ +//===--- OrcRPCTargetProcessControl.h - Remote target control ---*- 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 +// +//===----------------------------------------------------------------------===// +// +// Utilities for interacting with target processes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORC_ORCRPCTARGETPROCESSCONTROL_H +#define LLVM_EXECUTIONENGINE_ORC_ORCRPCTARGETPROCESSCONTROL_H + +#include "llvm/ExecutionEngine/Orc/Shared/RPCUtils.h" +#include "llvm/ExecutionEngine/Orc/Shared/RawByteChannel.h" +#include "llvm/ExecutionEngine/Orc/TargetProcess/OrcRPCTPCServer.h" +#include "llvm/ExecutionEngine/Orc/TargetProcessControl.h" +#include "llvm/Support/MSVCErrorWorkarounds.h" + +namespace llvm { +namespace orc { + +/// JITLinkMemoryManager implementation for a process connected via an ORC RPC +/// endpoint. +template <typename OrcRPCTPCImplT> +class OrcRPCTPCJITLinkMemoryManager : public jitlink::JITLinkMemoryManager { +private: + struct HostAlloc { + std::unique_ptr<char[]> Mem; + uint64_t Size; + }; + + struct TargetAlloc { + JITTargetAddress Address = 0; + uint64_t AllocatedSize = 0; + }; + + using HostAllocMap = DenseMap<int, HostAlloc>; + using TargetAllocMap = DenseMap<int, TargetAlloc>; + +public: + class OrcRPCAllocation : public Allocation { + public: + OrcRPCAllocation(OrcRPCTPCJITLinkMemoryManager<OrcRPCTPCImplT> &Parent, + HostAllocMap HostAllocs, TargetAllocMap TargetAllocs) + : Parent(Parent), HostAllocs(std::move(HostAllocs)), + TargetAllocs(std::move(TargetAllocs)) { + assert(HostAllocs.size() == TargetAllocs.size() && + "HostAllocs size should match TargetAllocs"); + } + + ~OrcRPCAllocation() override { + assert(TargetAllocs.empty() && "failed to deallocate"); + } + + MutableArrayRef<char> getWorkingMemory(ProtectionFlags Seg) override { + auto I = HostAllocs.find(Seg); + assert(I != HostAllocs.end() && "No host allocation for segment"); + auto &HA = I->second; + return {HA.Mem.get(), static_cast<size_t>(HA.Size)}; + } + + JITTargetAddress getTargetMemory(ProtectionFlags Seg) override { + auto I = TargetAllocs.find(Seg); + assert(I != TargetAllocs.end() && "No target allocation for segment"); + return I->second.Address; + } + + void finalizeAsync(FinalizeContinuation OnFinalize) override { + + std::vector<tpctypes::BufferWrite> BufferWrites; + orcrpctpc::ReleaseOrFinalizeMemRequest FMR; + + for (auto &KV : HostAllocs) { + assert(TargetAllocs.count(KV.first) && + "No target allocation for buffer"); + auto &HA = KV.second; + auto &TA = TargetAllocs[KV.first]; + BufferWrites.push_back({TA.Address, StringRef(HA.Mem.get(), HA.Size)}); + FMR.push_back({orcrpctpc::toWireProtectionFlags( + static_cast<sys::Memory::ProtectionFlags>(KV.first)), + TA.Address, TA.AllocatedSize}); + } + + DEBUG_WITH_TYPE("orc", { + dbgs() << "finalizeAsync " << (void *)this << ":\n"; + auto FMRI = FMR.begin(); + for (auto &B : BufferWrites) { + auto Prot = FMRI->Prot; + ++FMRI; + dbgs() << " Writing " << formatv("{0:x16}", B.Buffer.size()) + << " bytes to " << ((Prot & orcrpctpc::WPF_Read) ? 'R' : '-') + << ((Prot & orcrpctpc::WPF_Write) ? 'W' : '-') + << ((Prot & orcrpctpc::WPF_Exec) ? 'X' : '-') + << " segment: local " << (const void *)B.Buffer.data() + << " -> target " << formatv("{0:x16}", B.Address) << "\n"; + } + }); + if (auto Err = + Parent.Parent.getMemoryAccess().writeBuffers(BufferWrites)) { + OnFinalize(std::move(Err)); + return; + } + + DEBUG_WITH_TYPE("orc", dbgs() << " Applying permissions...\n"); + if (auto Err = + Parent.getEndpoint().template callAsync<orcrpctpc::FinalizeMem>( + [OF = std::move(OnFinalize)](Error Err2) { + // FIXME: Dispatch to work queue. + std::thread([OF = std::move(OF), + Err3 = std::move(Err2)]() mutable { + DEBUG_WITH_TYPE( + "orc", { dbgs() << " finalizeAsync complete\n"; }); + OF(std::move(Err3)); + }).detach(); + return Error::success(); + }, + FMR)) { + DEBUG_WITH_TYPE("orc", dbgs() << " failed.\n"); + Parent.getEndpoint().abandonPendingResponses(); + Parent.reportError(std::move(Err)); + } + DEBUG_WITH_TYPE("orc", { + dbgs() << "Leaving finalizeAsync (finalization may continue in " + "background)\n"; + }); + } + + Error deallocate() override { + orcrpctpc::ReleaseOrFinalizeMemRequest RMR; + for (auto &KV : TargetAllocs) + RMR.push_back({orcrpctpc::toWireProtectionFlags( + static_cast<sys::Memory::ProtectionFlags>(KV.first)), + KV.second.Address, KV.second.AllocatedSize}); + TargetAllocs.clear(); + + return Parent.getEndpoint().template callB<orcrpctpc::ReleaseMem>(RMR); + } + + private: + OrcRPCTPCJITLinkMemoryManager<OrcRPCTPCImplT> &Parent; + HostAllocMap HostAllocs; + TargetAllocMap TargetAllocs; + }; + + OrcRPCTPCJITLinkMemoryManager(OrcRPCTPCImplT &Parent) : Parent(Parent) {} + + Expected<std::unique_ptr<Allocation>> + allocate(const jitlink::JITLinkDylib *JD, + const SegmentsRequestMap &Request) override { + orcrpctpc::ReserveMemRequest RMR; + HostAllocMap HostAllocs; + + for (auto &KV : Request) { + assert(KV.second.getContentSize() <= std::numeric_limits<size_t>::max() && + "Content size is out-of-range for host"); + + RMR.push_back({orcrpctpc::toWireProtectionFlags( + static_cast<sys::Memory::ProtectionFlags>(KV.first)), + KV.second.getContentSize() + KV.second.getZeroFillSize(), + KV.second.getAlignment()}); + HostAllocs[KV.first] = { + std::make_unique<char[]>(KV.second.getContentSize()), + KV.second.getContentSize()}; + } + + DEBUG_WITH_TYPE("orc", { + dbgs() << "Orc remote memmgr got request:\n"; + for (auto &KV : Request) + dbgs() << " permissions: " + << ((KV.first & sys::Memory::MF_READ) ? 'R' : '-') + << ((KV.first & sys::Memory::MF_WRITE) ? 'W' : '-') + << ((KV.first & sys::Memory::MF_EXEC) ? 'X' : '-') + << ", content size: " + << formatv("{0:x16}", KV.second.getContentSize()) + << " + zero-fill-size: " + << formatv("{0:x16}", KV.second.getZeroFillSize()) + << ", align: " << KV.second.getAlignment() << "\n"; + }); + + // FIXME: LLVM RPC needs to be fixed to support alt + // serialization/deserialization on return types. For now just + // translate from std::map to DenseMap manually. + auto TmpTargetAllocs = + Parent.getEndpoint().template callB<orcrpctpc::ReserveMem>(RMR); + if (!TmpTargetAllocs) + return TmpTargetAllocs.takeError(); + + if (TmpTargetAllocs->size() != RMR.size()) + return make_error<StringError>( + "Number of target allocations does not match request", + inconvertibleErrorCode()); + + TargetAllocMap TargetAllocs; + for (auto &E : *TmpTargetAllocs) + TargetAllocs[orcrpctpc::fromWireProtectionFlags(E.Prot)] = { + E.Address, E.AllocatedSize}; + + DEBUG_WITH_TYPE("orc", { + auto HAI = HostAllocs.begin(); + for (auto &KV : TargetAllocs) + dbgs() << " permissions: " + << ((KV.first & sys::Memory::MF_READ) ? 'R' : '-') + << ((KV.first & sys::Memory::MF_WRITE) ? 'W' : '-') + << ((KV.first & sys::Memory::MF_EXEC) ? 'X' : '-') + << " assigned local " << (void *)HAI->second.Mem.get() + << ", target " << formatv("{0:x16}", KV.second.Address) << "\n"; + }); + + return std::make_unique<OrcRPCAllocation>(*this, std::move(HostAllocs), + std::move(TargetAllocs)); + } + +private: + void reportError(Error Err) { Parent.reportError(std::move(Err)); } + + decltype(std::declval<OrcRPCTPCImplT>().getEndpoint()) getEndpoint() { + return Parent.getEndpoint(); + } + + OrcRPCTPCImplT &Parent; +}; + +/// TargetProcessControl::MemoryAccess implementation for a process connected +/// via an ORC RPC endpoint. +template <typename OrcRPCTPCImplT> +class OrcRPCTPCMemoryAccess : public TargetProcessControl::MemoryAccess { +public: + OrcRPCTPCMemoryAccess(OrcRPCTPCImplT &Parent) : Parent(Parent) {} + + void writeUInt8s(ArrayRef<tpctypes::UInt8Write> Ws, + WriteResultFn OnWriteComplete) override { + writeViaRPC<orcrpctpc::WriteUInt8s>(Ws, std::move(OnWriteComplete)); + } + + void writeUInt16s(ArrayRef<tpctypes::UInt16Write> Ws, + WriteResultFn OnWriteComplete) override { + writeViaRPC<orcrpctpc::WriteUInt16s>(Ws, std::move(OnWriteComplete)); + } + + void writeUInt32s(ArrayRef<tpctypes::UInt32Write> Ws, + WriteResultFn OnWriteComplete) override { + writeViaRPC<orcrpctpc::WriteUInt32s>(Ws, std::move(OnWriteComplete)); + } + + void writeUInt64s(ArrayRef<tpctypes::UInt64Write> Ws, + WriteResultFn OnWriteComplete) override { + writeViaRPC<orcrpctpc::WriteUInt64s>(Ws, std::move(OnWriteComplete)); + } + + void writeBuffers(ArrayRef<tpctypes::BufferWrite> Ws, + WriteResultFn OnWriteComplete) override { + writeViaRPC<orcrpctpc::WriteBuffers>(Ws, std::move(OnWriteComplete)); + } + +private: + template <typename WriteRPCFunction, typename WriteElementT> + void writeViaRPC(ArrayRef<WriteElementT> Ws, WriteResultFn OnWriteComplete) { + if (auto Err = Parent.getEndpoint().template callAsync<WriteRPCFunction>( + [OWC = std::move(OnWriteComplete)](Error Err2) mutable -> Error { + OWC(std::move(Err2)); + return Error::success(); + }, + Ws)) { + Parent.reportError(std::move(Err)); + Parent.getEndpoint().abandonPendingResponses(); + } + } + + OrcRPCTPCImplT &Parent; +}; + +// TargetProcessControl for a process connected via an ORC RPC Endpoint. +template <typename RPCEndpointT> +class OrcRPCTargetProcessControlBase : public TargetProcessControl { +public: + using ErrorReporter = unique_function<void(Error)>; + + using OnCloseConnectionFunction = unique_function<Error(Error)>; + + OrcRPCTargetProcessControlBase(std::shared_ptr<SymbolStringPool> SSP, + RPCEndpointT &EP, ErrorReporter ReportError) + : TargetProcessControl(std::move(SSP)), + ReportError(std::move(ReportError)), EP(EP) {} + + void reportError(Error Err) { ReportError(std::move(Err)); } + + RPCEndpointT &getEndpoint() { return EP; } + + Expected<tpctypes::DylibHandle> loadDylib(const char *DylibPath) override { + DEBUG_WITH_TYPE("orc", { + dbgs() << "Loading dylib \"" << (DylibPath ? DylibPath : "") << "\" "; + if (!DylibPath) + dbgs() << "(process symbols)"; + dbgs() << "\n"; + }); + if (!DylibPath) + DylibPath = ""; + auto H = EP.template callB<orcrpctpc::LoadDylib>(DylibPath); + DEBUG_WITH_TYPE("orc", { + if (H) + dbgs() << " got handle " << formatv("{0:x16}", *H) << "\n"; + else + dbgs() << " error, unable to load\n"; + }); + return H; + } + + Expected<std::vector<tpctypes::LookupResult>> + lookupSymbols(ArrayRef<LookupRequest> Request) override { + std::vector<orcrpctpc::RemoteLookupRequest> RR; + for (auto &E : Request) { + RR.push_back({}); + RR.back().first = E.Handle; + for (auto &KV : E.Symbols) + RR.back().second.push_back( + {(*KV.first).str(), + KV.second == SymbolLookupFlags::WeaklyReferencedSymbol}); + } + DEBUG_WITH_TYPE("orc", { + dbgs() << "Compound lookup:\n"; + for (auto &R : Request) { + dbgs() << " In " << formatv("{0:x16}", R.Handle) << ": {"; + bool First = true; + for (auto &KV : R.Symbols) { + dbgs() << (First ? "" : ",") << " " << *KV.first; + First = false; + } + dbgs() << " }\n"; + } + }); + return EP.template callB<orcrpctpc::LookupSymbols>(RR); + } + + Expected<int32_t> runAsMain(JITTargetAddress MainFnAddr, + ArrayRef<std::string> Args) override { + DEBUG_WITH_TYPE("orc", { + dbgs() << "Running as main: " << formatv("{0:x16}", MainFnAddr) + << ", args = ["; + for (unsigned I = 0; I != Args.size(); ++I) + dbgs() << (I ? "," : "") << " \"" << Args[I] << "\""; + dbgs() << "]\n"; + }); + auto Result = EP.template callB<orcrpctpc::RunMain>(MainFnAddr, Args); + DEBUG_WITH_TYPE("orc", { + dbgs() << " call to " << formatv("{0:x16}", MainFnAddr); + if (Result) + dbgs() << " returned result " << *Result << "\n"; + else + dbgs() << " failed\n"; + }); + return Result; + } + + Expected<tpctypes::WrapperFunctionResult> + runWrapper(JITTargetAddress WrapperFnAddr, + ArrayRef<uint8_t> ArgBuffer) override { + DEBUG_WITH_TYPE("orc", { + dbgs() << "Running as wrapper function " + << formatv("{0:x16}", WrapperFnAddr) << " with " + << formatv("{0:x16}", ArgBuffer.size()) << " argument buffer\n"; + }); + auto Result = + EP.template callB<orcrpctpc::RunWrapper>(WrapperFnAddr, ArgBuffer); + // dbgs() << "Returned from runWrapper...\n"; + return Result; + } + + Error closeConnection(OnCloseConnectionFunction OnCloseConnection) { + DEBUG_WITH_TYPE("orc", dbgs() << "Closing connection to remote\n"); + return EP.template callAsync<orcrpctpc::CloseConnection>( + std::move(OnCloseConnection)); + } + + Error closeConnectionAndWait() { + std::promise<MSVCPError> P; + auto F = P.get_future(); + if (auto Err = closeConnection([&](Error Err2) -> Error { + P.set_value(std::move(Err2)); + return Error::success(); + })) { + EP.abandonAllPendingResponses(); + return joinErrors(std::move(Err), F.get()); + } + return F.get(); + } + +protected: + /// Subclasses must call this during construction to initialize the + /// TargetTriple and PageSize members. + Error initializeORCRPCTPCBase() { + if (auto TripleOrErr = EP.template callB<orcrpctpc::GetTargetTriple>()) + TargetTriple = Triple(*TripleOrErr); + else + return TripleOrErr.takeError(); + + if (auto PageSizeOrErr = EP.template callB<orcrpctpc::GetPageSize>()) + PageSize = *PageSizeOrErr; + else + return PageSizeOrErr.takeError(); + + return Error::success(); + } + +private: + ErrorReporter ReportError; + RPCEndpointT &EP; +}; + +} // end namespace orc +} // end namespace llvm + +#endif // LLVM_EXECUTIONENGINE_ORC_ORCRPCTARGETPROCESSCONTROL_H diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h index 86e8d5df3ad9..3d139740d677 100644 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h @@ -20,6 +20,7 @@ #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/ExecutionEngine/JITSymbol.h" +#include "llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h" #include "llvm/ExecutionEngine/Orc/IndirectionUtils.h" #include "llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h" #include "llvm/ExecutionEngine/RuntimeDyld.h" @@ -53,7 +54,7 @@ namespace remote { /// OrcRemoteTargetServer class) via an RPC system (see RPCUtils.h) to carry out /// its actions. class OrcRemoteTargetClient - : public rpc::SingleThreadedRPCEndpoint<rpc::RawByteChannel> { + : public shared::SingleThreadedRPCEndpoint<shared::RawByteChannel> { public: /// Remote-mapped RuntimeDyld-compatible memory manager. class RemoteRTDyldMemoryManager : public RuntimeDyld::MemoryManager { @@ -329,6 +330,221 @@ public: std::vector<EHFrame> RegisteredEHFrames; }; + class RPCMMAlloc : public jitlink::JITLinkMemoryManager::Allocation { + using AllocationMap = DenseMap<unsigned, sys::MemoryBlock>; + using FinalizeContinuation = + jitlink::JITLinkMemoryManager::Allocation::FinalizeContinuation; + using ProtectionFlags = sys::Memory::ProtectionFlags; + using SegmentsRequestMap = + DenseMap<unsigned, jitlink::JITLinkMemoryManager::SegmentRequest>; + + RPCMMAlloc(OrcRemoteTargetClient &Client, ResourceIdMgr::ResourceId Id) + : Client(Client), Id(Id) {} + + public: + static Expected<std::unique_ptr<RPCMMAlloc>> + Create(OrcRemoteTargetClient &Client, ResourceIdMgr::ResourceId Id, + const SegmentsRequestMap &Request) { + auto *MM = new RPCMMAlloc(Client, Id); + + if (Error Err = MM->allocateHostBlocks(Request)) + return std::move(Err); + + if (Error Err = MM->allocateTargetBlocks()) + return std::move(Err); + + return std::unique_ptr<RPCMMAlloc>(MM); + } + + MutableArrayRef<char> getWorkingMemory(ProtectionFlags Seg) override { + assert(HostSegBlocks.count(Seg) && "No allocation for segment"); + return {static_cast<char *>(HostSegBlocks[Seg].base()), + HostSegBlocks[Seg].allocatedSize()}; + } + + JITTargetAddress getTargetMemory(ProtectionFlags Seg) override { + assert(TargetSegBlocks.count(Seg) && "No allocation for segment"); + return pointerToJITTargetAddress(TargetSegBlocks[Seg].base()); + } + + void finalizeAsync(FinalizeContinuation OnFinalize) override { + // Host allocations (working memory) remain ReadWrite. + OnFinalize(copyAndProtect()); + } + + Error deallocate() override { + // TODO: Cannot release target allocation. RPCAPI has no function + // symmetric to reserveMem(). Add RPC call like freeMem()? + return errorCodeToError(sys::Memory::releaseMappedMemory(HostAllocation)); + } + + private: + OrcRemoteTargetClient &Client; + ResourceIdMgr::ResourceId Id; + AllocationMap HostSegBlocks; + AllocationMap TargetSegBlocks; + JITTargetAddress TargetSegmentAddr; + sys::MemoryBlock HostAllocation; + + Error allocateHostBlocks(const SegmentsRequestMap &Request) { + unsigned TargetPageSize = Client.getPageSize(); + + if (!isPowerOf2_64(static_cast<uint64_t>(TargetPageSize))) + return make_error<StringError>("Host page size is not a power of 2", + inconvertibleErrorCode()); + + auto TotalSize = calcTotalAllocSize(Request, TargetPageSize); + if (!TotalSize) + return TotalSize.takeError(); + + // Allocate one slab to cover all the segments. + const sys::Memory::ProtectionFlags ReadWrite = + static_cast<sys::Memory::ProtectionFlags>(sys::Memory::MF_READ | + sys::Memory::MF_WRITE); + std::error_code EC; + HostAllocation = + sys::Memory::allocateMappedMemory(*TotalSize, nullptr, ReadWrite, EC); + if (EC) + return errorCodeToError(EC); + + char *SlabAddr = static_cast<char *>(HostAllocation.base()); +#ifndef NDEBUG + char *SlabAddrEnd = SlabAddr + HostAllocation.allocatedSize(); +#endif + + // Allocate segment memory from the slab. + for (auto &KV : Request) { + const auto &Seg = KV.second; + + uint64_t SegmentSize = Seg.getContentSize() + Seg.getZeroFillSize(); + uint64_t AlignedSegmentSize = alignTo(SegmentSize, TargetPageSize); + + // Zero out zero-fill memory. + char *ZeroFillBegin = SlabAddr + Seg.getContentSize(); + memset(ZeroFillBegin, 0, Seg.getZeroFillSize()); + + // Record the block for this segment. + HostSegBlocks[KV.first] = + sys::MemoryBlock(SlabAddr, AlignedSegmentSize); + + SlabAddr += AlignedSegmentSize; + assert(SlabAddr <= SlabAddrEnd && "Out of range"); + } + + return Error::success(); + } + + Error allocateTargetBlocks() { + // Reserve memory for all blocks on the target. We need as much space on + // the target as we allocated on the host. + TargetSegmentAddr = Client.reserveMem(Id, HostAllocation.allocatedSize(), + Client.getPageSize()); + if (!TargetSegmentAddr) + return make_error<StringError>("Failed to reserve memory on the target", + inconvertibleErrorCode()); + + // Map memory blocks into the allocation, that match the host allocation. + JITTargetAddress TargetAllocAddr = TargetSegmentAddr; + for (const auto &KV : HostSegBlocks) { + size_t TargetAllocSize = KV.second.allocatedSize(); + + TargetSegBlocks[KV.first] = + sys::MemoryBlock(jitTargetAddressToPointer<void *>(TargetAllocAddr), + TargetAllocSize); + + TargetAllocAddr += TargetAllocSize; + assert(TargetAllocAddr - TargetSegmentAddr <= + HostAllocation.allocatedSize() && + "Out of range on target"); + } + + return Error::success(); + } + + Error copyAndProtect() { + unsigned Permissions = 0u; + + // Copy segments one by one. + for (auto &KV : TargetSegBlocks) { + Permissions |= KV.first; + + const sys::MemoryBlock &TargetBlock = KV.second; + const sys::MemoryBlock &HostBlock = HostSegBlocks.lookup(KV.first); + + size_t TargetAllocSize = TargetBlock.allocatedSize(); + auto TargetAllocAddr = pointerToJITTargetAddress(TargetBlock.base()); + auto *HostAllocBegin = static_cast<const char *>(HostBlock.base()); + + bool CopyErr = + Client.writeMem(TargetAllocAddr, HostAllocBegin, TargetAllocSize); + if (CopyErr) + return createStringError(inconvertibleErrorCode(), + "Failed to copy %d segment to the target", + KV.first); + } + + // Set permission flags for all segments at once. + bool ProtectErr = + Client.setProtections(Id, TargetSegmentAddr, Permissions); + if (ProtectErr) + return createStringError(inconvertibleErrorCode(), + "Failed to apply permissions for %d segment " + "on the target", + Permissions); + return Error::success(); + } + + static Expected<size_t> + calcTotalAllocSize(const SegmentsRequestMap &Request, + unsigned TargetPageSize) { + size_t TotalSize = 0; + for (const auto &KV : Request) { + const auto &Seg = KV.second; + + if (Seg.getAlignment() > TargetPageSize) + return make_error<StringError>("Cannot request alignment higher than " + "page alignment on target", + inconvertibleErrorCode()); + + TotalSize = alignTo(TotalSize, TargetPageSize); + TotalSize += Seg.getContentSize(); + TotalSize += Seg.getZeroFillSize(); + } + + return TotalSize; + } + }; + + class RemoteJITLinkMemoryManager : public jitlink::JITLinkMemoryManager { + public: + RemoteJITLinkMemoryManager(OrcRemoteTargetClient &Client, + ResourceIdMgr::ResourceId Id) + : Client(Client), Id(Id) {} + + RemoteJITLinkMemoryManager(const RemoteJITLinkMemoryManager &) = delete; + RemoteJITLinkMemoryManager(RemoteJITLinkMemoryManager &&) = default; + + RemoteJITLinkMemoryManager & + operator=(const RemoteJITLinkMemoryManager &) = delete; + RemoteJITLinkMemoryManager & + operator=(RemoteJITLinkMemoryManager &&) = delete; + + ~RemoteJITLinkMemoryManager() { + Client.destroyRemoteAllocator(Id); + LLVM_DEBUG(dbgs() << "Destroyed remote allocator " << Id << "\n"); + } + + Expected<std::unique_ptr<Allocation>> + allocate(const jitlink::JITLinkDylib *JD, + const SegmentsRequestMap &Request) override { + return RPCMMAlloc::Create(Client, Id, Request); + } + + private: + OrcRemoteTargetClient &Client; + ResourceIdMgr::ResourceId Id; + }; + /// Remote indirect stubs manager. class RemoteIndirectStubsManager : public IndirectStubsManager { public: @@ -453,20 +669,8 @@ public: public: RemoteTrampolinePool(OrcRemoteTargetClient &Client) : Client(Client) {} - Expected<JITTargetAddress> getTrampoline() override { - std::lock_guard<std::mutex> Lock(RTPMutex); - if (AvailableTrampolines.empty()) { - if (auto Err = grow()) - return std::move(Err); - } - assert(!AvailableTrampolines.empty() && "Failed to grow trampoline pool"); - auto TrampolineAddr = AvailableTrampolines.back(); - AvailableTrampolines.pop_back(); - return TrampolineAddr; - } - private: - Error grow() { + Error grow() override { JITTargetAddress BlockAddr = 0; uint32_t NumTrampolines = 0; if (auto TrampolineInfoOrErr = Client.emitTrampolineBlock()) @@ -476,14 +680,12 @@ public: uint32_t TrampolineSize = Client.getTrampolineSize(); for (unsigned I = 0; I < NumTrampolines; ++I) - this->AvailableTrampolines.push_back(BlockAddr + (I * TrampolineSize)); + AvailableTrampolines.push_back(BlockAddr + (I * TrampolineSize)); return Error::success(); } - std::mutex RTPMutex; OrcRemoteTargetClient &Client; - std::vector<JITTargetAddress> AvailableTrampolines; }; /// Remote compile callback manager. @@ -501,7 +703,7 @@ public: /// Channel is the ChannelT instance to communicate on. It is assumed that /// the channel is ready to be read from and written to. static Expected<std::unique_ptr<OrcRemoteTargetClient>> - Create(rpc::RawByteChannel &Channel, ExecutionSession &ES) { + Create(shared::RawByteChannel &Channel, ExecutionSession &ES) { Error Err = Error::success(); auto Client = std::unique_ptr<OrcRemoteTargetClient>( new OrcRemoteTargetClient(Channel, ES, Err)); @@ -518,6 +720,14 @@ public: return callB<exec::CallIntVoid>(Addr); } + /// Call the int(int) function at the given address in the target and return + /// its result. + Expected<int> callIntInt(JITTargetAddress Addr, int Arg) { + LLVM_DEBUG(dbgs() << "Calling int(*)(int) " << format("0x%016" PRIx64, Addr) + << "\n"); + return callB<exec::CallIntInt>(Addr, Arg); + } + /// Call the int(int, char*[]) function at the given address in the target and /// return its result. Expected<int> callMain(JITTargetAddress Addr, @@ -546,6 +756,18 @@ public: new RemoteRTDyldMemoryManager(*this, Id)); } + /// Create a JITLink-compatible memory manager which will allocate working + /// memory on the host and target memory on the remote target. + Expected<std::unique_ptr<RemoteJITLinkMemoryManager>> + createRemoteJITLinkMemoryManager() { + auto Id = AllocatorIds.getNext(); + if (auto Err = callB<mem::CreateRemoteAllocator>(Id)) + return std::move(Err); + LLVM_DEBUG(dbgs() << "Created remote allocator " << Id << "\n"); + return std::unique_ptr<RemoteJITLinkMemoryManager>( + new RemoteJITLinkMemoryManager(*this, Id)); + } + /// Create an RCIndirectStubsManager that will allocate stubs on the remote /// target. Expected<std::unique_ptr<RemoteIndirectStubsManager>> @@ -583,9 +805,10 @@ public: Error terminateSession() { return callB<utils::TerminateSession>(); } private: - OrcRemoteTargetClient(rpc::RawByteChannel &Channel, ExecutionSession &ES, + OrcRemoteTargetClient(shared::RawByteChannel &Channel, ExecutionSession &ES, Error &Err) - : rpc::SingleThreadedRPCEndpoint<rpc::RawByteChannel>(Channel, true), + : shared::SingleThreadedRPCEndpoint<shared::RawByteChannel>(Channel, + true), ES(ES) { ErrorAsOutParameter EAO(&Err); diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h index 52a328165240..367bfb369191 100644 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h @@ -16,8 +16,8 @@ #define LLVM_EXECUTIONENGINE_ORC_ORCREMOTETARGETRPCAPI_H #include "llvm/ExecutionEngine/JITSymbol.h" -#include "llvm/ExecutionEngine/Orc/RPC/RPCUtils.h" -#include "llvm/ExecutionEngine/Orc/RPC/RawByteChannel.h" +#include "llvm/ExecutionEngine/Orc/Shared/RPCUtils.h" +#include "llvm/ExecutionEngine/Orc/Shared/RawByteChannel.h" namespace llvm { namespace orc { @@ -73,10 +73,9 @@ private: } // end namespace remote -namespace rpc { +namespace shared { -template <> -class RPCTypeName<JITSymbolFlags> { +template <> class SerializationTypeName<JITSymbolFlags> { public: static const char *getName() { return "JITSymbolFlags"; } }; @@ -100,7 +99,7 @@ public: } }; -template <> class RPCTypeName<remote::DirectBufferWriter> { +template <> class SerializationTypeName<remote::DirectBufferWriter> { public: static const char *getName() { return "DirectBufferWriter"; } }; @@ -133,7 +132,7 @@ public: } }; -} // end namespace rpc +} // end namespace shared namespace remote { @@ -167,20 +166,20 @@ private: namespace eh { /// Registers EH frames on the remote. - class RegisterEHFrames - : public rpc::Function<RegisterEHFrames, - void(JITTargetAddress Addr, uint32_t Size)> { - public: - static const char *getName() { return "RegisterEHFrames"; } - }; +class RegisterEHFrames + : public shared::RPCFunction<RegisterEHFrames, + void(JITTargetAddress Addr, uint32_t Size)> { +public: + static const char *getName() { return "RegisterEHFrames"; } +}; /// Deregisters EH frames on the remote. - class DeregisterEHFrames - : public rpc::Function<DeregisterEHFrames, - void(JITTargetAddress Addr, uint32_t Size)> { - public: - static const char *getName() { return "DeregisterEHFrames"; } - }; +class DeregisterEHFrames + : public shared::RPCFunction<DeregisterEHFrames, + void(JITTargetAddress Addr, uint32_t Size)> { +public: + static const char *getName() { return "DeregisterEHFrames"; } +}; } // end namespace eh @@ -189,28 +188,38 @@ namespace exec { /// Call an 'int32_t()'-type function on the remote, returns the called /// function's return value. - class CallIntVoid - : public rpc::Function<CallIntVoid, int32_t(JITTargetAddress Addr)> { - public: - static const char *getName() { return "CallIntVoid"; } - }; +class CallIntVoid + : public shared::RPCFunction<CallIntVoid, int32_t(JITTargetAddress Addr)> { +public: + static const char *getName() { return "CallIntVoid"; } +}; + + /// Call an 'int32_t(int32_t)'-type function on the remote, returns the called + /// function's return value. +class CallIntInt + : public shared::RPCFunction<CallIntInt, + int32_t(JITTargetAddress Addr, int)> { +public: + static const char *getName() { return "CallIntInt"; } +}; /// Call an 'int32_t(int32_t, char**)'-type function on the remote, returns the /// called function's return value. - class CallMain - : public rpc::Function<CallMain, int32_t(JITTargetAddress Addr, - std::vector<std::string> Args)> { - public: - static const char *getName() { return "CallMain"; } - }; +class CallMain + : public shared::RPCFunction<CallMain, + int32_t(JITTargetAddress Addr, + std::vector<std::string> Args)> { +public: + static const char *getName() { return "CallMain"; } +}; /// Calls a 'void()'-type function on the remote, returns when the called /// function completes. - class CallVoidVoid - : public rpc::Function<CallVoidVoid, void(JITTargetAddress FnAddr)> { - public: - static const char *getName() { return "CallVoidVoid"; } - }; +class CallVoidVoid + : public shared::RPCFunction<CallVoidVoid, void(JITTargetAddress FnAddr)> { +public: + static const char *getName() { return "CallVoidVoid"; } +}; } // end namespace exec @@ -218,60 +227,62 @@ namespace exec { namespace mem { /// Creates a memory allocator on the remote. - class CreateRemoteAllocator - : public rpc::Function<CreateRemoteAllocator, - void(ResourceIdMgr::ResourceId AllocatorID)> { - public: - static const char *getName() { return "CreateRemoteAllocator"; } - }; +class CreateRemoteAllocator + : public shared::RPCFunction<CreateRemoteAllocator, + void(ResourceIdMgr::ResourceId AllocatorID)> { +public: + static const char *getName() { return "CreateRemoteAllocator"; } +}; /// Destroys a remote allocator, freeing any memory allocated by it. - class DestroyRemoteAllocator - : public rpc::Function<DestroyRemoteAllocator, - void(ResourceIdMgr::ResourceId AllocatorID)> { - public: - static const char *getName() { return "DestroyRemoteAllocator"; } - }; +class DestroyRemoteAllocator + : public shared::RPCFunction<DestroyRemoteAllocator, + void(ResourceIdMgr::ResourceId AllocatorID)> { +public: + static const char *getName() { return "DestroyRemoteAllocator"; } +}; /// Read a remote memory block. - class ReadMem - : public rpc::Function<ReadMem, std::vector<uint8_t>(JITTargetAddress Src, - uint64_t Size)> { - public: - static const char *getName() { return "ReadMem"; } - }; +class ReadMem + : public shared::RPCFunction< + ReadMem, std::vector<uint8_t>(JITTargetAddress Src, uint64_t Size)> { +public: + static const char *getName() { return "ReadMem"; } +}; /// Reserve a block of memory on the remote via the given allocator. - class ReserveMem - : public rpc::Function<ReserveMem, - JITTargetAddress(ResourceIdMgr::ResourceId AllocID, - uint64_t Size, uint32_t Align)> { - public: - static const char *getName() { return "ReserveMem"; } - }; +class ReserveMem + : public shared::RPCFunction< + ReserveMem, JITTargetAddress(ResourceIdMgr::ResourceId AllocID, + uint64_t Size, uint32_t Align)> { +public: + static const char *getName() { return "ReserveMem"; } +}; /// Set the memory protection on a memory block. - class SetProtections - : public rpc::Function<SetProtections, - void(ResourceIdMgr::ResourceId AllocID, - JITTargetAddress Dst, uint32_t ProtFlags)> { - public: - static const char *getName() { return "SetProtections"; } - }; +class SetProtections + : public shared::RPCFunction< + SetProtections, void(ResourceIdMgr::ResourceId AllocID, + JITTargetAddress Dst, uint32_t ProtFlags)> { +public: + static const char *getName() { return "SetProtections"; } +}; /// Write to a remote memory block. - class WriteMem - : public rpc::Function<WriteMem, void(remote::DirectBufferWriter DB)> { - public: - static const char *getName() { return "WriteMem"; } - }; +class WriteMem + : public shared::RPCFunction<WriteMem, + void(remote::DirectBufferWriter DB)> { +public: + static const char *getName() { return "WriteMem"; } +}; /// Write to a remote pointer. - class WritePtr : public rpc::Function<WritePtr, void(JITTargetAddress Dst, - JITTargetAddress Val)> { - public: - static const char *getName() { return "WritePtr"; } - }; +class WritePtr + : public shared::RPCFunction<WritePtr, void(JITTargetAddress Dst, + JITTargetAddress Val)> { +public: + static const char *getName() { return "WritePtr"; } +}; } // end namespace mem @@ -279,45 +290,46 @@ namespace mem { namespace stubs { /// Creates an indirect stub owner on the remote. - class CreateIndirectStubsOwner - : public rpc::Function<CreateIndirectStubsOwner, - void(ResourceIdMgr::ResourceId StubOwnerID)> { - public: - static const char *getName() { return "CreateIndirectStubsOwner"; } - }; +class CreateIndirectStubsOwner + : public shared::RPCFunction<CreateIndirectStubsOwner, + void(ResourceIdMgr::ResourceId StubOwnerID)> { +public: + static const char *getName() { return "CreateIndirectStubsOwner"; } +}; /// RPC function for destroying an indirect stubs owner. - class DestroyIndirectStubsOwner - : public rpc::Function<DestroyIndirectStubsOwner, - void(ResourceIdMgr::ResourceId StubsOwnerID)> { - public: - static const char *getName() { return "DestroyIndirectStubsOwner"; } - }; +class DestroyIndirectStubsOwner + : public shared::RPCFunction<DestroyIndirectStubsOwner, + void(ResourceIdMgr::ResourceId StubsOwnerID)> { +public: + static const char *getName() { return "DestroyIndirectStubsOwner"; } +}; /// EmitIndirectStubs result is (StubsBase, PtrsBase, NumStubsEmitted). - class EmitIndirectStubs - : public rpc::Function< - EmitIndirectStubs, - std::tuple<JITTargetAddress, JITTargetAddress, uint32_t>( - ResourceIdMgr::ResourceId StubsOwnerID, - uint32_t NumStubsRequired)> { - public: - static const char *getName() { return "EmitIndirectStubs"; } - }; +class EmitIndirectStubs + : public shared::RPCFunction< + EmitIndirectStubs, + std::tuple<JITTargetAddress, JITTargetAddress, uint32_t>( + ResourceIdMgr::ResourceId StubsOwnerID, + uint32_t NumStubsRequired)> { +public: + static const char *getName() { return "EmitIndirectStubs"; } +}; /// RPC function to emit the resolver block and return its address. - class EmitResolverBlock : public rpc::Function<EmitResolverBlock, void()> { - public: - static const char *getName() { return "EmitResolverBlock"; } - }; +class EmitResolverBlock + : public shared::RPCFunction<EmitResolverBlock, void()> { +public: + static const char *getName() { return "EmitResolverBlock"; } +}; /// EmitTrampolineBlock result is (BlockAddr, NumTrampolines). - class EmitTrampolineBlock - : public rpc::Function<EmitTrampolineBlock, - std::tuple<JITTargetAddress, uint32_t>()> { - public: - static const char *getName() { return "EmitTrampolineBlock"; } - }; +class EmitTrampolineBlock + : public shared::RPCFunction<EmitTrampolineBlock, + std::tuple<JITTargetAddress, uint32_t>()> { +public: + static const char *getName() { return "EmitTrampolineBlock"; } +}; } // end namespace stubs @@ -326,44 +338,44 @@ namespace utils { /// GetRemoteInfo result is (Triple, PointerSize, PageSize, TrampolineSize, /// IndirectStubsSize). - class GetRemoteInfo - : public rpc::Function< - GetRemoteInfo, - std::tuple<std::string, uint32_t, uint32_t, uint32_t, uint32_t>()> { - public: - static const char *getName() { return "GetRemoteInfo"; } - }; +class GetRemoteInfo + : public shared::RPCFunction< + GetRemoteInfo, + std::tuple<std::string, uint32_t, uint32_t, uint32_t, uint32_t>()> { +public: + static const char *getName() { return "GetRemoteInfo"; } +}; /// Get the address of a remote symbol. - class GetSymbolAddress - : public rpc::Function<GetSymbolAddress, - JITTargetAddress(std::string SymbolName)> { - public: - static const char *getName() { return "GetSymbolAddress"; } - }; +class GetSymbolAddress + : public shared::RPCFunction<GetSymbolAddress, + JITTargetAddress(std::string SymbolName)> { +public: + static const char *getName() { return "GetSymbolAddress"; } +}; /// Request that the host execute a compile callback. - class RequestCompile - : public rpc::Function< - RequestCompile, JITTargetAddress(JITTargetAddress TrampolineAddr)> { - public: - static const char *getName() { return "RequestCompile"; } - }; +class RequestCompile + : public shared::RPCFunction< + RequestCompile, JITTargetAddress(JITTargetAddress TrampolineAddr)> { +public: + static const char *getName() { return "RequestCompile"; } +}; /// Notify the remote and terminate the session. - class TerminateSession : public rpc::Function<TerminateSession, void()> { - public: - static const char *getName() { return "TerminateSession"; } - }; +class TerminateSession : public shared::RPCFunction<TerminateSession, void()> { +public: + static const char *getName() { return "TerminateSession"; } +}; } // namespace utils class OrcRemoteTargetRPCAPI - : public rpc::SingleThreadedRPCEndpoint<rpc::RawByteChannel> { + : public shared::SingleThreadedRPCEndpoint<shared::RawByteChannel> { public: // FIXME: Remove constructors once MSVC supports synthesizing move-ops. - OrcRemoteTargetRPCAPI(rpc::RawByteChannel &C) - : rpc::SingleThreadedRPCEndpoint<rpc::RawByteChannel>(C, true) {} + OrcRemoteTargetRPCAPI(shared::RawByteChannel &C) + : shared::SingleThreadedRPCEndpoint<shared::RawByteChannel>(C, true) {} }; } // end namespace remote diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h index 50c155d77db1..ce9bf064303d 100644 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h @@ -16,8 +16,8 @@ #include "llvm/ExecutionEngine/JITSymbol.h" #include "llvm/ExecutionEngine/Orc/IndirectionUtils.h" -#include "llvm/ExecutionEngine/Orc/OrcError.h" #include "llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h" +#include "llvm/ExecutionEngine/Orc/Shared/OrcError.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Error.h" #include "llvm/Support/Format.h" @@ -46,7 +46,7 @@ namespace remote { template <typename ChannelT, typename TargetT> class OrcRemoteTargetServer - : public rpc::SingleThreadedRPCEndpoint<rpc::RawByteChannel> { + : public shared::SingleThreadedRPCEndpoint<shared::RawByteChannel> { public: using SymbolLookupFtor = std::function<JITTargetAddress(const std::string &Name)>; @@ -57,12 +57,14 @@ public: OrcRemoteTargetServer(ChannelT &Channel, SymbolLookupFtor SymbolLookup, EHFrameRegistrationFtor EHFramesRegister, EHFrameRegistrationFtor EHFramesDeregister) - : rpc::SingleThreadedRPCEndpoint<rpc::RawByteChannel>(Channel, true), + : shared::SingleThreadedRPCEndpoint<shared::RawByteChannel>(Channel, + true), SymbolLookup(std::move(SymbolLookup)), EHFramesRegister(std::move(EHFramesRegister)), EHFramesDeregister(std::move(EHFramesDeregister)) { using ThisT = std::remove_reference_t<decltype(*this)>; addHandler<exec::CallIntVoid>(*this, &ThisT::handleCallIntVoid); + addHandler<exec::CallIntInt>(*this, &ThisT::handleCallIntInt); addHandler<exec::CallMain>(*this, &ThisT::handleCallMain); addHandler<exec::CallVoidVoid>(*this, &ThisT::handleCallVoidVoid); addHandler<mem::CreateRemoteAllocator>(*this, @@ -168,6 +170,19 @@ private: return Result; } + Expected<int32_t> handleCallIntInt(JITTargetAddress Addr, int Arg) { + using IntIntFnTy = int (*)(int); + + IntIntFnTy Fn = reinterpret_cast<IntIntFnTy>(static_cast<uintptr_t>(Addr)); + + LLVM_DEBUG(dbgs() << " Calling " << format("0x%016x", Addr) + << " with argument " << Arg << "\n"); + int Result = Fn(Arg); + LLVM_DEBUG(dbgs() << " Result = " << Result << "\n"); + + return Result; + } + Expected<int32_t> handleCallMain(JITTargetAddress Addr, std::vector<std::string> Args) { using MainFnTy = int (*)(int, const char *[]); diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h index 9ada0871cf0c..7dfbf32b1ffa 100644 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h @@ -20,7 +20,6 @@ #include "llvm/ExecutionEngine/JITSymbol.h" #include "llvm/ExecutionEngine/Orc/Core.h" #include "llvm/ExecutionEngine/Orc/Layer.h" -#include "llvm/ExecutionEngine/Orc/Legacy.h" #include "llvm/ExecutionEngine/RuntimeDyld.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/Error.h" @@ -36,16 +35,16 @@ namespace llvm { namespace orc { -class RTDyldObjectLinkingLayer : public ObjectLayer { +class RTDyldObjectLinkingLayer : public ObjectLayer, private ResourceManager { public: /// Functor for receiving object-loaded notifications. - using NotifyLoadedFunction = - std::function<void(VModuleKey, const object::ObjectFile &Obj, - const RuntimeDyld::LoadedObjectInfo &)>; + using NotifyLoadedFunction = std::function<void( + MaterializationResponsibility &R, const object::ObjectFile &Obj, + const RuntimeDyld::LoadedObjectInfo &)>; /// Functor for receiving finalization notifications. - using NotifyEmittedFunction = - std::function<void(VModuleKey, std::unique_ptr<MemoryBuffer>)>; + using NotifyEmittedFunction = std::function<void( + MaterializationResponsibility &R, std::unique_ptr<MemoryBuffer>)>; using GetMemoryManagerFunction = std::function<std::unique_ptr<RuntimeDyld::MemoryManager>()>; @@ -58,7 +57,7 @@ public: ~RTDyldObjectLinkingLayer(); /// Emit the object. - void emit(MaterializationResponsibility R, + void emit(std::unique_ptr<MaterializationResponsibility> R, std::unique_ptr<MemoryBuffer> O) override; /// Set the NotifyLoaded callback. @@ -123,16 +122,23 @@ public: void unregisterJITEventListener(JITEventListener &L); private: - Error onObjLoad(VModuleKey K, MaterializationResponsibility &R, + using MemoryManagerUP = std::unique_ptr<RuntimeDyld::MemoryManager>; + + Error onObjLoad(MaterializationResponsibility &R, const object::ObjectFile &Obj, - RuntimeDyld::MemoryManager *MemMgr, - std::unique_ptr<RuntimeDyld::LoadedObjectInfo> LoadedObjInfo, + RuntimeDyld::MemoryManager &MemMgr, + RuntimeDyld::LoadedObjectInfo &LoadedObjInfo, std::map<StringRef, JITEvaluatedSymbol> Resolved, std::set<StringRef> &InternalSymbols); - void onObjEmit(VModuleKey K, MaterializationResponsibility &R, + void onObjEmit(MaterializationResponsibility &R, object::OwningBinary<object::ObjectFile> O, - RuntimeDyld::MemoryManager *MemMgr, Error Err); + std::unique_ptr<RuntimeDyld::MemoryManager> MemMgr, + std::unique_ptr<RuntimeDyld::LoadedObjectInfo> LoadedObjInfo, + Error Err); + + Error handleRemoveResources(ResourceKey K) override; + void handleTransferResources(ResourceKey DstKey, ResourceKey SrcKey) override; mutable std::mutex RTDyldLayerMutex; GetMemoryManagerFunction GetMemoryManager; @@ -141,361 +147,8 @@ private: bool ProcessAllSections = false; bool OverrideObjectFlags = false; bool AutoClaimObjectSymbols = false; - std::vector<std::unique_ptr<RuntimeDyld::MemoryManager>> MemMgrs; + DenseMap<ResourceKey, std::vector<MemoryManagerUP>> MemMgrs; std::vector<JITEventListener *> EventListeners; - DenseMap<RuntimeDyld::MemoryManager *, - std::unique_ptr<RuntimeDyld::LoadedObjectInfo>> - LoadedObjInfos; -}; - -class LegacyRTDyldObjectLinkingLayerBase { -public: - using ObjectPtr = std::unique_ptr<MemoryBuffer>; - -protected: - - /// Holds an object to be allocated/linked as a unit in the JIT. - /// - /// An instance of this class will be created for each object added - /// via JITObjectLayer::addObject. Deleting the instance (via - /// removeObject) frees its memory, removing all symbol definitions that - /// had been provided by this instance. Higher level layers are responsible - /// for taking any action required to handle the missing symbols. - class LinkedObject { - public: - LinkedObject() = default; - LinkedObject(const LinkedObject&) = delete; - void operator=(const LinkedObject&) = delete; - virtual ~LinkedObject() = default; - - virtual Error finalize() = 0; - - virtual JITSymbol::GetAddressFtor - getSymbolMaterializer(std::string Name) = 0; - - virtual void mapSectionAddress(const void *LocalAddress, - JITTargetAddress TargetAddr) const = 0; - - JITSymbol getSymbol(StringRef Name, bool ExportedSymbolsOnly) { - auto SymEntry = SymbolTable.find(Name); - if (SymEntry == SymbolTable.end()) - return nullptr; - if (!SymEntry->second.getFlags().isExported() && ExportedSymbolsOnly) - return nullptr; - if (!Finalized) - return JITSymbol(getSymbolMaterializer(std::string(Name)), - SymEntry->second.getFlags()); - return JITSymbol(SymEntry->second); - } - - protected: - StringMap<JITEvaluatedSymbol> SymbolTable; - bool Finalized = false; - }; -}; - -/// Bare bones object linking layer. -/// -/// This class is intended to be used as the base layer for a JIT. It allows -/// object files to be loaded into memory, linked, and the addresses of their -/// symbols queried. All objects added to this layer can see each other's -/// symbols. -class LegacyRTDyldObjectLinkingLayer : public LegacyRTDyldObjectLinkingLayerBase { -public: - - using LegacyRTDyldObjectLinkingLayerBase::ObjectPtr; - - /// Functor for receiving object-loaded notifications. - using NotifyLoadedFtor = - std::function<void(VModuleKey, const object::ObjectFile &Obj, - const RuntimeDyld::LoadedObjectInfo &)>; - - /// Functor for receiving finalization notifications. - using NotifyFinalizedFtor = - std::function<void(VModuleKey, const object::ObjectFile &Obj, - const RuntimeDyld::LoadedObjectInfo &)>; - - /// Functor for receiving deallocation notifications. - using NotifyFreedFtor = std::function<void(VModuleKey, const object::ObjectFile &Obj)>; - -private: - using OwnedObject = object::OwningBinary<object::ObjectFile>; - - template <typename MemoryManagerPtrT> - class ConcreteLinkedObject : public LinkedObject { - public: - ConcreteLinkedObject(LegacyRTDyldObjectLinkingLayer &Parent, VModuleKey K, - OwnedObject Obj, MemoryManagerPtrT MemMgr, - std::shared_ptr<SymbolResolver> Resolver, - bool ProcessAllSections) - : K(std::move(K)), - Parent(Parent), - MemMgr(std::move(MemMgr)), - PFC(std::make_unique<PreFinalizeContents>( - std::move(Obj), std::move(Resolver), - ProcessAllSections)) { - buildInitialSymbolTable(PFC->Obj); - } - - ~ConcreteLinkedObject() override { - if (this->Parent.NotifyFreed && ObjForNotify.getBinary()) - this->Parent.NotifyFreed(K, *ObjForNotify.getBinary()); - - MemMgr->deregisterEHFrames(); - } - - Error finalize() override { - assert(PFC && "mapSectionAddress called on finalized LinkedObject"); - - JITSymbolResolverAdapter ResolverAdapter(Parent.ES, *PFC->Resolver, - nullptr); - PFC->RTDyld = std::make_unique<RuntimeDyld>(*MemMgr, ResolverAdapter); - PFC->RTDyld->setProcessAllSections(PFC->ProcessAllSections); - - Finalized = true; - - std::unique_ptr<RuntimeDyld::LoadedObjectInfo> Info = - PFC->RTDyld->loadObject(*PFC->Obj.getBinary()); - - // Copy the symbol table out of the RuntimeDyld instance. - { - auto SymTab = PFC->RTDyld->getSymbolTable(); - for (auto &KV : SymTab) - SymbolTable[KV.first] = KV.second; - } - - if (Parent.NotifyLoaded) - Parent.NotifyLoaded(K, *PFC->Obj.getBinary(), *Info); - - PFC->RTDyld->finalizeWithMemoryManagerLocking(); - - if (PFC->RTDyld->hasError()) - return make_error<StringError>(PFC->RTDyld->getErrorString(), - inconvertibleErrorCode()); - - if (Parent.NotifyFinalized) - Parent.NotifyFinalized(K, *PFC->Obj.getBinary(), *Info); - - // Release resources. - if (this->Parent.NotifyFreed) - ObjForNotify = std::move(PFC->Obj); // needed for callback - PFC = nullptr; - return Error::success(); - } - - JITSymbol::GetAddressFtor getSymbolMaterializer(std::string Name) override { - return [this, Name]() -> Expected<JITTargetAddress> { - // The symbol may be materialized between the creation of this lambda - // and its execution, so we need to double check. - if (!this->Finalized) - if (auto Err = this->finalize()) - return std::move(Err); - return this->getSymbol(Name, false).getAddress(); - }; - } - - void mapSectionAddress(const void *LocalAddress, - JITTargetAddress TargetAddr) const override { - assert(PFC && "mapSectionAddress called on finalized LinkedObject"); - assert(PFC->RTDyld && "mapSectionAddress called on raw LinkedObject"); - PFC->RTDyld->mapSectionAddress(LocalAddress, TargetAddr); - } - - private: - void buildInitialSymbolTable(const OwnedObject &Obj) { - for (auto &Symbol : Obj.getBinary()->symbols()) { - if (Expected<uint32_t> SymbolFlagsOrErr = Symbol.getFlags()) { - if (*SymbolFlagsOrErr & object::SymbolRef::SF_Undefined) - continue; - } else { - // FIXME: Raise an error for bad symbols. - consumeError(SymbolFlagsOrErr.takeError()); - continue; - } - - Expected<StringRef> SymbolName = Symbol.getName(); - // FIXME: Raise an error for bad symbols. - if (!SymbolName) { - consumeError(SymbolName.takeError()); - continue; - } - // FIXME: Raise an error for bad symbols. - auto Flags = JITSymbolFlags::fromObjectSymbol(Symbol); - if (!Flags) { - consumeError(Flags.takeError()); - continue; - } - SymbolTable.insert( - std::make_pair(*SymbolName, JITEvaluatedSymbol(0, *Flags))); - } - } - - // Contains the information needed prior to finalization: the object files, - // memory manager, resolver, and flags needed for RuntimeDyld. - struct PreFinalizeContents { - PreFinalizeContents(OwnedObject Obj, - std::shared_ptr<SymbolResolver> Resolver, - bool ProcessAllSections) - : Obj(std::move(Obj)), - Resolver(std::move(Resolver)), - ProcessAllSections(ProcessAllSections) {} - - OwnedObject Obj; - std::shared_ptr<SymbolResolver> Resolver; - bool ProcessAllSections; - std::unique_ptr<RuntimeDyld> RTDyld; - }; - - VModuleKey K; - LegacyRTDyldObjectLinkingLayer &Parent; - MemoryManagerPtrT MemMgr; - OwnedObject ObjForNotify; - std::unique_ptr<PreFinalizeContents> PFC; - }; - - template <typename MemoryManagerPtrT> - std::unique_ptr<ConcreteLinkedObject<MemoryManagerPtrT>> - createLinkedObject(LegacyRTDyldObjectLinkingLayer &Parent, VModuleKey K, - OwnedObject Obj, MemoryManagerPtrT MemMgr, - std::shared_ptr<SymbolResolver> Resolver, - bool ProcessAllSections) { - using LOS = ConcreteLinkedObject<MemoryManagerPtrT>; - return std::make_unique<LOS>(Parent, std::move(K), std::move(Obj), - std::move(MemMgr), std::move(Resolver), - ProcessAllSections); - } - -public: - struct Resources { - std::shared_ptr<RuntimeDyld::MemoryManager> MemMgr; - std::shared_ptr<SymbolResolver> Resolver; - }; - - using ResourcesGetter = std::function<Resources(VModuleKey)>; - - /// Construct an ObjectLinkingLayer with the given NotifyLoaded, - /// and NotifyFinalized functors. - LLVM_ATTRIBUTE_DEPRECATED( - LegacyRTDyldObjectLinkingLayer( - ExecutionSession &ES, ResourcesGetter GetResources, - NotifyLoadedFtor NotifyLoaded = NotifyLoadedFtor(), - NotifyFinalizedFtor NotifyFinalized = NotifyFinalizedFtor(), - NotifyFreedFtor NotifyFreed = NotifyFreedFtor()), - "ORCv1 layers (layers with the 'Legacy' prefix) are deprecated. Please " - "use " - "ORCv2 (see docs/ORCv2.rst)"); - - // Legacy layer constructor with deprecation acknowledgement. - LegacyRTDyldObjectLinkingLayer( - ORCv1DeprecationAcknowledgement, ExecutionSession &ES, - ResourcesGetter GetResources, - NotifyLoadedFtor NotifyLoaded = NotifyLoadedFtor(), - NotifyFinalizedFtor NotifyFinalized = NotifyFinalizedFtor(), - NotifyFreedFtor NotifyFreed = NotifyFreedFtor()) - : ES(ES), GetResources(std::move(GetResources)), - NotifyLoaded(std::move(NotifyLoaded)), - NotifyFinalized(std::move(NotifyFinalized)), - NotifyFreed(std::move(NotifyFreed)), ProcessAllSections(false) {} - - /// Set the 'ProcessAllSections' flag. - /// - /// If set to true, all sections in each object file will be allocated using - /// the memory manager, rather than just the sections required for execution. - /// - /// This is kludgy, and may be removed in the future. - void setProcessAllSections(bool ProcessAllSections) { - this->ProcessAllSections = ProcessAllSections; - } - - /// Add an object to the JIT. - Error addObject(VModuleKey K, ObjectPtr ObjBuffer) { - - auto Obj = - object::ObjectFile::createObjectFile(ObjBuffer->getMemBufferRef()); - if (!Obj) - return Obj.takeError(); - - assert(!LinkedObjects.count(K) && "VModuleKey already in use"); - - auto R = GetResources(K); - - LinkedObjects[K] = createLinkedObject( - *this, K, OwnedObject(std::move(*Obj), std::move(ObjBuffer)), - std::move(R.MemMgr), std::move(R.Resolver), ProcessAllSections); - - return Error::success(); - } - - /// Remove the object associated with VModuleKey K. - /// - /// All memory allocated for the object will be freed, and the sections and - /// symbols it provided will no longer be available. No attempt is made to - /// re-emit the missing symbols, and any use of these symbols (directly or - /// indirectly) will result in undefined behavior. If dependence tracking is - /// required to detect or resolve such issues it should be added at a higher - /// layer. - Error removeObject(VModuleKey K) { - assert(LinkedObjects.count(K) && "VModuleKey not associated with object"); - // How do we invalidate the symbols in H? - LinkedObjects.erase(K); - return Error::success(); - } - - /// Search for the given named symbol. - /// @param Name The name of the symbol to search for. - /// @param ExportedSymbolsOnly If true, search only for exported symbols. - /// @return A handle for the given named symbol, if it exists. - JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly) { - for (auto &KV : LinkedObjects) - if (auto Sym = KV.second->getSymbol(Name, ExportedSymbolsOnly)) - return Sym; - else if (auto Err = Sym.takeError()) - return std::move(Err); - - return nullptr; - } - - /// Search for the given named symbol in the context of the loaded - /// object represented by the VModuleKey K. - /// @param K The VModuleKey for the object to search in. - /// @param Name The name of the symbol to search for. - /// @param ExportedSymbolsOnly If true, search only for exported symbols. - /// @return A handle for the given named symbol, if it is found in the - /// given object. - JITSymbol findSymbolIn(VModuleKey K, StringRef Name, - bool ExportedSymbolsOnly) { - assert(LinkedObjects.count(K) && "VModuleKey not associated with object"); - return LinkedObjects[K]->getSymbol(Name, ExportedSymbolsOnly); - } - - /// Map section addresses for the object associated with the - /// VModuleKey K. - void mapSectionAddress(VModuleKey K, const void *LocalAddress, - JITTargetAddress TargetAddr) { - assert(LinkedObjects.count(K) && "VModuleKey not associated with object"); - LinkedObjects[K]->mapSectionAddress(LocalAddress, TargetAddr); - } - - /// Immediately emit and finalize the object represented by the given - /// VModuleKey. - /// @param K VModuleKey for object to emit/finalize. - Error emitAndFinalize(VModuleKey K) { - assert(LinkedObjects.count(K) && "VModuleKey not associated with object"); - return LinkedObjects[K]->finalize(); - } - -private: - ExecutionSession &ES; - - ResourcesGetter GetResources; - NotifyLoadedFtor NotifyLoaded; - NotifyFinalizedFtor NotifyFinalized; - NotifyFreedFtor NotifyFreed; - - // NB! `LinkedObjects` needs to be destroyed before `NotifyFreed` because - // `~ConcreteLinkedObject` calls `NotifyFreed` - std::map<VModuleKey, std::unique_ptr<LinkedObject>> LinkedObjects; - bool ProcessAllSections = false; }; } // end namespace orc diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/RemoteObjectLayer.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/RemoteObjectLayer.h deleted file mode 100644 index d7304cfcf931..000000000000 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/RemoteObjectLayer.h +++ /dev/null @@ -1,564 +0,0 @@ -//===------ RemoteObjectLayer.h - Forwards objs to a remote -----*- 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 -// -//===----------------------------------------------------------------------===// -// -// Forwards objects to a remote object layer via RPC. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_EXECUTIONENGINE_ORC_REMOTEOBJECTLAYER_H -#define LLVM_EXECUTIONENGINE_ORC_REMOTEOBJECTLAYER_H - -#include "llvm/ExecutionEngine/Orc/Core.h" -#include "llvm/ExecutionEngine/Orc/LambdaResolver.h" -#include "llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h" -#include "llvm/Object/ObjectFile.h" -#include <map> - -namespace llvm { -namespace orc { - -/// RPC API needed by RemoteObjectClientLayer and RemoteObjectServerLayer. -class RemoteObjectLayerAPI { -public: - - using ObjHandleT = remote::ResourceIdMgr::ResourceId; - -protected: - - using RemoteSymbolId = remote::ResourceIdMgr::ResourceId; - using RemoteSymbol = std::pair<RemoteSymbolId, JITSymbolFlags>; - -public: - - using BadSymbolHandleError = remote::ResourceNotFound<RemoteSymbolId>; - using BadObjectHandleError = remote::ResourceNotFound<ObjHandleT>; - -protected: - - static const ObjHandleT InvalidObjectHandleId = 0; - static const RemoteSymbolId NullSymbolId = 0; - - class AddObject - : public rpc::Function<AddObject, Expected<ObjHandleT>(std::string)> { - public: - static const char *getName() { return "AddObject"; } - }; - - class RemoveObject - : public rpc::Function<RemoveObject, Error(ObjHandleT)> { - public: - static const char *getName() { return "RemoveObject"; } - }; - - class FindSymbol - : public rpc::Function<FindSymbol, Expected<RemoteSymbol>(std::string, - bool)> { - public: - static const char *getName() { return "FindSymbol"; } - }; - - class FindSymbolIn - : public rpc::Function<FindSymbolIn, - Expected<RemoteSymbol>(ObjHandleT, std::string, - bool)> { - public: - static const char *getName() { return "FindSymbolIn"; } - }; - - class EmitAndFinalize - : public rpc::Function<EmitAndFinalize, - Error(ObjHandleT)> { - public: - static const char *getName() { return "EmitAndFinalize"; } - }; - - class Lookup - : public rpc::Function<Lookup, - Expected<RemoteSymbol>(ObjHandleT, std::string)> { - public: - static const char *getName() { return "Lookup"; } - }; - - class LookupInLogicalDylib - : public rpc::Function<LookupInLogicalDylib, - Expected<RemoteSymbol>(ObjHandleT, std::string)> { - public: - static const char *getName() { return "LookupInLogicalDylib"; } - }; - - class ReleaseRemoteSymbol - : public rpc::Function<ReleaseRemoteSymbol, Error(RemoteSymbolId)> { - public: - static const char *getName() { return "ReleaseRemoteSymbol"; } - }; - - class MaterializeRemoteSymbol - : public rpc::Function<MaterializeRemoteSymbol, - Expected<JITTargetAddress>(RemoteSymbolId)> { - public: - static const char *getName() { return "MaterializeRemoteSymbol"; } - }; -}; - -/// Base class containing common utilities for RemoteObjectClientLayer and -/// RemoteObjectServerLayer. -template <typename RPCEndpoint> -class RemoteObjectLayer : public RemoteObjectLayerAPI { -public: - - RemoteObjectLayer(RPCEndpoint &Remote, - std::function<void(Error)> ReportError) - : Remote(Remote), ReportError(std::move(ReportError)), - SymbolIdMgr(NullSymbolId + 1) { - using ThisT = RemoteObjectLayer<RPCEndpoint>; - Remote.template addHandler<ReleaseRemoteSymbol>( - *this, &ThisT::handleReleaseRemoteSymbol); - Remote.template addHandler<MaterializeRemoteSymbol>( - *this, &ThisT::handleMaterializeRemoteSymbol); - } - -protected: - - /// This class is used as the symbol materializer for JITSymbols returned by - /// RemoteObjectLayerClient/RemoteObjectLayerServer -- the materializer knows - /// how to call back to the other RPC endpoint to get the address when - /// requested. - class RemoteSymbolMaterializer { - public: - - /// Construct a RemoteSymbolMaterializer for the given RemoteObjectLayer - /// with the given Id. - RemoteSymbolMaterializer(RemoteObjectLayer &C, - RemoteSymbolId Id) - : C(C), Id(Id) {} - - RemoteSymbolMaterializer(RemoteSymbolMaterializer &&Other) - : C(Other.C), Id(Other.Id) { - Other.Id = 0; - } - - RemoteSymbolMaterializer &operator=(RemoteSymbolMaterializer &&) = delete; - - /// Release the remote symbol. - ~RemoteSymbolMaterializer() { - if (Id) - C.releaseRemoteSymbol(Id); - } - - /// Materialize the symbol on the remote and get its address. - Expected<JITTargetAddress> materialize() { - auto Addr = C.materializeRemoteSymbol(Id); - Id = 0; - return Addr; - } - - private: - RemoteObjectLayer &C; - RemoteSymbolId Id; - }; - - /// Convenience function for getting a null remote symbol value. - RemoteSymbol nullRemoteSymbol() { - return RemoteSymbol(0, JITSymbolFlags()); - } - - /// Creates a StringError that contains a copy of Err's log message, then - /// sends that StringError to ReportError. - /// - /// This allows us to locally log error messages for errors that will actually - /// be delivered to the remote. - Error teeLog(Error Err) { - return handleErrors(std::move(Err), - [this](std::unique_ptr<ErrorInfoBase> EIB) { - ReportError(make_error<StringError>( - EIB->message(), - EIB->convertToErrorCode())); - return Error(std::move(EIB)); - }); - } - - Error badRemoteSymbolIdError(RemoteSymbolId Id) { - return make_error<BadSymbolHandleError>(Id, "Remote JIT Symbol"); - } - - Error badObjectHandleError(ObjHandleT H) { - return make_error<RemoteObjectLayerAPI::BadObjectHandleError>( - H, "Bad object handle"); - } - - /// Create a RemoteSymbol wrapping the given JITSymbol. - Expected<RemoteSymbol> jitSymbolToRemote(JITSymbol Sym) { - if (Sym) { - auto Id = SymbolIdMgr.getNext(); - auto Flags = Sym.getFlags(); - assert(!InUseSymbols.count(Id) && "Symbol id already in use"); - InUseSymbols.insert(std::make_pair(Id, std::move(Sym))); - return RemoteSymbol(Id, Flags); - } else if (auto Err = Sym.takeError()) - return teeLog(std::move(Err)); - // else... - return nullRemoteSymbol(); - } - - /// Convert an Expected<RemoteSymbol> to a JITSymbol. - JITSymbol remoteToJITSymbol(Expected<RemoteSymbol> RemoteSymOrErr) { - if (RemoteSymOrErr) { - auto &RemoteSym = *RemoteSymOrErr; - if (RemoteSym == nullRemoteSymbol()) - return nullptr; - // else... - RemoteSymbolMaterializer RSM(*this, RemoteSym.first); - auto Sym = JITSymbol( - [RSM = std::move(RSM)]() mutable { return RSM.materialize(); }, - RemoteSym.second); - return Sym; - } else - return RemoteSymOrErr.takeError(); - } - - RPCEndpoint &Remote; - std::function<void(Error)> ReportError; - -private: - - /// Notify the remote to release the given JITSymbol. - void releaseRemoteSymbol(RemoteSymbolId Id) { - if (auto Err = Remote.template callB<ReleaseRemoteSymbol>(Id)) - ReportError(std::move(Err)); - } - - /// Notify the remote to materialize the JITSymbol with the given Id and - /// return its address. - Expected<JITTargetAddress> materializeRemoteSymbol(RemoteSymbolId Id) { - return Remote.template callB<MaterializeRemoteSymbol>(Id); - } - - /// Release the JITSymbol with the given Id. - Error handleReleaseRemoteSymbol(RemoteSymbolId Id) { - auto SI = InUseSymbols.find(Id); - if (SI != InUseSymbols.end()) { - InUseSymbols.erase(SI); - return Error::success(); - } else - return teeLog(badRemoteSymbolIdError(Id)); - } - - /// Run the materializer for the JITSymbol with the given Id and return its - /// address. - Expected<JITTargetAddress> handleMaterializeRemoteSymbol(RemoteSymbolId Id) { - auto SI = InUseSymbols.find(Id); - if (SI != InUseSymbols.end()) { - auto AddrOrErr = SI->second.getAddress(); - InUseSymbols.erase(SI); - SymbolIdMgr.release(Id); - if (AddrOrErr) - return *AddrOrErr; - else - return teeLog(AddrOrErr.takeError()); - } else { - return teeLog(badRemoteSymbolIdError(Id)); - } - } - - remote::ResourceIdMgr SymbolIdMgr; - std::map<RemoteSymbolId, JITSymbol> InUseSymbols; -}; - -/// RemoteObjectClientLayer forwards the ORC Object Layer API over an RPC -/// connection. -/// -/// This class can be used as the base layer of a JIT stack on the client and -/// will forward operations to a corresponding RemoteObjectServerLayer on the -/// server (which can be composed on top of a "real" object layer like -/// RTDyldObjectLinkingLayer to actually carry out the operations). -/// -/// Sending relocatable objects to the server (rather than fully relocated -/// bits) allows JIT'd code to be cached on the server side and re-used in -/// subsequent JIT sessions. -template <typename RPCEndpoint> -class RemoteObjectClientLayer : public RemoteObjectLayer<RPCEndpoint> { -private: - - using AddObject = RemoteObjectLayerAPI::AddObject; - using RemoveObject = RemoteObjectLayerAPI::RemoveObject; - using FindSymbol = RemoteObjectLayerAPI::FindSymbol; - using FindSymbolIn = RemoteObjectLayerAPI::FindSymbolIn; - using EmitAndFinalize = RemoteObjectLayerAPI::EmitAndFinalize; - using Lookup = RemoteObjectLayerAPI::Lookup; - using LookupInLogicalDylib = RemoteObjectLayerAPI::LookupInLogicalDylib; - - using RemoteObjectLayer<RPCEndpoint>::teeLog; - using RemoteObjectLayer<RPCEndpoint>::badObjectHandleError; - using RemoteObjectLayer<RPCEndpoint>::remoteToJITSymbol; - -public: - - using ObjHandleT = RemoteObjectLayerAPI::ObjHandleT; - using RemoteSymbol = RemoteObjectLayerAPI::RemoteSymbol; - - using ObjectPtr = std::unique_ptr<MemoryBuffer>; - - /// Create a RemoteObjectClientLayer that communicates with a - /// RemoteObjectServerLayer instance via the given RPCEndpoint. - /// - /// The ReportError functor can be used locally log errors that are intended - /// to be sent sent - LLVM_ATTRIBUTE_DEPRECATED( - RemoteObjectClientLayer(RPCEndpoint &Remote, - std::function<void(Error)> ReportError), - "ORCv1 layers (including RemoteObjectClientLayer) are deprecated. Please " - "use " - "ORCv2 (see docs/ORCv2.rst)"); - - RemoteObjectClientLayer(ORCv1DeprecationAcknowledgement, RPCEndpoint &Remote, - std::function<void(Error)> ReportError) - : RemoteObjectLayer<RPCEndpoint>(Remote, std::move(ReportError)) { - using ThisT = RemoteObjectClientLayer<RPCEndpoint>; - Remote.template addHandler<Lookup>(*this, &ThisT::lookup); - Remote.template addHandler<LookupInLogicalDylib>( - *this, &ThisT::lookupInLogicalDylib); - } - - /// Add an object to the JIT. - /// - /// @return A handle that can be used to refer to the loaded object (for - /// symbol searching, finalization, freeing memory, etc.). - Expected<ObjHandleT> - addObject(ObjectPtr ObjBuffer, - std::shared_ptr<LegacyJITSymbolResolver> Resolver) { - if (auto HandleOrErr = - this->Remote.template callB<AddObject>(ObjBuffer->getBuffer())) { - auto &Handle = *HandleOrErr; - // FIXME: Return an error for this: - assert(!Resolvers.count(Handle) && "Handle already in use?"); - Resolvers[Handle] = std::move(Resolver); - return Handle; - } else - return HandleOrErr.takeError(); - } - - /// Remove the given object from the JIT. - Error removeObject(ObjHandleT H) { - return this->Remote.template callB<RemoveObject>(H); - } - - /// Search for the given named symbol. - JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly) { - return remoteToJITSymbol( - this->Remote.template callB<FindSymbol>(Name, - ExportedSymbolsOnly)); - } - - /// Search for the given named symbol within the given context. - JITSymbol findSymbolIn(ObjHandleT H, StringRef Name, bool ExportedSymbolsOnly) { - return remoteToJITSymbol( - this->Remote.template callB<FindSymbolIn>(H, Name, - ExportedSymbolsOnly)); - } - - /// Immediately emit and finalize the object with the given handle. - Error emitAndFinalize(ObjHandleT H) { - return this->Remote.template callB<EmitAndFinalize>(H); - } - -private: - - Expected<RemoteSymbol> lookup(ObjHandleT H, const std::string &Name) { - auto RI = Resolvers.find(H); - if (RI != Resolvers.end()) { - return this->jitSymbolToRemote(RI->second->findSymbol(Name)); - } else - return teeLog(badObjectHandleError(H)); - } - - Expected<RemoteSymbol> lookupInLogicalDylib(ObjHandleT H, - const std::string &Name) { - auto RI = Resolvers.find(H); - if (RI != Resolvers.end()) - return this->jitSymbolToRemote( - RI->second->findSymbolInLogicalDylib(Name)); - else - return teeLog(badObjectHandleError(H)); - } - - std::map<remote::ResourceIdMgr::ResourceId, - std::shared_ptr<LegacyJITSymbolResolver>> - Resolvers; -}; - -/// RemoteObjectServerLayer acts as a server and handling RPC calls for the -/// object layer API from the given RPC connection. -/// -/// This class can be composed on top of a 'real' object layer (e.g. -/// RTDyldObjectLinkingLayer) to do the actual work of relocating objects -/// and making them executable. -template <typename BaseLayerT, typename RPCEndpoint> -class RemoteObjectServerLayer : public RemoteObjectLayer<RPCEndpoint> { -private: - - using ObjHandleT = RemoteObjectLayerAPI::ObjHandleT; - using RemoteSymbol = RemoteObjectLayerAPI::RemoteSymbol; - - using AddObject = RemoteObjectLayerAPI::AddObject; - using RemoveObject = RemoteObjectLayerAPI::RemoveObject; - using FindSymbol = RemoteObjectLayerAPI::FindSymbol; - using FindSymbolIn = RemoteObjectLayerAPI::FindSymbolIn; - using EmitAndFinalize = RemoteObjectLayerAPI::EmitAndFinalize; - using Lookup = RemoteObjectLayerAPI::Lookup; - using LookupInLogicalDylib = RemoteObjectLayerAPI::LookupInLogicalDylib; - - using RemoteObjectLayer<RPCEndpoint>::teeLog; - using RemoteObjectLayer<RPCEndpoint>::badObjectHandleError; - using RemoteObjectLayer<RPCEndpoint>::remoteToJITSymbol; - -public: - - /// Create a RemoteObjectServerLayer with the given base layer (which must be - /// an object layer), RPC endpoint, and error reporter function. - LLVM_ATTRIBUTE_DEPRECATED( - RemoteObjectServerLayer(BaseLayerT &BaseLayer, RPCEndpoint &Remote, - std::function<void(Error)> ReportError), - "ORCv1 layers (including RemoteObjectServerLayer) are deprecated. Please " - "use " - "ORCv2 (see docs/ORCv2.rst)"); - - RemoteObjectServerLayer(ORCv1DeprecationAcknowledgement, - BaseLayerT &BaseLayer, RPCEndpoint &Remote, - std::function<void(Error)> ReportError) - : RemoteObjectLayer<RPCEndpoint>(Remote, std::move(ReportError)), - BaseLayer(BaseLayer), HandleIdMgr(1) { - using ThisT = RemoteObjectServerLayer<BaseLayerT, RPCEndpoint>; - - Remote.template addHandler<AddObject>(*this, &ThisT::addObject); - Remote.template addHandler<RemoveObject>(*this, &ThisT::removeObject); - Remote.template addHandler<FindSymbol>(*this, &ThisT::findSymbol); - Remote.template addHandler<FindSymbolIn>(*this, &ThisT::findSymbolIn); - Remote.template addHandler<EmitAndFinalize>(*this, &ThisT::emitAndFinalize); - } - -private: - - class StringMemoryBuffer : public MemoryBuffer { - public: - StringMemoryBuffer(std::string Buffer) - : Buffer(std::move(Buffer)) { - init(this->Buffer.data(), this->Buffer.data() + this->Buffer.size(), - false); - } - - BufferKind getBufferKind() const override { return MemoryBuffer_Malloc; } - private: - std::string Buffer; - }; - - JITSymbol lookup(ObjHandleT Id, const std::string &Name) { - return remoteToJITSymbol( - this->Remote.template callB<Lookup>(Id, Name)); - } - - JITSymbol lookupInLogicalDylib(ObjHandleT Id, const std::string &Name) { - return remoteToJITSymbol( - this->Remote.template callB<LookupInLogicalDylib>(Id, Name)); - } - - Expected<ObjHandleT> addObject(std::string ObjBuffer) { - auto Buffer = std::make_unique<StringMemoryBuffer>(std::move(ObjBuffer)); - auto Id = HandleIdMgr.getNext(); - assert(!BaseLayerHandles.count(Id) && "Id already in use?"); - - auto Resolver = createLambdaResolver( - AcknowledgeORCv1Deprecation, - [this, Id](const std::string &Name) { return lookup(Id, Name); }, - [this, Id](const std::string &Name) { - return lookupInLogicalDylib(Id, Name); - }); - - if (auto HandleOrErr = - BaseLayer.addObject(std::move(Buffer), std::move(Resolver))) { - BaseLayerHandles[Id] = std::move(*HandleOrErr); - return Id; - } else - return teeLog(HandleOrErr.takeError()); - } - - Error removeObject(ObjHandleT H) { - auto HI = BaseLayerHandles.find(H); - if (HI != BaseLayerHandles.end()) { - if (auto Err = BaseLayer.removeObject(HI->second)) - return teeLog(std::move(Err)); - return Error::success(); - } else - return teeLog(badObjectHandleError(H)); - } - - Expected<RemoteSymbol> findSymbol(const std::string &Name, - bool ExportedSymbolsOnly) { - if (auto Sym = BaseLayer.findSymbol(Name, ExportedSymbolsOnly)) - return this->jitSymbolToRemote(std::move(Sym)); - else if (auto Err = Sym.takeError()) - return teeLog(std::move(Err)); - return this->nullRemoteSymbol(); - } - - Expected<RemoteSymbol> findSymbolIn(ObjHandleT H, const std::string &Name, - bool ExportedSymbolsOnly) { - auto HI = BaseLayerHandles.find(H); - if (HI != BaseLayerHandles.end()) { - if (auto Sym = BaseLayer.findSymbolIn(HI->second, Name, ExportedSymbolsOnly)) - return this->jitSymbolToRemote(std::move(Sym)); - else if (auto Err = Sym.takeError()) - return teeLog(std::move(Err)); - return this->nullRemoteSymbol(); - } else - return teeLog(badObjectHandleError(H)); - } - - Error emitAndFinalize(ObjHandleT H) { - auto HI = BaseLayerHandles.find(H); - if (HI != BaseLayerHandles.end()) { - if (auto Err = BaseLayer.emitAndFinalize(HI->second)) - return teeLog(std::move(Err)); - return Error::success(); - } else - return teeLog(badObjectHandleError(H)); - } - - BaseLayerT &BaseLayer; - remote::ResourceIdMgr HandleIdMgr; - std::map<ObjHandleT, typename BaseLayerT::ObjHandleT> BaseLayerHandles; -}; - -template <typename RPCEndpoint> -RemoteObjectClientLayer<RPCEndpoint>::RemoteObjectClientLayer( - RPCEndpoint &Remote, std::function<void(Error)> ReportError) - : RemoteObjectLayer<RPCEndpoint>(Remote, std::move(ReportError)) { - using ThisT = RemoteObjectClientLayer<RPCEndpoint>; - Remote.template addHandler<Lookup>(*this, &ThisT::lookup); - Remote.template addHandler<LookupInLogicalDylib>( - *this, &ThisT::lookupInLogicalDylib); -} - -template <typename BaseLayerT, typename RPCEndpoint> -RemoteObjectServerLayer<BaseLayerT, RPCEndpoint>::RemoteObjectServerLayer( - BaseLayerT &BaseLayer, RPCEndpoint &Remote, - std::function<void(Error)> ReportError) - : RemoteObjectLayer<RPCEndpoint>(Remote, std::move(ReportError)), - BaseLayer(BaseLayer), HandleIdMgr(1) { - using ThisT = RemoteObjectServerLayer<BaseLayerT, RPCEndpoint>; - - Remote.template addHandler<AddObject>(*this, &ThisT::addObject); - Remote.template addHandler<RemoveObject>(*this, &ThisT::removeObject); - Remote.template addHandler<FindSymbol>(*this, &ThisT::findSymbol); - Remote.template addHandler<FindSymbolIn>(*this, &ThisT::findSymbolIn); - Remote.template addHandler<EmitAndFinalize>(*this, &ThisT::emitAndFinalize); -} - -} // end namespace orc -} // end namespace llvm - -#endif // LLVM_EXECUTIONENGINE_ORC_REMOTEOBJECTLAYER_H diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/Shared/FDRawByteChannel.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/Shared/FDRawByteChannel.h new file mode 100644 index 000000000000..3f96fe3da49d --- /dev/null +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/Shared/FDRawByteChannel.h @@ -0,0 +1,79 @@ +//===- FDRawByteChannel.h - File descriptor based byte-channel -*- 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 +// +//===----------------------------------------------------------------------===// +// +// File descriptor based RawByteChannel. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORC_SHARED_FDRAWBYTECHANNEL_H +#define LLVM_EXECUTIONENGINE_ORC_SHARED_FDRAWBYTECHANNEL_H + +#include "llvm/ExecutionEngine/Orc/Shared/RawByteChannel.h" + +#if !defined(_MSC_VER) && !defined(__MINGW32__) +#include <unistd.h> +#else +#include <io.h> +#endif + +namespace llvm { +namespace orc { +namespace shared { + +/// Serialization channel that reads from and writes from file descriptors. +class FDRawByteChannel final : public RawByteChannel { +public: + FDRawByteChannel(int InFD, int OutFD) : InFD(InFD), OutFD(OutFD) {} + + llvm::Error readBytes(char *Dst, unsigned Size) override { + assert(Dst && "Attempt to read into null."); + ssize_t Completed = 0; + while (Completed < static_cast<ssize_t>(Size)) { + ssize_t Read = ::read(InFD, Dst + Completed, Size - Completed); + if (Read <= 0) { + auto ErrNo = errno; + if (ErrNo == EAGAIN || ErrNo == EINTR) + continue; + else + return llvm::errorCodeToError( + std::error_code(errno, std::generic_category())); + } + Completed += Read; + } + return llvm::Error::success(); + } + + llvm::Error appendBytes(const char *Src, unsigned Size) override { + assert(Src && "Attempt to append from null."); + ssize_t Completed = 0; + while (Completed < static_cast<ssize_t>(Size)) { + ssize_t Written = ::write(OutFD, Src + Completed, Size - Completed); + if (Written < 0) { + auto ErrNo = errno; + if (ErrNo == EAGAIN || ErrNo == EINTR) + continue; + else + return llvm::errorCodeToError( + std::error_code(errno, std::generic_category())); + } + Completed += Written; + } + return llvm::Error::success(); + } + + llvm::Error send() override { return llvm::Error::success(); } + +private: + int InFD, OutFD; +}; + +} // namespace shared +} // namespace orc +} // namespace llvm + +#endif // LLVM_EXECUTIONENGINE_ORC_SHARED_FDRAWBYTECHANNEL_H diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/OrcError.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/Shared/OrcError.h index 9b0d941f5459..9b0d941f5459 100644 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/OrcError.h +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/Shared/OrcError.h diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/RPC/RPCUtils.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/Shared/RPCUtils.h index f348844f39ce..e0ac640ebcdd 100644 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/RPC/RPCUtils.h +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/Shared/RPCUtils.h @@ -14,23 +14,23 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_EXECUTIONENGINE_ORC_RPCUTILS_H -#define LLVM_EXECUTIONENGINE_ORC_RPCUTILS_H +#ifndef LLVM_EXECUTIONENGINE_ORC_SHARED_RPCUTILS_H +#define LLVM_EXECUTIONENGINE_ORC_SHARED_RPCUTILS_H #include <map> #include <thread> #include <vector> #include "llvm/ADT/STLExtras.h" -#include "llvm/ExecutionEngine/Orc/OrcError.h" -#include "llvm/ExecutionEngine/Orc/RPC/RPCSerialization.h" +#include "llvm/ExecutionEngine/Orc/Shared/OrcError.h" +#include "llvm/ExecutionEngine/Orc/Shared/Serialization.h" #include "llvm/Support/MSVCErrorWorkarounds.h" #include <future> namespace llvm { namespace orc { -namespace rpc { +namespace shared { /// Base class of all fatal RPC errors (those that necessarily result in the /// termination of the RPC session). @@ -56,7 +56,7 @@ public: /// function id it cannot parse the call. template <typename FnIdT, typename SeqNoT> class BadFunctionCall - : public ErrorInfo<BadFunctionCall<FnIdT, SeqNoT>, RPCFatalError> { + : public ErrorInfo<BadFunctionCall<FnIdT, SeqNoT>, RPCFatalError> { public: static char ID; @@ -68,8 +68,10 @@ public: } void log(raw_ostream &OS) const override { - OS << "Call to invalid RPC function id '" << FnId << "' with " - "sequence number " << SeqNo; + OS << "Call to invalid RPC function id '" << FnId + << "' with " + "sequence number " + << SeqNo; } private: @@ -89,12 +91,12 @@ char BadFunctionCall<FnIdT, SeqNoT>::ID = 0; /// a result parser for this sequence number it can't do that. template <typename SeqNoT> class InvalidSequenceNumberForResponse - : public ErrorInfo<InvalidSequenceNumberForResponse<SeqNoT>, RPCFatalError> { + : public ErrorInfo<InvalidSequenceNumberForResponse<SeqNoT>, + RPCFatalError> { public: static char ID; - InvalidSequenceNumberForResponse(SeqNoT SeqNo) - : SeqNo(std::move(SeqNo)) {} + InvalidSequenceNumberForResponse(SeqNoT SeqNo) : SeqNo(std::move(SeqNo)) {} std::error_code convertToErrorCode() const override { return orcError(OrcErrorCode::UnexpectedRPCCall); @@ -103,6 +105,7 @@ public: void log(raw_ostream &OS) const override { OS << "Response has unknown sequence number " << SeqNo; } + private: SeqNoT SeqNo; }; @@ -131,17 +134,18 @@ public: std::error_code convertToErrorCode() const override; void log(raw_ostream &OS) const override; const std::string &getSignature() const { return Signature; } + private: std::string Signature; }; -template <typename DerivedFunc, typename FnT> class Function; +template <typename DerivedFunc, typename FnT> class RPCFunction; // RPC Function class. // DerivedFunc should be a user defined class with a static 'getName()' method // returning a const char* representing the function's name. template <typename DerivedFunc, typename RetT, typename... ArgTs> -class Function<DerivedFunc, RetT(ArgTs...)> { +class RPCFunction<DerivedFunc, RetT(ArgTs...)> { public: /// User defined function type. using Type = RetT(ArgTs...); @@ -154,8 +158,9 @@ public: static std::string Name = [] { std::string Name; raw_string_ostream(Name) - << RPCTypeName<RetT>::getName() << " " << DerivedFunc::getName() - << "(" << llvm::orc::rpc::RPCTypeNameSequence<ArgTs...>() << ")"; + << SerializationTypeName<RetT>::getName() << " " + << DerivedFunc::getName() << "(" + << SerializationTypeNameSequence<ArgTs...>() << ")"; return Name; }(); return Name.data(); @@ -199,10 +204,10 @@ private: namespace detail { /// Provides a typedef for a tuple containing the decayed argument types. -template <typename T> class FunctionArgsTuple; +template <typename T> class RPCFunctionArgsTuple; template <typename RetT, typename... ArgTs> -class FunctionArgsTuple<RetT(ArgTs...)> { +class RPCFunctionArgsTuple<RetT(ArgTs...)> { public: using Type = std::tuple<std::decay_t<std::remove_reference_t<ArgTs>>...>; }; @@ -287,34 +292,28 @@ class ResultTraits<Expected<RetT>> : public ResultTraits<RetT> {}; // Determines whether an RPC function's defined error return type supports // error return value. -template <typename T> -class SupportsErrorReturn { +template <typename T> class SupportsErrorReturn { public: static const bool value = false; }; -template <> -class SupportsErrorReturn<Error> { +template <> class SupportsErrorReturn<Error> { public: static const bool value = true; }; -template <typename T> -class SupportsErrorReturn<Expected<T>> { +template <typename T> class SupportsErrorReturn<Expected<T>> { public: static const bool value = true; }; // RespondHelper packages return values based on whether or not the declared // RPC function return type supports error returns. -template <bool FuncSupportsErrorReturn> -class RespondHelper; +template <bool FuncSupportsErrorReturn> class RespondHelper; // RespondHelper specialization for functions that support error returns. -template <> -class RespondHelper<true> { +template <> class RespondHelper<true> { public: - // Send Expected<T>. template <typename WireRetT, typename HandlerRetT, typename ChannelT, typename FunctionIdT, typename SequenceNumberT> @@ -330,9 +329,8 @@ public: // Serialize the result. if (auto Err = - SerializationTraits<ChannelT, WireRetT, - Expected<HandlerRetT>>::serialize( - C, std::move(ResultOrErr))) + SerializationTraits<ChannelT, WireRetT, Expected<HandlerRetT>>:: + serialize(C, std::move(ResultOrErr))) return Err; // Close the response message. @@ -354,14 +352,11 @@ public: return Err2; return C.send(); } - }; // RespondHelper specialization for functions that do not support error returns. -template <> -class RespondHelper<false> { +template <> class RespondHelper<false> { public: - template <typename WireRetT, typename HandlerRetT, typename ChannelT, typename FunctionIdT, typename SequenceNumberT> static Error sendResult(ChannelT &C, const FunctionIdT &ResponseId, @@ -376,8 +371,8 @@ public: // Serialize the result. if (auto Err = - SerializationTraits<ChannelT, WireRetT, HandlerRetT>::serialize( - C, *ResultOrErr)) + SerializationTraits<ChannelT, WireRetT, HandlerRetT>::serialize( + C, *ResultOrErr)) return Err; // End the response message. @@ -398,18 +393,17 @@ public: return Err2; return C.send(); } - }; - // Send a response of the given wire return type (WireRetT) over the // channel, with the given sequence number. template <typename WireRetT, typename HandlerRetT, typename ChannelT, typename FunctionIdT, typename SequenceNumberT> -Error respond(ChannelT &C, const FunctionIdT &ResponseId, - SequenceNumberT SeqNo, Expected<HandlerRetT> ResultOrErr) { +Error respond(ChannelT &C, const FunctionIdT &ResponseId, SequenceNumberT SeqNo, + Expected<HandlerRetT> ResultOrErr) { return RespondHelper<SupportsErrorReturn<WireRetT>::value>:: - template sendResult<WireRetT>(C, ResponseId, SeqNo, std::move(ResultOrErr)); + template sendResult<WireRetT>(C, ResponseId, SeqNo, + std::move(ResultOrErr)); } // Send an empty response message on the given channel to indicate that @@ -418,8 +412,8 @@ template <typename WireRetT, typename ChannelT, typename FunctionIdT, typename SequenceNumberT> Error respond(ChannelT &C, const FunctionIdT &ResponseId, SequenceNumberT SeqNo, Error Err) { - return RespondHelper<SupportsErrorReturn<WireRetT>::value>:: - sendResult(C, ResponseId, SeqNo, std::move(Err)); + return RespondHelper<SupportsErrorReturn<WireRetT>::value>::sendResult( + C, ResponseId, SeqNo, std::move(Err)); } // Converts a given type to the equivalent error return type. @@ -453,7 +447,8 @@ public: template <typename FnT> class AsyncHandlerTraits; template <typename ResultT, typename... ArgTs> -class AsyncHandlerTraits<Error(std::function<Error(Expected<ResultT>)>, ArgTs...)> { +class AsyncHandlerTraits<Error(std::function<Error(Expected<ResultT>)>, + ArgTs...)> { public: using Type = Error(ArgTs...); using ResultType = Expected<ResultT>; @@ -490,9 +485,9 @@ class AsyncHandlerTraits<Error(ResponseHandlerT, ArgTs...)> // specialized for function types) and inherits from the appropriate // speciilization for the given non-function type's call operator. template <typename HandlerT> -class HandlerTraits : public HandlerTraits<decltype( - &std::remove_reference<HandlerT>::type::operator())> { -}; +class HandlerTraits + : public HandlerTraits< + decltype(&std::remove_reference<HandlerT>::type::operator())> {}; // Traits for handlers with a given function type. template <typename RetT, typename... ArgTs> @@ -524,7 +519,7 @@ public: template <typename HandlerT> static std::enable_if_t< std::is_void<typename HandlerTraits<HandlerT>::ReturnType>::value, Error> - run(HandlerT &Handler, ArgTs &&... Args) { + run(HandlerT &Handler, ArgTs &&...Args) { Handler(std::move(Args)...); return Error::success(); } @@ -577,8 +572,8 @@ private: // Handler traits for free functions. template <typename RetT, typename... ArgTs> -class HandlerTraits<RetT(*)(ArgTs...)> - : public HandlerTraits<RetT(ArgTs...)> {}; +class HandlerTraits<RetT (*)(ArgTs...)> : public HandlerTraits<RetT(ArgTs...)> { +}; // Handler traits for class methods (especially call operators for lambdas). template <typename Class, typename RetT, typename... ArgTs> @@ -714,9 +709,8 @@ public: typename HandlerTraits<HandlerT>::Type>::ArgType; HandlerArgType Result((typename HandlerArgType::value_type())); - if (auto Err = - SerializationTraits<ChannelT, Expected<FuncRetT>, - HandlerArgType>::deserialize(C, Result)) + if (auto Err = SerializationTraits<ChannelT, Expected<FuncRetT>, + HandlerArgType>::deserialize(C, Result)) return Err; if (auto Err = C.endReceiveMessage()) return Err; @@ -786,7 +780,7 @@ public: using MethodT = RetT (ClassT::*)(ArgTs...); MemberFnWrapper(ClassT &Instance, MethodT Method) : Instance(Instance), Method(Method) {} - RetT operator()(ArgTs &&... Args) { + RetT operator()(ArgTs &&...Args) { return (Instance.*Method)(std::move(Args)...); } @@ -804,10 +798,9 @@ public: template <typename ArgT, typename... ArgTs> class ReadArgs<ArgT, ArgTs...> : public ReadArgs<ArgTs...> { public: - ReadArgs(ArgT &Arg, ArgTs &... Args) - : ReadArgs<ArgTs...>(Args...), Arg(Arg) {} + ReadArgs(ArgT &Arg, ArgTs &...Args) : ReadArgs<ArgTs...>(Args...), Arg(Arg) {} - Error operator()(ArgT &ArgVal, ArgTs &... ArgVals) { + Error operator()(ArgT &ArgVal, ArgTs &...ArgVals) { this->Arg = std::move(ArgVal); return ReadArgs<ArgTs...>::operator()(ArgVals...); } @@ -872,8 +865,8 @@ public: template <template <class, class> class P, typename T1Sig, typename T2Sig> class RPCArgTypeCheck { public: - using T1Tuple = typename FunctionArgsTuple<T1Sig>::Type; - using T2Tuple = typename FunctionArgsTuple<T2Sig>::Type; + using T1Tuple = typename RPCFunctionArgsTuple<T1Sig>::Type; + using T2Tuple = typename RPCFunctionArgsTuple<T2Sig>::Type; static_assert(std::tuple_size<T1Tuple>::value >= std::tuple_size<T2Tuple>::value, @@ -937,18 +930,18 @@ template <typename ImplT, typename ChannelT, typename FunctionIdT, typename SequenceNumberT> class RPCEndpointBase { protected: - class OrcRPCInvalid : public Function<OrcRPCInvalid, void()> { + class OrcRPCInvalid : public RPCFunction<OrcRPCInvalid, void()> { public: static const char *getName() { return "__orc_rpc$invalid"; } }; - class OrcRPCResponse : public Function<OrcRPCResponse, void()> { + class OrcRPCResponse : public RPCFunction<OrcRPCResponse, void()> { public: static const char *getName() { return "__orc_rpc$response"; } }; class OrcRPCNegotiate - : public Function<OrcRPCNegotiate, FunctionIdT(std::string)> { + : public RPCFunction<OrcRPCNegotiate, FunctionIdT(std::string)> { public: static const char *getName() { return "__orc_rpc$negotiate"; } }; @@ -994,7 +987,6 @@ public: [this](const std::string &Name) { return handleNegotiate(Name); }); } - /// Negotiate a function id for Func with the other end of the channel. template <typename Func> Error negotiateFunction(bool Retry = false) { return getRemoteFunctionId<Func>(true, Retry).takeError(); @@ -1006,7 +998,7 @@ public: /// or an Error (if Func::ReturnType is void). The handler will be called /// with an error if the return value is abandoned due to a channel error. template <typename Func, typename HandlerT, typename... ArgTs> - Error appendCallAsync(HandlerT Handler, const ArgTs &... Args) { + Error appendCallAsync(HandlerT Handler, const ArgTs &...Args) { static_assert( detail::RPCArgTypeCheck<CanSerializeCheck, typename Func::Type, @@ -1036,8 +1028,8 @@ public: // Install the user handler. PendingResponses[SeqNo] = - detail::createResponseHandler<ChannelT, typename Func::ReturnType>( - std::move(Handler)); + detail::createResponseHandler<ChannelT, typename Func::ReturnType>( + std::move(Handler)); } // Open the function call message. @@ -1065,7 +1057,7 @@ public: Error sendAppendedCalls() { return C.send(); }; template <typename Func, typename HandlerT, typename... ArgTs> - Error callAsync(HandlerT Handler, const ArgTs &... Args) { + Error callAsync(HandlerT Handler, const ArgTs &...Args) { if (auto Err = appendCallAsync<Func>(std::move(Handler), Args...)) return Err; return C.send(); @@ -1104,7 +1096,7 @@ public: /// /* Handle Args */ ; /// template <typename... ArgTs> - static detail::ReadArgs<ArgTs...> readArgs(ArgTs &... Args) { + static detail::ReadArgs<ArgTs...> readArgs(ArgTs &...Args) { return detail::ReadArgs<ArgTs...>(Args...); } @@ -1128,8 +1120,7 @@ public: /// Remove the handler for the given function. /// A handler must currently be registered for this function. - template <typename Func> - void removeHandler() { + template <typename Func> void removeHandler() { auto IdItr = LocalFunctionIds.find(Func::getPrototype()); assert(IdItr != LocalFunctionIds.end() && "Function does not have a registered handler"); @@ -1140,12 +1131,9 @@ public: } /// Clear all handlers. - void clearHandlers() { - Handlers.clear(); - } + void clearHandlers() { Handlers.clear(); } protected: - FunctionIdT getInvalidFunctionId() const { return FnIdAllocator.getInvalidId(); } @@ -1168,12 +1156,12 @@ protected: template <typename Func, typename HandlerT> void addAsyncHandlerImpl(HandlerT Handler) { - static_assert(detail::RPCArgTypeCheck< - CanDeserializeCheck, typename Func::Type, - typename detail::AsyncHandlerTraits< - typename detail::HandlerTraits<HandlerT>::Type - >::Type>::value, - ""); + static_assert( + detail::RPCArgTypeCheck< + CanDeserializeCheck, typename Func::Type, + typename detail::AsyncHandlerTraits< + typename detail::HandlerTraits<HandlerT>::Type>::Type>::value, + ""); FunctionIdT NewFnId = FnIdAllocator.template allocate<Func>(); LocalFunctionIds[Func::getPrototype()] = NewFnId; @@ -1197,8 +1185,8 @@ protected: // Unlock the pending results map to prevent recursive lock. Lock.unlock(); abandonPendingResponses(); - return make_error< - InvalidSequenceNumberForResponse<SequenceNumberT>>(SeqNo); + return make_error<InvalidSequenceNumberForResponse<SequenceNumberT>>( + SeqNo); } } @@ -1241,7 +1229,7 @@ protected: if (DoNegotiate) { auto &Impl = static_cast<ImplT &>(*this); if (auto RemoteIdOrErr = - Impl.template callB<OrcRPCNegotiate>(Func::getPrototype())) { + Impl.template callB<OrcRPCNegotiate>(Func::getPrototype())) { RemoteFunctionIds[Func::getPrototype()] = *RemoteIdOrErr; if (*RemoteIdOrErr == getInvalidFunctionId()) return make_error<CouldNotNegotiate>(Func::getPrototype()); @@ -1264,9 +1252,8 @@ protected: return [this, Handler](ChannelT &Channel, SequenceNumberT SeqNo) mutable -> Error { // Start by deserializing the arguments. - using ArgsTuple = - typename detail::FunctionArgsTuple< - typename detail::HandlerTraits<HandlerT>::Type>::Type; + using ArgsTuple = typename detail::RPCFunctionArgsTuple< + typename detail::HandlerTraits<HandlerT>::Type>::Type; auto Args = std::make_shared<ArgsTuple>(); if (auto Err = @@ -1298,9 +1285,9 @@ protected: SequenceNumberT SeqNo) mutable -> Error { // Start by deserializing the arguments. using AHTraits = detail::AsyncHandlerTraits< - typename detail::HandlerTraits<HandlerT>::Type>; + typename detail::HandlerTraits<HandlerT>::Type>; using ArgsTuple = - typename detail::FunctionArgsTuple<typename AHTraits::Type>::Type; + typename detail::RPCFunctionArgsTuple<typename AHTraits::Type>::Type; auto Args = std::make_shared<ArgsTuple>(); if (auto Err = @@ -1319,11 +1306,11 @@ protected: using HTraits = detail::HandlerTraits<HandlerT>; using FuncReturn = typename Func::ReturnType; - auto Responder = - [this, SeqNo](typename AHTraits::ResultType RetVal) -> Error { - return detail::respond<FuncReturn>(C, ResponseId, SeqNo, - std::move(RetVal)); - }; + auto Responder = [this, + SeqNo](typename AHTraits::ResultType RetVal) -> Error { + return detail::respond<FuncReturn>(C, ResponseId, SeqNo, + std::move(RetVal)); + }; return HTraits::unpackAndRunAsync(Handler, Responder, *Args); }; @@ -1356,17 +1343,16 @@ class MultiThreadedRPCEndpoint MultiThreadedRPCEndpoint<ChannelT, FunctionIdT, SequenceNumberT>, ChannelT, FunctionIdT, SequenceNumberT> { private: - using BaseClass = - detail::RPCEndpointBase< - MultiThreadedRPCEndpoint<ChannelT, FunctionIdT, SequenceNumberT>, - ChannelT, FunctionIdT, SequenceNumberT>; + using BaseClass = detail::RPCEndpointBase< + MultiThreadedRPCEndpoint<ChannelT, FunctionIdT, SequenceNumberT>, + ChannelT, FunctionIdT, SequenceNumberT>; public: MultiThreadedRPCEndpoint(ChannelT &C, bool LazyAutoNegotiation) : BaseClass(C, LazyAutoNegotiation) {} /// Add a handler for the given RPC function. - /// This installs the given handler functor for the given RPC Function, and + /// This installs the given handler functor for the given RPCFunction, and /// makes the RPC function available for negotiation/calling from the remote. template <typename Func, typename HandlerT> void addHandler(HandlerT Handler) { @@ -1377,7 +1363,7 @@ public: template <typename Func, typename ClassT, typename RetT, typename... ArgTs> void addHandler(ClassT &Object, RetT (ClassT::*Method)(ArgTs...)) { addHandler<Func>( - detail::MemberFnWrapper<ClassT, RetT, ArgTs...>(Object, Method)); + detail::MemberFnWrapper<ClassT, RetT, ArgTs...>(Object, Method)); } template <typename Func, typename HandlerT> @@ -1389,7 +1375,7 @@ public: template <typename Func, typename ClassT, typename RetT, typename... ArgTs> void addAsyncHandler(ClassT &Object, RetT (ClassT::*Method)(ArgTs...)) { addAsyncHandler<Func>( - detail::MemberFnWrapper<ClassT, RetT, ArgTs...>(Object, Method)); + detail::MemberFnWrapper<ClassT, RetT, ArgTs...>(Object, Method)); } /// Return type for non-blocking call primitives. @@ -1405,7 +1391,7 @@ public: /// result. In multi-threaded mode the appendCallNB method, which does not /// return the sequence numeber, should be preferred. template <typename Func, typename... ArgTs> - Expected<NonBlockingCallResult<Func>> appendCallNB(const ArgTs &... Args) { + Expected<NonBlockingCallResult<Func>> appendCallNB(const ArgTs &...Args) { using RTraits = detail::ResultTraits<typename Func::ReturnType>; using ErrorReturn = typename RTraits::ErrorReturnType; using ErrorReturnPromise = typename RTraits::ReturnPromiseType; @@ -1428,7 +1414,7 @@ public: /// The same as appendCallNBWithSeq, except that it calls C.send() to /// flush the channel after serializing the call. template <typename Func, typename... ArgTs> - Expected<NonBlockingCallResult<Func>> callNB(const ArgTs &... Args) { + Expected<NonBlockingCallResult<Func>> callNB(const ArgTs &...Args) { auto Result = appendCallNB<Func>(Args...); if (!Result) return Result; @@ -1449,7 +1435,7 @@ public: template <typename Func, typename... ArgTs, typename AltRetT = typename Func::ReturnType> typename detail::ResultTraits<AltRetT>::ErrorReturnType - callB(const ArgTs &... Args) { + callB(const ArgTs &...Args) { if (auto FutureResOrErr = callNB<Func>(Args...)) return FutureResOrErr->get(); else @@ -1472,10 +1458,9 @@ class SingleThreadedRPCEndpoint SingleThreadedRPCEndpoint<ChannelT, FunctionIdT, SequenceNumberT>, ChannelT, FunctionIdT, SequenceNumberT> { private: - using BaseClass = - detail::RPCEndpointBase< - SingleThreadedRPCEndpoint<ChannelT, FunctionIdT, SequenceNumberT>, - ChannelT, FunctionIdT, SequenceNumberT>; + using BaseClass = detail::RPCEndpointBase< + SingleThreadedRPCEndpoint<ChannelT, FunctionIdT, SequenceNumberT>, + ChannelT, FunctionIdT, SequenceNumberT>; public: SingleThreadedRPCEndpoint(ChannelT &C, bool LazyAutoNegotiation) @@ -1501,13 +1486,13 @@ public: template <typename Func, typename ClassT, typename RetT, typename... ArgTs> void addAsyncHandler(ClassT &Object, RetT (ClassT::*Method)(ArgTs...)) { addAsyncHandler<Func>( - detail::MemberFnWrapper<ClassT, RetT, ArgTs...>(Object, Method)); + detail::MemberFnWrapper<ClassT, RetT, ArgTs...>(Object, Method)); } template <typename Func, typename... ArgTs, typename AltRetT = typename Func::ReturnType> typename detail::ResultTraits<AltRetT>::ErrorReturnType - callB(const ArgTs &... Args) { + callB(const ArgTs &...Args) { bool ReceivedResponse = false; using ResultType = typename detail::ResultTraits<AltRetT>::ErrorReturnType; auto Result = detail::ResultTraits<AltRetT>::createBlankErrorReturnValue(); @@ -1547,13 +1532,12 @@ public: }; /// Asynchronous dispatch for a function on an RPC endpoint. -template <typename RPCClass, typename Func> -class RPCAsyncDispatch { +template <typename RPCClass, typename Func> class RPCAsyncDispatch { public: RPCAsyncDispatch(RPCClass &Endpoint) : Endpoint(Endpoint) {} template <typename HandlerT, typename... ArgTs> - Error operator()(HandlerT Handler, const ArgTs &... Args) const { + Error operator()(HandlerT Handler, const ArgTs &...Args) const { return Endpoint.template appendCallAsync<Func>(std::move(Handler), Args...); } @@ -1571,7 +1555,6 @@ RPCAsyncDispatch<RPCEndpointT, Func> rpcAsyncDispatch(RPCEndpointT &Endpoint) { /// waited on as a group. class ParallelCallGroup { public: - ParallelCallGroup() = default; ParallelCallGroup(const ParallelCallGroup &) = delete; ParallelCallGroup &operator=(const ParallelCallGroup &) = delete; @@ -1579,7 +1562,7 @@ public: /// Make as asynchronous call. template <typename AsyncDispatcher, typename HandlerT, typename... ArgTs> Error call(const AsyncDispatcher &AsyncDispatch, HandlerT Handler, - const ArgTs &... Args) { + const ArgTs &...Args) { // Increment the count of outstanding calls. This has to happen before // we invoke the call, as the handler may (depending on scheduling) // be run immediately on another thread, and we don't want the decrement @@ -1618,70 +1601,57 @@ private: uint32_t NumOutstandingCalls = 0; }; -/// Convenience class for grouping RPC Functions into APIs that can be +/// Convenience class for grouping RPCFunctions into APIs that can be /// negotiated as a block. /// -template <typename... Funcs> -class APICalls { +template <typename... Funcs> class APICalls { public: - /// Test whether this API contains Function F. - template <typename F> - class Contains { + template <typename F> class Contains { public: static const bool value = false; }; /// Negotiate all functions in this API. - template <typename RPCEndpoint> - static Error negotiate(RPCEndpoint &R) { + template <typename RPCEndpoint> static Error negotiate(RPCEndpoint &R) { return Error::success(); } }; -template <typename Func, typename... Funcs> -class APICalls<Func, Funcs...> { +template <typename Func, typename... Funcs> class APICalls<Func, Funcs...> { public: - - template <typename F> - class Contains { + template <typename F> class Contains { public: static const bool value = std::is_same<F, Func>::value | APICalls<Funcs...>::template Contains<F>::value; }; - template <typename RPCEndpoint> - static Error negotiate(RPCEndpoint &R) { + template <typename RPCEndpoint> static Error negotiate(RPCEndpoint &R) { if (auto Err = R.template negotiateFunction<Func>()) return Err; return APICalls<Funcs...>::negotiate(R); } - }; template <typename... InnerFuncs, typename... Funcs> class APICalls<APICalls<InnerFuncs...>, Funcs...> { public: - - template <typename F> - class Contains { + template <typename F> class Contains { public: static const bool value = - APICalls<InnerFuncs...>::template Contains<F>::value | - APICalls<Funcs...>::template Contains<F>::value; + APICalls<InnerFuncs...>::template Contains<F>::value | + APICalls<Funcs...>::template Contains<F>::value; }; - template <typename RPCEndpoint> - static Error negotiate(RPCEndpoint &R) { + template <typename RPCEndpoint> static Error negotiate(RPCEndpoint &R) { if (auto Err = APICalls<InnerFuncs...>::negotiate(R)) return Err; return APICalls<Funcs...>::negotiate(R); } - }; -} // end namespace rpc +} // end namespace shared } // end namespace orc } // end namespace llvm -#endif +#endif // LLVM_EXECUTIONENGINE_ORC_SHARED_RPCUTILS_H diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/RPC/RawByteChannel.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/Shared/RawByteChannel.h index 35745993248c..2ee471939251 100644 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/RPC/RawByteChannel.h +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/Shared/RawByteChannel.h @@ -1,4 +1,4 @@ -//===- llvm/ExecutionEngine/Orc/RPC/RawByteChannel.h ----------------*- C++ -*-===// +//===- RawByteChannel.h -----------------------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,11 +6,11 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_EXECUTIONENGINE_ORC_RAWBYTECHANNEL_H -#define LLVM_EXECUTIONENGINE_ORC_RAWBYTECHANNEL_H +#ifndef LLVM_EXECUTIONENGINE_ORC_SHARED_RAWBYTECHANNEL_H +#define LLVM_EXECUTIONENGINE_ORC_SHARED_RAWBYTECHANNEL_H #include "llvm/ADT/StringRef.h" -#include "llvm/ExecutionEngine/Orc/RPC/RPCSerialization.h" +#include "llvm/ExecutionEngine/Orc/Shared/Serialization.h" #include "llvm/Support/Endian.h" #include "llvm/Support/Error.h" #include <cstdint> @@ -20,9 +20,9 @@ namespace llvm { namespace orc { -namespace rpc { +namespace shared { -/// Interface for byte-streams to be used with RPC. +/// Interface for byte-streams to be used with ORC Serialization. class RawByteChannel { public: virtual ~RawByteChannel() = default; @@ -115,8 +115,7 @@ class SerializationTraits< public: static Error serialize(ChannelT &C, bool V) { uint8_t Tmp = V ? 1 : 0; - if (auto Err = - C.appendBytes(reinterpret_cast<const char *>(&Tmp), 1)) + if (auto Err = C.appendBytes(reinterpret_cast<const char *>(&Tmp), 1)) return Err; return Error::success(); } @@ -135,7 +134,7 @@ class SerializationTraits< ChannelT, std::string, StringRef, std::enable_if_t<std::is_base_of<RawByteChannel, ChannelT>::value>> { public: - /// RPC channel serialization for std::strings. + /// Serialization channel serialization for std::strings. static Error serialize(RawByteChannel &C, StringRef S) { if (auto Err = serializeSeq(C, static_cast<uint64_t>(S.size()))) return Err; @@ -161,13 +160,13 @@ class SerializationTraits< ChannelT, std::string, std::string, std::enable_if_t<std::is_base_of<RawByteChannel, ChannelT>::value>> { public: - /// RPC channel serialization for std::strings. + /// Serialization channel serialization for std::strings. static Error serialize(RawByteChannel &C, const std::string &S) { return SerializationTraits<ChannelT, std::string, StringRef>::serialize(C, S); } - /// RPC channel deserialization for std::strings. + /// Serialization channel deserialization for std::strings. static Error deserialize(RawByteChannel &C, std::string &S) { uint64_t Count = 0; if (auto Err = deserializeSeq(C, Count)) @@ -177,8 +176,8 @@ public: } }; -} // end namespace rpc +} // end namespace shared } // end namespace orc } // end namespace llvm -#endif // LLVM_EXECUTIONENGINE_ORC_RAWBYTECHANNEL_H +#endif // LLVM_EXECUTIONENGINE_ORC_SHARED_RAWBYTECHANNEL_H diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/RPC/RPCSerialization.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/Shared/Serialization.h index 2f37ab40c7f8..f2d07632bd5d 100644 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/RPC/RPCSerialization.h +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/Shared/Serialization.h @@ -1,4 +1,4 @@ -//===- llvm/ExecutionEngine/Orc/RPC/RPCSerialization.h --------------*- C++ -*-===// +//===- Serialization.h ------------------------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,10 +6,12 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_EXECUTIONENGINE_ORC_RPCSERIALIZATION_H -#define LLVM_EXECUTIONENGINE_ORC_RPCSERIALIZATION_H +#ifndef LLVM_EXECUTIONENGINE_ORC_SHARED_SERIALIZATION_H +#define LLVM_EXECUTIONENGINE_ORC_SHARED_SERIALIZATION_H -#include "llvm/ExecutionEngine/Orc/OrcError.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ExecutionEngine/Orc/Shared/OrcError.h" #include "llvm/Support/thread.h" #include <map> #include <mutex> @@ -20,118 +22,104 @@ namespace llvm { namespace orc { -namespace rpc { +namespace shared { -template <typename T> -class RPCTypeName; +template <typename T> class SerializationTypeName; /// TypeNameSequence is a utility for rendering sequences of types to a string /// by rendering each type, separated by ", ". -template <typename... ArgTs> class RPCTypeNameSequence {}; +template <typename... ArgTs> class SerializationTypeNameSequence {}; /// Render an empty TypeNameSequence to an ostream. template <typename OStream> -OStream &operator<<(OStream &OS, const RPCTypeNameSequence<> &V) { +OStream &operator<<(OStream &OS, const SerializationTypeNameSequence<> &V) { return OS; } /// Render a TypeNameSequence of a single type to an ostream. template <typename OStream, typename ArgT> -OStream &operator<<(OStream &OS, const RPCTypeNameSequence<ArgT> &V) { - OS << RPCTypeName<ArgT>::getName(); +OStream &operator<<(OStream &OS, const SerializationTypeNameSequence<ArgT> &V) { + OS << SerializationTypeName<ArgT>::getName(); return OS; } /// Render a TypeNameSequence of more than one type to an ostream. template <typename OStream, typename ArgT1, typename ArgT2, typename... ArgTs> -OStream& -operator<<(OStream &OS, const RPCTypeNameSequence<ArgT1, ArgT2, ArgTs...> &V) { - OS << RPCTypeName<ArgT1>::getName() << ", " - << RPCTypeNameSequence<ArgT2, ArgTs...>(); +OStream & +operator<<(OStream &OS, + const SerializationTypeNameSequence<ArgT1, ArgT2, ArgTs...> &V) { + OS << SerializationTypeName<ArgT1>::getName() << ", " + << SerializationTypeNameSequence<ArgT2, ArgTs...>(); return OS; } -template <> -class RPCTypeName<void> { +template <> class SerializationTypeName<void> { public: - static const char* getName() { return "void"; } + static const char *getName() { return "void"; } }; -template <> -class RPCTypeName<int8_t> { +template <> class SerializationTypeName<int8_t> { public: - static const char* getName() { return "int8_t"; } + static const char *getName() { return "int8_t"; } }; -template <> -class RPCTypeName<uint8_t> { +template <> class SerializationTypeName<uint8_t> { public: - static const char* getName() { return "uint8_t"; } + static const char *getName() { return "uint8_t"; } }; -template <> -class RPCTypeName<int16_t> { +template <> class SerializationTypeName<int16_t> { public: - static const char* getName() { return "int16_t"; } + static const char *getName() { return "int16_t"; } }; -template <> -class RPCTypeName<uint16_t> { +template <> class SerializationTypeName<uint16_t> { public: - static const char* getName() { return "uint16_t"; } + static const char *getName() { return "uint16_t"; } }; -template <> -class RPCTypeName<int32_t> { +template <> class SerializationTypeName<int32_t> { public: - static const char* getName() { return "int32_t"; } + static const char *getName() { return "int32_t"; } }; -template <> -class RPCTypeName<uint32_t> { +template <> class SerializationTypeName<uint32_t> { public: - static const char* getName() { return "uint32_t"; } + static const char *getName() { return "uint32_t"; } }; -template <> -class RPCTypeName<int64_t> { +template <> class SerializationTypeName<int64_t> { public: - static const char* getName() { return "int64_t"; } + static const char *getName() { return "int64_t"; } }; -template <> -class RPCTypeName<uint64_t> { +template <> class SerializationTypeName<uint64_t> { public: - static const char* getName() { return "uint64_t"; } + static const char *getName() { return "uint64_t"; } }; -template <> -class RPCTypeName<bool> { +template <> class SerializationTypeName<bool> { public: - static const char* getName() { return "bool"; } + static const char *getName() { return "bool"; } }; -template <> -class RPCTypeName<std::string> { +template <> class SerializationTypeName<std::string> { public: - static const char* getName() { return "std::string"; } + static const char *getName() { return "std::string"; } }; -template <> -class RPCTypeName<Error> { +template <> class SerializationTypeName<Error> { public: - static const char* getName() { return "Error"; } + static const char *getName() { return "Error"; } }; -template <typename T> -class RPCTypeName<Expected<T>> { +template <typename T> class SerializationTypeName<Expected<T>> { public: - static const char* getName() { + static const char *getName() { static std::string Name = [] { std::string Name; - raw_string_ostream(Name) << "Expected<" - << RPCTypeNameSequence<T>() - << ">"; + raw_string_ostream(Name) + << "Expected<" << SerializationTypeNameSequence<T>() << ">"; return Name; }(); return Name.data(); @@ -139,67 +127,78 @@ public: }; template <typename T1, typename T2> -class RPCTypeName<std::pair<T1, T2>> { +class SerializationTypeName<std::pair<T1, T2>> { +public: + static const char *getName() { + static std::string Name = [] { + std::string Name; + raw_string_ostream(Name) + << "std::pair<" << SerializationTypeNameSequence<T1, T2>() << ">"; + return Name; + }(); + return Name.data(); + } +}; + +template <typename... ArgTs> class SerializationTypeName<std::tuple<ArgTs...>> { public: - static const char* getName() { + static const char *getName() { static std::string Name = [] { std::string Name; - raw_string_ostream(Name) << "std::pair<" << RPCTypeNameSequence<T1, T2>() - << ">"; + raw_string_ostream(Name) + << "std::tuple<" << SerializationTypeNameSequence<ArgTs...>() << ">"; return Name; }(); return Name.data(); } }; -template <typename... ArgTs> -class RPCTypeName<std::tuple<ArgTs...>> { +template <typename T> class SerializationTypeName<Optional<T>> { public: - static const char* getName() { + static const char *getName() { static std::string Name = [] { std::string Name; - raw_string_ostream(Name) << "std::tuple<" - << RPCTypeNameSequence<ArgTs...>() << ">"; + raw_string_ostream(Name) + << "Optional<" << SerializationTypeName<T>::getName() << ">"; return Name; }(); return Name.data(); } }; -template <typename T> -class RPCTypeName<std::vector<T>> { +template <typename T> class SerializationTypeName<std::vector<T>> { public: - static const char*getName() { + static const char *getName() { static std::string Name = [] { std::string Name; - raw_string_ostream(Name) << "std::vector<" << RPCTypeName<T>::getName() - << ">"; + raw_string_ostream(Name) + << "std::vector<" << SerializationTypeName<T>::getName() << ">"; return Name; }(); return Name.data(); } }; -template <typename T> class RPCTypeName<std::set<T>> { +template <typename T> class SerializationTypeName<std::set<T>> { public: static const char *getName() { static std::string Name = [] { std::string Name; raw_string_ostream(Name) - << "std::set<" << RPCTypeName<T>::getName() << ">"; + << "std::set<" << SerializationTypeName<T>::getName() << ">"; return Name; }(); return Name.data(); } }; -template <typename K, typename V> class RPCTypeName<std::map<K, V>> { +template <typename K, typename V> class SerializationTypeName<std::map<K, V>> { public: static const char *getName() { static std::string Name = [] { std::string Name; raw_string_ostream(Name) - << "std::map<" << RPCTypeNameSequence<K, V>() << ">"; + << "std::map<" << SerializationTypeNameSequence<K, V>() << ">"; return Name; }(); return Name.data(); @@ -242,8 +241,7 @@ template <typename ChannelT, typename WireType, typename ConcreteType = WireType, typename = void> class SerializationTraits; -template <typename ChannelT> -class SequenceTraits { +template <typename ChannelT> class SequenceTraits { public: static Error emitSeparator(ChannelT &C) { return Error::success(); } static Error consumeSeparator(ChannelT &C) { return Error::success(); } @@ -258,11 +256,9 @@ public: /// is a SerializationTraits specialization /// SerializeTraits<ChannelT, ArgT, CArgT> with methods that can serialize the /// caller argument to over-the-wire value. -template <typename ChannelT, typename... ArgTs> -class SequenceSerialization; +template <typename ChannelT, typename... ArgTs> class SequenceSerialization; -template <typename ChannelT> -class SequenceSerialization<ChannelT> { +template <typename ChannelT> class SequenceSerialization<ChannelT> { public: static Error serialize(ChannelT &C) { return Error::success(); } static Error deserialize(ChannelT &C) { return Error::success(); } @@ -271,15 +267,12 @@ public: template <typename ChannelT, typename ArgT> class SequenceSerialization<ChannelT, ArgT> { public: - - template <typename CArgT> - static Error serialize(ChannelT &C, CArgT &&CArg) { + template <typename CArgT> static Error serialize(ChannelT &C, CArgT &&CArg) { return SerializationTraits<ChannelT, ArgT, std::decay_t<CArgT>>::serialize( C, std::forward<CArgT>(CArg)); } - template <typename CArgT> - static Error deserialize(ChannelT &C, CArgT &CArg) { + template <typename CArgT> static Error deserialize(ChannelT &C, CArgT &CArg) { return SerializationTraits<ChannelT, ArgT, CArgT>::deserialize(C, CArg); } }; @@ -287,25 +280,22 @@ public: template <typename ChannelT, typename ArgT, typename... ArgTs> class SequenceSerialization<ChannelT, ArgT, ArgTs...> { public: - template <typename CArgT, typename... CArgTs> - static Error serialize(ChannelT &C, CArgT &&CArg, - CArgTs &&... CArgs) { + static Error serialize(ChannelT &C, CArgT &&CArg, CArgTs &&...CArgs) { if (auto Err = SerializationTraits<ChannelT, ArgT, std::decay_t<CArgT>>::serialize( C, std::forward<CArgT>(CArg))) return Err; if (auto Err = SequenceTraits<ChannelT>::emitSeparator(C)) return Err; - return SequenceSerialization<ChannelT, ArgTs...>:: - serialize(C, std::forward<CArgTs>(CArgs)...); + return SequenceSerialization<ChannelT, ArgTs...>::serialize( + C, std::forward<CArgTs>(CArgs)...); } template <typename CArgT, typename... CArgTs> - static Error deserialize(ChannelT &C, CArgT &CArg, - CArgTs &... CArgs) { + static Error deserialize(ChannelT &C, CArgT &CArg, CArgTs &...CArgs) { if (auto Err = - SerializationTraits<ChannelT, ArgT, CArgT>::deserialize(C, CArg)) + SerializationTraits<ChannelT, ArgT, CArgT>::deserialize(C, CArg)) return Err; if (auto Err = SequenceTraits<ChannelT>::consumeSeparator(C)) return Err; @@ -314,25 +304,23 @@ public: }; template <typename ChannelT, typename... ArgTs> -Error serializeSeq(ChannelT &C, ArgTs &&... Args) { +Error serializeSeq(ChannelT &C, ArgTs &&...Args) { return SequenceSerialization<ChannelT, std::decay_t<ArgTs>...>::serialize( C, std::forward<ArgTs>(Args)...); } template <typename ChannelT, typename... ArgTs> -Error deserializeSeq(ChannelT &C, ArgTs &... Args) { +Error deserializeSeq(ChannelT &C, ArgTs &...Args) { return SequenceSerialization<ChannelT, ArgTs...>::deserialize(C, Args...); } -template <typename ChannelT> -class SerializationTraits<ChannelT, Error> { +template <typename ChannelT> class SerializationTraits<ChannelT, Error> { public: - using WrappedErrorSerializer = - std::function<Error(ChannelT &C, const ErrorInfoBase&)>; + std::function<Error(ChannelT &C, const ErrorInfoBase &)>; using WrappedErrorDeserializer = - std::function<Error(ChannelT &C, Error &Err)>; + std::function<Error(ChannelT &C, Error &Err)>; template <typename ErrorInfoT, typename SerializeFtor, typename DeserializeFtor> @@ -343,15 +331,14 @@ public: const std::string *KeyName = nullptr; { - // We're abusing the stability of std::map here: We take a reference to the - // key of the deserializers map to save us from duplicating the string in - // the serializer. This should be changed to use a stringpool if we switch - // to a map type that may move keys in memory. + // We're abusing the stability of std::map here: We take a reference to + // the key of the deserializers map to save us from duplicating the string + // in the serializer. This should be changed to use a stringpool if we + // switch to a map type that may move keys in memory. std::lock_guard<std::recursive_mutex> Lock(DeserializersMutex); - auto I = - Deserializers.insert(Deserializers.begin(), - std::make_pair(std::move(Name), - std::move(Deserialize))); + auto I = Deserializers.insert( + Deserializers.begin(), + std::make_pair(std::move(Name), std::move(Deserialize))); KeyName = &I->first; } @@ -376,13 +363,12 @@ public: if (!Err) return serializeSeq(C, std::string()); - return handleErrors(std::move(Err), - [&C](const ErrorInfoBase &EIB) { - auto SI = Serializers.find(EIB.dynamicClassID()); - if (SI == Serializers.end()) - return serializeAsStringError(C, EIB); - return (SI->second)(C, EIB); - }); + return handleErrors(std::move(Err), [&C](const ErrorInfoBase &EIB) { + auto SI = Serializers.find(EIB.dynamicClassID()); + if (SI == Serializers.end()) + return serializeAsStringError(C, EIB); + return (SI->second)(C, EIB); + }); } static Error deserialize(ChannelT &C, Error &Err) { @@ -404,7 +390,6 @@ public: } private: - static Error serializeAsStringError(ChannelT &C, const ErrorInfoBase &EIB) { std::string ErrMsg; { @@ -417,7 +402,7 @@ private: static std::recursive_mutex SerializersMutex; static std::recursive_mutex DeserializersMutex; - static std::map<const void*, WrappedErrorSerializer> Serializers; + static std::map<const void *, WrappedErrorSerializer> Serializers; static std::map<std::string, WrappedErrorDeserializer> Deserializers; }; @@ -428,14 +413,14 @@ template <typename ChannelT> std::recursive_mutex SerializationTraits<ChannelT, Error>::DeserializersMutex; template <typename ChannelT> -std::map<const void*, +std::map<const void *, typename SerializationTraits<ChannelT, Error>::WrappedErrorSerializer> -SerializationTraits<ChannelT, Error>::Serializers; + SerializationTraits<ChannelT, Error>::Serializers; template <typename ChannelT> -std::map<std::string, - typename SerializationTraits<ChannelT, Error>::WrappedErrorDeserializer> -SerializationTraits<ChannelT, Error>::Deserializers; +std::map<std::string, typename SerializationTraits< + ChannelT, Error>::WrappedErrorDeserializer> + SerializationTraits<ChannelT, Error>::Deserializers; /// Registers a serializer and deserializer for the given error type on the /// given channel type. @@ -444,32 +429,29 @@ template <typename ChannelT, typename ErrorInfoT, typename SerializeFtor, void registerErrorSerialization(std::string Name, SerializeFtor &&Serialize, DeserializeFtor &&Deserialize) { SerializationTraits<ChannelT, Error>::template registerErrorType<ErrorInfoT>( - std::move(Name), - std::forward<SerializeFtor>(Serialize), - std::forward<DeserializeFtor>(Deserialize)); + std::move(Name), std::forward<SerializeFtor>(Serialize), + std::forward<DeserializeFtor>(Deserialize)); } /// Registers serialization/deserialization for StringError. -template <typename ChannelT> -void registerStringError() { +template <typename ChannelT> void registerStringError() { static bool AlreadyRegistered = false; if (!AlreadyRegistered) { registerErrorSerialization<ChannelT, StringError>( - "StringError", - [](ChannelT &C, const StringError &SE) { - return serializeSeq(C, SE.getMessage()); - }, - [](ChannelT &C, Error &Err) -> Error { - ErrorAsOutParameter EAO(&Err); - std::string Msg; - if (auto E2 = deserializeSeq(C, Msg)) - return E2; - Err = - make_error<StringError>(std::move(Msg), - orcError( - OrcErrorCode::UnknownErrorCodeFromRemote)); - return Error::success(); - }); + "StringError", + [](ChannelT &C, const StringError &SE) { + return serializeSeq(C, SE.getMessage()); + }, + [](ChannelT &C, Error &Err) -> Error { + ErrorAsOutParameter EAO(&Err); + std::string Msg; + if (auto E2 = deserializeSeq(C, Msg)) + return E2; + Err = make_error<StringError>( + std::move(Msg), + orcError(OrcErrorCode::UnknownErrorCodeFromRemote)); + return Error::success(); + }); AlreadyRegistered = true; } } @@ -478,7 +460,6 @@ void registerStringError() { template <typename ChannelT, typename T1, typename T2> class SerializationTraits<ChannelT, Expected<T1>, Expected<T2>> { public: - static Error serialize(ChannelT &C, Expected<T2> &&ValOrErr) { if (ValOrErr) { if (auto Err = serializeSeq(C, true)) @@ -509,7 +490,6 @@ public: template <typename ChannelT, typename T1, typename T2> class SerializationTraits<ChannelT, Expected<T1>, T2> { public: - static Error serialize(ChannelT &C, T2 &&Val) { return serializeSeq(C, Expected<T2>(std::forward<T2>(Val))); } @@ -519,7 +499,6 @@ public: template <typename ChannelT, typename T> class SerializationTraits<ChannelT, Expected<T>, Error> { public: - static Error serialize(ChannelT &C, Error &&Err) { return serializeSeq(C, Expected<T>(std::move(Err))); } @@ -547,7 +526,6 @@ public: template <typename ChannelT, typename... ArgTs> class SerializationTraits<ChannelT, std::tuple<ArgTs...>> { public: - /// RPC channel serialization for std::tuple. static Error serialize(ChannelT &C, const std::tuple<ArgTs...> &V) { return serializeTupleHelper(C, V, std::index_sequence_for<ArgTs...>()); @@ -574,11 +552,35 @@ private: } }; +template <typename ChannelT, typename T> +class SerializationTraits<ChannelT, Optional<T>> { +public: + /// Serialize an Optional<T>. + static Error serialize(ChannelT &C, const Optional<T> &O) { + if (auto Err = serializeSeq(C, O != None)) + return Err; + if (O) + if (auto Err = serializeSeq(C, *O)) + return Err; + return Error::success(); + } + + /// Deserialize an Optional<T>. + static Error deserialize(ChannelT &C, Optional<T> &O) { + bool HasValue = false; + if (auto Err = deserializeSeq(C, HasValue)) + return Err; + if (HasValue) + if (auto Err = deserializeSeq(C, *O)) + return Err; + return Error::success(); + }; +}; + /// SerializationTraits default specialization for std::vector. template <typename ChannelT, typename T> class SerializationTraits<ChannelT, std::vector<T>> { public: - /// Serialize a std::vector<T> from std::vector<T>. static Error serialize(ChannelT &C, const std::vector<T> &V) { if (auto Err = serializeSeq(C, static_cast<uint64_t>(V.size()))) @@ -609,6 +611,22 @@ public: } }; +/// Enable vector serialization from an ArrayRef. +template <typename ChannelT, typename T> +class SerializationTraits<ChannelT, std::vector<T>, ArrayRef<T>> { +public: + static Error serialize(ChannelT &C, ArrayRef<T> V) { + if (auto Err = serializeSeq(C, static_cast<uint64_t>(V.size()))) + return Err; + + for (const auto &E : V) + if (auto Err = serializeSeq(C, E)) + return Err; + + return Error::success(); + } +}; + template <typename ChannelT, typename T, typename T2> class SerializationTraits<ChannelT, std::set<T>, std::set<T2>> { public: @@ -695,8 +713,57 @@ public: } }; -} // end namespace rpc +template <typename ChannelT, typename K, typename V, typename K2, typename V2> +class SerializationTraits<ChannelT, std::map<K, V>, DenseMap<K2, V2>> { +public: + /// Serialize a std::map<K, V> from DenseMap<K2, V2>. + static Error serialize(ChannelT &C, const DenseMap<K2, V2> &M) { + if (auto Err = serializeSeq(C, static_cast<uint64_t>(M.size()))) + return Err; + + for (auto &E : M) { + if (auto Err = + SerializationTraits<ChannelT, K, K2>::serialize(C, E.first)) + return Err; + + if (auto Err = + SerializationTraits<ChannelT, V, V2>::serialize(C, E.second)) + return Err; + } + + return Error::success(); + } + + /// Serialize a std::map<K, V> from DenseMap<K2, V2>. + static Error deserialize(ChannelT &C, DenseMap<K2, V2> &M) { + assert(M.empty() && "Expected default-constructed map to deserialize into"); + + uint64_t Count = 0; + if (auto Err = deserializeSeq(C, Count)) + return Err; + + while (Count-- != 0) { + std::pair<K2, V2> Val; + if (auto Err = + SerializationTraits<ChannelT, K, K2>::deserialize(C, Val.first)) + return Err; + + if (auto Err = + SerializationTraits<ChannelT, V, V2>::deserialize(C, Val.second)) + return Err; + + auto Added = M.insert(Val).second; + if (!Added) + return make_error<StringError>("Duplicate element in deserialized map", + orcError(OrcErrorCode::UnknownORCError)); + } + + return Error::success(); + } +}; + +} // namespace shared } // end namespace orc } // end namespace llvm -#endif // LLVM_EXECUTIONENGINE_ORC_RPCSERIALIZATION_H +#endif // LLVM_EXECUTIONENGINE_ORC_RPC_RPCSERIALIZATION_H diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h new file mode 100644 index 000000000000..d01b3ef21f80 --- /dev/null +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h @@ -0,0 +1,165 @@ +//===--- TargetProcessControlTypes.h -- Shared Core/TPC types ---*- 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 +// +//===----------------------------------------------------------------------===// +// +// TargetProcessControl types that are used by both the Orc and +// OrcTargetProcess libraries. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORC_SHARED_TARGETPROCESSCONTROLTYPES_H +#define LLVM_EXECUTIONENGINE_ORC_SHARED_TARGETPROCESSCONTROLTYPES_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ExecutionEngine/JITSymbol.h" + +#include <vector> + +namespace llvm { +namespace orc { +namespace tpctypes { + +template <typename T> struct UIntWrite { + UIntWrite() = default; + UIntWrite(JITTargetAddress Address, T Value) + : Address(Address), Value(Value) {} + + JITTargetAddress Address = 0; + T Value = 0; +}; + +/// Describes a write to a uint8_t. +using UInt8Write = UIntWrite<uint8_t>; + +/// Describes a write to a uint16_t. +using UInt16Write = UIntWrite<uint16_t>; + +/// Describes a write to a uint32_t. +using UInt32Write = UIntWrite<uint32_t>; + +/// Describes a write to a uint64_t. +using UInt64Write = UIntWrite<uint64_t>; + +/// Describes a write to a buffer. +/// For use with TargetProcessControl::MemoryAccess objects. +struct BufferWrite { + BufferWrite() = default; + BufferWrite(JITTargetAddress Address, StringRef Buffer) + : Address(Address), Buffer(Buffer) {} + + JITTargetAddress Address = 0; + StringRef Buffer; +}; + +/// A handle used to represent a loaded dylib in the target process. +using DylibHandle = JITTargetAddress; + +using LookupResult = std::vector<JITTargetAddress>; + +/// Either a uint8_t array or a uint8_t*. +union CWrapperFunctionResultData { + uint8_t Value[8]; + uint8_t *ValuePtr; +}; + +/// C ABI compatible wrapper function result. +/// +/// This can be safely returned from extern "C" functions, but should be used +/// to construct a WrapperFunctionResult for safety. +struct CWrapperFunctionResult { + uint64_t Size; + CWrapperFunctionResultData Data; + void (*Destroy)(CWrapperFunctionResultData Data, uint64_t Size); +}; + +/// C++ wrapper function result: Same as CWrapperFunctionResult but +/// auto-releases memory. +class WrapperFunctionResult { +public: + /// Create a default WrapperFunctionResult. + WrapperFunctionResult() { zeroInit(R); } + + /// Create a WrapperFunctionResult from a CWrapperFunctionResult. This + /// instance takes ownership of the result object and will automatically + /// call the Destroy member upon destruction. + WrapperFunctionResult(CWrapperFunctionResult R) : R(R) {} + + WrapperFunctionResult(const WrapperFunctionResult &) = delete; + WrapperFunctionResult &operator=(const WrapperFunctionResult &) = delete; + + WrapperFunctionResult(WrapperFunctionResult &&Other) { + zeroInit(R); + std::swap(R, Other.R); + } + + WrapperFunctionResult &operator=(WrapperFunctionResult &&Other) { + CWrapperFunctionResult Tmp; + zeroInit(Tmp); + std::swap(Tmp, Other.R); + std::swap(R, Tmp); + return *this; + } + + ~WrapperFunctionResult() { + if (R.Destroy) + R.Destroy(R.Data, R.Size); + } + + /// Relinquish ownership of and return the CWrapperFunctionResult. + CWrapperFunctionResult release() { + CWrapperFunctionResult Tmp; + zeroInit(Tmp); + std::swap(R, Tmp); + return Tmp; + } + + /// Get an ArrayRef covering the data in the result. + ArrayRef<uint8_t> getData() const { + if (R.Size <= 8) + return ArrayRef<uint8_t>(R.Data.Value, R.Size); + return ArrayRef<uint8_t>(R.Data.ValuePtr, R.Size); + } + + /// Create a WrapperFunctionResult from the given integer, provided its + /// size is no greater than 64 bits. + template <typename T, + typename _ = std::enable_if_t<std::is_integral<T>::value && + sizeof(T) <= sizeof(uint64_t)>> + static WrapperFunctionResult from(T Value) { + CWrapperFunctionResult R; + R.Size = sizeof(T); + memcpy(&R.Data.Value, Value, R.Size); + R.Destroy = nullptr; + return R; + } + + /// Create a WrapperFunctionResult from the given string. + static WrapperFunctionResult from(StringRef S); + + /// Always free Data.ValuePtr by calling free on it. + static void destroyWithFree(CWrapperFunctionResultData Data, uint64_t Size); + + /// Always free Data.ValuePtr by calling delete[] on it. + static void destroyWithDeleteArray(CWrapperFunctionResultData Data, + uint64_t Size); + +private: + static void zeroInit(CWrapperFunctionResult &R) { + R.Size = 0; + R.Data.ValuePtr = nullptr; + R.Destroy = nullptr; + } + + CWrapperFunctionResult R; +}; + +} // end namespace tpctypes +} // end namespace orc +} // end namespace llvm + +#endif // LLVM_EXECUTIONENGINE_ORC_SHARED_TARGETPROCESSCONTROLTYPES_H diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/Speculation.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/Speculation.h index d8213d3b35e8..a138f60a7756 100644 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/Speculation.h +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/Speculation.h @@ -18,14 +18,10 @@ #include "llvm/ExecutionEngine/Orc/Core.h" #include "llvm/ExecutionEngine/Orc/DebugUtils.h" #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" -#include "llvm/IR/PassManager.h" -#include "llvm/Passes/PassBuilder.h" #include "llvm/Support/Debug.h" - #include <mutex> #include <type_traits> #include <utility> -#include <vector> namespace llvm { namespace orc { @@ -185,7 +181,8 @@ public: : IRLayer(ES, BaseLayer.getManglingOptions()), NextLayer(BaseLayer), S(Spec), Mangle(Mangle), QueryAnalysis(Interpreter) {} - void emit(MaterializationResponsibility R, ThreadSafeModule TSM); + void emit(std::unique_ptr<MaterializationResponsibility> R, + ThreadSafeModule TSM) override; private: TargetAndLikelies diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/TPCDynamicLibrarySearchGenerator.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/TPCDynamicLibrarySearchGenerator.h new file mode 100644 index 000000000000..ed4f6080bb4e --- /dev/null +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/TPCDynamicLibrarySearchGenerator.h @@ -0,0 +1,66 @@ +//===------------ TPCDynamicLibrarySearchGenerator.h ------------*- 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 +// +//===----------------------------------------------------------------------===// +// +// Support loading and searching of dynamic libraries in a target process via +// the TargetProcessControl class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORC_TPCDYNAMICLIBRARYSEARCHGENERATOR_H +#define LLVM_EXECUTIONENGINE_ORC_TPCDYNAMICLIBRARYSEARCHGENERATOR_H + +#include "llvm/ADT/FunctionExtras.h" +#include "llvm/ExecutionEngine/Orc/TargetProcessControl.h" + +namespace llvm { +namespace orc { + +class TPCDynamicLibrarySearchGenerator : public DefinitionGenerator { +public: + using SymbolPredicate = unique_function<bool(const SymbolStringPtr &)>; + + /// Create a DynamicLibrarySearchGenerator that searches for symbols in the + /// library with the given handle. + /// + /// If the Allow predicate is given then only symbols matching the predicate + /// will be searched for. If the predicate is not given then all symbols will + /// be searched for. + TPCDynamicLibrarySearchGenerator(TargetProcessControl &TPC, + tpctypes::DylibHandle H, + SymbolPredicate Allow = SymbolPredicate()) + : TPC(TPC), H(H), Allow(std::move(Allow)) {} + + /// Permanently loads the library at the given path and, on success, returns + /// a DynamicLibrarySearchGenerator that will search it for symbol definitions + /// in the library. On failure returns the reason the library failed to load. + static Expected<std::unique_ptr<TPCDynamicLibrarySearchGenerator>> + Load(TargetProcessControl &TPC, const char *LibraryPath, + SymbolPredicate Allow = SymbolPredicate()); + + /// Creates a TPCDynamicLibrarySearchGenerator that searches for symbols in + /// the target process. + static Expected<std::unique_ptr<TPCDynamicLibrarySearchGenerator>> + GetForTargetProcess(TargetProcessControl &TPC, + SymbolPredicate Allow = SymbolPredicate()) { + return Load(TPC, nullptr, std::move(Allow)); + } + + Error tryToGenerate(LookupState &LS, LookupKind K, JITDylib &JD, + JITDylibLookupFlags JDLookupFlags, + const SymbolLookupSet &Symbols) override; + +private: + TargetProcessControl &TPC; + tpctypes::DylibHandle H; + SymbolPredicate Allow; +}; + +} // end namespace orc +} // end namespace llvm + +#endif // LLVM_EXECUTIONENGINE_ORC_TPCDYNAMICLIBRARYSEARCHGENERATOR_H diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/TPCEHFrameRegistrar.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/TPCEHFrameRegistrar.h new file mode 100644 index 000000000000..519f818907f9 --- /dev/null +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/TPCEHFrameRegistrar.h @@ -0,0 +1,54 @@ +//===-- TPCEHFrameRegistrar.h - TPC based eh-frame registration -*- 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 +// +//===----------------------------------------------------------------------===// +// +// TargetProcessControl based eh-frame registration. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORC_TPCEHFRAMEREGISTRAR_H +#define LLVM_EXECUTIONENGINE_ORC_TPCEHFRAMEREGISTRAR_H + +#include "llvm/ExecutionEngine/JITLink/EHFrameSupport.h" +#include "llvm/ExecutionEngine/Orc/TargetProcessControl.h" + +namespace llvm { +namespace orc { + +/// Register/Deregisters EH frames in a remote process via a +/// TargetProcessControl instance. +class TPCEHFrameRegistrar : public jitlink::EHFrameRegistrar { +public: + /// Create from a TargetProcessControl instance alone. This will use + /// the TPC's lookupSymbols method to find the registration/deregistration + /// funciton addresses by name. + static Expected<std::unique_ptr<TPCEHFrameRegistrar>> + Create(TargetProcessControl &TPC); + + /// Create a TPCEHFrameRegistrar with the given TargetProcessControl + /// object and registration/deregistration function addresses. + TPCEHFrameRegistrar(TargetProcessControl &TPC, + JITTargetAddress RegisterEHFrameWrapperFnAddr, + JITTargetAddress DeregisterEHFRameWrapperFnAddr) + : TPC(TPC), RegisterEHFrameWrapperFnAddr(RegisterEHFrameWrapperFnAddr), + DeregisterEHFrameWrapperFnAddr(DeregisterEHFRameWrapperFnAddr) {} + + Error registerEHFrames(JITTargetAddress EHFrameSectionAddr, + size_t EHFrameSectionSize) override; + Error deregisterEHFrames(JITTargetAddress EHFrameSectionAddr, + size_t EHFrameSectionSize) override; + +private: + TargetProcessControl &TPC; + JITTargetAddress RegisterEHFrameWrapperFnAddr; + JITTargetAddress DeregisterEHFrameWrapperFnAddr; +}; + +} // end namespace orc +} // end namespace llvm + +#endif // LLVM_EXECUTIONENGINE_ORC_TPCEHFRAMEREGISTRAR_H diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/TPCIndirectionUtils.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/TPCIndirectionUtils.h new file mode 100644 index 000000000000..e7abd7fb90df --- /dev/null +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/TPCIndirectionUtils.h @@ -0,0 +1,222 @@ +//===--- TPCIndirectionUtils.h - TPC based indirection utils ----*- 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 +// +//===----------------------------------------------------------------------===// +// +// Indirection utilities (stubs, trampolines, lazy call-throughs) that use the +// TargetProcessControl API to interact with the target process. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORC_TPCINDIRECTIONUTILS_H +#define LLVM_EXECUTIONENGINE_ORC_TPCINDIRECTIONUTILS_H + +#include "llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h" +#include "llvm/ExecutionEngine/Orc/IndirectionUtils.h" +#include "llvm/ExecutionEngine/Orc/LazyReexports.h" + +#include <mutex> + +namespace llvm { +namespace orc { + +class TargetProcessControl; + +/// Provides TargetProcessControl based indirect stubs, trampoline pool and +/// lazy call through manager. +class TPCIndirectionUtils { + friend class TPCIndirectionUtilsAccess; + +public: + /// ABI support base class. Used to write resolver, stub, and trampoline + /// blocks. + class ABISupport { + protected: + ABISupport(unsigned PointerSize, unsigned TrampolineSize, unsigned StubSize, + unsigned StubToPointerMaxDisplacement, unsigned ResolverCodeSize) + : PointerSize(PointerSize), TrampolineSize(TrampolineSize), + StubSize(StubSize), + StubToPointerMaxDisplacement(StubToPointerMaxDisplacement), + ResolverCodeSize(ResolverCodeSize) {} + + public: + virtual ~ABISupport(); + + unsigned getPointerSize() const { return PointerSize; } + unsigned getTrampolineSize() const { return TrampolineSize; } + unsigned getStubSize() const { return StubSize; } + unsigned getStubToPointerMaxDisplacement() const { + return StubToPointerMaxDisplacement; + } + unsigned getResolverCodeSize() const { return ResolverCodeSize; } + + virtual void writeResolverCode(char *ResolverWorkingMem, + JITTargetAddress ResolverTargetAddr, + JITTargetAddress ReentryFnAddr, + JITTargetAddress ReentryCtxAddr) const = 0; + + virtual void writeTrampolines(char *TrampolineBlockWorkingMem, + JITTargetAddress TrampolineBlockTragetAddr, + JITTargetAddress ResolverAddr, + unsigned NumTrampolines) const = 0; + + virtual void + writeIndirectStubsBlock(char *StubsBlockWorkingMem, + JITTargetAddress StubsBlockTargetAddress, + JITTargetAddress PointersBlockTargetAddress, + unsigned NumStubs) const = 0; + + private: + unsigned PointerSize = 0; + unsigned TrampolineSize = 0; + unsigned StubSize = 0; + unsigned StubToPointerMaxDisplacement = 0; + unsigned ResolverCodeSize = 0; + }; + + /// Create using the given ABI class. + template <typename ORCABI> + static std::unique_ptr<TPCIndirectionUtils> + CreateWithABI(TargetProcessControl &TPC); + + /// Create based on the TargetProcessControl triple. + static Expected<std::unique_ptr<TPCIndirectionUtils>> + Create(TargetProcessControl &TPC); + + /// Return a reference to the TargetProcessControl object. + TargetProcessControl &getTargetProcessControl() const { return TPC; } + + /// Return a reference to the ABISupport object for this instance. + ABISupport &getABISupport() const { return *ABI; } + + /// Release memory for resources held by this instance. This *must* be called + /// prior to destruction of the class. + Error cleanup(); + + /// Write resolver code to the target process and return its address. + /// This must be called before any call to createTrampolinePool or + /// createLazyCallThroughManager. + Expected<JITTargetAddress> + writeResolverBlock(JITTargetAddress ReentryFnAddr, + JITTargetAddress ReentryCtxAddr); + + /// Returns the address of the Resolver block. Returns zero if the + /// writeResolverBlock method has not previously been called. + JITTargetAddress getResolverBlockAddress() const { return ResolverBlockAddr; } + + /// Create an IndirectStubsManager for the target process. + std::unique_ptr<IndirectStubsManager> createIndirectStubsManager(); + + /// Create a TrampolinePool for the target process. + TrampolinePool &getTrampolinePool(); + + /// Create a LazyCallThroughManager. + /// This function should only be called once. + LazyCallThroughManager & + createLazyCallThroughManager(ExecutionSession &ES, + JITTargetAddress ErrorHandlerAddr); + + /// Create a LazyCallThroughManager for the target process. + LazyCallThroughManager &getLazyCallThroughManager() { + assert(LCTM && "createLazyCallThroughManager must be called first"); + return *LCTM; + } + +private: + using Allocation = jitlink::JITLinkMemoryManager::Allocation; + + struct IndirectStubInfo { + IndirectStubInfo() = default; + IndirectStubInfo(JITTargetAddress StubAddress, + JITTargetAddress PointerAddress) + : StubAddress(StubAddress), PointerAddress(PointerAddress) {} + JITTargetAddress StubAddress = 0; + JITTargetAddress PointerAddress = 0; + }; + + using IndirectStubInfoVector = std::vector<IndirectStubInfo>; + + /// Create a TPCIndirectionUtils instance. + TPCIndirectionUtils(TargetProcessControl &TPC, + std::unique_ptr<ABISupport> ABI); + + Expected<IndirectStubInfoVector> getIndirectStubs(unsigned NumStubs); + + std::mutex TPCUIMutex; + TargetProcessControl &TPC; + std::unique_ptr<ABISupport> ABI; + JITTargetAddress ResolverBlockAddr; + std::unique_ptr<jitlink::JITLinkMemoryManager::Allocation> ResolverBlock; + std::unique_ptr<TrampolinePool> TP; + std::unique_ptr<LazyCallThroughManager> LCTM; + + std::vector<IndirectStubInfo> AvailableIndirectStubs; + std::vector<std::unique_ptr<Allocation>> IndirectStubAllocs; +}; + +/// This will call writeResolver on the given TPCIndirectionUtils instance +/// to set up re-entry via a function that will directly return the trampoline +/// landing address. +/// +/// The TPCIndirectionUtils' LazyCallThroughManager must have been previously +/// created via TPCIndirectionUtils::createLazyCallThroughManager. +/// +/// The TPCIndirectionUtils' writeResolver method must not have been previously +/// called. +/// +/// This function is experimental and likely subject to revision. +Error setUpInProcessLCTMReentryViaTPCIU(TPCIndirectionUtils &TPCIU); + +namespace detail { + +template <typename ORCABI> +class ABISupportImpl : public TPCIndirectionUtils::ABISupport { +public: + ABISupportImpl() + : ABISupport(ORCABI::PointerSize, ORCABI::TrampolineSize, + ORCABI::StubSize, ORCABI::StubToPointerMaxDisplacement, + ORCABI::ResolverCodeSize) {} + + void writeResolverCode(char *ResolverWorkingMem, + JITTargetAddress ResolverTargetAddr, + JITTargetAddress ReentryFnAddr, + JITTargetAddress ReentryCtxAddr) const override { + ORCABI::writeResolverCode(ResolverWorkingMem, ResolverTargetAddr, + ReentryFnAddr, ReentryCtxAddr); + } + + void writeTrampolines(char *TrampolineBlockWorkingMem, + JITTargetAddress TrampolineBlockTargetAddr, + JITTargetAddress ResolverAddr, + unsigned NumTrampolines) const override { + ORCABI::writeTrampolines(TrampolineBlockWorkingMem, + TrampolineBlockTargetAddr, ResolverAddr, + NumTrampolines); + } + + void writeIndirectStubsBlock(char *StubsBlockWorkingMem, + JITTargetAddress StubsBlockTargetAddress, + JITTargetAddress PointersBlockTargetAddress, + unsigned NumStubs) const override { + ORCABI::writeIndirectStubsBlock(StubsBlockWorkingMem, + StubsBlockTargetAddress, + PointersBlockTargetAddress, NumStubs); + } +}; + +} // end namespace detail + +template <typename ORCABI> +std::unique_ptr<TPCIndirectionUtils> +TPCIndirectionUtils::CreateWithABI(TargetProcessControl &TPC) { + return std::unique_ptr<TPCIndirectionUtils>(new TPCIndirectionUtils( + TPC, std::make_unique<detail::ABISupportImpl<ORCABI>>())); +} + +} // end namespace orc +} // end namespace llvm + +#endif // LLVM_EXECUTIONENGINE_ORC_TPCINDIRECTIONUTILS_H diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/OrcRPCTPCServer.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/OrcRPCTPCServer.h new file mode 100644 index 000000000000..253e06ba0ba1 --- /dev/null +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/OrcRPCTPCServer.h @@ -0,0 +1,620 @@ +//===-- OrcRPCTPCServer.h -- OrcRPCTargetProcessControl Server --*- 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 +// +//===----------------------------------------------------------------------===// +// +// OrcRPCTargetProcessControl server class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_ORCRPCTPCSERVER_H +#define LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_ORCRPCTPCSERVER_H + +#include "llvm/ADT/BitmaskEnum.h" +#include "llvm/ExecutionEngine/Orc/Shared/RPCUtils.h" +#include "llvm/ExecutionEngine/Orc/Shared/RawByteChannel.h" +#include "llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h" +#include "llvm/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.h" +#include "llvm/ExecutionEngine/Orc/TargetProcessControl.h" +#include "llvm/Support/DynamicLibrary.h" +#include "llvm/Support/FormatVariadic.h" +#include "llvm/Support/Host.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/Memory.h" +#include "llvm/Support/Process.h" + +#include <atomic> + +namespace llvm { +namespace orc { + +namespace orcrpctpc { + +enum WireProtectionFlags : uint8_t { + WPF_None = 0, + WPF_Read = 1U << 0, + WPF_Write = 1U << 1, + WPF_Exec = 1U << 2, + LLVM_MARK_AS_BITMASK_ENUM(WPF_Exec) +}; + +/// Convert from sys::Memory::ProtectionFlags +inline WireProtectionFlags +toWireProtectionFlags(sys::Memory::ProtectionFlags PF) { + WireProtectionFlags WPF = WPF_None; + if (PF & sys::Memory::MF_READ) + WPF |= WPF_Read; + if (PF & sys::Memory::MF_WRITE) + WPF |= WPF_Write; + if (PF & sys::Memory::MF_EXEC) + WPF |= WPF_Exec; + return WPF; +} + +inline sys::Memory::ProtectionFlags +fromWireProtectionFlags(WireProtectionFlags WPF) { + int PF = 0; + if (WPF & WPF_Read) + PF |= sys::Memory::MF_READ; + if (WPF & WPF_Write) + PF |= sys::Memory::MF_WRITE; + if (WPF & WPF_Exec) + PF |= sys::Memory::MF_EXEC; + return static_cast<sys::Memory::ProtectionFlags>(PF); +} + +struct ReserveMemRequestElement { + WireProtectionFlags Prot = WPF_None; + uint64_t Size = 0; + uint64_t Alignment = 0; +}; + +using ReserveMemRequest = std::vector<ReserveMemRequestElement>; + +struct ReserveMemResultElement { + WireProtectionFlags Prot = WPF_None; + JITTargetAddress Address = 0; + uint64_t AllocatedSize = 0; +}; + +using ReserveMemResult = std::vector<ReserveMemResultElement>; + +struct ReleaseOrFinalizeMemRequestElement { + WireProtectionFlags Prot = WPF_None; + JITTargetAddress Address = 0; + uint64_t Size = 0; +}; + +using ReleaseOrFinalizeMemRequest = + std::vector<ReleaseOrFinalizeMemRequestElement>; + +} // end namespace orcrpctpc + +namespace shared { + +template <> class SerializationTypeName<tpctypes::UInt8Write> { +public: + static const char *getName() { return "UInt8Write"; } +}; + +template <> class SerializationTypeName<tpctypes::UInt16Write> { +public: + static const char *getName() { return "UInt16Write"; } +}; + +template <> class SerializationTypeName<tpctypes::UInt32Write> { +public: + static const char *getName() { return "UInt32Write"; } +}; + +template <> class SerializationTypeName<tpctypes::UInt64Write> { +public: + static const char *getName() { return "UInt64Write"; } +}; + +template <> class SerializationTypeName<tpctypes::BufferWrite> { +public: + static const char *getName() { return "BufferWrite"; } +}; + +template <> class SerializationTypeName<orcrpctpc::ReserveMemRequestElement> { +public: + static const char *getName() { return "ReserveMemRequestElement"; } +}; + +template <> class SerializationTypeName<orcrpctpc::ReserveMemResultElement> { +public: + static const char *getName() { return "ReserveMemResultElement"; } +}; + +template <> +class SerializationTypeName<orcrpctpc::ReleaseOrFinalizeMemRequestElement> { +public: + static const char *getName() { return "ReleaseOrFinalizeMemRequestElement"; } +}; + +template <> class SerializationTypeName<tpctypes::WrapperFunctionResult> { +public: + static const char *getName() { return "WrapperFunctionResult"; } +}; + +template <typename ChannelT, typename WriteT> +class SerializationTraits< + ChannelT, WriteT, WriteT, + std::enable_if_t<std::is_same<WriteT, tpctypes::UInt8Write>::value || + std::is_same<WriteT, tpctypes::UInt16Write>::value || + std::is_same<WriteT, tpctypes::UInt32Write>::value || + std::is_same<WriteT, tpctypes::UInt64Write>::value>> { +public: + static Error serialize(ChannelT &C, const WriteT &W) { + return serializeSeq(C, W.Address, W.Value); + } + static Error deserialize(ChannelT &C, WriteT &W) { + return deserializeSeq(C, W.Address, W.Value); + } +}; + +template <typename ChannelT> +class SerializationTraits< + ChannelT, tpctypes::BufferWrite, tpctypes::BufferWrite, + std::enable_if_t<std::is_base_of<RawByteChannel, ChannelT>::value>> { +public: + static Error serialize(ChannelT &C, const tpctypes::BufferWrite &W) { + uint64_t Size = W.Buffer.size(); + if (auto Err = serializeSeq(C, W.Address, Size)) + return Err; + + return C.appendBytes(W.Buffer.data(), Size); + } + static Error deserialize(ChannelT &C, tpctypes::BufferWrite &W) { + JITTargetAddress Address; + uint64_t Size; + + if (auto Err = deserializeSeq(C, Address, Size)) + return Err; + + char *Buffer = jitTargetAddressToPointer<char *>(Address); + + if (auto Err = C.readBytes(Buffer, Size)) + return Err; + + W = {Address, StringRef(Buffer, Size)}; + return Error::success(); + } +}; + +template <typename ChannelT> +class SerializationTraits<ChannelT, orcrpctpc::ReserveMemRequestElement> { +public: + static Error serialize(ChannelT &C, + const orcrpctpc::ReserveMemRequestElement &E) { + return serializeSeq(C, static_cast<uint8_t>(E.Prot), E.Size, E.Alignment); + } + + static Error deserialize(ChannelT &C, + orcrpctpc::ReserveMemRequestElement &E) { + return deserializeSeq(C, *reinterpret_cast<uint8_t *>(&E.Prot), E.Size, + E.Alignment); + } +}; + +template <typename ChannelT> +class SerializationTraits<ChannelT, orcrpctpc::ReserveMemResultElement> { +public: + static Error serialize(ChannelT &C, + const orcrpctpc::ReserveMemResultElement &E) { + return serializeSeq(C, static_cast<uint8_t>(E.Prot), E.Address, + E.AllocatedSize); + } + + static Error deserialize(ChannelT &C, orcrpctpc::ReserveMemResultElement &E) { + return deserializeSeq(C, *reinterpret_cast<uint8_t *>(&E.Prot), E.Address, + E.AllocatedSize); + } +}; + +template <typename ChannelT> +class SerializationTraits<ChannelT, + orcrpctpc::ReleaseOrFinalizeMemRequestElement> { +public: + static Error + serialize(ChannelT &C, + const orcrpctpc::ReleaseOrFinalizeMemRequestElement &E) { + return serializeSeq(C, static_cast<uint8_t>(E.Prot), E.Address, E.Size); + } + + static Error deserialize(ChannelT &C, + orcrpctpc::ReleaseOrFinalizeMemRequestElement &E) { + return deserializeSeq(C, *reinterpret_cast<uint8_t *>(&E.Prot), E.Address, + E.Size); + } +}; + +template <typename ChannelT> +class SerializationTraits< + ChannelT, tpctypes::WrapperFunctionResult, tpctypes::WrapperFunctionResult, + std::enable_if_t<std::is_base_of<RawByteChannel, ChannelT>::value>> { +public: + static Error serialize(ChannelT &C, + const tpctypes::WrapperFunctionResult &E) { + auto Data = E.getData(); + if (auto Err = serializeSeq(C, static_cast<uint64_t>(Data.size()))) + return Err; + if (Data.size() == 0) + return Error::success(); + return C.appendBytes(reinterpret_cast<const char *>(Data.data()), + Data.size()); + } + + static Error deserialize(ChannelT &C, tpctypes::WrapperFunctionResult &E) { + tpctypes::CWrapperFunctionResult R; + + R.Size = 0; + R.Data.ValuePtr = nullptr; + R.Destroy = nullptr; + + if (auto Err = deserializeSeq(C, R.Size)) + return Err; + if (R.Size == 0) + return Error::success(); + R.Data.ValuePtr = new uint8_t[R.Size]; + if (auto Err = + C.readBytes(reinterpret_cast<char *>(R.Data.ValuePtr), R.Size)) { + R.Destroy = tpctypes::WrapperFunctionResult::destroyWithDeleteArray; + return Err; + } + + E = tpctypes::WrapperFunctionResult(R); + return Error::success(); + } +}; + +} // end namespace shared + +namespace orcrpctpc { + +using RemoteSymbolLookupSet = std::vector<std::pair<std::string, bool>>; +using RemoteLookupRequest = + std::pair<tpctypes::DylibHandle, RemoteSymbolLookupSet>; + +class GetTargetTriple + : public shared::RPCFunction<GetTargetTriple, std::string()> { +public: + static const char *getName() { return "GetTargetTriple"; } +}; + +class GetPageSize : public shared::RPCFunction<GetPageSize, uint64_t()> { +public: + static const char *getName() { return "GetPageSize"; } +}; + +class ReserveMem + : public shared::RPCFunction<ReserveMem, Expected<ReserveMemResult>( + ReserveMemRequest)> { +public: + static const char *getName() { return "ReserveMem"; } +}; + +class FinalizeMem + : public shared::RPCFunction<FinalizeMem, + Error(ReleaseOrFinalizeMemRequest)> { +public: + static const char *getName() { return "FinalizeMem"; } +}; + +class ReleaseMem + : public shared::RPCFunction<ReleaseMem, + Error(ReleaseOrFinalizeMemRequest)> { +public: + static const char *getName() { return "ReleaseMem"; } +}; + +class WriteUInt8s + : public shared::RPCFunction<WriteUInt8s, + Error(std::vector<tpctypes::UInt8Write>)> { +public: + static const char *getName() { return "WriteUInt8s"; } +}; + +class WriteUInt16s + : public shared::RPCFunction<WriteUInt16s, + Error(std::vector<tpctypes::UInt16Write>)> { +public: + static const char *getName() { return "WriteUInt16s"; } +}; + +class WriteUInt32s + : public shared::RPCFunction<WriteUInt32s, + Error(std::vector<tpctypes::UInt32Write>)> { +public: + static const char *getName() { return "WriteUInt32s"; } +}; + +class WriteUInt64s + : public shared::RPCFunction<WriteUInt64s, + Error(std::vector<tpctypes::UInt64Write>)> { +public: + static const char *getName() { return "WriteUInt64s"; } +}; + +class WriteBuffers + : public shared::RPCFunction<WriteBuffers, + Error(std::vector<tpctypes::BufferWrite>)> { +public: + static const char *getName() { return "WriteBuffers"; } +}; + +class LoadDylib + : public shared::RPCFunction<LoadDylib, Expected<tpctypes::DylibHandle>( + std::string DylibPath)> { +public: + static const char *getName() { return "LoadDylib"; } +}; + +class LookupSymbols + : public shared::RPCFunction<LookupSymbols, + Expected<std::vector<tpctypes::LookupResult>>( + std::vector<RemoteLookupRequest>)> { +public: + static const char *getName() { return "LookupSymbols"; } +}; + +class RunMain + : public shared::RPCFunction<RunMain, + int32_t(JITTargetAddress MainAddr, + std::vector<std::string> Args)> { +public: + static const char *getName() { return "RunMain"; } +}; + +class RunWrapper + : public shared::RPCFunction<RunWrapper, + tpctypes::WrapperFunctionResult( + JITTargetAddress, std::vector<uint8_t>)> { +public: + static const char *getName() { return "RunWrapper"; } +}; + +class CloseConnection : public shared::RPCFunction<CloseConnection, void()> { +public: + static const char *getName() { return "CloseConnection"; } +}; + +} // end namespace orcrpctpc + +/// TargetProcessControl for a process connected via an ORC RPC Endpoint. +template <typename RPCEndpointT> class OrcRPCTPCServer { +public: + /// Create an OrcRPCTPCServer from the given endpoint. + OrcRPCTPCServer(RPCEndpointT &EP) : EP(EP) { + using ThisT = OrcRPCTPCServer<RPCEndpointT>; + + TripleStr = sys::getProcessTriple(); + PageSize = sys::Process::getPageSizeEstimate(); + + EP.template addHandler<orcrpctpc::GetTargetTriple>(*this, + &ThisT::getTargetTriple); + EP.template addHandler<orcrpctpc::GetPageSize>(*this, &ThisT::getPageSize); + + EP.template addHandler<orcrpctpc::ReserveMem>(*this, &ThisT::reserveMemory); + EP.template addHandler<orcrpctpc::FinalizeMem>(*this, + &ThisT::finalizeMemory); + EP.template addHandler<orcrpctpc::ReleaseMem>(*this, &ThisT::releaseMemory); + + EP.template addHandler<orcrpctpc::WriteUInt8s>( + handleWriteUInt<tpctypes::UInt8Write>); + EP.template addHandler<orcrpctpc::WriteUInt16s>( + handleWriteUInt<tpctypes::UInt16Write>); + EP.template addHandler<orcrpctpc::WriteUInt32s>( + handleWriteUInt<tpctypes::UInt32Write>); + EP.template addHandler<orcrpctpc::WriteUInt64s>( + handleWriteUInt<tpctypes::UInt64Write>); + EP.template addHandler<orcrpctpc::WriteBuffers>(handleWriteBuffer); + + EP.template addHandler<orcrpctpc::LoadDylib>(*this, &ThisT::loadDylib); + EP.template addHandler<orcrpctpc::LookupSymbols>(*this, + &ThisT::lookupSymbols); + + EP.template addHandler<orcrpctpc::RunMain>(*this, &ThisT::runMain); + EP.template addHandler<orcrpctpc::RunWrapper>(*this, &ThisT::runWrapper); + + EP.template addHandler<orcrpctpc::CloseConnection>(*this, + &ThisT::closeConnection); + } + + /// Set the ProgramName to be used as the first argv element when running + /// functions via runAsMain. + void setProgramName(Optional<std::string> ProgramName = None) { + this->ProgramName = std::move(ProgramName); + } + + /// Get the RPC endpoint for this server. + RPCEndpointT &getEndpoint() { return EP; } + + /// Run the server loop. + Error run() { + while (!Finished) { + if (auto Err = EP.handleOne()) + return Err; + } + return Error::success(); + } + +private: + std::string getTargetTriple() { return TripleStr; } + uint64_t getPageSize() { return PageSize; } + + template <typename WriteT> + static void handleWriteUInt(const std::vector<WriteT> &Ws) { + using ValueT = decltype(std::declval<WriteT>().Value); + for (auto &W : Ws) + *jitTargetAddressToPointer<ValueT *>(W.Address) = W.Value; + } + + std::string getProtStr(orcrpctpc::WireProtectionFlags WPF) { + std::string Result; + Result += (WPF & orcrpctpc::WPF_Read) ? 'R' : '-'; + Result += (WPF & orcrpctpc::WPF_Write) ? 'W' : '-'; + Result += (WPF & orcrpctpc::WPF_Exec) ? 'X' : '-'; + return Result; + } + + static void handleWriteBuffer(const std::vector<tpctypes::BufferWrite> &Ws) { + for (auto &W : Ws) { + memcpy(jitTargetAddressToPointer<char *>(W.Address), W.Buffer.data(), + W.Buffer.size()); + } + } + + Expected<orcrpctpc::ReserveMemResult> + reserveMemory(const orcrpctpc::ReserveMemRequest &Request) { + orcrpctpc::ReserveMemResult Allocs; + auto PF = sys::Memory::MF_READ | sys::Memory::MF_WRITE; + + uint64_t TotalSize = 0; + + for (const auto &E : Request) { + uint64_t Size = alignTo(E.Size, PageSize); + uint16_t Align = E.Alignment; + + if ((Align > PageSize) || (PageSize % Align)) + return make_error<StringError>( + "Page alignmen does not satisfy requested alignment", + inconvertibleErrorCode()); + + TotalSize += Size; + } + + // Allocate memory slab. + std::error_code EC; + auto MB = sys::Memory::allocateMappedMemory(TotalSize, nullptr, PF, EC); + if (EC) + return make_error<StringError>("Unable to allocate memory: " + + EC.message(), + inconvertibleErrorCode()); + + // Zero-fill the whole thing. + memset(MB.base(), 0, MB.allocatedSize()); + + // Carve up sections to return. + uint64_t SectionBase = 0; + for (const auto &E : Request) { + uint64_t SectionSize = alignTo(E.Size, PageSize); + Allocs.push_back({E.Prot, + pointerToJITTargetAddress(MB.base()) + SectionBase, + SectionSize}); + SectionBase += SectionSize; + } + + return Allocs; + } + + Error finalizeMemory(const orcrpctpc::ReleaseOrFinalizeMemRequest &FMR) { + for (const auto &E : FMR) { + sys::MemoryBlock MB(jitTargetAddressToPointer<void *>(E.Address), E.Size); + + auto PF = orcrpctpc::fromWireProtectionFlags(E.Prot); + if (auto EC = + sys::Memory::protectMappedMemory(MB, static_cast<unsigned>(PF))) + return make_error<StringError>("error protecting memory: " + + EC.message(), + inconvertibleErrorCode()); + } + return Error::success(); + } + + Error releaseMemory(const orcrpctpc::ReleaseOrFinalizeMemRequest &RMR) { + for (const auto &E : RMR) { + sys::MemoryBlock MB(jitTargetAddressToPointer<void *>(E.Address), E.Size); + + if (auto EC = sys::Memory::releaseMappedMemory(MB)) + return make_error<StringError>("error release memory: " + EC.message(), + inconvertibleErrorCode()); + } + return Error::success(); + } + + Expected<tpctypes::DylibHandle> loadDylib(const std::string &Path) { + std::string ErrMsg; + const char *DLPath = !Path.empty() ? Path.c_str() : nullptr; + auto DL = sys::DynamicLibrary::getPermanentLibrary(DLPath, &ErrMsg); + if (!DL.isValid()) + return make_error<StringError>(std::move(ErrMsg), + inconvertibleErrorCode()); + + tpctypes::DylibHandle H = Dylibs.size(); + Dylibs[H] = std::move(DL); + return H; + } + + Expected<std::vector<tpctypes::LookupResult>> + lookupSymbols(const std::vector<orcrpctpc::RemoteLookupRequest> &Request) { + std::vector<tpctypes::LookupResult> Result; + + for (const auto &E : Request) { + auto I = Dylibs.find(E.first); + if (I == Dylibs.end()) + return make_error<StringError>("Unrecognized handle", + inconvertibleErrorCode()); + auto &DL = I->second; + Result.push_back({}); + + for (const auto &KV : E.second) { + auto &SymString = KV.first; + bool WeakReference = KV.second; + + const char *Sym = SymString.c_str(); +#ifdef __APPLE__ + if (*Sym == '_') + ++Sym; +#endif + + void *Addr = DL.getAddressOfSymbol(Sym); + if (!Addr && !WeakReference) + return make_error<StringError>(Twine("Missing definition for ") + Sym, + inconvertibleErrorCode()); + + Result.back().push_back(pointerToJITTargetAddress(Addr)); + } + } + + return Result; + } + + int32_t runMain(JITTargetAddress MainFnAddr, + const std::vector<std::string> &Args) { + Optional<StringRef> ProgramNameOverride; + if (ProgramName) + ProgramNameOverride = *ProgramName; + + return runAsMain( + jitTargetAddressToFunction<int (*)(int, char *[])>(MainFnAddr), Args, + ProgramNameOverride); + } + + tpctypes::WrapperFunctionResult + runWrapper(JITTargetAddress WrapperFnAddr, + const std::vector<uint8_t> &ArgBuffer) { + using WrapperFnTy = tpctypes::CWrapperFunctionResult (*)( + const uint8_t *Data, uint64_t Size); + auto *WrapperFn = jitTargetAddressToFunction<WrapperFnTy>(WrapperFnAddr); + return WrapperFn(ArgBuffer.data(), ArgBuffer.size()); + } + + void closeConnection() { Finished = true; } + + std::string TripleStr; + uint64_t PageSize = 0; + Optional<std::string> ProgramName; + RPCEndpointT &EP; + std::atomic<bool> Finished{false}; + DenseMap<tpctypes::DylibHandle, sys::DynamicLibrary> Dylibs; +}; + +} // end namespace orc +} // end namespace llvm + +#endif // LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_ORCRPCTPCSERVER_H diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.h new file mode 100644 index 000000000000..811c50e3ce4d --- /dev/null +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.h @@ -0,0 +1,41 @@ +//===----- RegisterEHFrames.h -- Register EH frame sections -----*- 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 +// +//===----------------------------------------------------------------------===// +// +// Support for dynamically registering and deregistering eh-frame sections +// in-process via libunwind. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_REGISTEREHFRAMES_H +#define LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_REGISTEREHFRAMES_H + +#include "llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h" +#include "llvm/Support/Error.h" +#include <vector> + +namespace llvm { +namespace orc { + +/// Register frames in the given eh-frame section with libunwind. +Error registerEHFrameSection(const void *EHFrameSectionAddr, + size_t EHFrameSectionSize); + +/// Unregister frames in the given eh-frame section with libunwind. +Error deregisterEHFrameSection(const void *EHFrameSectionAddr, + size_t EHFrameSectionSize); + +} // end namespace orc +} // end namespace llvm + +extern "C" llvm::orc::tpctypes::CWrapperFunctionResult +llvm_orc_registerEHFrameSectionWrapper(uint8_t *Data, uint64_t Size); + +extern "C" llvm::orc::tpctypes::CWrapperFunctionResult +llvm_orc_deregisterEHFrameSectionWrapper(uint8_t *Data, uint64_t Size); + +#endif // LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_REGISTEREHFRAMES_H diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.h new file mode 100644 index 000000000000..1d2f6d2be089 --- /dev/null +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.h @@ -0,0 +1,38 @@ +//===-- TargetExecutionUtils.h - Utils for execution in target --*- 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 +// +//===----------------------------------------------------------------------===// +// +// Utilities for execution in the target process. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_TARGETEXECUTIONUTILS_H +#define LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_TARGETEXECUTIONUTILS_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/StringRef.h" +#include <string> + +namespace llvm { +namespace orc { + +/// Run a main function, returning the result. +/// +/// If the optional ProgramName argument is given then it will be inserted +/// before the strings in Args as the first argument to the called function. +/// +/// It is legal to have an empty argument list and no program name, however +/// many main functions will expect a name argument at least, and will fail +/// if none is provided. +int runAsMain(int (*Main)(int, char *[]), ArrayRef<std::string> Args, + Optional<StringRef> ProgramName = None); + +} // end namespace orc +} // end namespace llvm + +#endif // LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_TARGETEXECUTIONUTILS_H diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/TargetProcessControl.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/TargetProcessControl.h new file mode 100644 index 000000000000..b60b1ca6e372 --- /dev/null +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/TargetProcessControl.h @@ -0,0 +1,218 @@ +//===--- TargetProcessControl.h - Target process control APIs ---*- 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 +// +//===----------------------------------------------------------------------===// +// +// Utilities for interacting with target processes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORC_TARGETPROCESSCONTROL_H +#define LLVM_EXECUTIONENGINE_ORC_TARGETPROCESSCONTROL_H + +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Triple.h" +#include "llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h" +#include "llvm/ExecutionEngine/Orc/Core.h" +#include "llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h" +#include "llvm/Support/DynamicLibrary.h" +#include "llvm/Support/MSVCErrorWorkarounds.h" + +#include <future> +#include <vector> + +namespace llvm { +namespace orc { + +/// TargetProcessControl supports interaction with a JIT target process. +class TargetProcessControl { +public: + /// APIs for manipulating memory in the target process. + class MemoryAccess { + public: + /// Callback function for asynchronous writes. + using WriteResultFn = unique_function<void(Error)>; + + virtual ~MemoryAccess(); + + virtual void writeUInt8s(ArrayRef<tpctypes::UInt8Write> Ws, + WriteResultFn OnWriteComplete) = 0; + + virtual void writeUInt16s(ArrayRef<tpctypes::UInt16Write> Ws, + WriteResultFn OnWriteComplete) = 0; + + virtual void writeUInt32s(ArrayRef<tpctypes::UInt32Write> Ws, + WriteResultFn OnWriteComplete) = 0; + + virtual void writeUInt64s(ArrayRef<tpctypes::UInt64Write> Ws, + WriteResultFn OnWriteComplete) = 0; + + virtual void writeBuffers(ArrayRef<tpctypes::BufferWrite> Ws, + WriteResultFn OnWriteComplete) = 0; + + Error writeUInt8s(ArrayRef<tpctypes::UInt8Write> Ws) { + std::promise<MSVCPError> ResultP; + auto ResultF = ResultP.get_future(); + writeUInt8s(Ws, [&](Error Err) { ResultP.set_value(std::move(Err)); }); + return ResultF.get(); + } + + Error writeUInt16s(ArrayRef<tpctypes::UInt16Write> Ws) { + std::promise<MSVCPError> ResultP; + auto ResultF = ResultP.get_future(); + writeUInt16s(Ws, [&](Error Err) { ResultP.set_value(std::move(Err)); }); + return ResultF.get(); + } + + Error writeUInt32s(ArrayRef<tpctypes::UInt32Write> Ws) { + std::promise<MSVCPError> ResultP; + auto ResultF = ResultP.get_future(); + writeUInt32s(Ws, [&](Error Err) { ResultP.set_value(std::move(Err)); }); + return ResultF.get(); + } + + Error writeUInt64s(ArrayRef<tpctypes::UInt64Write> Ws) { + std::promise<MSVCPError> ResultP; + auto ResultF = ResultP.get_future(); + writeUInt64s(Ws, [&](Error Err) { ResultP.set_value(std::move(Err)); }); + return ResultF.get(); + } + + Error writeBuffers(ArrayRef<tpctypes::BufferWrite> Ws) { + std::promise<MSVCPError> ResultP; + auto ResultF = ResultP.get_future(); + writeBuffers(Ws, [&](Error Err) { ResultP.set_value(std::move(Err)); }); + return ResultF.get(); + } + }; + + /// A pair of a dylib and a set of symbols to be looked up. + struct LookupRequest { + LookupRequest(tpctypes::DylibHandle Handle, const SymbolLookupSet &Symbols) + : Handle(Handle), Symbols(Symbols) {} + tpctypes::DylibHandle Handle; + const SymbolLookupSet &Symbols; + }; + + virtual ~TargetProcessControl(); + + /// Intern a symbol name in the SymbolStringPool. + SymbolStringPtr intern(StringRef SymName) { return SSP->intern(SymName); } + + /// Return a shared pointer to the SymbolStringPool for this instance. + std::shared_ptr<SymbolStringPool> getSymbolStringPool() const { return SSP; } + + /// Return the Triple for the target process. + const Triple &getTargetTriple() const { return TargetTriple; } + + /// Get the page size for the target process. + unsigned getPageSize() const { return PageSize; } + + /// Return a MemoryAccess object for the target process. + MemoryAccess &getMemoryAccess() const { return *MemAccess; } + + /// Return a JITLinkMemoryManager for the target process. + jitlink::JITLinkMemoryManager &getMemMgr() const { return *MemMgr; } + + /// Load the dynamic library at the given path and return a handle to it. + /// If LibraryPath is null this function will return the global handle for + /// the target process. + virtual Expected<tpctypes::DylibHandle> loadDylib(const char *DylibPath) = 0; + + /// Search for symbols in the target process. + /// + /// The result of the lookup is a 2-dimentional array of target addresses + /// that correspond to the lookup order. If a required symbol is not + /// found then this method will return an error. If a weakly referenced + /// symbol is not found then it be assigned a '0' value in the result. + /// that correspond to the lookup order. + virtual Expected<std::vector<tpctypes::LookupResult>> + lookupSymbols(ArrayRef<LookupRequest> Request) = 0; + + /// Run function with a main-like signature. + virtual Expected<int32_t> runAsMain(JITTargetAddress MainFnAddr, + ArrayRef<std::string> Args) = 0; + + /// Run a wrapper function with signature: + /// + /// \code{.cpp} + /// CWrapperFunctionResult fn(uint8_t *Data, uint64_t Size); + /// \endcode{.cpp} + /// + virtual Expected<tpctypes::WrapperFunctionResult> + runWrapper(JITTargetAddress WrapperFnAddr, ArrayRef<uint8_t> ArgBuffer) = 0; + + /// Disconnect from the target process. + /// + /// This should be called after the JIT session is shut down. + virtual Error disconnect() = 0; + +protected: + TargetProcessControl(std::shared_ptr<SymbolStringPool> SSP) + : SSP(std::move(SSP)) {} + + std::shared_ptr<SymbolStringPool> SSP; + Triple TargetTriple; + unsigned PageSize = 0; + MemoryAccess *MemAccess = nullptr; + jitlink::JITLinkMemoryManager *MemMgr = nullptr; +}; + +/// A TargetProcessControl implementation targeting the current process. +class SelfTargetProcessControl : public TargetProcessControl, + private TargetProcessControl::MemoryAccess { +public: + SelfTargetProcessControl( + std::shared_ptr<SymbolStringPool> SSP, Triple TargetTriple, + unsigned PageSize, std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr); + + /// Create a SelfTargetProcessControl with the given memory manager. + /// If no memory manager is given a jitlink::InProcessMemoryManager will + /// be used by default. + static Expected<std::unique_ptr<SelfTargetProcessControl>> + Create(std::shared_ptr<SymbolStringPool> SSP, + std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr = nullptr); + + Expected<tpctypes::DylibHandle> loadDylib(const char *DylibPath) override; + + Expected<std::vector<tpctypes::LookupResult>> + lookupSymbols(ArrayRef<LookupRequest> Request) override; + + Expected<int32_t> runAsMain(JITTargetAddress MainFnAddr, + ArrayRef<std::string> Args) override; + + Expected<tpctypes::WrapperFunctionResult> + runWrapper(JITTargetAddress WrapperFnAddr, + ArrayRef<uint8_t> ArgBuffer) override; + + Error disconnect() override; + +private: + void writeUInt8s(ArrayRef<tpctypes::UInt8Write> Ws, + WriteResultFn OnWriteComplete) override; + + void writeUInt16s(ArrayRef<tpctypes::UInt16Write> Ws, + WriteResultFn OnWriteComplete) override; + + void writeUInt32s(ArrayRef<tpctypes::UInt32Write> Ws, + WriteResultFn OnWriteComplete) override; + + void writeUInt64s(ArrayRef<tpctypes::UInt64Write> Ws, + WriteResultFn OnWriteComplete) override; + + void writeBuffers(ArrayRef<tpctypes::BufferWrite> Ws, + WriteResultFn OnWriteComplete) override; + + std::unique_ptr<jitlink::JITLinkMemoryManager> OwnedMemMgr; + char GlobalManglingPrefix = 0; + std::vector<std::unique_ptr<sys::DynamicLibrary>> DynamicLibraries; +}; + +} // end namespace orc +} // end namespace llvm + +#endif // LLVM_EXECUTIONENGINE_ORC_TARGETPROCESSCONTROL_H diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/ThreadSafeModule.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/ThreadSafeModule.h index 58c96737e580..82f2b7464953 100644 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/ThreadSafeModule.h +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/ThreadSafeModule.h @@ -162,7 +162,7 @@ using GVModifier = std::function<void(GlobalValue &)>; /// Clones the given module on to a new context. ThreadSafeModule -cloneToNewContext(ThreadSafeModule &TSMW, +cloneToNewContext(const ThreadSafeModule &TSMW, GVPredicate ShouldCloneDef = GVPredicate(), GVModifier UpdateClonedDefSource = GVModifier()); diff --git a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/RuntimeDyld.h b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/RuntimeDyld.h index 1b3ce1127e4a..9b83092e653f 100644 --- a/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/RuntimeDyld.h +++ b/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/RuntimeDyld.h @@ -271,11 +271,11 @@ private: object::OwningBinary<object::ObjectFile> O, RuntimeDyld::MemoryManager &MemMgr, JITSymbolResolver &Resolver, bool ProcessAllSections, - unique_function<Error(const object::ObjectFile &Obj, - std::unique_ptr<LoadedObjectInfo>, + unique_function<Error(const object::ObjectFile &Obj, LoadedObjectInfo &, std::map<StringRef, JITEvaluatedSymbol>)> OnLoaded, - unique_function<void(object::OwningBinary<object::ObjectFile> O, Error)> + unique_function<void(object::OwningBinary<object::ObjectFile> O, + std::unique_ptr<LoadedObjectInfo>, Error)> OnEmitted); // RuntimeDyldImpl is the actual class. RuntimeDyld is just the public @@ -298,10 +298,11 @@ void jitLinkForORC( RuntimeDyld::MemoryManager &MemMgr, JITSymbolResolver &Resolver, bool ProcessAllSections, unique_function<Error(const object::ObjectFile &Obj, - std::unique_ptr<RuntimeDyld::LoadedObjectInfo>, + RuntimeDyld::LoadedObjectInfo &, std::map<StringRef, JITEvaluatedSymbol>)> OnLoaded, - unique_function<void(object::OwningBinary<object::ObjectFile>, Error)> + unique_function<void(object::OwningBinary<object::ObjectFile>, + std::unique_ptr<RuntimeDyld::LoadedObjectInfo>, Error)> OnEmitted); } // end namespace llvm |