LCOV - code coverage report
Current view: top level - include/llvm/ExecutionEngine/Orc - OrcRemoteTargetClient.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 105 194 54.1 %
Date: 2018-10-20 13:21:21 Functions: 21 40 52.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- OrcRemoteTargetClient.h - Orc Remote-target Client -------*- C++ -*-===//
       2             : //
       3             : //                     The LLVM Compiler Infrastructure
       4             : //
       5             : // This file is distributed under the University of Illinois Open Source
       6             : // License. See LICENSE.TXT for details.
       7             : //
       8             : //===----------------------------------------------------------------------===//
       9             : //
      10             : // This file defines the OrcRemoteTargetClient class and helpers. This class
      11             : // can be used to communicate over an RawByteChannel with an
      12             : // OrcRemoteTargetServer instance to support remote-JITing.
      13             : //
      14             : //===----------------------------------------------------------------------===//
      15             : 
      16             : #ifndef LLVM_EXECUTIONENGINE_ORC_ORCREMOTETARGETCLIENT_H
      17             : #define LLVM_EXECUTIONENGINE_ORC_ORCREMOTETARGETCLIENT_H
      18             : 
      19             : #include "llvm/ADT/Optional.h"
      20             : #include "llvm/ADT/STLExtras.h"
      21             : #include "llvm/ADT/StringMap.h"
      22             : #include "llvm/ADT/StringRef.h"
      23             : #include "llvm/ExecutionEngine/JITSymbol.h"
      24             : #include "llvm/ExecutionEngine/Orc/IndirectionUtils.h"
      25             : #include "llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h"
      26             : #include "llvm/ExecutionEngine/RuntimeDyld.h"
      27             : #include "llvm/Support/Debug.h"
      28             : #include "llvm/Support/Error.h"
      29             : #include "llvm/Support/ErrorHandling.h"
      30             : #include "llvm/Support/Format.h"
      31             : #include "llvm/Support/MathExtras.h"
      32             : #include "llvm/Support/Memory.h"
      33             : #include "llvm/Support/raw_ostream.h"
      34             : #include <algorithm>
      35             : #include <cassert>
      36             : #include <cstdint>
      37             : #include <memory>
      38             : #include <string>
      39             : #include <tuple>
      40             : #include <utility>
      41             : #include <vector>
      42             : 
      43             : #define DEBUG_TYPE "orc-remote"
      44             : 
      45             : namespace llvm {
      46             : namespace orc {
      47             : namespace remote {
      48             : 
      49             : /// This class provides utilities (including memory manager, indirect stubs
      50             : /// manager, and compile callback manager types) that support remote JITing
      51             : /// in ORC.
      52             : ///
      53             : /// Each of the utility classes talks to a JIT server (an instance of the
      54             : /// OrcRemoteTargetServer class) via an RPC system (see RPCUtils.h) to carry out
      55             : /// its actions.
      56             : class OrcRemoteTargetClient
      57             :     : public rpc::SingleThreadedRPCEndpoint<rpc::RawByteChannel> {
      58             : public:
      59             :   /// Remote-mapped RuntimeDyld-compatible memory manager.
      60             :   class RemoteRTDyldMemoryManager : public RuntimeDyld::MemoryManager {
      61             :     friend class OrcRemoteTargetClient;
      62             : 
      63             :   public:
      64          48 :     ~RemoteRTDyldMemoryManager() {
      65          24 :       Client.destroyRemoteAllocator(Id);
      66             :       LLVM_DEBUG(dbgs() << "Destroyed remote allocator " << Id << "\n");
      67          48 :     }
      68          24 : 
      69             :     RemoteRTDyldMemoryManager(const RemoteRTDyldMemoryManager &) = delete;
      70             :     RemoteRTDyldMemoryManager &
      71          24 :     operator=(const RemoteRTDyldMemoryManager &) = delete;
      72          24 :     RemoteRTDyldMemoryManager(RemoteRTDyldMemoryManager &&) = default;
      73          24 :     RemoteRTDyldMemoryManager &operator=(RemoteRTDyldMemoryManager &&) = delete;
      74             : 
      75          24 :     uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
      76             :                                  unsigned SectionID,
      77             :                                  StringRef SectionName) override {
      78             :       Unmapped.back().CodeAllocs.emplace_back(Size, Alignment);
      79             :       uint8_t *Alloc = reinterpret_cast<uint8_t *>(
      80             :           Unmapped.back().CodeAllocs.back().getLocalAddress());
      81             :       LLVM_DEBUG(dbgs() << "Allocator " << Id << " allocated code for "
      82             :                         << SectionName << ": " << Alloc << " (" << Size
      83          30 :                         << " bytes, alignment " << Alignment << ")\n");
      84             :       return Alloc;
      85             :     }
      86          30 : 
      87             :     uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
      88             :                                  unsigned SectionID, StringRef SectionName,
      89             :                                  bool IsReadOnly) override {
      90             :       if (IsReadOnly) {
      91             :         Unmapped.back().RODataAllocs.emplace_back(Size, Alignment);
      92          30 :         uint8_t *Alloc = reinterpret_cast<uint8_t *>(
      93             :             Unmapped.back().RODataAllocs.back().getLocalAddress());
      94             :         LLVM_DEBUG(dbgs() << "Allocator " << Id << " allocated ro-data for "
      95          34 :                           << SectionName << ": " << Alloc << " (" << Size
      96             :                           << " bytes, alignment " << Alignment << ")\n");
      97             :         return Alloc;
      98          34 :       } // else...
      99          16 : 
     100             :       Unmapped.back().RWDataAllocs.emplace_back(Size, Alignment);
     101             :       uint8_t *Alloc = reinterpret_cast<uint8_t *>(
     102             :           Unmapped.back().RWDataAllocs.back().getLocalAddress());
     103             :       LLVM_DEBUG(dbgs() << "Allocator " << Id << " allocated rw-data for "
     104             :                         << SectionName << ": " << Alloc << " (" << Size
     105          16 :                         << " bytes, alignment " << Alignment << ")\n");
     106             :       return Alloc;
     107             :     }
     108          18 : 
     109             :     void reserveAllocationSpace(uintptr_t CodeSize, uint32_t CodeAlign,
     110             :                                 uintptr_t RODataSize, uint32_t RODataAlign,
     111             :                                 uintptr_t RWDataSize,
     112             :                                 uint32_t RWDataAlign) override {
     113             :       Unmapped.push_back(ObjectAllocs());
     114          18 : 
     115             :       LLVM_DEBUG(dbgs() << "Allocator " << Id << " reserved:\n");
     116             : 
     117          30 :       if (CodeSize != 0) {
     118             :         Unmapped.back().RemoteCodeAddr =
     119             :             Client.reserveMem(Id, CodeSize, CodeAlign);
     120             : 
     121          30 :         LLVM_DEBUG(dbgs() << "  code: "
     122             :                           << format("0x%016x", Unmapped.back().RemoteCodeAddr)
     123             :                           << " (" << CodeSize << " bytes, alignment "
     124             :                           << CodeAlign << ")\n");
     125          30 :       }
     126          30 : 
     127          60 :       if (RODataSize != 0) {
     128             :         Unmapped.back().RemoteRODataAddr =
     129             :             Client.reserveMem(Id, RODataSize, RODataAlign);
     130             : 
     131             :         LLVM_DEBUG(dbgs() << "  ro-data: "
     132             :                           << format("0x%016x", Unmapped.back().RemoteRODataAddr)
     133             :                           << " (" << RODataSize << " bytes, alignment "
     134             :                           << RODataAlign << ")\n");
     135          30 :       }
     136          14 : 
     137          28 :       if (RWDataSize != 0) {
     138             :         Unmapped.back().RemoteRWDataAddr =
     139             :             Client.reserveMem(Id, RWDataSize, RWDataAlign);
     140             : 
     141             :         LLVM_DEBUG(dbgs() << "  rw-data: "
     142             :                           << format("0x%016x", Unmapped.back().RemoteRWDataAddr)
     143             :                           << " (" << RWDataSize << " bytes, alignment "
     144             :                           << RWDataAlign << ")\n");
     145          30 :       }
     146          14 :     }
     147          28 : 
     148             :     bool needsToReserveAllocationSpace() override { return true; }
     149             : 
     150             :     void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr,
     151             :                           size_t Size) override {
     152             :       UnfinalizedEHFrames.push_back({LoadAddr, Size});
     153             :     }
     154          30 : 
     155             :     void deregisterEHFrames() override {
     156          30 :       for (auto &Frame : RegisteredEHFrames) {
     157             :         // FIXME: Add error poll.
     158           4 :         Client.deregisterEHFrames(Frame.Addr, Frame.Size);
     159             :       }
     160           4 :     }
     161           4 : 
     162             :     void notifyObjectLoaded(RuntimeDyld &Dyld,
     163          27 :                             const object::ObjectFile &Obj) override {
     164          28 :       LLVM_DEBUG(dbgs() << "Allocator " << Id << " applied mappings:\n");
     165             :       for (auto &ObjAllocs : Unmapped) {
     166           1 :         mapAllocsToRemoteAddrs(Dyld, ObjAllocs.CodeAllocs,
     167             :                                ObjAllocs.RemoteCodeAddr);
     168          27 :         mapAllocsToRemoteAddrs(Dyld, ObjAllocs.RODataAllocs,
     169             :                                ObjAllocs.RemoteRODataAddr);
     170          30 :         mapAllocsToRemoteAddrs(Dyld, ObjAllocs.RWDataAllocs,
     171             :                                ObjAllocs.RemoteRWDataAddr);
     172             :         Unfinalized.push_back(std::move(ObjAllocs));
     173          60 :       }
     174          30 :       Unmapped.clear();
     175             :     }
     176          30 : 
     177             :     bool finalizeMemory(std::string *ErrMsg = nullptr) override {
     178          30 :       LLVM_DEBUG(dbgs() << "Allocator " << Id << " finalizing:\n");
     179             : 
     180          30 :       for (auto &ObjAllocs : Unfinalized) {
     181             :         if (copyAndProtect(ObjAllocs.CodeAllocs, ObjAllocs.RemoteCodeAddr,
     182             :                            sys::Memory::MF_READ | sys::Memory::MF_EXEC))
     183          30 :           return true;
     184             : 
     185          37 :         if (copyAndProtect(ObjAllocs.RODataAllocs, ObjAllocs.RemoteRODataAddr,
     186             :                            sys::Memory::MF_READ))
     187             :           return true;
     188          67 : 
     189          30 :         if (copyAndProtect(ObjAllocs.RWDataAllocs, ObjAllocs.RemoteRWDataAddr,
     190             :                            sys::Memory::MF_READ | sys::Memory::MF_WRITE))
     191             :           return true;
     192             :       }
     193          30 :       Unfinalized.clear();
     194             : 
     195             :       for (auto &EHFrame : UnfinalizedEHFrames) {
     196             :         if (auto Err = Client.registerEHFrames(EHFrame.Addr, EHFrame.Size)) {
     197          30 :           // FIXME: Replace this once finalizeMemory can return an Error.
     198             :           handleAllErrors(std::move(Err), [&](ErrorInfoBase &EIB) {
     199             :             if (ErrMsg) {
     200             :               raw_string_ostream ErrOut(*ErrMsg);
     201             :               EIB.log(ErrOut);
     202             :             }
     203          41 :           });
     204           4 :           return false;
     205             :         }
     206           0 :       }
     207             :       RegisteredEHFrames = std::move(UnfinalizedEHFrames);
     208             :       UnfinalizedEHFrames = {};
     209             : 
     210             :       return false;
     211             :     }
     212             : 
     213             :   private:
     214             :     class Alloc {
     215          37 :     public:
     216             :       Alloc(uint64_t Size, unsigned Align)
     217             :           : Size(Size), Align(Align), Contents(new char[Size + Align - 1]) {}
     218          37 : 
     219             :       Alloc(const Alloc &) = delete;
     220             :       Alloc &operator=(const Alloc &) = delete;
     221             :       Alloc(Alloc &&) = default;
     222          70 :       Alloc &operator=(Alloc &&) = default;
     223             : 
     224             :       uint64_t getSize() const { return Size; }
     225          64 : 
     226             :       unsigned getAlign() const { return Align; }
     227             : 
     228             :       char *getLocalAddress() const {
     229          12 :         uintptr_t LocalAddr = reinterpret_cast<uintptr_t>(Contents.get());
     230             :         LocalAddr = alignTo(LocalAddr, Align);
     231             :         return reinterpret_cast<char *>(LocalAddr);
     232           0 :       }
     233             : 
     234           0 :       void setRemoteAddress(JITTargetAddress RemoteAddr) {
     235             :         this->RemoteAddr = RemoteAddr;
     236             :       }
     237          64 : 
     238          98 :       JITTargetAddress getRemoteAddress() const { return RemoteAddr; }
     239          34 : 
     240             :     private:
     241             :       uint64_t Size;
     242           0 :       unsigned Align;
     243          64 :       std::unique_ptr<char[]> Contents;
     244           0 :       JITTargetAddress RemoteAddr = 0;
     245             :     };
     246           0 : 
     247             :     struct ObjectAllocs {
     248             :       ObjectAllocs() = default;
     249             :       ObjectAllocs(const ObjectAllocs &) = delete;
     250             :       ObjectAllocs &operator=(const ObjectAllocs &) = delete;
     251             :       ObjectAllocs(ObjectAllocs &&) = default;
     252             :       ObjectAllocs &operator=(ObjectAllocs &&) = default;
     253             : 
     254             :       JITTargetAddress RemoteCodeAddr = 0;
     255             :       JITTargetAddress RemoteRODataAddr = 0;
     256             :       JITTargetAddress RemoteRWDataAddr = 0;
     257             :       std::vector<Alloc> CodeAllocs, RODataAllocs, RWDataAllocs;
     258             :     };
     259         136 : 
     260             :     RemoteRTDyldMemoryManager(OrcRemoteTargetClient &Client,
     261             :                               ResourceIdMgr::ResourceId Id)
     262             :         : Client(Client), Id(Id) {
     263             :       LLVM_DEBUG(dbgs() << "Created remote allocator " << Id << "\n");
     264             :     }
     265             : 
     266             :     // Maps all allocations in Allocs to aligned blocks
     267             :     void mapAllocsToRemoteAddrs(RuntimeDyld &Dyld, std::vector<Alloc> &Allocs,
     268             :                                 JITTargetAddress NextAddr) {
     269             :       for (auto &Alloc : Allocs) {
     270          24 :         NextAddr = alignTo(NextAddr, Alloc.getAlign());
     271             :         Dyld.mapSectionAddress(Alloc.getLocalAddress(), NextAddr);
     272             :         LLVM_DEBUG(dbgs() << "     "
     273             :                           << static_cast<void *>(Alloc.getLocalAddress())
     274             :                           << " -> " << format("0x%016x", NextAddr) << "\n");
     275          90 :         Alloc.setRemoteAddress(NextAddr);
     276             : 
     277         154 :         // Only advance NextAddr if it was non-null to begin with,
     278          64 :         // otherwise leave it as null.
     279          64 :         if (NextAddr)
     280             :           NextAddr += Alloc.getSize();
     281             :       }
     282             :     }
     283             : 
     284             :     // Copies data for each alloc in the list, then set permissions on the
     285             :     // segment.
     286             :     bool copyAndProtect(const std::vector<Alloc> &Allocs,
     287          64 :                         JITTargetAddress RemoteSegmentAddr,
     288          64 :                         unsigned Permissions) {
     289             :       if (RemoteSegmentAddr) {
     290          90 :         assert(!Allocs.empty() && "No sections in allocated segment");
     291             : 
     292             :         for (auto &Alloc : Allocs) {
     293             :           LLVM_DEBUG(dbgs() << "  copying section: "
     294          90 :                             << static_cast<void *>(Alloc.getLocalAddress())
     295             :                             << " -> "
     296             :                             << format("0x%016x", Alloc.getRemoteAddress())
     297          90 :                             << " (" << Alloc.getSize() << " bytes)\n";);
     298             : 
     299             :           if (Client.writeMem(Alloc.getRemoteAddress(), Alloc.getLocalAddress(),
     300         122 :                               Alloc.getSize()))
     301             :             return true;
     302             :         }
     303             : 
     304             :         LLVM_DEBUG(dbgs() << "  setting "
     305             :                           << (Permissions & sys::Memory::MF_READ ? 'R' : '-')
     306             :                           << (Permissions & sys::Memory::MF_WRITE ? 'W' : '-')
     307         128 :                           << (Permissions & sys::Memory::MF_EXEC ? 'X' : '-')
     308             :                           << " permissions on block: "
     309             :                           << format("0x%016x", RemoteSegmentAddr) << "\n");
     310             :         if (Client.setProtections(Id, RemoteSegmentAddr, Permissions))
     311             :           return true;
     312             :       }
     313             :       return false;
     314             :     }
     315             : 
     316             :     OrcRemoteTargetClient &Client;
     317             :     ResourceIdMgr::ResourceId Id;
     318          58 :     std::vector<ObjectAllocs> Unmapped;
     319           0 :     std::vector<ObjectAllocs> Unfinalized;
     320             : 
     321             :     struct EHFrame {
     322             :       JITTargetAddress Addr;
     323             :       uint64_t Size;
     324             :     };
     325             :     std::vector<EHFrame> UnfinalizedEHFrames;
     326             :     std::vector<EHFrame> RegisteredEHFrames;
     327             :   };
     328             : 
     329             :   /// Remote indirect stubs manager.
     330             :   class RemoteIndirectStubsManager : public IndirectStubsManager {
     331             :   public:
     332             :     RemoteIndirectStubsManager(OrcRemoteTargetClient &Client,
     333             :                                ResourceIdMgr::ResourceId Id)
     334             :         : Client(Client), Id(Id) {}
     335             : 
     336             :     ~RemoteIndirectStubsManager() override {
     337             :       Client.destroyIndirectStubsManager(Id);
     338             :     }
     339             : 
     340             :     Error createStub(StringRef StubName, JITTargetAddress StubAddr,
     341             :                      JITSymbolFlags StubFlags) override {
     342             :       if (auto Err = reserveStubs(1))
     343             :         return Err;
     344           0 : 
     345           0 :       return createStubInternal(StubName, StubAddr, StubFlags);
     346           0 :     }
     347           0 : 
     348             :     Error createStubs(const StubInitsMap &StubInits) override {
     349           0 :       if (auto Err = reserveStubs(StubInits.size()))
     350           0 :         return Err;
     351           0 : 
     352           0 :       for (auto &Entry : StubInits)
     353             :         if (auto Err = createStubInternal(Entry.first(), Entry.second.first,
     354           0 :                                           Entry.second.second))
     355             :           return Err;
     356           0 : 
     357             :       return Error::success();
     358             :     }
     359           0 : 
     360             :     JITEvaluatedSymbol findStub(StringRef Name, bool ExportedStubsOnly) override {
     361             :       auto I = StubIndexes.find(Name);
     362           0 :       if (I == StubIndexes.end())
     363           0 :         return nullptr;
     364             :       auto Key = I->second.first;
     365             :       auto Flags = I->second.second;
     366           0 :       auto StubSymbol = JITEvaluatedSymbol(getStubAddr(Key), Flags);
     367           0 :       if (ExportedStubsOnly && !StubSymbol.getFlags().isExported())
     368           0 :         return nullptr;
     369             :       return StubSymbol;
     370             :     }
     371             : 
     372             :     JITEvaluatedSymbol findPointer(StringRef Name) override {
     373             :       auto I = StubIndexes.find(Name);
     374           0 :       if (I == StubIndexes.end())
     375           0 :         return nullptr;
     376           0 :       auto Key = I->second.first;
     377             :       auto Flags = I->second.second;
     378           0 :       return JITEvaluatedSymbol(getPtrAddr(Key), Flags);
     379           0 :     }
     380             : 
     381           0 :     Error updatePointer(StringRef Name, JITTargetAddress NewAddr) override {
     382             :       auto I = StubIndexes.find(Name);
     383           0 :       assert(I != StubIndexes.end() && "No stub pointer for symbol");
     384             :       auto Key = I->second.first;
     385             :       return Client.writePointer(getPtrAddr(Key), NewAddr);
     386           0 :     }
     387           0 : 
     388           0 :   private:
     389             :     struct RemoteIndirectStubsInfo {
     390           0 :       JITTargetAddress StubBase;
     391           0 :       JITTargetAddress PtrBase;
     392           0 :       unsigned NumStubs;
     393             :     };
     394             : 
     395           0 :     using StubKey = std::pair<uint16_t, uint16_t>;
     396           0 : 
     397             :     Error reserveStubs(unsigned NumStubs) {
     398           0 :       if (NumStubs <= FreeStubs.size())
     399           0 :         return Error::success();
     400             : 
     401             :       unsigned NewStubsRequired = NumStubs - FreeStubs.size();
     402             :       JITTargetAddress StubBase;
     403             :       JITTargetAddress PtrBase;
     404             :       unsigned NumStubsEmitted;
     405             : 
     406             :       if (auto StubInfoOrErr = Client.emitIndirectStubs(Id, NewStubsRequired))
     407             :         std::tie(StubBase, PtrBase, NumStubsEmitted) = *StubInfoOrErr;
     408             :       else
     409             :         return StubInfoOrErr.takeError();
     410             : 
     411           0 :       unsigned NewBlockId = RemoteIndirectStubsInfos.size();
     412           0 :       RemoteIndirectStubsInfos.push_back({StubBase, PtrBase, NumStubsEmitted});
     413             : 
     414             :       for (unsigned I = 0; I < NumStubsEmitted; ++I)
     415           0 :         FreeStubs.push_back(std::make_pair(NewBlockId, I));
     416             : 
     417             :       return Error::success();
     418             :     }
     419             : 
     420           0 :     Error createStubInternal(StringRef StubName, JITTargetAddress InitAddr,
     421             :                              JITSymbolFlags StubFlags) {
     422             :       auto Key = FreeStubs.back();
     423             :       FreeStubs.pop_back();
     424             :       StubIndexes[StubName] = std::make_pair(Key, StubFlags);
     425           0 :       return Client.writePointer(getPtrAddr(Key), InitAddr);
     426           0 :     }
     427             : 
     428           0 :     JITTargetAddress getStubAddr(StubKey K) {
     429           0 :       assert(RemoteIndirectStubsInfos[K.first].StubBase != 0 &&
     430             :              "Missing stub address");
     431             :       return RemoteIndirectStubsInfos[K.first].StubBase +
     432             :              K.second * Client.getIndirectStubSize();
     433             :     }
     434           0 : 
     435             :     JITTargetAddress getPtrAddr(StubKey K) {
     436           0 :       assert(RemoteIndirectStubsInfos[K.first].PtrBase != 0 &&
     437             :              "Missing pointer address");
     438           0 :       return RemoteIndirectStubsInfos[K.first].PtrBase +
     439           0 :              K.second * Client.getPointerSize();
     440             :     }
     441             : 
     442             :     OrcRemoteTargetClient &Client;
     443             :     ResourceIdMgr::ResourceId Id;
     444             :     std::vector<RemoteIndirectStubsInfo> RemoteIndirectStubsInfos;
     445           0 :     std::vector<StubKey> FreeStubs;
     446           0 :     StringMap<std::pair<StubKey, JITSymbolFlags>> StubIndexes;
     447             :   };
     448             : 
     449             :   class RemoteTrampolinePool : public TrampolinePool {
     450             :   public:
     451             :     RemoteTrampolinePool(OrcRemoteTargetClient &Client) : Client(Client) {}
     452           0 : 
     453           0 :     Expected<JITTargetAddress> getTrampoline() override {
     454             :       std::lock_guard<std::mutex> Lock(RTPMutex);
     455             :       if (AvailableTrampolines.empty()) {
     456             :         if (auto Err = grow())
     457             :           return std::move(Err);
     458             :       }
     459             :       assert(!AvailableTrampolines.empty() && "Failed to grow trampoline pool");
     460             :       auto TrampolineAddr = AvailableTrampolines.back();
     461             :       AvailableTrampolines.pop_back();
     462             :       return TrampolineAddr;
     463             :     }
     464             : 
     465             :   private:
     466             :     Error grow() {
     467           0 :       JITTargetAddress BlockAddr = 0;
     468           0 :       uint32_t NumTrampolines = 0;
     469           0 :       if (auto TrampolineInfoOrErr = Client.emitTrampolineBlock())
     470           0 :         std::tie(BlockAddr, NumTrampolines) = *TrampolineInfoOrErr;
     471             :       else
     472             :         return TrampolineInfoOrErr.takeError();
     473             : 
     474           0 :       uint32_t TrampolineSize = Client.getTrampolineSize();
     475             :       for (unsigned I = 0; I < NumTrampolines; ++I)
     476             :         this->AvailableTrampolines.push_back(BlockAddr + (I * TrampolineSize));
     477             : 
     478             :       return Error::success();
     479             :     }
     480           0 : 
     481           0 :     std::mutex RTPMutex;
     482           0 :     OrcRemoteTargetClient &Client;
     483           0 :     std::vector<JITTargetAddress> AvailableTrampolines;
     484             :   };
     485             : 
     486             :   /// Remote compile callback manager.
     487             :   class RemoteCompileCallbackManager : public JITCompileCallbackManager {
     488           0 :   public:
     489           0 :     RemoteCompileCallbackManager(OrcRemoteTargetClient &Client,
     490           0 :                                  ExecutionSession &ES,
     491             :                                  JITTargetAddress ErrorHandlerAddress)
     492             :         : JITCompileCallbackManager(
     493             :               llvm::make_unique<RemoteTrampolinePool>(Client), ES,
     494             :               ErrorHandlerAddress) {}
     495             :   };
     496             : 
     497             :   /// Create an OrcRemoteTargetClient.
     498             :   /// Channel is the ChannelT instance to communicate on. It is assumed that
     499             :   /// the channel is ready to be read from and written to.
     500             :   static Expected<std::unique_ptr<OrcRemoteTargetClient>>
     501             :   Create(rpc::RawByteChannel &Channel, ExecutionSession &ES) {
     502             :     Error Err = Error::success();
     503             :     auto Client = std::unique_ptr<OrcRemoteTargetClient>(
     504             :         new OrcRemoteTargetClient(Channel, ES, Err));
     505             :     if (Err)
     506             :       return std::move(Err);
     507             :     return std::move(Client);
     508             :   }
     509             : 
     510             :   /// Call the int(void) function at the given address in the target and return
     511             :   /// its result.
     512             :   Expected<int> callIntVoid(JITTargetAddress Addr) {
     513             :     LLVM_DEBUG(dbgs() << "Calling int(*)(void) " << format("0x%016x", Addr)
     514             :                       << "\n");
     515          24 :     return callB<exec::CallIntVoid>(Addr);
     516             :   }
     517             : 
     518          48 :   /// Call the int(int, char*[]) function at the given address in the target and
     519          24 :   /// return its result.
     520             :   Expected<int> callMain(JITTargetAddress Addr,
     521             :                          const std::vector<std::string> &Args) {
     522             :     LLVM_DEBUG(dbgs() << "Calling int(*)(int, char*[]) "
     523             :                       << format("0x%016x", Addr) << "\n");
     524             :     return callB<exec::CallMain>(Addr, Args);
     525             :   }
     526             : 
     527             :   /// Call the void() function at the given address in the target and wait for
     528             :   /// it to finish.
     529          24 :   Error callVoidVoid(JITTargetAddress Addr) {
     530             :     LLVM_DEBUG(dbgs() << "Calling void(*)(void) " << format("0x%016x", Addr)
     531             :                       << "\n");
     532             :     return callB<exec::CallVoidVoid>(Addr);
     533             :   }
     534             : 
     535             :   /// Create an RCMemoryManager which will allocate its memory on the remote
     536             :   /// target.
     537             :   Expected<std::unique_ptr<RemoteRTDyldMemoryManager>>
     538             :   createRemoteMemoryManager() {
     539             :     auto Id = AllocatorIds.getNext();
     540             :     if (auto Err = callB<mem::CreateRemoteAllocator>(Id))
     541             :       return std::move(Err);
     542             :     return std::unique_ptr<RemoteRTDyldMemoryManager>(
     543             :         new RemoteRTDyldMemoryManager(*this, Id));
     544             :   }
     545             : 
     546             :   /// Create an RCIndirectStubsManager that will allocate stubs on the remote
     547             :   /// target.
     548             :   Expected<std::unique_ptr<RemoteIndirectStubsManager>>
     549             :   createIndirectStubsManager() {
     550             :     auto Id = IndirectStubOwnerIds.getNext();
     551             :     if (auto Err = callB<stubs::CreateIndirectStubsOwner>(Id))
     552          24 :       return std::move(Err);
     553          24 :     return llvm::make_unique<RemoteIndirectStubsManager>(*this, Id);
     554          48 :   }
     555             : 
     556             :   Expected<RemoteCompileCallbackManager &>
     557          24 :   enableCompileCallbacks(JITTargetAddress ErrorHandlerAddress) {
     558             :     assert(!CallbackManager && "CallbackManager already obtained");
     559             : 
     560             :     // Emit the resolver block on the JIT server.
     561             :     if (auto Err = callB<stubs::EmitResolverBlock>())
     562             :       return std::move(Err);
     563             : 
     564             :     // Create the callback manager.
     565             :     CallbackManager.emplace(*this, ES, ErrorHandlerAddress);
     566             :     RemoteCompileCallbackManager &Mgr = *CallbackManager;
     567             :     return Mgr;
     568             :   }
     569             : 
     570             :   /// Search for symbols in the remote process. Note: This should be used by
     571             :   /// symbol resolvers *after* they've searched the local symbol table in the
     572             :   /// JIT stack.
     573             :   Expected<JITTargetAddress> getSymbolAddress(StringRef Name) {
     574             :     return callB<utils::GetSymbolAddress>(Name);
     575             :   }
     576             : 
     577             :   /// Get the triple for the remote target.
     578             :   const std::string &getTargetTriple() const { return RemoteTargetTriple; }
     579             : 
     580             :   Error terminateSession() { return callB<utils::TerminateSession>(); }
     581             : 
     582             : private:
     583             :   OrcRemoteTargetClient(rpc::RawByteChannel &Channel, ExecutionSession &ES,
     584             :                         Error &Err)
     585             :       : rpc::SingleThreadedRPCEndpoint<rpc::RawByteChannel>(Channel, true),
     586             :         ES(ES) {
     587             :     ErrorAsOutParameter EAO(&Err);
     588             : 
     589             :     addHandler<utils::RequestCompile>(
     590             :         [this](JITTargetAddress Addr) -> JITTargetAddress {
     591             :           if (CallbackManager)
     592             :             return CallbackManager->executeCompileCallback(Addr);
     593             :           return 0;
     594          24 :         });
     595             : 
     596             :     if (auto RIOrErr = callB<utils::GetRemoteInfo>()) {
     597          24 :       std::tie(RemoteTargetTriple, RemotePointerSize, RemotePageSize,
     598             :                RemoteTrampolineSize, RemoteIndirectStubSize) = *RIOrErr;
     599          24 :       Err = Error::success();
     600          24 :     } else
     601             :       Err = RIOrErr.takeError();
     602             :   }
     603          24 : 
     604             :   void deregisterEHFrames(JITTargetAddress Addr, uint32_t Size) {
     605           0 :     if (auto Err = callB<eh::RegisterEHFrames>(Addr, Size))
     606           0 :       ES.reportError(std::move(Err));
     607             :   }
     608             : 
     609             :   void destroyRemoteAllocator(ResourceIdMgr::ResourceId Id) {
     610          48 :     if (auto Err = callB<mem::DestroyRemoteAllocator>(Id)) {
     611          24 :       // FIXME: This will be triggered by a removeModuleSet call: Propagate
     612          24 :       //        error return up through that.
     613             :       llvm_unreachable("Failed to destroy remote allocator.");
     614             :       AllocatorIds.release(Id);
     615             :     }
     616          24 :   }
     617             : 
     618           1 :   void destroyIndirectStubsManager(ResourceIdMgr::ResourceId Id) {
     619           2 :     IndirectStubOwnerIds.release(Id);
     620           0 :     if (auto Err = callB<stubs::DestroyIndirectStubsOwner>(Id))
     621           1 :       ES.reportError(std::move(Err));
     622             :   }
     623          24 : 
     624          48 :   Expected<std::tuple<JITTargetAddress, JITTargetAddress, uint32_t>>
     625             :   emitIndirectStubs(ResourceIdMgr::ResourceId Id, uint32_t NumStubsRequired) {
     626             :     return callB<stubs::EmitIndirectStubs>(Id, NumStubsRequired);
     627           0 :   }
     628             : 
     629             :   Expected<std::tuple<JITTargetAddress, uint32_t>> emitTrampolineBlock() {
     630          24 :     return callB<stubs::EmitTrampolineBlock>();
     631             :   }
     632           0 : 
     633           0 :   uint32_t getIndirectStubSize() const { return RemoteIndirectStubSize; }
     634           0 :   uint32_t getPageSize() const { return RemotePageSize; }
     635           0 :   uint32_t getPointerSize() const { return RemotePointerSize; }
     636           0 : 
     637             :   uint32_t getTrampolineSize() const { return RemoteTrampolineSize; }
     638             : 
     639             :   Expected<std::vector<uint8_t>> readMem(char *Dst, JITTargetAddress Src,
     640           0 :                                          uint64_t Size) {
     641             :     return callB<mem::ReadMem>(Src, Size);
     642             :   }
     643             : 
     644           0 :   Error registerEHFrames(JITTargetAddress &RAddr, uint32_t Size) {
     645             :     // FIXME: Duplicate error and report it via ReportError too?
     646             :     return callB<eh::RegisterEHFrames>(RAddr, Size);
     647           0 :   }
     648             : 
     649           0 :   JITTargetAddress reserveMem(ResourceIdMgr::ResourceId Id, uint64_t Size,
     650             :                               uint32_t Align) {
     651           0 :     if (auto AddrOrErr = callB<mem::ReserveMem>(Id, Size, Align))
     652             :       return *AddrOrErr;
     653             :     else {
     654             :       ES.reportError(AddrOrErr.takeError());
     655             :       return 0;
     656             :     }
     657             :   }
     658             : 
     659             :   bool setProtections(ResourceIdMgr::ResourceId Id,
     660           4 :                       JITTargetAddress RemoteSegAddr, unsigned ProtFlags) {
     661             :     if (auto Err = callB<mem::SetProtections>(Id, RemoteSegAddr, ProtFlags)) {
     662             :       ES.reportError(std::move(Err));
     663          58 :       return true;
     664             :     } else
     665          58 :       return false;
     666          58 :   }
     667             : 
     668           0 :   bool writeMem(JITTargetAddress Addr, const char *Src, uint64_t Size) {
     669           0 :     if (auto Err = callB<mem::WriteMem>(DirectBufferWriter(Src, Addr, Size))) {
     670             :       ES.reportError(std::move(Err));
     671             :       return true;
     672             :     } else
     673          58 :       return false;
     674             :   }
     675         116 : 
     676           0 :   Error writePointer(JITTargetAddress Addr, JITTargetAddress PtrVal) {
     677           0 :     return callB<mem::WritePtr>(Addr, PtrVal);
     678             :   }
     679             : 
     680             :   static Error doNothing() { return Error::success(); }
     681             : 
     682          64 :   ExecutionSession &ES;
     683         128 :   std::function<void(Error)> ReportError;
     684           0 :   std::string RemoteTargetTriple;
     685           0 :   uint32_t RemotePointerSize = 0;
     686             :   uint32_t RemotePageSize = 0;
     687             :   uint32_t RemoteTrampolineSize = 0;
     688             :   uint32_t RemoteIndirectStubSize = 0;
     689             :   ResourceIdMgr AllocatorIds, IndirectStubOwnerIds;
     690             :   Optional<RemoteCompileCallbackManager> CallbackManager;
     691           0 : };
     692             : 
     693             : } // end namespace remote
     694             : } // end namespace orc
     695             : } // end namespace llvm
     696             : 
     697             : #undef DEBUG_TYPE
     698             : 
     699             : #endif // LLVM_EXECUTIONENGINE_ORC_ORCREMOTETARGETCLIENT_H

Generated by: LCOV version 1.13