[Orc] Take another shot at working around the GCC 4.7 ICE in
[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 serialization for a variadic list of arguments.
32 template <typename T, typename... Ts>
33 std::error_code serialize_seq(RPCChannel &C, const T &Arg, const Ts &... Args) {
34   if (auto EC = serialize(C, Arg))
35     return EC;
36   return serialize_seq(C, Args...);
37 }
38
39 /// RPC channel serialization for an (empty) variadic list of arguments.
40 inline std::error_code serialize_seq(RPCChannel &C) {
41   return std::error_code();
42 }
43
44 /// RPC channel deserialization for a variadic list of arguments.
45 template <typename T, typename... Ts>
46 std::error_code deserialize_seq(RPCChannel &C, T &Arg, Ts &... Args) {
47   if (auto EC = deserialize(C, Arg))
48     return EC;
49   return deserialize_seq(C, Args...);
50 }
51
52 /// RPC channel serialization for an (empty) variadic list of arguments.
53 inline std::error_code deserialize_seq(RPCChannel &C) {
54   return std::error_code();
55 }
56
57 /// RPC channel serialization for integer primitives.
58 template <typename T>
59 typename std::enable_if<
60     std::is_same<T, uint64_t>::value || std::is_same<T, int64_t>::value ||
61         std::is_same<T, uint32_t>::value || std::is_same<T, int32_t>::value ||
62         std::is_same<T, uint16_t>::value || std::is_same<T, int16_t>::value ||
63         std::is_same<T, uint8_t>::value || std::is_same<T, int8_t>::value,
64     std::error_code>::type
65 serialize(RPCChannel &C, T V) {
66   support::endian::byte_swap<T, support::big>(V);
67   return C.appendBytes(reinterpret_cast<const char *>(&V), sizeof(T));
68 }
69
70 /// RPC channel deserialization for integer primitives.
71 template <typename T>
72 typename std::enable_if<
73     std::is_same<T, uint64_t>::value || std::is_same<T, int64_t>::value ||
74         std::is_same<T, uint32_t>::value || std::is_same<T, int32_t>::value ||
75         std::is_same<T, uint16_t>::value || std::is_same<T, int16_t>::value ||
76         std::is_same<T, uint8_t>::value || std::is_same<T, int8_t>::value,
77     std::error_code>::type
78 deserialize(RPCChannel &C, T &V) {
79   if (auto EC = C.readBytes(reinterpret_cast<char *>(&V), sizeof(T)))
80     return EC;
81   support::endian::byte_swap<T, support::big>(V);
82   return std::error_code();
83 }
84
85 /// RPC channel serialization for enums.
86 template <typename T>
87 typename std::enable_if<std::is_enum<T>::value, std::error_code>::type
88 serialize(RPCChannel &C, T V) {
89   return serialize(C, static_cast<typename std::underlying_type<T>::type>(V));
90 }
91
92 /// RPC channel deserialization for enums.
93 template <typename T>
94 typename std::enable_if<std::is_enum<T>::value, std::error_code>::type
95 deserialize(RPCChannel &C, T &V) {
96   typename std::underlying_type<T>::type Tmp;
97   std::error_code EC = deserialize(C, Tmp);
98   V = static_cast<T>(Tmp);
99   return EC;
100 }
101
102 /// RPC channel serialization for bools.
103 inline std::error_code serialize(RPCChannel &C, bool V) {
104   uint8_t VN = V ? 1 : 0;
105   return C.appendBytes(reinterpret_cast<const char *>(&VN), 1);
106 }
107
108 /// RPC channel deserialization for bools.
109 inline std::error_code deserialize(RPCChannel &C, bool &V) {
110   uint8_t VN = 0;
111   if (auto EC = C.readBytes(reinterpret_cast<char *>(&VN), 1))
112     return EC;
113
114   V = (VN != 0) ? true : false;
115   return std::error_code();
116 }
117
118 /// RPC channel serialization for StringRefs.
119 /// Note: There is no corresponding deseralization for this, as StringRef
120 /// doesn't own its memory and so can't hold the deserialized data.
121 inline std::error_code serialize(RPCChannel &C, StringRef S) {
122   if (auto EC = serialize(C, static_cast<uint64_t>(S.size())))
123     return EC;
124   return C.appendBytes((const char *)S.bytes_begin(), S.size());
125 }
126
127 /// RPC channel serialization for std::strings.
128 inline std::error_code serialize(RPCChannel &C, const std::string &S) {
129   return serialize(C, StringRef(S));
130 }
131
132 /// RPC channel deserialization for std::strings.
133 inline std::error_code deserialize(RPCChannel &C, std::string &S) {
134   uint64_t Count;
135   if (auto EC = deserialize(C, Count))
136     return EC;
137   S.resize(Count);
138   return C.readBytes(&S[0], Count);
139 }
140
141 /// RPC channel serialization for ArrayRef<T>.
142 template <typename T>
143 std::error_code serialize(RPCChannel &C, const ArrayRef<T> &A) {
144   if (auto EC = serialize(C, static_cast<uint64_t>(A.size())))
145     return EC;
146
147   for (const auto &E : A)
148     if (auto EC = serialize(C, E))
149       return EC;
150
151   return std::error_code();
152 }
153
154 /// RPC channel serialization for std::array<T>.
155 template <typename T>
156 std::error_code serialize(RPCChannel &C, const std::vector<T> &V) {
157   return serialize(C, ArrayRef<T>(V));
158 }
159
160 /// RPC channel deserialization for std::array<T>.
161 template <typename T>
162 std::error_code deserialize(RPCChannel &C, std::vector<T> &V) {
163   uint64_t Count = 0;
164   if (auto EC = deserialize(C, Count))
165     return EC;
166
167   V.resize(Count);
168   for (auto &E : V)
169     if (auto EC = deserialize(C, E))
170       return EC;
171
172   return std::error_code();
173 }
174
175 } // end namespace remote
176 } // end namespace orc
177 } // end namespace llvm
178
179 #endif