//===- OrcRemoteTargetClient.h - Orc Remote-target Client -------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// 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);
      DEBUG(dbgs() << "Destroyed remote allocator " << Id << "\n");
    }

    RemoteRTDyldMemoryManager(const RemoteRTDyldMemoryManager &) = delete;
    RemoteRTDyldMemoryManager &
    operator=(const RemoteRTDyldMemoryManager &) = delete;
    RemoteRTDyldMemoryManager(RemoteRTDyldMemoryManager &&) = default;
    RemoteRTDyldMemoryManager &
    operator=(RemoteRTDyldMemoryManager &&) = default;

    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());
      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());
        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());
      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());

      DEBUG(dbgs() << "Allocator " << Id << " reserved:\n");

      if (CodeSize != 0) {
        Unmapped.back().RemoteCodeAddr =
            Client.reserveMem(Id, CodeSize, CodeAlign);

        DEBUG(dbgs() << "  code: "
                     << format("0x%016x", Unmapped.back().RemoteCodeAddr)
                     << " (" << CodeSize << " bytes, alignment " << CodeAlign
                     << ")\n");
      }

      if (RODataSize != 0) {
        Unmapped.back().RemoteRODataAddr =
            Client.reserveMem(Id, RODataSize, RODataAlign);

        DEBUG(dbgs() << "  ro-data: "
                     << format("0x%016x", Unmapped.back().RemoteRODataAddr)
                     << " (" << RODataSize << " bytes, alignment "
                     << RODataAlign << ")\n");
      }

      if (RWDataSize != 0) {
        Unmapped.back().RemoteRWDataAddr =
            Client.reserveMem(Id, RWDataSize, RWDataAlign);

        DEBUG(dbgs() << "  rw-data: "
                     << format("0x%016x", 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 {
      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 {
      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) {
      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);
        DEBUG(dbgs() << "     " << static_cast<void *>(Alloc.getLocalAddress())
                     << " -> " << format("0x%016x", 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) {
          DEBUG(dbgs() << "  copying section: "
                       << static_cast<void *>(Alloc.getLocalAddress()) << " -> "
                       << format("0x%016x", Alloc.getRemoteAddress()) << " ("
                       << Alloc.getSize() << " bytes)\n";);

          if (Client.writeMem(Alloc.getRemoteAddress(), Alloc.getLocalAddress(),
                              Alloc.getSize()))
            return true;
        }

        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%016x", 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();
    }

    JITSymbol 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 = JITSymbol(getStubAddr(Key), Flags);
      if (ExportedStubsOnly && !StubSymbol.getFlags().isExported())
        return nullptr;
      return StubSymbol;
    }

    JITSymbol 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 JITSymbol(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;
  };

  /// Remote compile callback manager.
  class RemoteCompileCallbackManager : public JITCompileCallbackManager {
  public:
    RemoteCompileCallbackManager(OrcRemoteTargetClient &Client,
                                 JITTargetAddress ErrorHandlerAddress)
        : JITCompileCallbackManager(ErrorHandlerAddress), 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)
        this->AvailableTrampolines.push_back(BlockAddr + (I * TrampolineSize));

      return Error::success();
    }

    OrcRemoteTargetClient &Client;
  };

  /// 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, std::function<void(Error)> ReportError) {
    Error Err = Error::success();
    auto Client = std::unique_ptr<OrcRemoteTargetClient>(
        new OrcRemoteTargetClient(Channel, std::move(ReportError), 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) {
    DEBUG(dbgs() << "Calling int(*)(void) " << format("0x%016x", 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) {
    DEBUG(dbgs() << "Calling int(*)(int, char*[]) " << format("0x%016x", 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) {
    DEBUG(dbgs() << "Calling void(*)(void) " << format("0x%016x", 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) {
    // 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, 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,
                        std::function<void(Error)> ReportError, Error &Err)
      : rpc::SingleThreadedRPCEndpoint<rpc::RawByteChannel>(Channel, true),
        ReportError(std::move(ReportError)) {
    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))
      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))
      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 {
      ReportError(AddrOrErr.takeError());
      return 0;
    }
  }

  bool setProtections(ResourceIdMgr::ResourceId Id,
                      JITTargetAddress RemoteSegAddr, unsigned ProtFlags) {
    if (auto Err = callB<mem::SetProtections>(Id, RemoteSegAddr, ProtFlags)) {
      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))) {
      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(); }

  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
