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