1//===-- RemoteJITUtils.h - Utilities for remote-JITing with LLI -*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Utilities for remote-JITing with LLI.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_TOOLS_LLI_REMOTEJITUTILS_H
14#define LLVM_TOOLS_LLI_REMOTEJITUTILS_H
15
16#include "llvm/ExecutionEngine/Orc/RPC/RawByteChannel.h"
17#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
18#include <mutex>
19
20#if !defined(_MSC_VER) && !defined(__MINGW32__)
21#include <unistd.h>
22#else
23#include <io.h>
24#endif
25
26/// RPC channel that reads from and writes from file descriptors.
27class FDRawChannel final : public llvm::orc::rpc::RawByteChannel {
28public:
29  FDRawChannel(int InFD, int OutFD) : InFD(InFD), OutFD(OutFD) {}
30
31  llvm::Error readBytes(char *Dst, unsigned Size) override {
32    assert(Dst && "Attempt to read into null.");
33    ssize_t Completed = 0;
34    while (Completed < static_cast<ssize_t>(Size)) {
35      ssize_t Read = ::read(InFD, Dst + Completed, Size - Completed);
36      if (Read <= 0) {
37        auto ErrNo = errno;
38        if (ErrNo == EAGAIN || ErrNo == EINTR)
39          continue;
40        else
41          return llvm::errorCodeToError(
42                   std::error_code(errno, std::generic_category()));
43      }
44      Completed += Read;
45    }
46    return llvm::Error::success();
47  }
48
49  llvm::Error appendBytes(const char *Src, unsigned Size) override {
50    assert(Src && "Attempt to append from null.");
51    ssize_t Completed = 0;
52    while (Completed < static_cast<ssize_t>(Size)) {
53      ssize_t Written = ::write(OutFD, Src + Completed, Size - Completed);
54      if (Written < 0) {
55        auto ErrNo = errno;
56        if (ErrNo == EAGAIN || ErrNo == EINTR)
57          continue;
58        else
59          return llvm::errorCodeToError(
60                   std::error_code(errno, std::generic_category()));
61      }
62      Completed += Written;
63    }
64    return llvm::Error::success();
65  }
66
67  llvm::Error send() override { return llvm::Error::success(); }
68
69private:
70  int InFD, OutFD;
71};
72
73// launch the remote process (see lli.cpp) and return a channel to it.
74std::unique_ptr<FDRawChannel> launchRemote();
75
76namespace llvm {
77
78// ForwardingMM - Adapter to connect MCJIT to Orc's Remote
79// memory manager.
80class ForwardingMemoryManager : public llvm::RTDyldMemoryManager {
81public:
82  void setMemMgr(std::unique_ptr<RuntimeDyld::MemoryManager> MemMgr) {
83    this->MemMgr = std::move(MemMgr);
84  }
85
86  void setResolver(std::shared_ptr<LegacyJITSymbolResolver> Resolver) {
87    this->Resolver = std::move(Resolver);
88  }
89
90  uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
91                               unsigned SectionID,
92                               StringRef SectionName) override {
93    return MemMgr->allocateCodeSection(Size, Alignment, SectionID, SectionName);
94  }
95
96  uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
97                               unsigned SectionID, StringRef SectionName,
98                               bool IsReadOnly) override {
99    return MemMgr->allocateDataSection(Size, Alignment, SectionID, SectionName,
100                                       IsReadOnly);
101  }
102
103  void reserveAllocationSpace(uintptr_t CodeSize, uint32_t CodeAlign,
104                              uintptr_t RODataSize, uint32_t RODataAlign,
105                              uintptr_t RWDataSize,
106                              uint32_t RWDataAlign) override {
107    MemMgr->reserveAllocationSpace(CodeSize, CodeAlign, RODataSize, RODataAlign,
108                                   RWDataSize, RWDataAlign);
109  }
110
111  bool needsToReserveAllocationSpace() override {
112    return MemMgr->needsToReserveAllocationSpace();
113  }
114
115  void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr,
116                        size_t Size) override {
117    MemMgr->registerEHFrames(Addr, LoadAddr, Size);
118  }
119
120  void deregisterEHFrames() override {
121    MemMgr->deregisterEHFrames();
122  }
123
124  bool finalizeMemory(std::string *ErrMsg = nullptr) override {
125    return MemMgr->finalizeMemory(ErrMsg);
126  }
127
128  void notifyObjectLoaded(RuntimeDyld &RTDyld,
129                          const object::ObjectFile &Obj) override {
130    MemMgr->notifyObjectLoaded(RTDyld, Obj);
131  }
132
133  // Don't hide the sibling notifyObjectLoaded from RTDyldMemoryManager.
134  using RTDyldMemoryManager::notifyObjectLoaded;
135
136  JITSymbol findSymbol(const std::string &Name) override {
137    return Resolver->findSymbol(Name);
138  }
139
140  JITSymbol
141  findSymbolInLogicalDylib(const std::string &Name) override {
142    return Resolver->findSymbolInLogicalDylib(Name);
143  }
144
145private:
146  std::unique_ptr<RuntimeDyld::MemoryManager> MemMgr;
147  std::shared_ptr<LegacyJITSymbolResolver> Resolver;
148};
149}
150
151#endif
152