//===---- SimplePackedSerialization.h - simple serialization ----*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // The behavior of the utilities in this header must be synchronized with the // behavior of the utilities in // compiler-rt/lib/orc/simple_packed_serialization.h. // // The Simple Packed Serialization (SPS) utilities are used to generate // argument and return buffers for wrapper functions using the following // serialization scheme: // // Primitives (signed types should be two's complement): // bool, char, int8_t, uint8_t -- 8-bit (0=false, 1=true) // int16_t, uint16_t -- 16-bit little endian // int32_t, uint32_t -- 32-bit little endian // int64_t, int64_t -- 64-bit little endian // // Sequence<T>: // Serialized as the sequence length (as a uint64_t) followed by the // serialization of each of the elements without padding. // // Tuple<T1, ..., TN>: // Serialized as each of the element types from T1 to TN without padding. // //===----------------------------------------------------------------------===// #ifndef LLVM_EXECUTIONENGINE_ORC_SHARED_SIMPLEPACKEDSERIALIZATION_H #define LLVM_EXECUTIONENGINE_ORC_SHARED_SIMPLEPACKEDSERIALIZATION_H #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Error.h" #include "llvm/Support/SwapByteOrder.h" #include <limits> #include <optional> #include <string> #include <tuple> #include <type_traits> #include <utility> #include <vector> namespace llvm { namespace orc { namespace shared { /// Output char buffer with overflow check. class SPSOutputBuffer { … }; /// Input char buffer with underflow check. class SPSInputBuffer { … }; /// Specialize to describe how to serialize/deserialize to/from the given /// concrete type. template <typename SPSTagT, typename ConcreteT, typename _ = void> class SPSSerializationTraits; /// A utility class for serializing to a blob from a variadic list. template <typename... ArgTs> class SPSArgList; // Empty list specialization for SPSArgList. template <> class SPSArgList<> { … }; // Non-empty list specialization for SPSArgList. SPSArgList<SPSTagT, SPSTagTs...>; /// SPS serialization for integral types, bool, and char. SPSSerializationTraits<SPSTagT, SPSTagT, std::enable_if_t<std::is_same<SPSTagT, bool>::value || std::is_same<SPSTagT, char>::value || std::is_same<SPSTagT, int8_t>::value || std::is_same<SPSTagT, int16_t>::value || std::is_same<SPSTagT, int32_t>::value || std::is_same<SPSTagT, int64_t>::value || std::is_same<SPSTagT, uint8_t>::value || std::is_same<SPSTagT, uint16_t>::value || std::is_same<SPSTagT, uint32_t>::value || std::is_same<SPSTagT, uint64_t>::value>>; // Any empty placeholder suitable as a substitute for void when deserializing class SPSEmpty { … }; /// SPS tag type for tuples. /// /// A blob tuple should be serialized by serializing each of the elements in /// sequence. template <typename... SPSTagTs> class SPSTuple { … }; /// SPS tag type for optionals. /// /// SPSOptionals should be serialized as a bool with true indicating that an /// SPSTagT value is present, and false indicating that there is no value. /// If the boolean is true then the serialized SPSTagT will follow immediately /// after it. template <typename SPSTagT> class SPSOptional { … }; /// SPS tag type for sequences. /// /// SPSSequences should be serialized as a uint64_t sequence length, /// followed by the serialization of each of the elements. template <typename SPSElementTagT> class SPSSequence; /// SPS tag type for strings, which are equivalent to sequences of chars. SPSString; /// SPS tag type for maps. /// /// SPS maps are just sequences of (Key, Value) tuples. SPSMap; /// Serialization for SPSEmpty type. template <> class SPSSerializationTraits<SPSEmpty, SPSEmpty> { … }; /// Specialize this to implement 'trivial' sequence serialization for /// a concrete sequence type. /// /// Trivial sequence serialization uses the sequence's 'size' member to get the /// length of the sequence, and uses a range-based for loop to iterate over the /// elements. /// /// Specializing this template class means that you do not need to provide a /// specialization of SPSSerializationTraits for your type. template <typename SPSElementTagT, typename ConcreteSequenceT> class TrivialSPSSequenceSerialization { … }; /// Specialize this to implement 'trivial' sequence deserialization for /// a concrete sequence type. /// /// Trivial deserialization calls a static 'reserve(SequenceT&)' method on your /// specialization (you must implement this) to reserve space, and then calls /// a static 'append(SequenceT&, ElementT&) method to append each of the /// deserialized elements. /// /// Specializing this template class means that you do not need to provide a /// specialization of SPSSerializationTraits for your type. template <typename SPSElementTagT, typename ConcreteSequenceT> class TrivialSPSSequenceDeserialization { … }; /// Trivial std::string -> SPSSequence<char> serialization. template <> class TrivialSPSSequenceSerialization<char, std::string> { … }; /// Trivial SPSSequence<char> -> std::string deserialization. template <> class TrivialSPSSequenceDeserialization<char, std::string> { … }; /// Trivial std::vector<T> -> SPSSequence<SPSElementTagT> serialization. TrivialSPSSequenceSerialization<SPSElementTagT, std::vector<T>>; /// Trivial SPSSequence<SPSElementTagT> -> std::vector<T> deserialization. TrivialSPSSequenceDeserialization<SPSElementTagT, std::vector<T>>; /// Trivial SmallVectorImpl<T> -> SPSSequence<char> serialization. TrivialSPSSequenceSerialization<SPSElementTagT, SmallVectorImpl<T>>; /// Trivial SPSSequence<SPSElementTagT> -> SmallVectorImpl<T> deserialization. TrivialSPSSequenceDeserialization<SPSElementTagT, SmallVectorImpl<T>>; /// Trivial SmallVectorImpl<T> -> SPSSequence<char> serialization. TrivialSPSSequenceSerialization<SPSElementTagT, SmallVector<T, N>>; /// Trivial SPSSequence<SPSElementTagT> -> SmallVectorImpl<T> deserialization. TrivialSPSSequenceDeserialization<SPSElementTagT, SmallVector<T, N>>; /// Trivial ArrayRef<T> -> SPSSequence<SPSElementTagT> serialization. TrivialSPSSequenceSerialization<SPSElementTagT, ArrayRef<T>>; /// Specialized SPSSequence<char> -> ArrayRef<char> serialization. /// /// On deserialize, points directly into the input buffer. template <> class SPSSerializationTraits<SPSSequence<char>, ArrayRef<char>> { … }; /// 'Trivial' sequence serialization: Sequence is serialized as a uint64_t size /// followed by a for-earch loop over the elements of the sequence to serialize /// each of them. SPSSerializationTraits<SPSSequence<SPSElementTagT>, SequenceT, std::enable_if_t<TrivialSPSSequenceSerialization<SPSElementTagT, SequenceT>::available>>; /// SPSTuple serialization for std::tuple. SPSSerializationTraits<SPSTuple<SPSTagTs...>, std::tuple<Ts...>>; /// SPSTuple serialization for std::pair. SPSSerializationTraits<SPSTuple<SPSTagT1, SPSTagT2>, std::pair<T1, T2>>; /// SPSOptional serialization for std::optional. SPSSerializationTraits<SPSOptional<SPSTagT>, std::optional<T>>; /// Serialization for StringRefs. /// /// Serialization is as for regular strings. Deserialization points directly /// into the blob. template <> class SPSSerializationTraits<SPSString, StringRef> { … }; /// Serialization for StringMap<ValueT>s. SPSSerializationTraits<SPSSequence<SPSTuple<SPSString, SPSValueT>>, StringMap<ValueT>>; /// SPS tag type for errors. class SPSError; /// SPS tag type for expecteds, which are either a T or a string representing /// an error. template <typename SPSTagT> class SPSExpected; namespace detail { /// Helper type for serializing Errors. /// /// llvm::Errors are move-only, and not inspectable except by consuming them. /// This makes them unsuitable for direct serialization via /// SPSSerializationTraits, which needs to inspect values twice (once to /// determine the amount of space to reserve, and then again to serialize). /// /// The SPSSerializableError type is a helper that can be /// constructed from an llvm::Error, but inspected more than once. struct SPSSerializableError { … }; /// Helper type for serializing Expected<T>s. /// /// See SPSSerializableError for more details. /// // FIXME: Use std::variant for storage once we have c++17. template <typename T> struct SPSSerializableExpected { … }; inline SPSSerializableError toSPSSerializable(Error Err) { … } inline Error fromSPSSerializable(SPSSerializableError BSE) { … } template <typename T> SPSSerializableExpected<T> toSPSSerializable(Expected<T> E) { … } template <typename T> Expected<T> fromSPSSerializable(SPSSerializableExpected<T> BSE) { … } } // end namespace detail /// Serialize to a SPSError from a detail::SPSSerializableError. template <> class SPSSerializationTraits<SPSError, detail::SPSSerializableError> { … }; /// Serialize to a SPSExpected<SPSTagT> from a /// detail::SPSSerializableExpected<T>. SPSSerializationTraits<SPSExpected<SPSTagT>, detail::SPSSerializableExpected<T>>; /// Serialize to a SPSExpected<SPSTagT> from a detail::SPSSerializableError. SPSSerializationTraits<SPSExpected<SPSTagT>, detail::SPSSerializableError>; /// Serialize to a SPSExpected<SPSTagT> from a T. SPSSerializationTraits<SPSExpected<SPSTagT>, T>; } // end namespace shared } // end namespace orc } // end namespace llvm #endif // LLVM_EXECUTIONENGINE_ORC_SHARED_SIMPLEPACKEDSERIALIZATION_H