SimplePackedSerialization.h 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===---- SimplePackedSerialization.h - simple serialization ----*- C++ -*-===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. //
  14. // The behavior of the utilities in this header must be synchronized with the
  15. // behavior of the utilities in
  16. // compiler-rt/lib/orc/simple_packed_serialization.h.
  17. //
  18. // The Simple Packed Serialization (SPS) utilities are used to generate
  19. // argument and return buffers for wrapper functions using the following
  20. // serialization scheme:
  21. //
  22. // Primitives (signed types should be two's complement):
  23. // bool, char, int8_t, uint8_t -- 8-bit (0=false, 1=true)
  24. // int16_t, uint16_t -- 16-bit little endian
  25. // int32_t, uint32_t -- 32-bit little endian
  26. // int64_t, int64_t -- 64-bit little endian
  27. //
  28. // Sequence<T>:
  29. // Serialized as the sequence length (as a uint64_t) followed by the
  30. // serialization of each of the elements without padding.
  31. //
  32. // Tuple<T1, ..., TN>:
  33. // Serialized as each of the element types from T1 to TN without padding.
  34. //
  35. //===----------------------------------------------------------------------===//
  36. #ifndef LLVM_EXECUTIONENGINE_ORC_SHARED_SIMPLEPACKEDSERIALIZATION_H
  37. #define LLVM_EXECUTIONENGINE_ORC_SHARED_SIMPLEPACKEDSERIALIZATION_H
  38. #include "llvm/ADT/STLExtras.h"
  39. #include "llvm/ADT/SmallVector.h"
  40. #include "llvm/ADT/StringMap.h"
  41. #include "llvm/ADT/StringRef.h"
  42. #include "llvm/Support/Error.h"
  43. #include "llvm/Support/SwapByteOrder.h"
  44. #include <limits>
  45. #include <string>
  46. #include <tuple>
  47. #include <type_traits>
  48. #include <utility>
  49. #include <vector>
  50. namespace llvm {
  51. namespace orc {
  52. namespace shared {
  53. /// Output char buffer with overflow check.
  54. class SPSOutputBuffer {
  55. public:
  56. SPSOutputBuffer(char *Buffer, size_t Remaining)
  57. : Buffer(Buffer), Remaining(Remaining) {}
  58. bool write(const char *Data, size_t Size) {
  59. if (Size > Remaining)
  60. return false;
  61. memcpy(Buffer, Data, Size);
  62. Buffer += Size;
  63. Remaining -= Size;
  64. return true;
  65. }
  66. private:
  67. char *Buffer = nullptr;
  68. size_t Remaining = 0;
  69. };
  70. /// Input char buffer with underflow check.
  71. class SPSInputBuffer {
  72. public:
  73. SPSInputBuffer() = default;
  74. SPSInputBuffer(const char *Buffer, size_t Remaining)
  75. : Buffer(Buffer), Remaining(Remaining) {}
  76. bool read(char *Data, size_t Size) {
  77. if (Size > Remaining)
  78. return false;
  79. memcpy(Data, Buffer, Size);
  80. Buffer += Size;
  81. Remaining -= Size;
  82. return true;
  83. }
  84. const char *data() const { return Buffer; }
  85. bool skip(size_t Size) {
  86. if (Size > Remaining)
  87. return false;
  88. Buffer += Size;
  89. Remaining -= Size;
  90. return true;
  91. }
  92. private:
  93. const char *Buffer = nullptr;
  94. size_t Remaining = 0;
  95. };
  96. /// Specialize to describe how to serialize/deserialize to/from the given
  97. /// concrete type.
  98. template <typename SPSTagT, typename ConcreteT, typename _ = void>
  99. class SPSSerializationTraits;
  100. /// A utility class for serializing to a blob from a variadic list.
  101. template <typename... ArgTs> class SPSArgList;
  102. // Empty list specialization for SPSArgList.
  103. template <> class SPSArgList<> {
  104. public:
  105. static size_t size() { return 0; }
  106. static bool serialize(SPSOutputBuffer &OB) { return true; }
  107. static bool deserialize(SPSInputBuffer &IB) { return true; }
  108. static bool serializeToSmallVector(SmallVectorImpl<char> &V) { return true; }
  109. static bool deserializeFromSmallVector(const SmallVectorImpl<char> &V) {
  110. return true;
  111. }
  112. };
  113. // Non-empty list specialization for SPSArgList.
  114. template <typename SPSTagT, typename... SPSTagTs>
  115. class SPSArgList<SPSTagT, SPSTagTs...> {
  116. public:
  117. // FIXME: This typedef is here to enable SPS arg serialization from
  118. // JITLink. It can be removed once JITLink can access SPS directly.
  119. using OutputBuffer = SPSOutputBuffer;
  120. template <typename ArgT, typename... ArgTs>
  121. static size_t size(const ArgT &Arg, const ArgTs &...Args) {
  122. return SPSSerializationTraits<SPSTagT, ArgT>::size(Arg) +
  123. SPSArgList<SPSTagTs...>::size(Args...);
  124. }
  125. template <typename ArgT, typename... ArgTs>
  126. static bool serialize(SPSOutputBuffer &OB, const ArgT &Arg,
  127. const ArgTs &...Args) {
  128. return SPSSerializationTraits<SPSTagT, ArgT>::serialize(OB, Arg) &&
  129. SPSArgList<SPSTagTs...>::serialize(OB, Args...);
  130. }
  131. template <typename ArgT, typename... ArgTs>
  132. static bool deserialize(SPSInputBuffer &IB, ArgT &Arg, ArgTs &...Args) {
  133. return SPSSerializationTraits<SPSTagT, ArgT>::deserialize(IB, Arg) &&
  134. SPSArgList<SPSTagTs...>::deserialize(IB, Args...);
  135. }
  136. };
  137. /// SPS serialization for integral types, bool, and char.
  138. template <typename SPSTagT>
  139. class SPSSerializationTraits<
  140. SPSTagT, SPSTagT,
  141. std::enable_if_t<std::is_same<SPSTagT, bool>::value ||
  142. std::is_same<SPSTagT, char>::value ||
  143. std::is_same<SPSTagT, int8_t>::value ||
  144. std::is_same<SPSTagT, int16_t>::value ||
  145. std::is_same<SPSTagT, int32_t>::value ||
  146. std::is_same<SPSTagT, int64_t>::value ||
  147. std::is_same<SPSTagT, uint8_t>::value ||
  148. std::is_same<SPSTagT, uint16_t>::value ||
  149. std::is_same<SPSTagT, uint32_t>::value ||
  150. std::is_same<SPSTagT, uint64_t>::value>> {
  151. public:
  152. static size_t size(const SPSTagT &Value) { return sizeof(SPSTagT); }
  153. static bool serialize(SPSOutputBuffer &OB, const SPSTagT &Value) {
  154. SPSTagT Tmp = Value;
  155. if (sys::IsBigEndianHost)
  156. sys::swapByteOrder(Tmp);
  157. return OB.write(reinterpret_cast<const char *>(&Tmp), sizeof(Tmp));
  158. }
  159. static bool deserialize(SPSInputBuffer &IB, SPSTagT &Value) {
  160. SPSTagT Tmp;
  161. if (!IB.read(reinterpret_cast<char *>(&Tmp), sizeof(Tmp)))
  162. return false;
  163. if (sys::IsBigEndianHost)
  164. sys::swapByteOrder(Tmp);
  165. Value = Tmp;
  166. return true;
  167. }
  168. };
  169. // Any empty placeholder suitable as a substitute for void when deserializing
  170. class SPSEmpty {};
  171. /// SPS tag type for tuples.
  172. ///
  173. /// A blob tuple should be serialized by serializing each of the elements in
  174. /// sequence.
  175. template <typename... SPSTagTs> class SPSTuple {
  176. public:
  177. /// Convenience typedef of the corresponding arg list.
  178. typedef SPSArgList<SPSTagTs...> AsArgList;
  179. };
  180. /// SPS tag type for sequences.
  181. ///
  182. /// SPSSequences should be serialized as a uint64_t sequence length,
  183. /// followed by the serialization of each of the elements.
  184. template <typename SPSElementTagT> class SPSSequence;
  185. /// SPS tag type for strings, which are equivalent to sequences of chars.
  186. using SPSString = SPSSequence<char>;
  187. /// SPS tag type for maps.
  188. ///
  189. /// SPS maps are just sequences of (Key, Value) tuples.
  190. template <typename SPSTagT1, typename SPSTagT2>
  191. using SPSMap = SPSSequence<SPSTuple<SPSTagT1, SPSTagT2>>;
  192. /// Serialization for SPSEmpty type.
  193. template <> class SPSSerializationTraits<SPSEmpty, SPSEmpty> {
  194. public:
  195. static size_t size(const SPSEmpty &EP) { return 0; }
  196. static bool serialize(SPSOutputBuffer &OB, const SPSEmpty &BE) {
  197. return true;
  198. }
  199. static bool deserialize(SPSInputBuffer &IB, SPSEmpty &BE) { return true; }
  200. };
  201. /// Specialize this to implement 'trivial' sequence serialization for
  202. /// a concrete sequence type.
  203. ///
  204. /// Trivial sequence serialization uses the sequence's 'size' member to get the
  205. /// length of the sequence, and uses a range-based for loop to iterate over the
  206. /// elements.
  207. ///
  208. /// Specializing this template class means that you do not need to provide a
  209. /// specialization of SPSSerializationTraits for your type.
  210. template <typename SPSElementTagT, typename ConcreteSequenceT>
  211. class TrivialSPSSequenceSerialization {
  212. public:
  213. static constexpr bool available = false;
  214. };
  215. /// Specialize this to implement 'trivial' sequence deserialization for
  216. /// a concrete sequence type.
  217. ///
  218. /// Trivial deserialization calls a static 'reserve(SequenceT&)' method on your
  219. /// specialization (you must implement this) to reserve space, and then calls
  220. /// a static 'append(SequenceT&, ElementT&) method to append each of the
  221. /// deserialized elements.
  222. ///
  223. /// Specializing this template class means that you do not need to provide a
  224. /// specialization of SPSSerializationTraits for your type.
  225. template <typename SPSElementTagT, typename ConcreteSequenceT>
  226. class TrivialSPSSequenceDeserialization {
  227. public:
  228. static constexpr bool available = false;
  229. };
  230. /// Trivial std::string -> SPSSequence<char> serialization.
  231. template <> class TrivialSPSSequenceSerialization<char, std::string> {
  232. public:
  233. static constexpr bool available = true;
  234. };
  235. /// Trivial SPSSequence<char> -> std::string deserialization.
  236. template <> class TrivialSPSSequenceDeserialization<char, std::string> {
  237. public:
  238. static constexpr bool available = true;
  239. using element_type = char;
  240. static void reserve(std::string &S, uint64_t Size) { S.reserve(Size); }
  241. static bool append(std::string &S, char C) {
  242. S.push_back(C);
  243. return true;
  244. }
  245. };
  246. /// Trivial std::vector<T> -> SPSSequence<SPSElementTagT> serialization.
  247. template <typename SPSElementTagT, typename T>
  248. class TrivialSPSSequenceSerialization<SPSElementTagT, std::vector<T>> {
  249. public:
  250. static constexpr bool available = true;
  251. };
  252. /// Trivial SPSSequence<SPSElementTagT> -> std::vector<T> deserialization.
  253. template <typename SPSElementTagT, typename T>
  254. class TrivialSPSSequenceDeserialization<SPSElementTagT, std::vector<T>> {
  255. public:
  256. static constexpr bool available = true;
  257. using element_type = typename std::vector<T>::value_type;
  258. static void reserve(std::vector<T> &V, uint64_t Size) { V.reserve(Size); }
  259. static bool append(std::vector<T> &V, T E) {
  260. V.push_back(std::move(E));
  261. return true;
  262. }
  263. };
  264. /// Trivial SmallVectorImpl<T> -> SPSSequence<char> serialization.
  265. template <typename SPSElementTagT, typename T>
  266. class TrivialSPSSequenceSerialization<SPSElementTagT, SmallVectorImpl<T>> {
  267. public:
  268. static constexpr bool available = true;
  269. };
  270. /// Trivial SPSSequence<SPSElementTagT> -> SmallVectorImpl<T> deserialization.
  271. template <typename SPSElementTagT, typename T>
  272. class TrivialSPSSequenceDeserialization<SPSElementTagT, SmallVectorImpl<T>> {
  273. public:
  274. static constexpr bool available = true;
  275. using element_type = typename SmallVectorImpl<T>::value_type;
  276. static void reserve(SmallVectorImpl<T> &V, uint64_t Size) { V.reserve(Size); }
  277. static bool append(SmallVectorImpl<T> &V, T E) {
  278. V.push_back(std::move(E));
  279. return true;
  280. }
  281. };
  282. /// Trivial SmallVectorImpl<T> -> SPSSequence<char> serialization.
  283. template <typename SPSElementTagT, typename T, unsigned N>
  284. class TrivialSPSSequenceSerialization<SPSElementTagT, SmallVector<T, N>>
  285. : public TrivialSPSSequenceSerialization<SPSElementTagT,
  286. SmallVectorImpl<T>> {};
  287. /// Trivial SPSSequence<SPSElementTagT> -> SmallVectorImpl<T> deserialization.
  288. template <typename SPSElementTagT, typename T, unsigned N>
  289. class TrivialSPSSequenceDeserialization<SPSElementTagT, SmallVector<T, N>>
  290. : public TrivialSPSSequenceDeserialization<SPSElementTagT,
  291. SmallVectorImpl<T>> {};
  292. /// Trivial ArrayRef<T> -> SPSSequence<SPSElementTagT> serialization.
  293. template <typename SPSElementTagT, typename T>
  294. class TrivialSPSSequenceSerialization<SPSElementTagT, ArrayRef<T>> {
  295. public:
  296. static constexpr bool available = true;
  297. };
  298. /// Specialized SPSSequence<char> -> ArrayRef<char> serialization.
  299. ///
  300. /// On deserialize, points directly into the input buffer.
  301. template <> class SPSSerializationTraits<SPSSequence<char>, ArrayRef<char>> {
  302. public:
  303. static size_t size(const ArrayRef<char> &A) {
  304. return SPSArgList<uint64_t>::size(static_cast<uint64_t>(A.size())) +
  305. A.size();
  306. }
  307. static bool serialize(SPSOutputBuffer &OB, const ArrayRef<char> &A) {
  308. if (!SPSArgList<uint64_t>::serialize(OB, static_cast<uint64_t>(A.size())))
  309. return false;
  310. return OB.write(A.data(), A.size());
  311. }
  312. static bool deserialize(SPSInputBuffer &IB, ArrayRef<char> &A) {
  313. uint64_t Size;
  314. if (!SPSArgList<uint64_t>::deserialize(IB, Size))
  315. return false;
  316. if (Size > std::numeric_limits<size_t>::max())
  317. return false;
  318. A = {IB.data(), static_cast<size_t>(Size)};
  319. return IB.skip(Size);
  320. }
  321. };
  322. /// 'Trivial' sequence serialization: Sequence is serialized as a uint64_t size
  323. /// followed by a for-earch loop over the elements of the sequence to serialize
  324. /// each of them.
  325. template <typename SPSElementTagT, typename SequenceT>
  326. class SPSSerializationTraits<SPSSequence<SPSElementTagT>, SequenceT,
  327. std::enable_if_t<TrivialSPSSequenceSerialization<
  328. SPSElementTagT, SequenceT>::available>> {
  329. public:
  330. static size_t size(const SequenceT &S) {
  331. size_t Size = SPSArgList<uint64_t>::size(static_cast<uint64_t>(S.size()));
  332. for (const auto &E : S)
  333. Size += SPSArgList<SPSElementTagT>::size(E);
  334. return Size;
  335. }
  336. static bool serialize(SPSOutputBuffer &OB, const SequenceT &S) {
  337. if (!SPSArgList<uint64_t>::serialize(OB, static_cast<uint64_t>(S.size())))
  338. return false;
  339. for (const auto &E : S)
  340. if (!SPSArgList<SPSElementTagT>::serialize(OB, E))
  341. return false;
  342. return true;
  343. }
  344. static bool deserialize(SPSInputBuffer &IB, SequenceT &S) {
  345. using TBSD = TrivialSPSSequenceDeserialization<SPSElementTagT, SequenceT>;
  346. uint64_t Size;
  347. if (!SPSArgList<uint64_t>::deserialize(IB, Size))
  348. return false;
  349. TBSD::reserve(S, Size);
  350. for (size_t I = 0; I != Size; ++I) {
  351. typename TBSD::element_type E;
  352. if (!SPSArgList<SPSElementTagT>::deserialize(IB, E))
  353. return false;
  354. if (!TBSD::append(S, std::move(E)))
  355. return false;
  356. }
  357. return true;
  358. }
  359. };
  360. /// SPSTuple serialization for std::tuple.
  361. template <typename... SPSTagTs, typename... Ts>
  362. class SPSSerializationTraits<SPSTuple<SPSTagTs...>, std::tuple<Ts...>> {
  363. private:
  364. using TupleArgList = typename SPSTuple<SPSTagTs...>::AsArgList;
  365. using ArgIndices = std::make_index_sequence<sizeof...(Ts)>;
  366. template <std::size_t... I>
  367. static size_t size(const std::tuple<Ts...> &T, std::index_sequence<I...>) {
  368. return TupleArgList::size(std::get<I>(T)...);
  369. }
  370. template <std::size_t... I>
  371. static bool serialize(SPSOutputBuffer &OB, const std::tuple<Ts...> &T,
  372. std::index_sequence<I...>) {
  373. return TupleArgList::serialize(OB, std::get<I>(T)...);
  374. }
  375. template <std::size_t... I>
  376. static bool deserialize(SPSInputBuffer &IB, std::tuple<Ts...> &T,
  377. std::index_sequence<I...>) {
  378. return TupleArgList::deserialize(IB, std::get<I>(T)...);
  379. }
  380. public:
  381. static size_t size(const std::tuple<Ts...> &T) {
  382. return size(T, ArgIndices{});
  383. }
  384. static bool serialize(SPSOutputBuffer &OB, const std::tuple<Ts...> &T) {
  385. return serialize(OB, T, ArgIndices{});
  386. }
  387. static bool deserialize(SPSInputBuffer &IB, std::tuple<Ts...> &T) {
  388. return deserialize(IB, T, ArgIndices{});
  389. }
  390. };
  391. /// SPSTuple serialization for std::pair.
  392. template <typename SPSTagT1, typename SPSTagT2, typename T1, typename T2>
  393. class SPSSerializationTraits<SPSTuple<SPSTagT1, SPSTagT2>, std::pair<T1, T2>> {
  394. public:
  395. static size_t size(const std::pair<T1, T2> &P) {
  396. return SPSArgList<SPSTagT1>::size(P.first) +
  397. SPSArgList<SPSTagT2>::size(P.second);
  398. }
  399. static bool serialize(SPSOutputBuffer &OB, const std::pair<T1, T2> &P) {
  400. return SPSArgList<SPSTagT1>::serialize(OB, P.first) &&
  401. SPSArgList<SPSTagT2>::serialize(OB, P.second);
  402. }
  403. static bool deserialize(SPSInputBuffer &IB, std::pair<T1, T2> &P) {
  404. return SPSArgList<SPSTagT1>::deserialize(IB, P.first) &&
  405. SPSArgList<SPSTagT2>::deserialize(IB, P.second);
  406. }
  407. };
  408. /// Serialization for StringRefs.
  409. ///
  410. /// Serialization is as for regular strings. Deserialization points directly
  411. /// into the blob.
  412. template <> class SPSSerializationTraits<SPSString, StringRef> {
  413. public:
  414. static size_t size(const StringRef &S) {
  415. return SPSArgList<uint64_t>::size(static_cast<uint64_t>(S.size())) +
  416. S.size();
  417. }
  418. static bool serialize(SPSOutputBuffer &OB, StringRef S) {
  419. if (!SPSArgList<uint64_t>::serialize(OB, static_cast<uint64_t>(S.size())))
  420. return false;
  421. return OB.write(S.data(), S.size());
  422. }
  423. static bool deserialize(SPSInputBuffer &IB, StringRef &S) {
  424. const char *Data = nullptr;
  425. uint64_t Size;
  426. if (!SPSArgList<uint64_t>::deserialize(IB, Size))
  427. return false;
  428. Data = IB.data();
  429. if (!IB.skip(Size))
  430. return false;
  431. S = StringRef(Data, Size);
  432. return true;
  433. }
  434. };
  435. /// Serialization for StringMap<ValueT>s.
  436. template <typename SPSValueT, typename ValueT>
  437. class SPSSerializationTraits<SPSSequence<SPSTuple<SPSString, SPSValueT>>,
  438. StringMap<ValueT>> {
  439. public:
  440. static size_t size(const StringMap<ValueT> &M) {
  441. size_t Sz = SPSArgList<uint64_t>::size(static_cast<uint64_t>(M.size()));
  442. for (auto &E : M)
  443. Sz += SPSArgList<SPSString, SPSValueT>::size(E.first(), E.second);
  444. return Sz;
  445. }
  446. static bool serialize(SPSOutputBuffer &OB, const StringMap<ValueT> &M) {
  447. if (!SPSArgList<uint64_t>::serialize(OB, static_cast<uint64_t>(M.size())))
  448. return false;
  449. for (auto &E : M)
  450. if (!SPSArgList<SPSString, SPSValueT>::serialize(OB, E.first(), E.second))
  451. return false;
  452. return true;
  453. }
  454. static bool deserialize(SPSInputBuffer &IB, StringMap<ValueT> &M) {
  455. uint64_t Size;
  456. assert(M.empty() && "M already contains elements");
  457. if (!SPSArgList<uint64_t>::deserialize(IB, Size))
  458. return false;
  459. while (Size--) {
  460. StringRef S;
  461. ValueT V;
  462. if (!SPSArgList<SPSString, SPSValueT>::deserialize(IB, S, V))
  463. return false;
  464. if (!M.insert(std::make_pair(S, V)).second)
  465. return false;
  466. }
  467. return true;
  468. }
  469. };
  470. /// SPS tag type for errors.
  471. class SPSError;
  472. /// SPS tag type for expecteds, which are either a T or a string representing
  473. /// an error.
  474. template <typename SPSTagT> class SPSExpected;
  475. namespace detail {
  476. /// Helper type for serializing Errors.
  477. ///
  478. /// llvm::Errors are move-only, and not inspectable except by consuming them.
  479. /// This makes them unsuitable for direct serialization via
  480. /// SPSSerializationTraits, which needs to inspect values twice (once to
  481. /// determine the amount of space to reserve, and then again to serialize).
  482. ///
  483. /// The SPSSerializableError type is a helper that can be
  484. /// constructed from an llvm::Error, but inspected more than once.
  485. struct SPSSerializableError {
  486. bool HasError = false;
  487. std::string ErrMsg;
  488. };
  489. /// Helper type for serializing Expected<T>s.
  490. ///
  491. /// See SPSSerializableError for more details.
  492. ///
  493. // FIXME: Use std::variant for storage once we have c++17.
  494. template <typename T> struct SPSSerializableExpected {
  495. bool HasValue = false;
  496. T Value{};
  497. std::string ErrMsg;
  498. };
  499. inline SPSSerializableError toSPSSerializable(Error Err) {
  500. if (Err)
  501. return {true, toString(std::move(Err))};
  502. return {false, {}};
  503. }
  504. inline Error fromSPSSerializable(SPSSerializableError BSE) {
  505. if (BSE.HasError)
  506. return make_error<StringError>(BSE.ErrMsg, inconvertibleErrorCode());
  507. return Error::success();
  508. }
  509. template <typename T>
  510. SPSSerializableExpected<T> toSPSSerializable(Expected<T> E) {
  511. if (E)
  512. return {true, std::move(*E), {}};
  513. else
  514. return {false, {}, toString(E.takeError())};
  515. }
  516. template <typename T>
  517. Expected<T> fromSPSSerializable(SPSSerializableExpected<T> BSE) {
  518. if (BSE.HasValue)
  519. return std::move(BSE.Value);
  520. else
  521. return make_error<StringError>(BSE.ErrMsg, inconvertibleErrorCode());
  522. }
  523. } // end namespace detail
  524. /// Serialize to a SPSError from a detail::SPSSerializableError.
  525. template <>
  526. class SPSSerializationTraits<SPSError, detail::SPSSerializableError> {
  527. public:
  528. static size_t size(const detail::SPSSerializableError &BSE) {
  529. size_t Size = SPSArgList<bool>::size(BSE.HasError);
  530. if (BSE.HasError)
  531. Size += SPSArgList<SPSString>::size(BSE.ErrMsg);
  532. return Size;
  533. }
  534. static bool serialize(SPSOutputBuffer &OB,
  535. const detail::SPSSerializableError &BSE) {
  536. if (!SPSArgList<bool>::serialize(OB, BSE.HasError))
  537. return false;
  538. if (BSE.HasError)
  539. if (!SPSArgList<SPSString>::serialize(OB, BSE.ErrMsg))
  540. return false;
  541. return true;
  542. }
  543. static bool deserialize(SPSInputBuffer &IB,
  544. detail::SPSSerializableError &BSE) {
  545. if (!SPSArgList<bool>::deserialize(IB, BSE.HasError))
  546. return false;
  547. if (!BSE.HasError)
  548. return true;
  549. return SPSArgList<SPSString>::deserialize(IB, BSE.ErrMsg);
  550. }
  551. };
  552. /// Serialize to a SPSExpected<SPSTagT> from a
  553. /// detail::SPSSerializableExpected<T>.
  554. template <typename SPSTagT, typename T>
  555. class SPSSerializationTraits<SPSExpected<SPSTagT>,
  556. detail::SPSSerializableExpected<T>> {
  557. public:
  558. static size_t size(const detail::SPSSerializableExpected<T> &BSE) {
  559. size_t Size = SPSArgList<bool>::size(BSE.HasValue);
  560. if (BSE.HasValue)
  561. Size += SPSArgList<SPSTagT>::size(BSE.Value);
  562. else
  563. Size += SPSArgList<SPSString>::size(BSE.ErrMsg);
  564. return Size;
  565. }
  566. static bool serialize(SPSOutputBuffer &OB,
  567. const detail::SPSSerializableExpected<T> &BSE) {
  568. if (!SPSArgList<bool>::serialize(OB, BSE.HasValue))
  569. return false;
  570. if (BSE.HasValue)
  571. return SPSArgList<SPSTagT>::serialize(OB, BSE.Value);
  572. return SPSArgList<SPSString>::serialize(OB, BSE.ErrMsg);
  573. }
  574. static bool deserialize(SPSInputBuffer &IB,
  575. detail::SPSSerializableExpected<T> &BSE) {
  576. if (!SPSArgList<bool>::deserialize(IB, BSE.HasValue))
  577. return false;
  578. if (BSE.HasValue)
  579. return SPSArgList<SPSTagT>::deserialize(IB, BSE.Value);
  580. return SPSArgList<SPSString>::deserialize(IB, BSE.ErrMsg);
  581. }
  582. };
  583. /// Serialize to a SPSExpected<SPSTagT> from a detail::SPSSerializableError.
  584. template <typename SPSTagT>
  585. class SPSSerializationTraits<SPSExpected<SPSTagT>,
  586. detail::SPSSerializableError> {
  587. public:
  588. static size_t size(const detail::SPSSerializableError &BSE) {
  589. assert(BSE.HasError && "Cannot serialize expected from a success value");
  590. return SPSArgList<bool>::size(false) +
  591. SPSArgList<SPSString>::size(BSE.ErrMsg);
  592. }
  593. static bool serialize(SPSOutputBuffer &OB,
  594. const detail::SPSSerializableError &BSE) {
  595. assert(BSE.HasError && "Cannot serialize expected from a success value");
  596. if (!SPSArgList<bool>::serialize(OB, false))
  597. return false;
  598. return SPSArgList<SPSString>::serialize(OB, BSE.ErrMsg);
  599. }
  600. };
  601. /// Serialize to a SPSExpected<SPSTagT> from a T.
  602. template <typename SPSTagT, typename T>
  603. class SPSSerializationTraits<SPSExpected<SPSTagT>, T> {
  604. public:
  605. static size_t size(const T &Value) {
  606. return SPSArgList<bool>::size(true) + SPSArgList<SPSTagT>::size(Value);
  607. }
  608. static bool serialize(SPSOutputBuffer &OB, const T &Value) {
  609. if (!SPSArgList<bool>::serialize(OB, true))
  610. return false;
  611. return SPSArgList<SPSTagT>::serialize(Value);
  612. }
  613. };
  614. } // end namespace shared
  615. } // end namespace orc
  616. } // end namespace llvm
  617. #endif // LLVM_EXECUTIONENGINE_ORC_SHARED_SIMPLEPACKEDSERIALIZATION_H
  618. #ifdef __GNUC__
  619. #pragma GCC diagnostic pop
  620. #endif