]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/include/llvm/ExecutionEngine/Orc/RPCSerialization.h
Merge ^/head r314178 through r314269.
[FreeBSD/FreeBSD.git] / contrib / llvm / include / llvm / ExecutionEngine / Orc / RPCSerialization.h
1 //===- llvm/ExecutionEngine/Orc/RPCSerialization.h --------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #ifndef LLVM_EXECUTIONENGINE_ORC_RPCSERIALIZATION_H
11 #define LLVM_EXECUTIONENGINE_ORC_RPCSERIALIZATION_H
12
13 #include "OrcError.h"
14 #include "llvm/Support/thread.h"
15 #include <mutex>
16 #include <sstream>
17
18 namespace llvm {
19 namespace orc {
20 namespace rpc {
21
22 template <typename T>
23 class RPCTypeName;
24
25 /// TypeNameSequence is a utility for rendering sequences of types to a string
26 /// by rendering each type, separated by ", ".
27 template <typename... ArgTs> class RPCTypeNameSequence {};
28
29 /// Render an empty TypeNameSequence to an ostream.
30 template <typename OStream>
31 OStream &operator<<(OStream &OS, const RPCTypeNameSequence<> &V) {
32   return OS;
33 }
34
35 /// Render a TypeNameSequence of a single type to an ostream.
36 template <typename OStream, typename ArgT>
37 OStream &operator<<(OStream &OS, const RPCTypeNameSequence<ArgT> &V) {
38   OS << RPCTypeName<ArgT>::getName();
39   return OS;
40 }
41
42 /// Render a TypeNameSequence of more than one type to an ostream.
43 template <typename OStream, typename ArgT1, typename ArgT2, typename... ArgTs>
44 OStream&
45 operator<<(OStream &OS, const RPCTypeNameSequence<ArgT1, ArgT2, ArgTs...> &V) {
46   OS << RPCTypeName<ArgT1>::getName() << ", "
47      << RPCTypeNameSequence<ArgT2, ArgTs...>();
48   return OS;
49 }
50
51 template <>
52 class RPCTypeName<void> {
53 public:
54   static const char* getName() { return "void"; }
55 };
56
57 template <>
58 class RPCTypeName<int8_t> {
59 public:
60   static const char* getName() { return "int8_t"; }
61 };
62
63 template <>
64 class RPCTypeName<uint8_t> {
65 public:
66   static const char* getName() { return "uint8_t"; }
67 };
68
69 template <>
70 class RPCTypeName<int16_t> {
71 public:
72   static const char* getName() { return "int16_t"; }
73 };
74
75 template <>
76 class RPCTypeName<uint16_t> {
77 public:
78   static const char* getName() { return "uint16_t"; }
79 };
80
81 template <>
82 class RPCTypeName<int32_t> {
83 public:
84   static const char* getName() { return "int32_t"; }
85 };
86
87 template <>
88 class RPCTypeName<uint32_t> {
89 public:
90   static const char* getName() { return "uint32_t"; }
91 };
92
93 template <>
94 class RPCTypeName<int64_t> {
95 public:
96   static const char* getName() { return "int64_t"; }
97 };
98
99 template <>
100 class RPCTypeName<uint64_t> {
101 public:
102   static const char* getName() { return "uint64_t"; }
103 };
104
105 template <>
106 class RPCTypeName<bool> {
107 public:
108   static const char* getName() { return "bool"; }
109 };
110
111 template <>
112 class RPCTypeName<std::string> {
113 public:
114   static const char* getName() { return "std::string"; }
115 };
116
117 template <typename T1, typename T2>
118 class RPCTypeName<std::pair<T1, T2>> {
119 public:
120   static const char* getName() {
121     std::lock_guard<std::mutex> Lock(NameMutex);
122     if (Name.empty())
123       raw_string_ostream(Name) << "std::pair<" << RPCTypeNameSequence<T1, T2>()
124                                << ">";
125     return Name.data();
126   }
127 private:
128   static std::mutex NameMutex;
129   static std::string Name;
130 };
131
132 template <typename T1, typename T2>
133 std::mutex RPCTypeName<std::pair<T1, T2>>::NameMutex;
134 template <typename T1, typename T2>
135 std::string RPCTypeName<std::pair<T1, T2>>::Name;
136
137 template <typename... ArgTs>
138 class RPCTypeName<std::tuple<ArgTs...>> {
139 public:
140   static const char* getName() {
141     std::lock_guard<std::mutex> Lock(NameMutex);
142     if (Name.empty())
143       raw_string_ostream(Name) << "std::tuple<"
144                                << RPCTypeNameSequence<ArgTs...>() << ">";
145     return Name.data();
146   }
147 private:
148   static std::mutex NameMutex;
149   static std::string Name;
150 };
151
152 template <typename... ArgTs>
153 std::mutex RPCTypeName<std::tuple<ArgTs...>>::NameMutex;
154 template <typename... ArgTs>
155 std::string RPCTypeName<std::tuple<ArgTs...>>::Name;
156
157 template <typename T>
158 class RPCTypeName<std::vector<T>> {
159 public:
160   static const char*getName() {
161     std::lock_guard<std::mutex> Lock(NameMutex);
162     if (Name.empty())
163       raw_string_ostream(Name) << "std::vector<" << RPCTypeName<T>::getName()
164                                << ">";
165     return Name.data();
166   }
167
168 private:
169   static std::mutex NameMutex;
170   static std::string Name;
171 };
172
173 template <typename T>
174 std::mutex RPCTypeName<std::vector<T>>::NameMutex;
175 template <typename T>
176 std::string RPCTypeName<std::vector<T>>::Name;
177
178
179 /// The SerializationTraits<ChannelT, T> class describes how to serialize and
180 /// deserialize an instance of type T to/from an abstract channel of type
181 /// ChannelT. It also provides a representation of the type's name via the
182 /// getName method.
183 ///
184 /// Specializations of this class should provide the following functions:
185 ///
186 ///   @code{.cpp}
187 ///
188 ///   static const char* getName();
189 ///   static Error serialize(ChannelT&, const T&);
190 ///   static Error deserialize(ChannelT&, T&);
191 ///
192 ///   @endcode
193 ///
194 /// The third argument of SerializationTraits is intended to support SFINAE.
195 /// E.g.:
196 ///
197 ///   @code{.cpp}
198 ///
199 ///   class MyVirtualChannel { ... };
200 ///
201 ///   template <DerivedChannelT>
202 ///   class SerializationTraits<DerivedChannelT, bool,
203 ///         typename std::enable_if<
204 ///           std::is_base_of<VirtChannel, DerivedChannel>::value
205 ///         >::type> {
206 ///   public:
207 ///     static const char* getName() { ... };
208 ///   }
209 ///
210 ///   @endcode
211 template <typename ChannelT, typename WireType,
212           typename ConcreteType = WireType, typename = void>
213 class SerializationTraits;
214
215 template <typename ChannelT>
216 class SequenceTraits {
217 public:
218   static Error emitSeparator(ChannelT &C) { return Error::success(); }
219   static Error consumeSeparator(ChannelT &C) { return Error::success(); }
220 };
221
222 /// Utility class for serializing sequences of values of varying types.
223 /// Specializations of this class contain 'serialize' and 'deserialize' methods
224 /// for the given channel. The ArgTs... list will determine the "over-the-wire"
225 /// types to be serialized. The serialize and deserialize methods take a list
226 /// CArgTs... ("caller arg types") which must be the same length as ArgTs...,
227 /// but may be different types from ArgTs, provided that for each CArgT there
228 /// is a SerializationTraits specialization
229 /// SerializeTraits<ChannelT, ArgT, CArgT> with methods that can serialize the
230 /// caller argument to over-the-wire value.
231 template <typename ChannelT, typename... ArgTs>
232 class SequenceSerialization;
233
234 template <typename ChannelT>
235 class SequenceSerialization<ChannelT> {
236 public:
237   static Error serialize(ChannelT &C) { return Error::success(); }
238   static Error deserialize(ChannelT &C) { return Error::success(); }
239 };
240
241 template <typename ChannelT, typename ArgT>
242 class SequenceSerialization<ChannelT, ArgT> {
243 public:
244
245   template <typename CArgT>
246   static Error serialize(ChannelT &C, const CArgT &CArg) {
247     return SerializationTraits<ChannelT, ArgT, CArgT>::serialize(C, CArg);
248   }
249
250   template <typename CArgT>
251   static Error deserialize(ChannelT &C, CArgT &CArg) {
252     return SerializationTraits<ChannelT, ArgT, CArgT>::deserialize(C, CArg);
253   }
254 };
255
256 template <typename ChannelT, typename ArgT, typename... ArgTs>
257 class SequenceSerialization<ChannelT, ArgT, ArgTs...> {
258 public:
259
260   template <typename CArgT, typename... CArgTs>
261   static Error serialize(ChannelT &C, const CArgT &CArg,
262                          const CArgTs&... CArgs) {
263     if (auto Err =
264         SerializationTraits<ChannelT, ArgT, CArgT>::serialize(C, CArg))
265       return Err;
266     if (auto Err = SequenceTraits<ChannelT>::emitSeparator(C))
267       return Err;
268     return SequenceSerialization<ChannelT, ArgTs...>::serialize(C, CArgs...);
269   }
270
271   template <typename CArgT, typename... CArgTs>
272   static Error deserialize(ChannelT &C, CArgT &CArg,
273                            CArgTs&... CArgs) {
274     if (auto Err =
275         SerializationTraits<ChannelT, ArgT, CArgT>::deserialize(C, CArg))
276       return Err;
277     if (auto Err = SequenceTraits<ChannelT>::consumeSeparator(C))
278       return Err;
279     return SequenceSerialization<ChannelT, ArgTs...>::deserialize(C, CArgs...);
280   }
281 };
282
283 template <typename ChannelT, typename... ArgTs>
284 Error serializeSeq(ChannelT &C, const ArgTs &... Args) {
285   return SequenceSerialization<ChannelT, ArgTs...>::serialize(C, Args...);
286 }
287
288 template <typename ChannelT, typename... ArgTs>
289 Error deserializeSeq(ChannelT &C, ArgTs &... Args) {
290   return SequenceSerialization<ChannelT, ArgTs...>::deserialize(C, Args...);
291 }
292
293 /// SerializationTraits default specialization for std::pair.
294 template <typename ChannelT, typename T1, typename T2>
295 class SerializationTraits<ChannelT, std::pair<T1, T2>> {
296 public:
297   static Error serialize(ChannelT &C, const std::pair<T1, T2> &V) {
298     return serializeSeq(C, V.first, V.second);
299   }
300
301   static Error deserialize(ChannelT &C, std::pair<T1, T2> &V) {
302     return deserializeSeq(C, V.first, V.second);
303   }
304 };
305
306 /// SerializationTraits default specialization for std::tuple.
307 template <typename ChannelT, typename... ArgTs>
308 class SerializationTraits<ChannelT, std::tuple<ArgTs...>> {
309 public:
310
311   /// RPC channel serialization for std::tuple.
312   static Error serialize(ChannelT &C, const std::tuple<ArgTs...> &V) {
313     return serializeTupleHelper(C, V, llvm::index_sequence_for<ArgTs...>());
314   }
315
316   /// RPC channel deserialization for std::tuple.
317   static Error deserialize(ChannelT &C, std::tuple<ArgTs...> &V) {
318     return deserializeTupleHelper(C, V, llvm::index_sequence_for<ArgTs...>());
319   }
320
321 private:
322   // Serialization helper for std::tuple.
323   template <size_t... Is>
324   static Error serializeTupleHelper(ChannelT &C, const std::tuple<ArgTs...> &V,
325                                     llvm::index_sequence<Is...> _) {
326     return serializeSeq(C, std::get<Is>(V)...);
327   }
328
329   // Serialization helper for std::tuple.
330   template <size_t... Is>
331   static Error deserializeTupleHelper(ChannelT &C, std::tuple<ArgTs...> &V,
332                                       llvm::index_sequence<Is...> _) {
333     return deserializeSeq(C, std::get<Is>(V)...);
334   }
335 };
336
337 /// SerializationTraits default specialization for std::vector.
338 template <typename ChannelT, typename T>
339 class SerializationTraits<ChannelT, std::vector<T>> {
340 public:
341
342   /// Serialize a std::vector<T> from std::vector<T>.
343   static Error serialize(ChannelT &C, const std::vector<T> &V) {
344     if (auto Err = serializeSeq(C, static_cast<uint64_t>(V.size())))
345       return Err;
346
347     for (const auto &E : V)
348       if (auto Err = serializeSeq(C, E))
349         return Err;
350
351     return Error::success();
352   }
353
354   /// Deserialize a std::vector<T> to a std::vector<T>.
355   static Error deserialize(ChannelT &C, std::vector<T> &V) {
356     uint64_t Count = 0;
357     if (auto Err = deserializeSeq(C, Count))
358       return Err;
359
360     V.resize(Count);
361     for (auto &E : V)
362       if (auto Err = deserializeSeq(C, E))
363         return Err;
364
365     return Error::success();
366   }
367 };
368
369 } // end namespace rpc
370 } // end namespace orc
371 } // end namespace llvm
372
373 #endif // LLVM_EXECUTIONENGINE_ORC_RPCSERIALIZATION_H