From f40685138ba182fc823f569f6d88b7d3ddf34b9e Mon Sep 17 00:00:00 2001 From: Lang Hames Date: Sun, 26 Sep 2021 11:02:37 -0700 Subject: [PATCH] [ORC] Remote OrcRemoteTargetClient and OrcRemoteTargetServer. Now that the lli and lli-child-target tools have been updated to use SimpleRemoteEPC (6498b0e991b) the OrcRemoteTarget* APIs are no longer needed. Once the LLJITWithRemoteDebugging example has been migrated to SimpleRemoteEPC we will remove OrcRPCExecutorProcessControl, and the ORC RPC system itself. --- .../Orc/OrcRemoteTargetClient.h | 925 ------------------ .../Orc/OrcRemoteTargetRPCAPI.h | 386 -------- .../Orc/OrcRemoteTargetServer.h | 464 --------- 3 files changed, 1775 deletions(-) delete mode 100644 llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h delete mode 100644 llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h delete mode 100644 llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h diff --git a/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h b/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h deleted file mode 100644 index 3d139740d677..000000000000 --- a/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h +++ /dev/null @@ -1,925 +0,0 @@ -//===- OrcRemoteTargetClient.h - Orc Remote-target Client -------*- 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 -// -//===----------------------------------------------------------------------===// -// -// This file defines the OrcRemoteTargetClient class and helpers. This class -// can be used to communicate over an RawByteChannel with an -// OrcRemoteTargetServer instance to support remote-JITing. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_EXECUTIONENGINE_ORC_ORCREMOTETARGETCLIENT_H -#define LLVM_EXECUTIONENGINE_ORC_ORCREMOTETARGETCLIENT_H - -#include "llvm/ADT/Optional.h" -#include "llvm/ADT/STLExtras.h" -#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" -#include "llvm/Support/Debug.h" -#include "llvm/Support/Error.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/Format.h" -#include "llvm/Support/MathExtras.h" -#include "llvm/Support/Memory.h" -#include "llvm/Support/raw_ostream.h" -#include -#include -#include -#include -#include -#include -#include -#include - -#define DEBUG_TYPE "orc-remote" - -namespace llvm { -namespace orc { -namespace remote { - -/// This class provides utilities (including memory manager, indirect stubs -/// manager, and compile callback manager types) that support remote JITing -/// in ORC. -/// -/// Each of the utility classes talks to a JIT server (an instance of the -/// OrcRemoteTargetServer class) via an RPC system (see RPCUtils.h) to carry out -/// its actions. -class OrcRemoteTargetClient - : public shared::SingleThreadedRPCEndpoint { -public: - /// Remote-mapped RuntimeDyld-compatible memory manager. - class RemoteRTDyldMemoryManager : public RuntimeDyld::MemoryManager { - friend class OrcRemoteTargetClient; - - public: - ~RemoteRTDyldMemoryManager() { - Client.destroyRemoteAllocator(Id); - LLVM_DEBUG(dbgs() << "Destroyed remote allocator " << Id << "\n"); - } - - RemoteRTDyldMemoryManager(const RemoteRTDyldMemoryManager &) = delete; - RemoteRTDyldMemoryManager & - operator=(const RemoteRTDyldMemoryManager &) = delete; - RemoteRTDyldMemoryManager(RemoteRTDyldMemoryManager &&) = default; - RemoteRTDyldMemoryManager &operator=(RemoteRTDyldMemoryManager &&) = delete; - - uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, - unsigned SectionID, - StringRef SectionName) override { - Unmapped.back().CodeAllocs.emplace_back(Size, Alignment); - uint8_t *Alloc = reinterpret_cast( - Unmapped.back().CodeAllocs.back().getLocalAddress()); - LLVM_DEBUG(dbgs() << "Allocator " << Id << " allocated code for " - << SectionName << ": " << Alloc << " (" << Size - << " bytes, alignment " << Alignment << ")\n"); - return Alloc; - } - - uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, - unsigned SectionID, StringRef SectionName, - bool IsReadOnly) override { - if (IsReadOnly) { - Unmapped.back().RODataAllocs.emplace_back(Size, Alignment); - uint8_t *Alloc = reinterpret_cast( - Unmapped.back().RODataAllocs.back().getLocalAddress()); - LLVM_DEBUG(dbgs() << "Allocator " << Id << " allocated ro-data for " - << SectionName << ": " << Alloc << " (" << Size - << " bytes, alignment " << Alignment << ")\n"); - return Alloc; - } // else... - - Unmapped.back().RWDataAllocs.emplace_back(Size, Alignment); - uint8_t *Alloc = reinterpret_cast( - Unmapped.back().RWDataAllocs.back().getLocalAddress()); - LLVM_DEBUG(dbgs() << "Allocator " << Id << " allocated rw-data for " - << SectionName << ": " << Alloc << " (" << Size - << " bytes, alignment " << Alignment << ")\n"); - return Alloc; - } - - void reserveAllocationSpace(uintptr_t CodeSize, uint32_t CodeAlign, - uintptr_t RODataSize, uint32_t RODataAlign, - uintptr_t RWDataSize, - uint32_t RWDataAlign) override { - Unmapped.push_back(ObjectAllocs()); - - LLVM_DEBUG(dbgs() << "Allocator " << Id << " reserved:\n"); - - if (CodeSize != 0) { - Unmapped.back().RemoteCodeAddr = - Client.reserveMem(Id, CodeSize, CodeAlign); - - LLVM_DEBUG( - dbgs() << " code: " - << format("0x%016" PRIx64, Unmapped.back().RemoteCodeAddr) - << " (" << CodeSize << " bytes, alignment " << CodeAlign - << ")\n"); - } - - if (RODataSize != 0) { - Unmapped.back().RemoteRODataAddr = - Client.reserveMem(Id, RODataSize, RODataAlign); - - LLVM_DEBUG( - dbgs() << " ro-data: " - << format("0x%016" PRIx64, Unmapped.back().RemoteRODataAddr) - << " (" << RODataSize << " bytes, alignment " << RODataAlign - << ")\n"); - } - - if (RWDataSize != 0) { - Unmapped.back().RemoteRWDataAddr = - Client.reserveMem(Id, RWDataSize, RWDataAlign); - - LLVM_DEBUG( - dbgs() << " rw-data: " - << format("0x%016" PRIx64, Unmapped.back().RemoteRWDataAddr) - << " (" << RWDataSize << " bytes, alignment " << RWDataAlign - << ")\n"); - } - } - - bool needsToReserveAllocationSpace() override { return true; } - - void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, - size_t Size) override { - UnfinalizedEHFrames.push_back({LoadAddr, Size}); - } - - void deregisterEHFrames() override { - for (auto &Frame : RegisteredEHFrames) { - // FIXME: Add error poll. - Client.deregisterEHFrames(Frame.Addr, Frame.Size); - } - } - - void notifyObjectLoaded(RuntimeDyld &Dyld, - const object::ObjectFile &Obj) override { - LLVM_DEBUG(dbgs() << "Allocator " << Id << " applied mappings:\n"); - for (auto &ObjAllocs : Unmapped) { - mapAllocsToRemoteAddrs(Dyld, ObjAllocs.CodeAllocs, - ObjAllocs.RemoteCodeAddr); - mapAllocsToRemoteAddrs(Dyld, ObjAllocs.RODataAllocs, - ObjAllocs.RemoteRODataAddr); - mapAllocsToRemoteAddrs(Dyld, ObjAllocs.RWDataAllocs, - ObjAllocs.RemoteRWDataAddr); - Unfinalized.push_back(std::move(ObjAllocs)); - } - Unmapped.clear(); - } - - bool finalizeMemory(std::string *ErrMsg = nullptr) override { - LLVM_DEBUG(dbgs() << "Allocator " << Id << " finalizing:\n"); - - for (auto &ObjAllocs : Unfinalized) { - if (copyAndProtect(ObjAllocs.CodeAllocs, ObjAllocs.RemoteCodeAddr, - sys::Memory::MF_READ | sys::Memory::MF_EXEC)) - return true; - - if (copyAndProtect(ObjAllocs.RODataAllocs, ObjAllocs.RemoteRODataAddr, - sys::Memory::MF_READ)) - return true; - - if (copyAndProtect(ObjAllocs.RWDataAllocs, ObjAllocs.RemoteRWDataAddr, - sys::Memory::MF_READ | sys::Memory::MF_WRITE)) - return true; - } - Unfinalized.clear(); - - for (auto &EHFrame : UnfinalizedEHFrames) { - if (auto Err = Client.registerEHFrames(EHFrame.Addr, EHFrame.Size)) { - // FIXME: Replace this once finalizeMemory can return an Error. - handleAllErrors(std::move(Err), [&](ErrorInfoBase &EIB) { - if (ErrMsg) { - raw_string_ostream ErrOut(*ErrMsg); - EIB.log(ErrOut); - } - }); - return false; - } - } - RegisteredEHFrames = std::move(UnfinalizedEHFrames); - UnfinalizedEHFrames = {}; - - return false; - } - - private: - class Alloc { - public: - Alloc(uint64_t Size, unsigned Align) - : Size(Size), Align(Align), Contents(new char[Size + Align - 1]) {} - - Alloc(const Alloc &) = delete; - Alloc &operator=(const Alloc &) = delete; - Alloc(Alloc &&) = default; - Alloc &operator=(Alloc &&) = default; - - uint64_t getSize() const { return Size; } - - unsigned getAlign() const { return Align; } - - char *getLocalAddress() const { - uintptr_t LocalAddr = reinterpret_cast(Contents.get()); - LocalAddr = alignTo(LocalAddr, Align); - return reinterpret_cast(LocalAddr); - } - - void setRemoteAddress(JITTargetAddress RemoteAddr) { - this->RemoteAddr = RemoteAddr; - } - - JITTargetAddress getRemoteAddress() const { return RemoteAddr; } - - private: - uint64_t Size; - unsigned Align; - std::unique_ptr Contents; - JITTargetAddress RemoteAddr = 0; - }; - - struct ObjectAllocs { - ObjectAllocs() = default; - ObjectAllocs(const ObjectAllocs &) = delete; - ObjectAllocs &operator=(const ObjectAllocs &) = delete; - ObjectAllocs(ObjectAllocs &&) = default; - ObjectAllocs &operator=(ObjectAllocs &&) = default; - - JITTargetAddress RemoteCodeAddr = 0; - JITTargetAddress RemoteRODataAddr = 0; - JITTargetAddress RemoteRWDataAddr = 0; - std::vector CodeAllocs, RODataAllocs, RWDataAllocs; - }; - - RemoteRTDyldMemoryManager(OrcRemoteTargetClient &Client, - ResourceIdMgr::ResourceId Id) - : Client(Client), Id(Id) { - LLVM_DEBUG(dbgs() << "Created remote allocator " << Id << "\n"); - } - - // Maps all allocations in Allocs to aligned blocks - void mapAllocsToRemoteAddrs(RuntimeDyld &Dyld, std::vector &Allocs, - JITTargetAddress NextAddr) { - for (auto &Alloc : Allocs) { - NextAddr = alignTo(NextAddr, Alloc.getAlign()); - Dyld.mapSectionAddress(Alloc.getLocalAddress(), NextAddr); - LLVM_DEBUG( - dbgs() << " " << static_cast(Alloc.getLocalAddress()) - << " -> " << format("0x%016" PRIx64, NextAddr) << "\n"); - Alloc.setRemoteAddress(NextAddr); - - // Only advance NextAddr if it was non-null to begin with, - // otherwise leave it as null. - if (NextAddr) - NextAddr += Alloc.getSize(); - } - } - - // Copies data for each alloc in the list, then set permissions on the - // segment. - bool copyAndProtect(const std::vector &Allocs, - JITTargetAddress RemoteSegmentAddr, - unsigned Permissions) { - if (RemoteSegmentAddr) { - assert(!Allocs.empty() && "No sections in allocated segment"); - - for (auto &Alloc : Allocs) { - LLVM_DEBUG(dbgs() << " copying section: " - << static_cast(Alloc.getLocalAddress()) - << " -> " - << format("0x%016" PRIx64, Alloc.getRemoteAddress()) - << " (" << Alloc.getSize() << " bytes)\n";); - - if (Client.writeMem(Alloc.getRemoteAddress(), Alloc.getLocalAddress(), - Alloc.getSize())) - return true; - } - - LLVM_DEBUG(dbgs() << " setting " - << (Permissions & sys::Memory::MF_READ ? 'R' : '-') - << (Permissions & sys::Memory::MF_WRITE ? 'W' : '-') - << (Permissions & sys::Memory::MF_EXEC ? 'X' : '-') - << " permissions on block: " - << format("0x%016" PRIx64, RemoteSegmentAddr) - << "\n"); - if (Client.setProtections(Id, RemoteSegmentAddr, Permissions)) - return true; - } - return false; - } - - OrcRemoteTargetClient &Client; - ResourceIdMgr::ResourceId Id; - std::vector Unmapped; - std::vector Unfinalized; - - struct EHFrame { - JITTargetAddress Addr; - uint64_t Size; - }; - std::vector UnfinalizedEHFrames; - std::vector RegisteredEHFrames; - }; - - class RPCMMAlloc : public jitlink::JITLinkMemoryManager::Allocation { - using AllocationMap = DenseMap; - using FinalizeContinuation = - jitlink::JITLinkMemoryManager::Allocation::FinalizeContinuation; - using ProtectionFlags = sys::Memory::ProtectionFlags; - using SegmentsRequestMap = - DenseMap; - - RPCMMAlloc(OrcRemoteTargetClient &Client, ResourceIdMgr::ResourceId Id) - : Client(Client), Id(Id) {} - - public: - static Expected> - 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(MM); - } - - MutableArrayRef getWorkingMemory(ProtectionFlags Seg) override { - assert(HostSegBlocks.count(Seg) && "No allocation for segment"); - return {static_cast(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(TargetPageSize))) - return make_error("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::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(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("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(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(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 - 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("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> - 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: - RemoteIndirectStubsManager(OrcRemoteTargetClient &Client, - ResourceIdMgr::ResourceId Id) - : Client(Client), Id(Id) {} - - ~RemoteIndirectStubsManager() override { - Client.destroyIndirectStubsManager(Id); - } - - Error createStub(StringRef StubName, JITTargetAddress StubAddr, - JITSymbolFlags StubFlags) override { - if (auto Err = reserveStubs(1)) - return Err; - - return createStubInternal(StubName, StubAddr, StubFlags); - } - - Error createStubs(const StubInitsMap &StubInits) override { - if (auto Err = reserveStubs(StubInits.size())) - return Err; - - for (auto &Entry : StubInits) - if (auto Err = createStubInternal(Entry.first(), Entry.second.first, - Entry.second.second)) - return Err; - - return Error::success(); - } - - JITEvaluatedSymbol findStub(StringRef Name, bool ExportedStubsOnly) override { - auto I = StubIndexes.find(Name); - if (I == StubIndexes.end()) - return nullptr; - auto Key = I->second.first; - auto Flags = I->second.second; - auto StubSymbol = JITEvaluatedSymbol(getStubAddr(Key), Flags); - if (ExportedStubsOnly && !StubSymbol.getFlags().isExported()) - return nullptr; - return StubSymbol; - } - - JITEvaluatedSymbol findPointer(StringRef Name) override { - auto I = StubIndexes.find(Name); - if (I == StubIndexes.end()) - return nullptr; - auto Key = I->second.first; - auto Flags = I->second.second; - return JITEvaluatedSymbol(getPtrAddr(Key), Flags); - } - - Error updatePointer(StringRef Name, JITTargetAddress NewAddr) override { - auto I = StubIndexes.find(Name); - assert(I != StubIndexes.end() && "No stub pointer for symbol"); - auto Key = I->second.first; - return Client.writePointer(getPtrAddr(Key), NewAddr); - } - - private: - struct RemoteIndirectStubsInfo { - JITTargetAddress StubBase; - JITTargetAddress PtrBase; - unsigned NumStubs; - }; - - using StubKey = std::pair; - - Error reserveStubs(unsigned NumStubs) { - if (NumStubs <= FreeStubs.size()) - return Error::success(); - - unsigned NewStubsRequired = NumStubs - FreeStubs.size(); - JITTargetAddress StubBase; - JITTargetAddress PtrBase; - unsigned NumStubsEmitted; - - if (auto StubInfoOrErr = Client.emitIndirectStubs(Id, NewStubsRequired)) - std::tie(StubBase, PtrBase, NumStubsEmitted) = *StubInfoOrErr; - else - return StubInfoOrErr.takeError(); - - unsigned NewBlockId = RemoteIndirectStubsInfos.size(); - RemoteIndirectStubsInfos.push_back({StubBase, PtrBase, NumStubsEmitted}); - - for (unsigned I = 0; I < NumStubsEmitted; ++I) - FreeStubs.push_back(std::make_pair(NewBlockId, I)); - - return Error::success(); - } - - Error createStubInternal(StringRef StubName, JITTargetAddress InitAddr, - JITSymbolFlags StubFlags) { - auto Key = FreeStubs.back(); - FreeStubs.pop_back(); - StubIndexes[StubName] = std::make_pair(Key, StubFlags); - return Client.writePointer(getPtrAddr(Key), InitAddr); - } - - JITTargetAddress getStubAddr(StubKey K) { - assert(RemoteIndirectStubsInfos[K.first].StubBase != 0 && - "Missing stub address"); - return RemoteIndirectStubsInfos[K.first].StubBase + - K.second * Client.getIndirectStubSize(); - } - - JITTargetAddress getPtrAddr(StubKey K) { - assert(RemoteIndirectStubsInfos[K.first].PtrBase != 0 && - "Missing pointer address"); - return RemoteIndirectStubsInfos[K.first].PtrBase + - K.second * Client.getPointerSize(); - } - - OrcRemoteTargetClient &Client; - ResourceIdMgr::ResourceId Id; - std::vector RemoteIndirectStubsInfos; - std::vector FreeStubs; - StringMap> StubIndexes; - }; - - class RemoteTrampolinePool : public TrampolinePool { - public: - RemoteTrampolinePool(OrcRemoteTargetClient &Client) : Client(Client) {} - - private: - Error grow() override { - JITTargetAddress BlockAddr = 0; - uint32_t NumTrampolines = 0; - if (auto TrampolineInfoOrErr = Client.emitTrampolineBlock()) - std::tie(BlockAddr, NumTrampolines) = *TrampolineInfoOrErr; - else - return TrampolineInfoOrErr.takeError(); - - uint32_t TrampolineSize = Client.getTrampolineSize(); - for (unsigned I = 0; I < NumTrampolines; ++I) - AvailableTrampolines.push_back(BlockAddr + (I * TrampolineSize)); - - return Error::success(); - } - - OrcRemoteTargetClient &Client; - }; - - /// Remote compile callback manager. - class RemoteCompileCallbackManager : public JITCompileCallbackManager { - public: - RemoteCompileCallbackManager(OrcRemoteTargetClient &Client, - ExecutionSession &ES, - JITTargetAddress ErrorHandlerAddress) - : JITCompileCallbackManager( - std::make_unique(Client), ES, - ErrorHandlerAddress) {} - }; - - /// Create an OrcRemoteTargetClient. - /// 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> - Create(shared::RawByteChannel &Channel, ExecutionSession &ES) { - Error Err = Error::success(); - auto Client = std::unique_ptr( - new OrcRemoteTargetClient(Channel, ES, Err)); - if (Err) - return std::move(Err); - return std::move(Client); - } - - /// Call the int(void) function at the given address in the target and return - /// its result. - Expected callIntVoid(JITTargetAddress Addr) { - LLVM_DEBUG(dbgs() << "Calling int(*)(void) " - << format("0x%016" PRIx64, Addr) << "\n"); - return callB(Addr); - } - - /// Call the int(int) function at the given address in the target and return - /// its result. - Expected callIntInt(JITTargetAddress Addr, int Arg) { - LLVM_DEBUG(dbgs() << "Calling int(*)(int) " << format("0x%016" PRIx64, Addr) - << "\n"); - return callB(Addr, Arg); - } - - /// Call the int(int, char*[]) function at the given address in the target and - /// return its result. - Expected callMain(JITTargetAddress Addr, - const std::vector &Args) { - LLVM_DEBUG(dbgs() << "Calling int(*)(int, char*[]) " - << format("0x%016" PRIx64, Addr) << "\n"); - return callB(Addr, Args); - } - - /// Call the void() function at the given address in the target and wait for - /// it to finish. - Error callVoidVoid(JITTargetAddress Addr) { - LLVM_DEBUG(dbgs() << "Calling void(*)(void) " - << format("0x%016" PRIx64, Addr) << "\n"); - return callB(Addr); - } - - /// Create an RCMemoryManager which will allocate its memory on the remote - /// target. - Expected> - createRemoteMemoryManager() { - auto Id = AllocatorIds.getNext(); - if (auto Err = callB(Id)) - return std::move(Err); - return std::unique_ptr( - 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> - createRemoteJITLinkMemoryManager() { - auto Id = AllocatorIds.getNext(); - if (auto Err = callB(Id)) - return std::move(Err); - LLVM_DEBUG(dbgs() << "Created remote allocator " << Id << "\n"); - return std::unique_ptr( - new RemoteJITLinkMemoryManager(*this, Id)); - } - - /// Create an RCIndirectStubsManager that will allocate stubs on the remote - /// target. - Expected> - createIndirectStubsManager() { - auto Id = IndirectStubOwnerIds.getNext(); - if (auto Err = callB(Id)) - return std::move(Err); - return std::make_unique(*this, Id); - } - - Expected - enableCompileCallbacks(JITTargetAddress ErrorHandlerAddress) { - assert(!CallbackManager && "CallbackManager already obtained"); - - // Emit the resolver block on the JIT server. - if (auto Err = callB()) - return std::move(Err); - - // Create the callback manager. - CallbackManager.emplace(*this, ES, ErrorHandlerAddress); - RemoteCompileCallbackManager &Mgr = *CallbackManager; - return Mgr; - } - - /// Search for symbols in the remote process. Note: This should be used by - /// symbol resolvers *after* they've searched the local symbol table in the - /// JIT stack. - Expected getSymbolAddress(StringRef Name) { - return callB(Name); - } - - /// Get the triple for the remote target. - const std::string &getTargetTriple() const { return RemoteTargetTriple; } - - Error terminateSession() { return callB(); } - -private: - OrcRemoteTargetClient(shared::RawByteChannel &Channel, ExecutionSession &ES, - Error &Err) - : shared::SingleThreadedRPCEndpoint(Channel, - true), - ES(ES) { - ErrorAsOutParameter EAO(&Err); - - addHandler( - [this](JITTargetAddress Addr) -> JITTargetAddress { - if (CallbackManager) - return CallbackManager->executeCompileCallback(Addr); - return 0; - }); - - if (auto RIOrErr = callB()) { - std::tie(RemoteTargetTriple, RemotePointerSize, RemotePageSize, - RemoteTrampolineSize, RemoteIndirectStubSize) = *RIOrErr; - Err = Error::success(); - } else - Err = RIOrErr.takeError(); - } - - void deregisterEHFrames(JITTargetAddress Addr, uint32_t Size) { - if (auto Err = callB(Addr, Size)) - ES.reportError(std::move(Err)); - } - - void destroyRemoteAllocator(ResourceIdMgr::ResourceId Id) { - if (auto Err = callB(Id)) { - // FIXME: This will be triggered by a removeModuleSet call: Propagate - // error return up through that. - llvm_unreachable("Failed to destroy remote allocator."); - AllocatorIds.release(Id); - } - } - - void destroyIndirectStubsManager(ResourceIdMgr::ResourceId Id) { - IndirectStubOwnerIds.release(Id); - if (auto Err = callB(Id)) - ES.reportError(std::move(Err)); - } - - Expected> - emitIndirectStubs(ResourceIdMgr::ResourceId Id, uint32_t NumStubsRequired) { - return callB(Id, NumStubsRequired); - } - - Expected> emitTrampolineBlock() { - return callB(); - } - - uint32_t getIndirectStubSize() const { return RemoteIndirectStubSize; } - uint32_t getPageSize() const { return RemotePageSize; } - uint32_t getPointerSize() const { return RemotePointerSize; } - - uint32_t getTrampolineSize() const { return RemoteTrampolineSize; } - - Expected> readMem(char *Dst, JITTargetAddress Src, - uint64_t Size) { - return callB(Src, Size); - } - - Error registerEHFrames(JITTargetAddress &RAddr, uint32_t Size) { - // FIXME: Duplicate error and report it via ReportError too? - return callB(RAddr, Size); - } - - JITTargetAddress reserveMem(ResourceIdMgr::ResourceId Id, uint64_t Size, - uint32_t Align) { - if (auto AddrOrErr = callB(Id, Size, Align)) - return *AddrOrErr; - else { - ES.reportError(AddrOrErr.takeError()); - return 0; - } - } - - bool setProtections(ResourceIdMgr::ResourceId Id, - JITTargetAddress RemoteSegAddr, unsigned ProtFlags) { - if (auto Err = callB(Id, RemoteSegAddr, ProtFlags)) { - ES.reportError(std::move(Err)); - return true; - } else - return false; - } - - bool writeMem(JITTargetAddress Addr, const char *Src, uint64_t Size) { - if (auto Err = callB(DirectBufferWriter(Src, Addr, Size))) { - ES.reportError(std::move(Err)); - return true; - } else - return false; - } - - Error writePointer(JITTargetAddress Addr, JITTargetAddress PtrVal) { - return callB(Addr, PtrVal); - } - - static Error doNothing() { return Error::success(); } - - ExecutionSession &ES; - std::function ReportError; - std::string RemoteTargetTriple; - uint32_t RemotePointerSize = 0; - uint32_t RemotePageSize = 0; - uint32_t RemoteTrampolineSize = 0; - uint32_t RemoteIndirectStubSize = 0; - ResourceIdMgr AllocatorIds, IndirectStubOwnerIds; - Optional CallbackManager; -}; - -} // end namespace remote -} // end namespace orc -} // end namespace llvm - -#undef DEBUG_TYPE - -#endif // LLVM_EXECUTIONENGINE_ORC_ORCREMOTETARGETCLIENT_H diff --git a/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h b/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h deleted file mode 100644 index 367bfb369191..000000000000 --- a/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h +++ /dev/null @@ -1,386 +0,0 @@ -//===- OrcRemoteTargetRPCAPI.h - Orc Remote-target RPC API ------*- 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 -// -//===----------------------------------------------------------------------===// -// -// This file defines the Orc remote-target RPC API. It should not be used -// directly, but is used by the RemoteTargetClient and RemoteTargetServer -// classes. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_EXECUTIONENGINE_ORC_ORCREMOTETARGETRPCAPI_H -#define LLVM_EXECUTIONENGINE_ORC_ORCREMOTETARGETRPCAPI_H - -#include "llvm/ExecutionEngine/JITSymbol.h" -#include "llvm/ExecutionEngine/Orc/Shared/RPCUtils.h" -#include "llvm/ExecutionEngine/Orc/Shared/RawByteChannel.h" - -namespace llvm { -namespace orc { - -namespace remote { - -/// Template error for missing resources. -template -class ResourceNotFound - : public ErrorInfo> { -public: - static char ID; - - ResourceNotFound(ResourceIdT ResourceId, - std::string ResourceDescription = "") - : ResourceId(std::move(ResourceId)), - ResourceDescription(std::move(ResourceDescription)) {} - - std::error_code convertToErrorCode() const override { - return orcError(OrcErrorCode::UnknownResourceHandle); - } - - void log(raw_ostream &OS) const override { - OS << (ResourceDescription.empty() - ? "Remote resource with id " - : ResourceDescription) - << " " << ResourceId << " not found"; - } - -private: - ResourceIdT ResourceId; - std::string ResourceDescription; -}; - -template -char ResourceNotFound::ID = 0; - -class DirectBufferWriter { -public: - DirectBufferWriter() = default; - DirectBufferWriter(const char *Src, JITTargetAddress Dst, uint64_t Size) - : Src(Src), Dst(Dst), Size(Size) {} - - const char *getSrc() const { return Src; } - JITTargetAddress getDst() const { return Dst; } - uint64_t getSize() const { return Size; } - -private: - const char *Src; - JITTargetAddress Dst; - uint64_t Size; -}; - -} // end namespace remote - -namespace shared { - -template <> class SerializationTypeName { -public: - static const char *getName() { return "JITSymbolFlags"; } -}; - -template -class SerializationTraits { -public: - - static Error serialize(ChannelT &C, const JITSymbolFlags &Flags) { - return serializeSeq(C, Flags.getRawFlagsValue(), Flags.getTargetFlags()); - } - - static Error deserialize(ChannelT &C, JITSymbolFlags &Flags) { - JITSymbolFlags::UnderlyingType JITFlags; - JITSymbolFlags::TargetFlagsType TargetFlags; - if (auto Err = deserializeSeq(C, JITFlags, TargetFlags)) - return Err; - Flags = JITSymbolFlags(static_cast(JITFlags), - TargetFlags); - return Error::success(); - } -}; - -template <> class SerializationTypeName { -public: - static const char *getName() { return "DirectBufferWriter"; } -}; - -template -class SerializationTraits< - ChannelT, remote::DirectBufferWriter, remote::DirectBufferWriter, - std::enable_if_t::value>> { -public: - static Error serialize(ChannelT &C, const remote::DirectBufferWriter &DBW) { - if (auto EC = serializeSeq(C, DBW.getDst())) - return EC; - if (auto EC = serializeSeq(C, DBW.getSize())) - return EC; - return C.appendBytes(DBW.getSrc(), DBW.getSize()); - } - - static Error deserialize(ChannelT &C, remote::DirectBufferWriter &DBW) { - JITTargetAddress Dst; - if (auto EC = deserializeSeq(C, Dst)) - return EC; - uint64_t Size; - if (auto EC = deserializeSeq(C, Size)) - return EC; - char *Addr = reinterpret_cast(static_cast(Dst)); - - DBW = remote::DirectBufferWriter(nullptr, Dst, Size); - - return C.readBytes(Addr, Size); - } -}; - -} // end namespace shared - -namespace remote { - -class ResourceIdMgr { -public: - using ResourceId = uint64_t; - static const ResourceId InvalidId = ~0U; - - ResourceIdMgr() = default; - explicit ResourceIdMgr(ResourceId FirstValidId) - : NextId(std::move(FirstValidId)) {} - - ResourceId getNext() { - if (!FreeIds.empty()) { - ResourceId I = FreeIds.back(); - FreeIds.pop_back(); - return I; - } - assert(NextId + 1 != ~0ULL && "All ids allocated"); - return NextId++; - } - - void release(ResourceId I) { FreeIds.push_back(I); } - -private: - ResourceId NextId = 1; - std::vector FreeIds; -}; - -/// Registers EH frames on the remote. -namespace eh { - - /// Registers EH frames on the remote. -class RegisterEHFrames - : public shared::RPCFunction { -public: - static const char *getName() { return "RegisterEHFrames"; } -}; - - /// Deregisters EH frames on the remote. -class DeregisterEHFrames - : public shared::RPCFunction { -public: - static const char *getName() { return "DeregisterEHFrames"; } -}; - -} // end namespace eh - -/// RPC functions for executing remote code. -namespace exec { - - /// Call an 'int32_t()'-type function on the remote, returns the called - /// function's return value. -class CallIntVoid - : public shared::RPCFunction { -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 { -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 shared::RPCFunction 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 shared::RPCFunction { -public: - static const char *getName() { return "CallVoidVoid"; } -}; - -} // end namespace exec - -/// RPC functions for remote memory management / inspection / modification. -namespace mem { - - /// Creates a memory allocator on the remote. -class CreateRemoteAllocator - : public shared::RPCFunction { -public: - static const char *getName() { return "CreateRemoteAllocator"; } -}; - - /// Destroys a remote allocator, freeing any memory allocated by it. -class DestroyRemoteAllocator - : public shared::RPCFunction { -public: - static const char *getName() { return "DestroyRemoteAllocator"; } -}; - - /// Read a remote memory block. -class ReadMem - : public shared::RPCFunction< - ReadMem, std::vector(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 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 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 shared::RPCFunction { -public: - static const char *getName() { return "WriteMem"; } -}; - - /// Write to a remote pointer. -class WritePtr - : public shared::RPCFunction { -public: - static const char *getName() { return "WritePtr"; } -}; - -} // end namespace mem - -/// RPC functions for remote stub and trampoline management. -namespace stubs { - - /// Creates an indirect stub owner on the remote. -class CreateIndirectStubsOwner - : public shared::RPCFunction { -public: - static const char *getName() { return "CreateIndirectStubsOwner"; } -}; - - /// RPC function for destroying an indirect stubs owner. -class DestroyIndirectStubsOwner - : public shared::RPCFunction { -public: - static const char *getName() { return "DestroyIndirectStubsOwner"; } -}; - - /// EmitIndirectStubs result is (StubsBase, PtrsBase, NumStubsEmitted). -class EmitIndirectStubs - : public shared::RPCFunction< - EmitIndirectStubs, - std::tuple( - 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 shared::RPCFunction { -public: - static const char *getName() { return "EmitResolverBlock"; } -}; - - /// EmitTrampolineBlock result is (BlockAddr, NumTrampolines). -class EmitTrampolineBlock - : public shared::RPCFunction()> { -public: - static const char *getName() { return "EmitTrampolineBlock"; } -}; - -} // end namespace stubs - -/// Miscelaneous RPC functions for dealing with remotes. -namespace utils { - - /// GetRemoteInfo result is (Triple, PointerSize, PageSize, TrampolineSize, - /// IndirectStubsSize). -class GetRemoteInfo - : public shared::RPCFunction< - GetRemoteInfo, - std::tuple()> { -public: - static const char *getName() { return "GetRemoteInfo"; } -}; - - /// Get the address of a remote symbol. -class GetSymbolAddress - : public shared::RPCFunction { -public: - static const char *getName() { return "GetSymbolAddress"; } -}; - - /// Request that the host execute a compile callback. -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 shared::RPCFunction { -public: - static const char *getName() { return "TerminateSession"; } -}; - -} // namespace utils - -class OrcRemoteTargetRPCAPI - : public shared::SingleThreadedRPCEndpoint { -public: - // FIXME: Remove constructors once MSVC supports synthesizing move-ops. - OrcRemoteTargetRPCAPI(shared::RawByteChannel &C) - : shared::SingleThreadedRPCEndpoint(C, true) {} -}; - -} // end namespace remote - -} // end namespace orc -} // end namespace llvm - -#endif // LLVM_EXECUTIONENGINE_ORC_ORCREMOTETARGETRPCAPI_H diff --git a/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h b/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h deleted file mode 100644 index ce9bf064303d..000000000000 --- a/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h +++ /dev/null @@ -1,464 +0,0 @@ -//===- OrcRemoteTargetServer.h - Orc Remote-target 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 -// -//===----------------------------------------------------------------------===// -// -// This file defines the OrcRemoteTargetServer class. It can be used to build a -// JIT server that can execute code sent from an OrcRemoteTargetClient. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_EXECUTIONENGINE_ORC_ORCREMOTETARGETSERVER_H -#define LLVM_EXECUTIONENGINE_ORC_ORCREMOTETARGETSERVER_H - -#include "llvm/ExecutionEngine/JITSymbol.h" -#include "llvm/ExecutionEngine/Orc/IndirectionUtils.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" -#include "llvm/Support/Host.h" -#include "llvm/Support/Memory.h" -#include "llvm/Support/Process.h" -#include "llvm/Support/raw_ostream.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define DEBUG_TYPE "orc-remote" - -namespace llvm { -namespace orc { -namespace remote { - -template -class OrcRemoteTargetServer - : public shared::SingleThreadedRPCEndpoint { -public: - using SymbolLookupFtor = - std::function; - - using EHFrameRegistrationFtor = - std::function; - - OrcRemoteTargetServer(ChannelT &Channel, SymbolLookupFtor SymbolLookup, - EHFrameRegistrationFtor EHFramesRegister, - EHFrameRegistrationFtor EHFramesDeregister) - : shared::SingleThreadedRPCEndpoint(Channel, - true), - SymbolLookup(std::move(SymbolLookup)), - EHFramesRegister(std::move(EHFramesRegister)), - EHFramesDeregister(std::move(EHFramesDeregister)) { - using ThisT = std::remove_reference_t; - addHandler(*this, &ThisT::handleCallIntVoid); - addHandler(*this, &ThisT::handleCallIntInt); - addHandler(*this, &ThisT::handleCallMain); - addHandler(*this, &ThisT::handleCallVoidVoid); - addHandler(*this, - &ThisT::handleCreateRemoteAllocator); - addHandler( - *this, &ThisT::handleDestroyRemoteAllocator); - addHandler(*this, &ThisT::handleReadMem); - addHandler(*this, &ThisT::handleReserveMem); - addHandler(*this, &ThisT::handleSetProtections); - addHandler(*this, &ThisT::handleWriteMem); - addHandler(*this, &ThisT::handleWritePtr); - addHandler(*this, &ThisT::handleRegisterEHFrames); - addHandler(*this, &ThisT::handleDeregisterEHFrames); - addHandler( - *this, &ThisT::handleCreateIndirectStubsOwner); - addHandler( - *this, &ThisT::handleDestroyIndirectStubsOwner); - addHandler(*this, - &ThisT::handleEmitIndirectStubs); - addHandler(*this, - &ThisT::handleEmitResolverBlock); - addHandler(*this, - &ThisT::handleEmitTrampolineBlock); - addHandler(*this, &ThisT::handleGetSymbolAddress); - addHandler(*this, &ThisT::handleGetRemoteInfo); - addHandler(*this, &ThisT::handleTerminateSession); - } - - // FIXME: Remove move/copy ops once MSVC supports synthesizing move ops. - OrcRemoteTargetServer(const OrcRemoteTargetServer &) = delete; - OrcRemoteTargetServer &operator=(const OrcRemoteTargetServer &) = delete; - - OrcRemoteTargetServer(OrcRemoteTargetServer &&Other) = default; - OrcRemoteTargetServer &operator=(OrcRemoteTargetServer &&) = delete; - - Expected requestCompile(JITTargetAddress TrampolineAddr) { - return callB(TrampolineAddr); - } - - bool receivedTerminate() const { return TerminateFlag; } - -private: - struct Allocator { - Allocator() = default; - Allocator(Allocator &&Other) : Allocs(std::move(Other.Allocs)) {} - - Allocator &operator=(Allocator &&Other) { - Allocs = std::move(Other.Allocs); - return *this; - } - - ~Allocator() { - for (auto &Alloc : Allocs) - sys::Memory::releaseMappedMemory(Alloc.second); - } - - Error allocate(void *&Addr, size_t Size, uint32_t Align) { - std::error_code EC; - sys::MemoryBlock MB = sys::Memory::allocateMappedMemory( - Size, nullptr, sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC); - if (EC) - return errorCodeToError(EC); - - Addr = MB.base(); - assert(Allocs.find(MB.base()) == Allocs.end() && "Duplicate alloc"); - Allocs[MB.base()] = std::move(MB); - return Error::success(); - } - - Error setProtections(void *block, unsigned Flags) { - auto I = Allocs.find(block); - if (I == Allocs.end()) - return errorCodeToError(orcError(OrcErrorCode::RemoteMProtectAddrUnrecognized)); - return errorCodeToError( - sys::Memory::protectMappedMemory(I->second, Flags)); - } - - private: - std::map Allocs; - }; - - static Error doNothing() { return Error::success(); } - - static JITTargetAddress reenter(void *JITTargetAddr, void *TrampolineAddr) { - auto T = static_cast(JITTargetAddr); - auto AddrOrErr = T->requestCompile(static_cast( - reinterpret_cast(TrampolineAddr))); - // FIXME: Allow customizable failure substitution functions. - assert(AddrOrErr && "Compile request failed"); - return *AddrOrErr; - } - - Expected handleCallIntVoid(JITTargetAddress Addr) { - using IntVoidFnTy = int (*)(); - - IntVoidFnTy Fn = - reinterpret_cast(static_cast(Addr)); - - LLVM_DEBUG(dbgs() << " Calling " << format("0x%016x", Addr) << "\n"); - int Result = Fn(); - LLVM_DEBUG(dbgs() << " Result = " << Result << "\n"); - - return Result; - } - - Expected handleCallIntInt(JITTargetAddress Addr, int Arg) { - using IntIntFnTy = int (*)(int); - - IntIntFnTy Fn = reinterpret_cast(static_cast(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 handleCallMain(JITTargetAddress Addr, - std::vector Args) { - using MainFnTy = int (*)(int, const char *[]); - - MainFnTy Fn = reinterpret_cast(static_cast(Addr)); - int ArgC = Args.size() + 1; - int Idx = 1; - std::unique_ptr ArgV(new const char *[ArgC + 1]); - ArgV[0] = ""; - for (auto &Arg : Args) - ArgV[Idx++] = Arg.c_str(); - ArgV[ArgC] = 0; - LLVM_DEBUG(for (int Idx = 0; Idx < ArgC; ++Idx) { - llvm::dbgs() << "Arg " << Idx << ": " << ArgV[Idx] << "\n"; - }); - - LLVM_DEBUG(dbgs() << " Calling " << format("0x%016x", Addr) << "\n"); - int Result = Fn(ArgC, ArgV.get()); - LLVM_DEBUG(dbgs() << " Result = " << Result << "\n"); - - return Result; - } - - Error handleCallVoidVoid(JITTargetAddress Addr) { - using VoidVoidFnTy = void (*)(); - - VoidVoidFnTy Fn = - reinterpret_cast(static_cast(Addr)); - - LLVM_DEBUG(dbgs() << " Calling " << format("0x%016x", Addr) << "\n"); - Fn(); - LLVM_DEBUG(dbgs() << " Complete.\n"); - - return Error::success(); - } - - Error handleCreateRemoteAllocator(ResourceIdMgr::ResourceId Id) { - auto I = Allocators.find(Id); - if (I != Allocators.end()) - return errorCodeToError( - orcError(OrcErrorCode::RemoteAllocatorIdAlreadyInUse)); - LLVM_DEBUG(dbgs() << " Created allocator " << Id << "\n"); - Allocators[Id] = Allocator(); - return Error::success(); - } - - Error handleCreateIndirectStubsOwner(ResourceIdMgr::ResourceId Id) { - auto I = IndirectStubsOwners.find(Id); - if (I != IndirectStubsOwners.end()) - return errorCodeToError( - orcError(OrcErrorCode::RemoteIndirectStubsOwnerIdAlreadyInUse)); - LLVM_DEBUG(dbgs() << " Create indirect stubs owner " << Id << "\n"); - IndirectStubsOwners[Id] = ISBlockOwnerList(); - return Error::success(); - } - - Error handleDeregisterEHFrames(JITTargetAddress TAddr, uint32_t Size) { - uint8_t *Addr = reinterpret_cast(static_cast(TAddr)); - LLVM_DEBUG(dbgs() << " Registering EH frames at " - << format("0x%016x", TAddr) << ", Size = " << Size - << " bytes\n"); - EHFramesDeregister(Addr, Size); - return Error::success(); - } - - Error handleDestroyRemoteAllocator(ResourceIdMgr::ResourceId Id) { - auto I = Allocators.find(Id); - if (I == Allocators.end()) - return errorCodeToError( - orcError(OrcErrorCode::RemoteAllocatorDoesNotExist)); - Allocators.erase(I); - LLVM_DEBUG(dbgs() << " Destroyed allocator " << Id << "\n"); - return Error::success(); - } - - Error handleDestroyIndirectStubsOwner(ResourceIdMgr::ResourceId Id) { - auto I = IndirectStubsOwners.find(Id); - if (I == IndirectStubsOwners.end()) - return errorCodeToError( - orcError(OrcErrorCode::RemoteIndirectStubsOwnerDoesNotExist)); - IndirectStubsOwners.erase(I); - return Error::success(); - } - - Expected> - handleEmitIndirectStubs(ResourceIdMgr::ResourceId Id, - uint32_t NumStubsRequired) { - LLVM_DEBUG(dbgs() << " ISMgr " << Id << " request " << NumStubsRequired - << " stubs.\n"); - - auto StubOwnerItr = IndirectStubsOwners.find(Id); - if (StubOwnerItr == IndirectStubsOwners.end()) - return errorCodeToError( - orcError(OrcErrorCode::RemoteIndirectStubsOwnerDoesNotExist)); - - auto IS = LocalIndirectStubsInfo::create( - NumStubsRequired, sys::Process::getPageSizeEstimate()); - if (!IS) - return IS.takeError(); - - JITTargetAddress StubsBase = pointerToJITTargetAddress(IS->getStub(0)); - JITTargetAddress PtrsBase = pointerToJITTargetAddress(IS->getPtr(0)); - uint32_t NumStubsEmitted = IS->getNumStubs(); - - auto &BlockList = StubOwnerItr->second; - BlockList.push_back(std::move(*IS)); - - return std::make_tuple(StubsBase, PtrsBase, NumStubsEmitted); - } - - Error handleEmitResolverBlock() { - std::error_code EC; - ResolverBlock = sys::OwningMemoryBlock(sys::Memory::allocateMappedMemory( - TargetT::ResolverCodeSize, nullptr, - sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC)); - if (EC) - return errorCodeToError(EC); - - TargetT::writeResolverCode(static_cast(ResolverBlock.base()), - pointerToJITTargetAddress(ResolverBlock.base()), - pointerToJITTargetAddress(&reenter), - pointerToJITTargetAddress(this)); - - return errorCodeToError(sys::Memory::protectMappedMemory( - ResolverBlock.getMemoryBlock(), - sys::Memory::MF_READ | sys::Memory::MF_EXEC)); - } - - Expected> handleEmitTrampolineBlock() { - std::error_code EC; - auto TrampolineBlock = - sys::OwningMemoryBlock(sys::Memory::allocateMappedMemory( - sys::Process::getPageSizeEstimate(), nullptr, - sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC)); - if (EC) - return errorCodeToError(EC); - - uint32_t NumTrampolines = - (sys::Process::getPageSizeEstimate() - TargetT::PointerSize) / - TargetT::TrampolineSize; - - char *TrampolineMem = static_cast(TrampolineBlock.base()); - TargetT::writeTrampolines( - TrampolineMem, pointerToJITTargetAddress(TrampolineMem), - pointerToJITTargetAddress(ResolverBlock.base()), NumTrampolines); - - EC = sys::Memory::protectMappedMemory(TrampolineBlock.getMemoryBlock(), - sys::Memory::MF_READ | - sys::Memory::MF_EXEC); - - TrampolineBlocks.push_back(std::move(TrampolineBlock)); - - return std::make_tuple(pointerToJITTargetAddress(TrampolineMem), - NumTrampolines); - } - - Expected handleGetSymbolAddress(const std::string &Name) { - JITTargetAddress Addr = SymbolLookup(Name); - LLVM_DEBUG(dbgs() << " Symbol '" << Name - << "' = " << format("0x%016x", Addr) << "\n"); - return Addr; - } - - Expected> - handleGetRemoteInfo() { - std::string ProcessTriple = sys::getProcessTriple(); - uint32_t PointerSize = TargetT::PointerSize; - uint32_t PageSize = sys::Process::getPageSizeEstimate(); - uint32_t TrampolineSize = TargetT::TrampolineSize; - uint32_t IndirectStubSize = TargetT::StubSize; - LLVM_DEBUG(dbgs() << " Remote info:\n" - << " triple = '" << ProcessTriple << "'\n" - << " pointer size = " << PointerSize << "\n" - << " page size = " << PageSize << "\n" - << " trampoline size = " << TrampolineSize << "\n" - << " indirect stub size = " << IndirectStubSize - << "\n"); - return std::make_tuple(ProcessTriple, PointerSize, PageSize, TrampolineSize, - IndirectStubSize); - } - - Expected> handleReadMem(JITTargetAddress RSrc, - uint64_t Size) { - uint8_t *Src = reinterpret_cast(static_cast(RSrc)); - - LLVM_DEBUG(dbgs() << " Reading " << Size << " bytes from " - << format("0x%016x", RSrc) << "\n"); - - std::vector Buffer; - Buffer.resize(Size); - for (uint8_t *P = Src; Size != 0; --Size) - Buffer.push_back(*P++); - - return Buffer; - } - - Error handleRegisterEHFrames(JITTargetAddress TAddr, uint32_t Size) { - uint8_t *Addr = reinterpret_cast(static_cast(TAddr)); - LLVM_DEBUG(dbgs() << " Registering EH frames at " - << format("0x%016x", TAddr) << ", Size = " << Size - << " bytes\n"); - EHFramesRegister(Addr, Size); - return Error::success(); - } - - Expected handleReserveMem(ResourceIdMgr::ResourceId Id, - uint64_t Size, uint32_t Align) { - auto I = Allocators.find(Id); - if (I == Allocators.end()) - return errorCodeToError( - orcError(OrcErrorCode::RemoteAllocatorDoesNotExist)); - auto &Allocator = I->second; - void *LocalAllocAddr = nullptr; - if (auto Err = Allocator.allocate(LocalAllocAddr, Size, Align)) - return std::move(Err); - - LLVM_DEBUG(dbgs() << " Allocator " << Id << " reserved " << LocalAllocAddr - << " (" << Size << " bytes, alignment " << Align - << ")\n"); - - JITTargetAddress AllocAddr = static_cast( - reinterpret_cast(LocalAllocAddr)); - - return AllocAddr; - } - - Error handleSetProtections(ResourceIdMgr::ResourceId Id, - JITTargetAddress Addr, uint32_t Flags) { - auto I = Allocators.find(Id); - if (I == Allocators.end()) - return errorCodeToError( - orcError(OrcErrorCode::RemoteAllocatorDoesNotExist)); - auto &Allocator = I->second; - void *LocalAddr = reinterpret_cast(static_cast(Addr)); - LLVM_DEBUG(dbgs() << " Allocator " << Id << " set permissions on " - << LocalAddr << " to " - << (Flags & sys::Memory::MF_READ ? 'R' : '-') - << (Flags & sys::Memory::MF_WRITE ? 'W' : '-') - << (Flags & sys::Memory::MF_EXEC ? 'X' : '-') << "\n"); - return Allocator.setProtections(LocalAddr, Flags); - } - - Error handleTerminateSession() { - TerminateFlag = true; - return Error::success(); - } - - Error handleWriteMem(DirectBufferWriter DBW) { - LLVM_DEBUG(dbgs() << " Writing " << DBW.getSize() << " bytes to " - << format("0x%016x", DBW.getDst()) << "\n"); - return Error::success(); - } - - Error handleWritePtr(JITTargetAddress Addr, JITTargetAddress PtrVal) { - LLVM_DEBUG(dbgs() << " Writing pointer *" << format("0x%016x", Addr) - << " = " << format("0x%016x", PtrVal) << "\n"); - uintptr_t *Ptr = - reinterpret_cast(static_cast(Addr)); - *Ptr = static_cast(PtrVal); - return Error::success(); - } - - SymbolLookupFtor SymbolLookup; - EHFrameRegistrationFtor EHFramesRegister, EHFramesDeregister; - std::map Allocators; - using ISBlockOwnerList = std::vector>; - std::map IndirectStubsOwners; - sys::OwningMemoryBlock ResolverBlock; - std::vector TrampolineBlocks; - bool TerminateFlag = false; -}; - -} // end namespace remote -} // end namespace orc -} // end namespace llvm - -#undef DEBUG_TYPE - -#endif // LLVM_EXECUTIONENGINE_ORC_ORCREMOTETARGETSERVER_H