LLVM  4.0.0
RPCSerialization.h
Go to the documentation of this file.
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>
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) {
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&
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 <>
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 <>
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())
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>
214 
215 template <typename ChannelT>
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>
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) {
248  }
249 
250  template <typename CArgT>
251  static Error deserialize(ChannelT &C, CArgT &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 =
265  return Err;
266  if (auto Err = SequenceTraits<ChannelT>::emitSeparator(C))
267  return Err;
269  }
270 
271  template <typename CArgT, typename... CArgTs>
272  static Error deserialize(ChannelT &C, CArgT &CArg,
273  CArgTs&... CArgs) {
274  if (auto Err =
276  return Err;
278  return Err;
280  }
281 };
282 
283 template <typename ChannelT, typename... ArgTs>
284 Error serializeSeq(ChannelT &C, const ArgTs &... Args) {
286 }
287 
288 template <typename ChannelT, typename... ArgTs>
289 Error deserializeSeq(ChannelT &C, ArgTs &... 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,
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,
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
static Error serialize(ChannelT &C, const CArgT &CArg)
static Error deserialize(ChannelT &C, std::vector< T > &V)
Deserialize a std::vector<T> to a std::vector<T>.
static sys::Mutex Lock
static Error serialize(ChannelT &C, const std::pair< T1, T2 > &V)
static StringRef getName(Value *V)
Alias for the common case of a sequence of size_ts.
Definition: STLExtras.h:354
static Error emitSeparator(ChannelT &C)
static Error deserialize(ChannelT &C, CArgT &CArg, CArgTs &...CArgs)
static GCRegistry::Add< CoreCLRGC > E("coreclr","CoreCLR-compatible GC")
The SerializationTraits<ChannelT, T> class describes how to serialize and deserialize an instance of ...
static Error deserialize(ChannelT &C, std::pair< T1, T2 > &V)
static Error serialize(ChannelT &C, const std::tuple< ArgTs...> &V)
RPC channel serialization for std::tuple.
OStream & operator<<(OStream &OS, const RPCTypeNameSequence<> &V)
Render an empty TypeNameSequence to an ostream.
static ErrorSuccess success()
Create a success value.
static Error serialize(ChannelT &C, const CArgT &CArg, const CArgTs &...CArgs)
Creates a compile-time integer sequence for a parameter pack.
Definition: STLExtras.h:356
static GCRegistry::Add< ShadowStackGC > C("shadow-stack","Very portable GC for uncooperative code generators")
Error deserializeSeq(ChannelT &C, ArgTs &...Args)
static Error serialize(ChannelT &C, const std::vector< T > &V)
Serialize a std::vector<T> from std::vector<T>.
Error serializeSeq(ChannelT &C, const ArgTs &...Args)
TypeNameSequence is a utility for rendering sequences of types to a string by rendering each type...
Utility class for serializing sequences of values of varying types.
A raw_ostream that writes to an std::string.
Definition: raw_ostream.h:463
static Error deserialize(ChannelT &C, CArgT &CArg)
Lightweight error class with error context and mandatory checking.
static Error consumeSeparator(ChannelT &C)
static Error deserialize(ChannelT &C, std::tuple< ArgTs...> &V)
RPC channel deserialization for std::tuple.