Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:43:51

0001 //===---- SimplePackedSerialization.h - simple serialization ----*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 // The behavior of the utilities in this header must be synchronized with the
0010 // behavior of the utilities in
0011 // compiler-rt/lib/orc/simple_packed_serialization.h.
0012 //
0013 // The Simple Packed Serialization (SPS) utilities are used to generate
0014 // argument and return buffers for wrapper functions using the following
0015 // serialization scheme:
0016 //
0017 // Primitives (signed types should be two's complement):
0018 //   bool, char, int8_t, uint8_t -- 8-bit (0=false, 1=true)
0019 //   int16_t, uint16_t           -- 16-bit little endian
0020 //   int32_t, uint32_t           -- 32-bit little endian
0021 //   int64_t, int64_t            -- 64-bit little endian
0022 //
0023 // Sequence<T>:
0024 //   Serialized as the sequence length (as a uint64_t) followed by the
0025 //   serialization of each of the elements without padding.
0026 //
0027 // Tuple<T1, ..., TN>:
0028 //   Serialized as each of the element types from T1 to TN without padding.
0029 //
0030 //===----------------------------------------------------------------------===//
0031 
0032 #ifndef LLVM_EXECUTIONENGINE_ORC_SHARED_SIMPLEPACKEDSERIALIZATION_H
0033 #define LLVM_EXECUTIONENGINE_ORC_SHARED_SIMPLEPACKEDSERIALIZATION_H
0034 
0035 #include "llvm/ADT/STLExtras.h"
0036 #include "llvm/ADT/SmallVector.h"
0037 #include "llvm/ADT/StringMap.h"
0038 #include "llvm/ADT/StringRef.h"
0039 #include "llvm/Support/Error.h"
0040 #include "llvm/Support/SwapByteOrder.h"
0041 
0042 #include <limits>
0043 #include <optional>
0044 #include <string>
0045 #include <tuple>
0046 #include <type_traits>
0047 #include <utility>
0048 #include <vector>
0049 
0050 namespace llvm {
0051 namespace orc {
0052 namespace shared {
0053 
0054 /// Output char buffer with overflow check.
0055 class SPSOutputBuffer {
0056 public:
0057   SPSOutputBuffer(char *Buffer, size_t Remaining)
0058       : Buffer(Buffer), Remaining(Remaining) {}
0059   bool write(const char *Data, size_t Size) {
0060     assert(Data && "Data must not be null");
0061     if (Size > Remaining)
0062       return false;
0063     memcpy(Buffer, Data, Size);
0064     Buffer += Size;
0065     Remaining -= Size;
0066     return true;
0067   }
0068 
0069 private:
0070   char *Buffer = nullptr;
0071   size_t Remaining = 0;
0072 };
0073 
0074 /// Input char buffer with underflow check.
0075 class SPSInputBuffer {
0076 public:
0077   SPSInputBuffer() = default;
0078   SPSInputBuffer(const char *Buffer, size_t Remaining)
0079       : Buffer(Buffer), Remaining(Remaining) {}
0080   bool read(char *Data, size_t Size) {
0081     if (Size > Remaining)
0082       return false;
0083     memcpy(Data, Buffer, Size);
0084     Buffer += Size;
0085     Remaining -= Size;
0086     return true;
0087   }
0088 
0089   const char *data() const { return Buffer; }
0090   bool skip(size_t Size) {
0091     if (Size > Remaining)
0092       return false;
0093     Buffer += Size;
0094     Remaining -= Size;
0095     return true;
0096   }
0097 
0098 private:
0099   const char *Buffer = nullptr;
0100   size_t Remaining = 0;
0101 };
0102 
0103 /// Specialize to describe how to serialize/deserialize to/from the given
0104 /// concrete type.
0105 template <typename SPSTagT, typename ConcreteT, typename _ = void>
0106 class SPSSerializationTraits;
0107 
0108 /// A utility class for serializing to a blob from a variadic list.
0109 template <typename... ArgTs> class SPSArgList;
0110 
0111 // Empty list specialization for SPSArgList.
0112 template <> class SPSArgList<> {
0113 public:
0114   static size_t size() { return 0; }
0115 
0116   static bool serialize(SPSOutputBuffer &OB) { return true; }
0117   static bool deserialize(SPSInputBuffer &IB) { return true; }
0118 
0119   static bool serializeToSmallVector(SmallVectorImpl<char> &V) { return true; }
0120 
0121   static bool deserializeFromSmallVector(const SmallVectorImpl<char> &V) {
0122     return true;
0123   }
0124 };
0125 
0126 // Non-empty list specialization for SPSArgList.
0127 template <typename SPSTagT, typename... SPSTagTs>
0128 class SPSArgList<SPSTagT, SPSTagTs...> {
0129 public:
0130   // FIXME: This typedef is here to enable SPS arg serialization from
0131   // JITLink. It can be removed once JITLink can access SPS directly.
0132   using OutputBuffer = SPSOutputBuffer;
0133 
0134   template <typename ArgT, typename... ArgTs>
0135   static size_t size(const ArgT &Arg, const ArgTs &...Args) {
0136     return SPSSerializationTraits<SPSTagT, ArgT>::size(Arg) +
0137            SPSArgList<SPSTagTs...>::size(Args...);
0138   }
0139 
0140   template <typename ArgT, typename... ArgTs>
0141   static bool serialize(SPSOutputBuffer &OB, const ArgT &Arg,
0142                         const ArgTs &...Args) {
0143     return SPSSerializationTraits<SPSTagT, ArgT>::serialize(OB, Arg) &&
0144            SPSArgList<SPSTagTs...>::serialize(OB, Args...);
0145   }
0146 
0147   template <typename ArgT, typename... ArgTs>
0148   static bool deserialize(SPSInputBuffer &IB, ArgT &Arg, ArgTs &...Args) {
0149     return SPSSerializationTraits<SPSTagT, ArgT>::deserialize(IB, Arg) &&
0150            SPSArgList<SPSTagTs...>::deserialize(IB, Args...);
0151   }
0152 };
0153 
0154 /// SPS serialization for integral types, bool, and char.
0155 template <typename SPSTagT>
0156 class SPSSerializationTraits<
0157     SPSTagT, SPSTagT,
0158     std::enable_if_t<std::is_same<SPSTagT, bool>::value ||
0159                      std::is_same<SPSTagT, char>::value ||
0160                      std::is_same<SPSTagT, int8_t>::value ||
0161                      std::is_same<SPSTagT, int16_t>::value ||
0162                      std::is_same<SPSTagT, int32_t>::value ||
0163                      std::is_same<SPSTagT, int64_t>::value ||
0164                      std::is_same<SPSTagT, uint8_t>::value ||
0165                      std::is_same<SPSTagT, uint16_t>::value ||
0166                      std::is_same<SPSTagT, uint32_t>::value ||
0167                      std::is_same<SPSTagT, uint64_t>::value>> {
0168 public:
0169   static size_t size(const SPSTagT &Value) { return sizeof(SPSTagT); }
0170 
0171   static bool serialize(SPSOutputBuffer &OB, const SPSTagT &Value) {
0172     SPSTagT Tmp = Value;
0173     if (sys::IsBigEndianHost)
0174       sys::swapByteOrder(Tmp);
0175     return OB.write(reinterpret_cast<const char *>(&Tmp), sizeof(Tmp));
0176   }
0177 
0178   static bool deserialize(SPSInputBuffer &IB, SPSTagT &Value) {
0179     SPSTagT Tmp;
0180     if (!IB.read(reinterpret_cast<char *>(&Tmp), sizeof(Tmp)))
0181       return false;
0182     if (sys::IsBigEndianHost)
0183       sys::swapByteOrder(Tmp);
0184     Value = Tmp;
0185     return true;
0186   }
0187 };
0188 
0189 // Any empty placeholder suitable as a substitute for void when deserializing
0190 class SPSEmpty {};
0191 
0192 /// SPS tag type for tuples.
0193 ///
0194 /// A blob tuple should be serialized by serializing each of the elements in
0195 /// sequence.
0196 template <typename... SPSTagTs> class SPSTuple {
0197 public:
0198   /// Convenience typedef of the corresponding arg list.
0199   typedef SPSArgList<SPSTagTs...> AsArgList;
0200 };
0201 
0202 /// SPS tag type for optionals.
0203 ///
0204 /// SPSOptionals should be serialized as a bool with true indicating that an
0205 /// SPSTagT value is present, and false indicating that there is no value.
0206 /// If the boolean is true then the serialized SPSTagT will follow immediately
0207 /// after it.
0208 template <typename SPSTagT> class SPSOptional {};
0209 
0210 /// SPS tag type for sequences.
0211 ///
0212 /// SPSSequences should be serialized as a uint64_t sequence length,
0213 /// followed by the serialization of each of the elements.
0214 template <typename SPSElementTagT> class SPSSequence;
0215 
0216 /// SPS tag type for strings, which are equivalent to sequences of chars.
0217 using SPSString = SPSSequence<char>;
0218 
0219 /// SPS tag type for maps.
0220 ///
0221 /// SPS maps are just sequences of (Key, Value) tuples.
0222 template <typename SPSTagT1, typename SPSTagT2>
0223 using SPSMap = SPSSequence<SPSTuple<SPSTagT1, SPSTagT2>>;
0224 
0225 /// Serialization for SPSEmpty type.
0226 template <> class SPSSerializationTraits<SPSEmpty, SPSEmpty> {
0227 public:
0228   static size_t size(const SPSEmpty &EP) { return 0; }
0229   static bool serialize(SPSOutputBuffer &OB, const SPSEmpty &BE) {
0230     return true;
0231   }
0232   static bool deserialize(SPSInputBuffer &IB, SPSEmpty &BE) { return true; }
0233 };
0234 
0235 /// Specialize this to implement 'trivial' sequence serialization for
0236 /// a concrete sequence type.
0237 ///
0238 /// Trivial sequence serialization uses the sequence's 'size' member to get the
0239 /// length of the sequence, and uses a range-based for loop to iterate over the
0240 /// elements.
0241 ///
0242 /// Specializing this template class means that you do not need to provide a
0243 /// specialization of SPSSerializationTraits for your type.
0244 template <typename SPSElementTagT, typename ConcreteSequenceT>
0245 class TrivialSPSSequenceSerialization {
0246 public:
0247   static constexpr bool available = false;
0248 };
0249 
0250 /// Specialize this to implement 'trivial' sequence deserialization for
0251 /// a concrete sequence type.
0252 ///
0253 /// Trivial deserialization calls a static 'reserve(SequenceT&)' method on your
0254 /// specialization (you must implement this) to reserve space, and then calls
0255 /// a static 'append(SequenceT&, ElementT&) method to append each of the
0256 /// deserialized elements.
0257 ///
0258 /// Specializing this template class means that you do not need to provide a
0259 /// specialization of SPSSerializationTraits for your type.
0260 template <typename SPSElementTagT, typename ConcreteSequenceT>
0261 class TrivialSPSSequenceDeserialization {
0262 public:
0263   static constexpr bool available = false;
0264 };
0265 
0266 /// Trivial std::string -> SPSSequence<char> serialization.
0267 template <> class TrivialSPSSequenceSerialization<char, std::string> {
0268 public:
0269   static constexpr bool available = true;
0270 };
0271 
0272 /// Trivial SPSSequence<char> -> std::string deserialization.
0273 template <> class TrivialSPSSequenceDeserialization<char, std::string> {
0274 public:
0275   static constexpr bool available = true;
0276 
0277   using element_type = char;
0278 
0279   static void reserve(std::string &S, uint64_t Size) { S.reserve(Size); }
0280   static bool append(std::string &S, char C) {
0281     S.push_back(C);
0282     return true;
0283   }
0284 };
0285 
0286 /// Trivial std::vector<T> -> SPSSequence<SPSElementTagT> serialization.
0287 template <typename SPSElementTagT, typename T>
0288 class TrivialSPSSequenceSerialization<SPSElementTagT, std::vector<T>> {
0289 public:
0290   static constexpr bool available = true;
0291 };
0292 
0293 /// Trivial SPSSequence<SPSElementTagT> -> std::vector<T> deserialization.
0294 template <typename SPSElementTagT, typename T>
0295 class TrivialSPSSequenceDeserialization<SPSElementTagT, std::vector<T>> {
0296 public:
0297   static constexpr bool available = true;
0298 
0299   using element_type = typename std::vector<T>::value_type;
0300 
0301   static void reserve(std::vector<T> &V, uint64_t Size) { V.reserve(Size); }
0302   static bool append(std::vector<T> &V, T E) {
0303     V.push_back(std::move(E));
0304     return true;
0305   }
0306 };
0307 
0308 /// Trivial SmallVectorImpl<T> -> SPSSequence<char> serialization.
0309 template <typename SPSElementTagT, typename T>
0310 class TrivialSPSSequenceSerialization<SPSElementTagT, SmallVectorImpl<T>> {
0311 public:
0312   static constexpr bool available = true;
0313 };
0314 
0315 /// Trivial SPSSequence<SPSElementTagT> -> SmallVectorImpl<T> deserialization.
0316 template <typename SPSElementTagT, typename T>
0317 class TrivialSPSSequenceDeserialization<SPSElementTagT, SmallVectorImpl<T>> {
0318 public:
0319   static constexpr bool available = true;
0320 
0321   using element_type = typename SmallVectorImpl<T>::value_type;
0322 
0323   static void reserve(SmallVectorImpl<T> &V, uint64_t Size) { V.reserve(Size); }
0324   static bool append(SmallVectorImpl<T> &V, T E) {
0325     V.push_back(std::move(E));
0326     return true;
0327   }
0328 };
0329 
0330 /// Trivial SmallVectorImpl<T> -> SPSSequence<char> serialization.
0331 template <typename SPSElementTagT, typename T, unsigned N>
0332 class TrivialSPSSequenceSerialization<SPSElementTagT, SmallVector<T, N>>
0333     : public TrivialSPSSequenceSerialization<SPSElementTagT,
0334                                              SmallVectorImpl<T>> {};
0335 
0336 /// Trivial SPSSequence<SPSElementTagT> -> SmallVectorImpl<T> deserialization.
0337 template <typename SPSElementTagT, typename T, unsigned N>
0338 class TrivialSPSSequenceDeserialization<SPSElementTagT, SmallVector<T, N>>
0339     : public TrivialSPSSequenceDeserialization<SPSElementTagT,
0340                                                SmallVectorImpl<T>> {};
0341 
0342 /// Trivial ArrayRef<T> -> SPSSequence<SPSElementTagT> serialization.
0343 template <typename SPSElementTagT, typename T>
0344 class TrivialSPSSequenceSerialization<SPSElementTagT, ArrayRef<T>> {
0345 public:
0346   static constexpr bool available = true;
0347 };
0348 
0349 /// Specialized SPSSequence<char> -> ArrayRef<char> serialization.
0350 ///
0351 /// On deserialize, points directly into the input buffer.
0352 template <> class SPSSerializationTraits<SPSSequence<char>, ArrayRef<char>> {
0353 public:
0354   static size_t size(const ArrayRef<char> &A) {
0355     return SPSArgList<uint64_t>::size(static_cast<uint64_t>(A.size())) +
0356            A.size();
0357   }
0358 
0359   static bool serialize(SPSOutputBuffer &OB, const ArrayRef<char> &A) {
0360     if (!SPSArgList<uint64_t>::serialize(OB, static_cast<uint64_t>(A.size())))
0361       return false;
0362     if (A.empty()) // Empty ArrayRef may have null data, so bail out early.
0363       return true;
0364     return OB.write(A.data(), A.size());
0365   }
0366 
0367   static bool deserialize(SPSInputBuffer &IB, ArrayRef<char> &A) {
0368     uint64_t Size;
0369     if (!SPSArgList<uint64_t>::deserialize(IB, Size))
0370       return false;
0371     if (Size > std::numeric_limits<size_t>::max())
0372       return false;
0373     A = {Size ? IB.data() : nullptr, static_cast<size_t>(Size)};
0374     return IB.skip(Size);
0375   }
0376 };
0377 
0378 /// 'Trivial' sequence serialization: Sequence is serialized as a uint64_t size
0379 /// followed by a for-earch loop over the elements of the sequence to serialize
0380 /// each of them.
0381 template <typename SPSElementTagT, typename SequenceT>
0382 class SPSSerializationTraits<SPSSequence<SPSElementTagT>, SequenceT,
0383                              std::enable_if_t<TrivialSPSSequenceSerialization<
0384                                  SPSElementTagT, SequenceT>::available>> {
0385 public:
0386   static size_t size(const SequenceT &S) {
0387     size_t Size = SPSArgList<uint64_t>::size(static_cast<uint64_t>(S.size()));
0388     for (const auto &E : S)
0389       Size += SPSArgList<SPSElementTagT>::size(E);
0390     return Size;
0391   }
0392 
0393   static bool serialize(SPSOutputBuffer &OB, const SequenceT &S) {
0394     if (!SPSArgList<uint64_t>::serialize(OB, static_cast<uint64_t>(S.size())))
0395       return false;
0396     for (const auto &E : S)
0397       if (!SPSArgList<SPSElementTagT>::serialize(OB, E))
0398         return false;
0399     return true;
0400   }
0401 
0402   static bool deserialize(SPSInputBuffer &IB, SequenceT &S) {
0403     using TBSD = TrivialSPSSequenceDeserialization<SPSElementTagT, SequenceT>;
0404     uint64_t Size;
0405     if (!SPSArgList<uint64_t>::deserialize(IB, Size))
0406       return false;
0407     TBSD::reserve(S, Size);
0408     for (size_t I = 0; I != Size; ++I) {
0409       typename TBSD::element_type E;
0410       if (!SPSArgList<SPSElementTagT>::deserialize(IB, E))
0411         return false;
0412       if (!TBSD::append(S, std::move(E)))
0413         return false;
0414     }
0415     return true;
0416   }
0417 };
0418 
0419 /// SPSTuple serialization for std::tuple.
0420 template <typename... SPSTagTs, typename... Ts>
0421 class SPSSerializationTraits<SPSTuple<SPSTagTs...>, std::tuple<Ts...>> {
0422 private:
0423   using TupleArgList = typename SPSTuple<SPSTagTs...>::AsArgList;
0424   using ArgIndices = std::make_index_sequence<sizeof...(Ts)>;
0425 
0426   template <std::size_t... I>
0427   static size_t size(const std::tuple<Ts...> &T, std::index_sequence<I...>) {
0428     return TupleArgList::size(std::get<I>(T)...);
0429   }
0430 
0431   template <std::size_t... I>
0432   static bool serialize(SPSOutputBuffer &OB, const std::tuple<Ts...> &T,
0433                         std::index_sequence<I...>) {
0434     return TupleArgList::serialize(OB, std::get<I>(T)...);
0435   }
0436 
0437   template <std::size_t... I>
0438   static bool deserialize(SPSInputBuffer &IB, std::tuple<Ts...> &T,
0439                           std::index_sequence<I...>) {
0440     return TupleArgList::deserialize(IB, std::get<I>(T)...);
0441   }
0442 
0443 public:
0444   static size_t size(const std::tuple<Ts...> &T) {
0445     return size(T, ArgIndices{});
0446   }
0447 
0448   static bool serialize(SPSOutputBuffer &OB, const std::tuple<Ts...> &T) {
0449     return serialize(OB, T, ArgIndices{});
0450   }
0451 
0452   static bool deserialize(SPSInputBuffer &IB, std::tuple<Ts...> &T) {
0453     return deserialize(IB, T, ArgIndices{});
0454   }
0455 };
0456 
0457 /// SPSTuple serialization for std::pair.
0458 template <typename SPSTagT1, typename SPSTagT2, typename T1, typename T2>
0459 class SPSSerializationTraits<SPSTuple<SPSTagT1, SPSTagT2>, std::pair<T1, T2>> {
0460 public:
0461   static size_t size(const std::pair<T1, T2> &P) {
0462     return SPSArgList<SPSTagT1>::size(P.first) +
0463            SPSArgList<SPSTagT2>::size(P.second);
0464   }
0465 
0466   static bool serialize(SPSOutputBuffer &OB, const std::pair<T1, T2> &P) {
0467     return SPSArgList<SPSTagT1>::serialize(OB, P.first) &&
0468            SPSArgList<SPSTagT2>::serialize(OB, P.second);
0469   }
0470 
0471   static bool deserialize(SPSInputBuffer &IB, std::pair<T1, T2> &P) {
0472     return SPSArgList<SPSTagT1>::deserialize(IB, P.first) &&
0473            SPSArgList<SPSTagT2>::deserialize(IB, P.second);
0474   }
0475 };
0476 
0477 /// SPSOptional serialization for std::optional.
0478 template <typename SPSTagT, typename T>
0479 class SPSSerializationTraits<SPSOptional<SPSTagT>, std::optional<T>> {
0480 public:
0481   static size_t size(const std::optional<T> &Value) {
0482     size_t Size = SPSArgList<bool>::size(!!Value);
0483     if (Value)
0484       Size += SPSArgList<SPSTagT>::size(*Value);
0485     return Size;
0486   }
0487 
0488   static bool serialize(SPSOutputBuffer &OB, const std::optional<T> &Value) {
0489     if (!SPSArgList<bool>::serialize(OB, !!Value))
0490       return false;
0491     if (Value)
0492       return SPSArgList<SPSTagT>::serialize(OB, *Value);
0493     return true;
0494   }
0495 
0496   static bool deserialize(SPSInputBuffer &IB, std::optional<T> &Value) {
0497     bool HasValue;
0498     if (!SPSArgList<bool>::deserialize(IB, HasValue))
0499       return false;
0500     if (HasValue) {
0501       Value = T();
0502       return SPSArgList<SPSTagT>::deserialize(IB, *Value);
0503     } else
0504       Value = std::optional<T>();
0505     return true;
0506   }
0507 };
0508 
0509 /// Serialization for StringRefs.
0510 ///
0511 /// Serialization is as for regular strings. Deserialization points directly
0512 /// into the blob.
0513 template <> class SPSSerializationTraits<SPSString, StringRef> {
0514 public:
0515   static size_t size(const StringRef &S) {
0516     return SPSArgList<uint64_t>::size(static_cast<uint64_t>(S.size())) +
0517            S.size();
0518   }
0519 
0520   static bool serialize(SPSOutputBuffer &OB, StringRef S) {
0521     if (!SPSArgList<uint64_t>::serialize(OB, static_cast<uint64_t>(S.size())))
0522       return false;
0523     if (S.empty()) // Empty StringRef may have null data, so bail out early.
0524       return true;
0525     return OB.write(S.data(), S.size());
0526   }
0527 
0528   static bool deserialize(SPSInputBuffer &IB, StringRef &S) {
0529     const char *Data = nullptr;
0530     uint64_t Size;
0531     if (!SPSArgList<uint64_t>::deserialize(IB, Size))
0532       return false;
0533     Data = IB.data();
0534     if (!IB.skip(Size))
0535       return false;
0536     S = StringRef(Size ? Data : nullptr, Size);
0537     return true;
0538   }
0539 };
0540 
0541 /// Serialization for StringMap<ValueT>s.
0542 template <typename SPSValueT, typename ValueT>
0543 class SPSSerializationTraits<SPSSequence<SPSTuple<SPSString, SPSValueT>>,
0544                              StringMap<ValueT>> {
0545 public:
0546   static size_t size(const StringMap<ValueT> &M) {
0547     size_t Sz = SPSArgList<uint64_t>::size(static_cast<uint64_t>(M.size()));
0548     for (auto &E : M)
0549       Sz += SPSArgList<SPSString, SPSValueT>::size(E.first(), E.second);
0550     return Sz;
0551   }
0552 
0553   static bool serialize(SPSOutputBuffer &OB, const StringMap<ValueT> &M) {
0554     if (!SPSArgList<uint64_t>::serialize(OB, static_cast<uint64_t>(M.size())))
0555       return false;
0556 
0557     for (auto &E : M)
0558       if (!SPSArgList<SPSString, SPSValueT>::serialize(OB, E.first(), E.second))
0559         return false;
0560 
0561     return true;
0562   }
0563 
0564   static bool deserialize(SPSInputBuffer &IB, StringMap<ValueT> &M) {
0565     uint64_t Size;
0566     assert(M.empty() && "M already contains elements");
0567 
0568     if (!SPSArgList<uint64_t>::deserialize(IB, Size))
0569       return false;
0570 
0571     while (Size--) {
0572       StringRef S;
0573       ValueT V;
0574       if (!SPSArgList<SPSString, SPSValueT>::deserialize(IB, S, V))
0575         return false;
0576       if (!M.insert(std::make_pair(S, V)).second)
0577         return false;
0578     }
0579 
0580     return true;
0581   }
0582 };
0583 
0584 /// SPS tag type for errors.
0585 class SPSError;
0586 
0587 /// SPS tag type for expecteds, which are either a T or a string representing
0588 /// an error.
0589 template <typename SPSTagT> class SPSExpected;
0590 
0591 namespace detail {
0592 
0593 /// Helper type for serializing Errors.
0594 ///
0595 /// llvm::Errors are move-only, and not inspectable except by consuming them.
0596 /// This makes them unsuitable for direct serialization via
0597 /// SPSSerializationTraits, which needs to inspect values twice (once to
0598 /// determine the amount of space to reserve, and then again to serialize).
0599 ///
0600 /// The SPSSerializableError type is a helper that can be
0601 /// constructed from an llvm::Error, but inspected more than once.
0602 struct SPSSerializableError {
0603   bool HasError = false;
0604   std::string ErrMsg;
0605 };
0606 
0607 /// Helper type for serializing Expected<T>s.
0608 ///
0609 /// See SPSSerializableError for more details.
0610 ///
0611 // FIXME: Use std::variant for storage once we have c++17.
0612 template <typename T> struct SPSSerializableExpected {
0613   bool HasValue = false;
0614   T Value{};
0615   std::string ErrMsg;
0616 };
0617 
0618 inline SPSSerializableError toSPSSerializable(Error Err) {
0619   if (Err)
0620     return {true, toString(std::move(Err))};
0621   return {false, {}};
0622 }
0623 
0624 inline Error fromSPSSerializable(SPSSerializableError BSE) {
0625   if (BSE.HasError)
0626     return make_error<StringError>(BSE.ErrMsg, inconvertibleErrorCode());
0627   return Error::success();
0628 }
0629 
0630 template <typename T>
0631 SPSSerializableExpected<T> toSPSSerializable(Expected<T> E) {
0632   if (E)
0633     return {true, std::move(*E), {}};
0634   else
0635     return {false, T(), toString(E.takeError())};
0636 }
0637 
0638 template <typename T>
0639 Expected<T> fromSPSSerializable(SPSSerializableExpected<T> BSE) {
0640   if (BSE.HasValue)
0641     return std::move(BSE.Value);
0642   else
0643     return make_error<StringError>(BSE.ErrMsg, inconvertibleErrorCode());
0644 }
0645 
0646 } // end namespace detail
0647 
0648 /// Serialize to a SPSError from a detail::SPSSerializableError.
0649 template <>
0650 class SPSSerializationTraits<SPSError, detail::SPSSerializableError> {
0651 public:
0652   static size_t size(const detail::SPSSerializableError &BSE) {
0653     size_t Size = SPSArgList<bool>::size(BSE.HasError);
0654     if (BSE.HasError)
0655       Size += SPSArgList<SPSString>::size(BSE.ErrMsg);
0656     return Size;
0657   }
0658 
0659   static bool serialize(SPSOutputBuffer &OB,
0660                         const detail::SPSSerializableError &BSE) {
0661     if (!SPSArgList<bool>::serialize(OB, BSE.HasError))
0662       return false;
0663     if (BSE.HasError)
0664       if (!SPSArgList<SPSString>::serialize(OB, BSE.ErrMsg))
0665         return false;
0666     return true;
0667   }
0668 
0669   static bool deserialize(SPSInputBuffer &IB,
0670                           detail::SPSSerializableError &BSE) {
0671     if (!SPSArgList<bool>::deserialize(IB, BSE.HasError))
0672       return false;
0673 
0674     if (!BSE.HasError)
0675       return true;
0676 
0677     return SPSArgList<SPSString>::deserialize(IB, BSE.ErrMsg);
0678   }
0679 };
0680 
0681 /// Serialize to a SPSExpected<SPSTagT> from a
0682 /// detail::SPSSerializableExpected<T>.
0683 template <typename SPSTagT, typename T>
0684 class SPSSerializationTraits<SPSExpected<SPSTagT>,
0685                              detail::SPSSerializableExpected<T>> {
0686 public:
0687   static size_t size(const detail::SPSSerializableExpected<T> &BSE) {
0688     size_t Size = SPSArgList<bool>::size(BSE.HasValue);
0689     if (BSE.HasValue)
0690       Size += SPSArgList<SPSTagT>::size(BSE.Value);
0691     else
0692       Size += SPSArgList<SPSString>::size(BSE.ErrMsg);
0693     return Size;
0694   }
0695 
0696   static bool serialize(SPSOutputBuffer &OB,
0697                         const detail::SPSSerializableExpected<T> &BSE) {
0698     if (!SPSArgList<bool>::serialize(OB, BSE.HasValue))
0699       return false;
0700 
0701     if (BSE.HasValue)
0702       return SPSArgList<SPSTagT>::serialize(OB, BSE.Value);
0703 
0704     return SPSArgList<SPSString>::serialize(OB, BSE.ErrMsg);
0705   }
0706 
0707   static bool deserialize(SPSInputBuffer &IB,
0708                           detail::SPSSerializableExpected<T> &BSE) {
0709     if (!SPSArgList<bool>::deserialize(IB, BSE.HasValue))
0710       return false;
0711 
0712     if (BSE.HasValue)
0713       return SPSArgList<SPSTagT>::deserialize(IB, BSE.Value);
0714 
0715     return SPSArgList<SPSString>::deserialize(IB, BSE.ErrMsg);
0716   }
0717 };
0718 
0719 /// Serialize to a SPSExpected<SPSTagT> from a detail::SPSSerializableError.
0720 template <typename SPSTagT>
0721 class SPSSerializationTraits<SPSExpected<SPSTagT>,
0722                              detail::SPSSerializableError> {
0723 public:
0724   static size_t size(const detail::SPSSerializableError &BSE) {
0725     assert(BSE.HasError && "Cannot serialize expected from a success value");
0726     return SPSArgList<bool>::size(false) +
0727            SPSArgList<SPSString>::size(BSE.ErrMsg);
0728   }
0729 
0730   static bool serialize(SPSOutputBuffer &OB,
0731                         const detail::SPSSerializableError &BSE) {
0732     assert(BSE.HasError && "Cannot serialize expected from a success value");
0733     if (!SPSArgList<bool>::serialize(OB, false))
0734       return false;
0735     return SPSArgList<SPSString>::serialize(OB, BSE.ErrMsg);
0736   }
0737 };
0738 
0739 /// Serialize to a SPSExpected<SPSTagT> from a T.
0740 template <typename SPSTagT, typename T>
0741 class SPSSerializationTraits<SPSExpected<SPSTagT>, T> {
0742 public:
0743   static size_t size(const T &Value) {
0744     return SPSArgList<bool>::size(true) + SPSArgList<SPSTagT>::size(Value);
0745   }
0746 
0747   static bool serialize(SPSOutputBuffer &OB, const T &Value) {
0748     if (!SPSArgList<bool>::serialize(OB, true))
0749       return false;
0750     return SPSArgList<SPSTagT>::serialize(Value);
0751   }
0752 };
0753 
0754 } // end namespace shared
0755 } // end namespace orc
0756 } // end namespace llvm
0757 
0758 #endif // LLVM_EXECUTIONENGINE_ORC_SHARED_SIMPLEPACKEDSERIALIZATION_H