diff options
Diffstat (limited to 'clang-r353983/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h')
| -rw-r--r-- | clang-r353983/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h | 702 |
1 files changed, 702 insertions, 0 deletions
diff --git a/clang-r353983/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h b/clang-r353983/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h new file mode 100644 index 00000000..8b875b79 --- /dev/null +++ b/clang-r353983/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h @@ -0,0 +1,702 @@ +//===- 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/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 <algorithm> +#include <cassert> +#include <cstdint> +#include <memory> +#include <string> +#include <tuple> +#include <utility> +#include <vector> + +#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 rpc::SingleThreadedRPCEndpoint<rpc::RawByteChannel> { +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<uint8_t *>( + 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<uint8_t *>( + 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<uint8_t *>( + 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<uintptr_t>(Contents.get()); + LocalAddr = alignTo(LocalAddr, Align); + return reinterpret_cast<char *>(LocalAddr); + } + + void setRemoteAddress(JITTargetAddress RemoteAddr) { + this->RemoteAddr = RemoteAddr; + } + + JITTargetAddress getRemoteAddress() const { return RemoteAddr; } + + private: + uint64_t Size; + unsigned Align; + std::unique_ptr<char[]> 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<Alloc> 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<Alloc> &Allocs, + JITTargetAddress NextAddr) { + for (auto &Alloc : Allocs) { + NextAddr = alignTo(NextAddr, Alloc.getAlign()); + Dyld.mapSectionAddress(Alloc.getLocalAddress(), NextAddr); + LLVM_DEBUG( + dbgs() << " " << static_cast<void *>(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<Alloc> &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<void *>(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<ObjectAllocs> Unmapped; + std::vector<ObjectAllocs> Unfinalized; + + struct EHFrame { + JITTargetAddress Addr; + uint64_t Size; + }; + std::vector<EHFrame> UnfinalizedEHFrames; + std::vector<EHFrame> RegisteredEHFrames; + }; + + /// 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<uint16_t, uint16_t>; + + 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<RemoteIndirectStubsInfo> RemoteIndirectStubsInfos; + std::vector<StubKey> FreeStubs; + StringMap<std::pair<StubKey, JITSymbolFlags>> StubIndexes; + }; + + class RemoteTrampolinePool : public TrampolinePool { + 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() { + 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) + this->AvailableTrampolines.push_back(BlockAddr + (I * TrampolineSize)); + + return Error::success(); + } + + std::mutex RTPMutex; + OrcRemoteTargetClient &Client; + std::vector<JITTargetAddress> AvailableTrampolines; + }; + + /// Remote compile callback manager. + class RemoteCompileCallbackManager : public JITCompileCallbackManager { + public: + RemoteCompileCallbackManager(OrcRemoteTargetClient &Client, + ExecutionSession &ES, + JITTargetAddress ErrorHandlerAddress) + : JITCompileCallbackManager( + llvm::make_unique<RemoteTrampolinePool>(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<std::unique_ptr<OrcRemoteTargetClient>> + Create(rpc::RawByteChannel &Channel, ExecutionSession &ES) { + Error Err = Error::success(); + auto Client = std::unique_ptr<OrcRemoteTargetClient>( + 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<int> callIntVoid(JITTargetAddress Addr) { + LLVM_DEBUG(dbgs() << "Calling int(*)(void) " + << format("0x%016" PRIx64, Addr) << "\n"); + return callB<exec::CallIntVoid>(Addr); + } + + /// Call the int(int, char*[]) function at the given address in the target and + /// return its result. + Expected<int> callMain(JITTargetAddress Addr, + const std::vector<std::string> &Args) { + LLVM_DEBUG(dbgs() << "Calling int(*)(int, char*[]) " + << format("0x%016" PRIx64, Addr) << "\n"); + return callB<exec::CallMain>(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<exec::CallVoidVoid>(Addr); + } + + /// Create an RCMemoryManager which will allocate its memory on the remote + /// target. + Expected<std::unique_ptr<RemoteRTDyldMemoryManager>> + createRemoteMemoryManager() { + auto Id = AllocatorIds.getNext(); + if (auto Err = callB<mem::CreateRemoteAllocator>(Id)) + return std::move(Err); + return std::unique_ptr<RemoteRTDyldMemoryManager>( + new RemoteRTDyldMemoryManager(*this, Id)); + } + + /// Create an RCIndirectStubsManager that will allocate stubs on the remote + /// target. + Expected<std::unique_ptr<RemoteIndirectStubsManager>> + createIndirectStubsManager() { + auto Id = IndirectStubOwnerIds.getNext(); + if (auto Err = callB<stubs::CreateIndirectStubsOwner>(Id)) + return std::move(Err); + return llvm::make_unique<RemoteIndirectStubsManager>(*this, Id); + } + + Expected<RemoteCompileCallbackManager &> + enableCompileCallbacks(JITTargetAddress ErrorHandlerAddress) { + assert(!CallbackManager && "CallbackManager already obtained"); + + // Emit the resolver block on the JIT server. + if (auto Err = callB<stubs::EmitResolverBlock>()) + 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<JITTargetAddress> getSymbolAddress(StringRef Name) { + return callB<utils::GetSymbolAddress>(Name); + } + + /// Get the triple for the remote target. + const std::string &getTargetTriple() const { return RemoteTargetTriple; } + + Error terminateSession() { return callB<utils::TerminateSession>(); } + +private: + OrcRemoteTargetClient(rpc::RawByteChannel &Channel, ExecutionSession &ES, + Error &Err) + : rpc::SingleThreadedRPCEndpoint<rpc::RawByteChannel>(Channel, true), + ES(ES) { + ErrorAsOutParameter EAO(&Err); + + addHandler<utils::RequestCompile>( + [this](JITTargetAddress Addr) -> JITTargetAddress { + if (CallbackManager) + return CallbackManager->executeCompileCallback(Addr); + return 0; + }); + + if (auto RIOrErr = callB<utils::GetRemoteInfo>()) { + 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<eh::RegisterEHFrames>(Addr, Size)) + ES.reportError(std::move(Err)); + } + + void destroyRemoteAllocator(ResourceIdMgr::ResourceId Id) { + if (auto Err = callB<mem::DestroyRemoteAllocator>(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<stubs::DestroyIndirectStubsOwner>(Id)) + ES.reportError(std::move(Err)); + } + + Expected<std::tuple<JITTargetAddress, JITTargetAddress, uint32_t>> + emitIndirectStubs(ResourceIdMgr::ResourceId Id, uint32_t NumStubsRequired) { + return callB<stubs::EmitIndirectStubs>(Id, NumStubsRequired); + } + + Expected<std::tuple<JITTargetAddress, uint32_t>> emitTrampolineBlock() { + return callB<stubs::EmitTrampolineBlock>(); + } + + 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<std::vector<uint8_t>> readMem(char *Dst, JITTargetAddress Src, + uint64_t Size) { + return callB<mem::ReadMem>(Src, Size); + } + + Error registerEHFrames(JITTargetAddress &RAddr, uint32_t Size) { + // FIXME: Duplicate error and report it via ReportError too? + return callB<eh::RegisterEHFrames>(RAddr, Size); + } + + JITTargetAddress reserveMem(ResourceIdMgr::ResourceId Id, uint64_t Size, + uint32_t Align) { + if (auto AddrOrErr = callB<mem::ReserveMem>(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<mem::SetProtections>(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<mem::WriteMem>(DirectBufferWriter(Src, Addr, Size))) { + ES.reportError(std::move(Err)); + return true; + } else + return false; + } + + Error writePointer(JITTargetAddress Addr, JITTargetAddress PtrVal) { + return callB<mem::WritePtr>(Addr, PtrVal); + } + + static Error doNothing() { return Error::success(); } + + ExecutionSession &ES; + std::function<void(Error)> ReportError; + std::string RemoteTargetTriple; + uint32_t RemotePointerSize = 0; + uint32_t RemotePageSize = 0; + uint32_t RemoteTrampolineSize = 0; + uint32_t RemoteIndirectStubSize = 0; + ResourceIdMgr AllocatorIds, IndirectStubOwnerIds; + Optional<RemoteCompileCallbackManager> CallbackManager; +}; + +} // end namespace remote +} // end namespace orc +} // end namespace llvm + +#undef DEBUG_TYPE + +#endif // LLVM_EXECUTIONENGINE_ORC_ORCREMOTETARGETCLIENT_H |
