[Orc] Add support for remote JITing to the ORC API.
[oota-llvm.git] / include / llvm / ExecutionEngine / Orc / RPCChannel.h
1 // -*- c++ -*-
2
3 #ifndef LLVM_EXECUTIONENGINE_ORC_RPCCHANNEL_H
4 #define LLVM_EXECUTIONENGINE_ORC_RPCCHANNEL_H
5
6 #include "OrcError.h"
7 #include "llvm/ADT/ArrayRef.h"
8 #include "llvm/Support/Endian.h"
9
10 #include <system_error>
11 #include <unistd.h>
12
13 namespace llvm {
14 namespace orc {
15 namespace remote {
16
17 /// Interface for byte-streams to be used with RPC.
18 class RPCChannel {
19 public:
20   virtual ~RPCChannel() {}
21
22   /// Read Size bytes from the stream into *Dst.
23   virtual std::error_code readBytes(char *Dst, unsigned Size) = 0;
24
25   /// Read size bytes from *Src and append them to the stream.
26   virtual std::error_code appendBytes(const char *Src, unsigned Size) = 0;
27
28   /// Flush the stream if possible.
29   virtual std::error_code send() = 0;
30 };
31
32 /// RPC channel that reads from and writes from file descriptors.
33 class FDRPCChannel : public RPCChannel {
34 public:
35   FDRPCChannel(int InFD, int OutFD) : InFD(InFD), OutFD(OutFD) {}
36
37   std::error_code readBytes(char *Dst, unsigned Size) override {
38     assert(Dst && "Attempt to read into null.");
39     ssize_t ReadResult = ::read(InFD, Dst, Size);
40     if (ReadResult != Size)
41       return std::error_code(errno, std::generic_category());
42     return std::error_code();
43   }
44
45   std::error_code appendBytes(const char *Src, unsigned Size) override {
46     assert(Src && "Attempt to append from null.");
47     ssize_t WriteResult = ::write(OutFD, Src, Size);
48     if (WriteResult != Size)
49       std::error_code(errno, std::generic_category());
50     return std::error_code();
51   }
52
53   std::error_code send() override { return std::error_code(); }
54
55 private:
56   int InFD, OutFD;
57 };
58
59 /// RPC channel serialization for a variadic list of arguments.
60 template <typename T, typename... Ts>
61 std::error_code serialize_seq(RPCChannel &C, const T &Arg, const Ts &... Args) {
62   if (auto EC = serialize(C, Arg))
63     return EC;
64   return serialize_seq(C, Args...);
65 }
66
67 /// RPC channel serialization for an (empty) variadic list of arguments.
68 inline std::error_code serialize_seq(RPCChannel &C) {
69   return std::error_code();
70 }
71
72 /// RPC channel deserialization for a variadic list of arguments.
73 template <typename T, typename... Ts>
74 std::error_code deserialize_seq(RPCChannel &C, T &Arg, Ts &... Args) {
75   if (auto EC = deserialize(C, Arg))
76     return EC;
77   return deserialize_seq(C, Args...);
78 }
79
80 /// RPC channel serialization for an (empty) variadic list of arguments.
81 inline std::error_code deserialize_seq(RPCChannel &C) {
82   return std::error_code();
83 }
84
85 /// RPC channel serialization for integer primitives.
86 template <typename T>
87 typename std::enable_if<
88     std::is_same<T, uint64_t>::value || std::is_same<T, int64_t>::value ||
89         std::is_same<T, uint32_t>::value || std::is_same<T, int32_t>::value ||
90         std::is_same<T, uint16_t>::value || std::is_same<T, int16_t>::value ||
91         std::is_same<T, uint8_t>::value || std::is_same<T, int8_t>::value,
92     std::error_code>::type
93 serialize(RPCChannel &C, T V) {
94   support::endian::byte_swap<T, support::big>(V);
95   return C.appendBytes(reinterpret_cast<const char *>(&V), sizeof(T));
96 }
97
98 /// RPC channel deserialization for integer primitives.
99 template <typename T>
100 typename std::enable_if<
101     std::is_same<T, uint64_t>::value || std::is_same<T, int64_t>::value ||
102         std::is_same<T, uint32_t>::value || std::is_same<T, int32_t>::value ||
103         std::is_same<T, uint16_t>::value || std::is_same<T, int16_t>::value ||
104         std::is_same<T, uint8_t>::value || std::is_same<T, int8_t>::value,
105     std::error_code>::type
106 deserialize(RPCChannel &C, T &V) {
107   if (auto EC = C.readBytes(reinterpret_cast<char *>(&V), sizeof(T)))
108     return EC;
109   support::endian::byte_swap<T, support::big>(V);
110   return std::error_code();
111 }
112
113 /// RPC channel serialization for enums.
114 template <typename T>
115 typename std::enable_if<std::is_enum<T>::value, std::error_code>::type
116 serialize(RPCChannel &C, T V) {
117   return serialize(C, static_cast<typename std::underlying_type<T>::type>(V));
118 }
119
120 /// RPC channel deserialization for enums.
121 template <typename T>
122 typename std::enable_if<std::is_enum<T>::value, std::error_code>::type
123 deserialize(RPCChannel &C, T &V) {
124   typename std::underlying_type<T>::type Tmp;
125   std::error_code EC = deserialize(C, Tmp);
126   V = static_cast<T>(Tmp);
127   return EC;
128 }
129
130 /// RPC channel serialization for bools.
131 inline std::error_code serialize(RPCChannel &C, bool V) {
132   uint8_t VN = V ? 1 : 0;
133   return C.appendBytes(reinterpret_cast<const char *>(&VN), 1);
134 }
135
136 /// RPC channel deserialization for bools.
137 inline std::error_code deserialize(RPCChannel &C, bool &V) {
138   uint8_t VN = 0;
139   if (auto EC = C.readBytes(reinterpret_cast<char *>(&VN), 1))
140     return EC;
141
142   V = (VN != 0) ? true : false;
143   return std::error_code();
144 }
145
146 /// RPC channel serialization for StringRefs.
147 /// Note: There is no corresponding deseralization for this, as StringRef
148 /// doesn't own its memory and so can't hold the deserialized data.
149 inline std::error_code serialize(RPCChannel &C, StringRef S) {
150   if (auto EC = serialize(C, static_cast<uint64_t>(S.size())))
151     return EC;
152   return C.appendBytes((const char *)S.bytes_begin(), S.size());
153 }
154
155 /// RPC channel serialization for std::strings.
156 inline std::error_code serialize(RPCChannel &C, const std::string &S) {
157   return serialize(C, StringRef(S));
158 }
159
160 /// RPC channel deserialization for std::strings.
161 inline std::error_code deserialize(RPCChannel &C, std::string &S) {
162   uint64_t Count;
163   if (auto EC = deserialize(C, Count))
164     return EC;
165   S.resize(Count);
166   return C.readBytes(&S[0], Count);
167 }
168
169 /// RPC channel serialization for ArrayRef<T>.
170 template <typename T>
171 std::error_code serialize(RPCChannel &C, const ArrayRef<T> &A) {
172   if (auto EC = serialize(C, static_cast<uint64_t>(A.size())))
173     return EC;
174
175   for (const auto &E : A)
176     if (auto EC = serialize(C, E))
177       return EC;
178
179   return std::error_code();
180 }
181
182 /// RPC channel serialization for std::array<T>.
183 template <typename T>
184 std::error_code serialize(RPCChannel &C, const std::vector<T> &V) {
185   return serialize(C, ArrayRef<T>(V));
186 }
187
188 /// RPC channel deserialization for std::array<T>.
189 template <typename T>
190 std::error_code deserialize(RPCChannel &C, std::vector<T> &V) {
191   uint64_t Count = 0;
192   if (auto EC = deserialize(C, Count))
193     return EC;
194
195   V.resize(Count);
196   for (auto &E : V)
197     if (auto EC = deserialize(C, E))
198       return EC;
199
200   return std::error_code();
201 }
202
203 } // end namespace remote
204 } // end namespace orc
205 } // end namespace llvm
206
207 #endif