LLVM 20.0.0git
SimplePackedSerialization.h
Go to the documentation of this file.
1//===---- SimplePackedSerialization.h - simple serialization ----*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// The behavior of the utilities in this header must be synchronized with the
10// behavior of the utilities in
11// compiler-rt/lib/orc/simple_packed_serialization.h.
12//
13// The Simple Packed Serialization (SPS) utilities are used to generate
14// argument and return buffers for wrapper functions using the following
15// serialization scheme:
16//
17// Primitives (signed types should be two's complement):
18// bool, char, int8_t, uint8_t -- 8-bit (0=false, 1=true)
19// int16_t, uint16_t -- 16-bit little endian
20// int32_t, uint32_t -- 32-bit little endian
21// int64_t, int64_t -- 64-bit little endian
22//
23// Sequence<T>:
24// Serialized as the sequence length (as a uint64_t) followed by the
25// serialization of each of the elements without padding.
26//
27// Tuple<T1, ..., TN>:
28// Serialized as each of the element types from T1 to TN without padding.
29//
30//===----------------------------------------------------------------------===//
31
32#ifndef LLVM_EXECUTIONENGINE_ORC_SHARED_SIMPLEPACKEDSERIALIZATION_H
33#define LLVM_EXECUTIONENGINE_ORC_SHARED_SIMPLEPACKEDSERIALIZATION_H
34
35#include "llvm/ADT/STLExtras.h"
37#include "llvm/ADT/StringMap.h"
38#include "llvm/ADT/StringRef.h"
39#include "llvm/Support/Error.h"
41
42#include <limits>
43#include <optional>
44#include <string>
45#include <tuple>
46#include <type_traits>
47#include <utility>
48#include <vector>
49
50namespace llvm {
51namespace orc {
52namespace shared {
53
54/// Output char buffer with overflow check.
56public:
57 SPSOutputBuffer(char *Buffer, size_t Remaining)
58 : Buffer(Buffer), Remaining(Remaining) {}
59 bool write(const char *Data, size_t Size) {
60 assert(Data && "Data must not be null");
61 if (Size > Remaining)
62 return false;
63 memcpy(Buffer, Data, Size);
64 Buffer += Size;
65 Remaining -= Size;
66 return true;
67 }
68
69private:
70 char *Buffer = nullptr;
71 size_t Remaining = 0;
72};
73
74/// Input char buffer with underflow check.
76public:
77 SPSInputBuffer() = default;
78 SPSInputBuffer(const char *Buffer, size_t Remaining)
79 : Buffer(Buffer), Remaining(Remaining) {}
80 bool read(char *Data, size_t Size) {
81 if (Size > Remaining)
82 return false;
83 memcpy(Data, Buffer, Size);
84 Buffer += Size;
85 Remaining -= Size;
86 return true;
87 }
88
89 const char *data() const { return Buffer; }
90 bool skip(size_t Size) {
91 if (Size > Remaining)
92 return false;
93 Buffer += Size;
94 Remaining -= Size;
95 return true;
96 }
97
98private:
99 const char *Buffer = nullptr;
100 size_t Remaining = 0;
101};
102
103/// Specialize to describe how to serialize/deserialize to/from the given
104/// concrete type.
105template <typename SPSTagT, typename ConcreteT, typename _ = void>
107
108/// A utility class for serializing to a blob from a variadic list.
109template <typename... ArgTs> class SPSArgList;
110
111// Empty list specialization for SPSArgList.
112template <> class SPSArgList<> {
113public:
114 static size_t size() { return 0; }
115
116 static bool serialize(SPSOutputBuffer &OB) { return true; }
117 static bool deserialize(SPSInputBuffer &IB) { return true; }
118
119 static bool serializeToSmallVector(SmallVectorImpl<char> &V) { return true; }
120
122 return true;
123 }
124};
125
126// Non-empty list specialization for SPSArgList.
127template <typename SPSTagT, typename... SPSTagTs>
128class SPSArgList<SPSTagT, SPSTagTs...> {
129public:
130 // FIXME: This typedef is here to enable SPS arg serialization from
131 // JITLink. It can be removed once JITLink can access SPS directly.
133
134 template <typename ArgT, typename... ArgTs>
135 static size_t size(const ArgT &Arg, const ArgTs &...Args) {
138 }
139
140 template <typename ArgT, typename... ArgTs>
141 static bool serialize(SPSOutputBuffer &OB, const ArgT &Arg,
142 const ArgTs &...Args) {
145 }
146
147 template <typename ArgT, typename... ArgTs>
148 static bool deserialize(SPSInputBuffer &IB, ArgT &Arg, ArgTs &...Args) {
151 }
152};
153
154/// SPS serialization for integral types, bool, and char.
155template <typename SPSTagT>
157 SPSTagT, SPSTagT,
158 std::enable_if_t<std::is_same<SPSTagT, bool>::value ||
159 std::is_same<SPSTagT, char>::value ||
160 std::is_same<SPSTagT, int8_t>::value ||
161 std::is_same<SPSTagT, int16_t>::value ||
162 std::is_same<SPSTagT, int32_t>::value ||
163 std::is_same<SPSTagT, int64_t>::value ||
164 std::is_same<SPSTagT, uint8_t>::value ||
165 std::is_same<SPSTagT, uint16_t>::value ||
166 std::is_same<SPSTagT, uint32_t>::value ||
167 std::is_same<SPSTagT, uint64_t>::value>> {
168public:
169 static size_t size(const SPSTagT &Value) { return sizeof(SPSTagT); }
170
171 static bool serialize(SPSOutputBuffer &OB, const SPSTagT &Value) {
172 SPSTagT Tmp = Value;
175 return OB.write(reinterpret_cast<const char *>(&Tmp), sizeof(Tmp));
176 }
177
178 static bool deserialize(SPSInputBuffer &IB, SPSTagT &Value) {
179 SPSTagT Tmp;
180 if (!IB.read(reinterpret_cast<char *>(&Tmp), sizeof(Tmp)))
181 return false;
184 Value = Tmp;
185 return true;
186 }
187};
188
189// Any empty placeholder suitable as a substitute for void when deserializing
190class SPSEmpty {};
191
192/// SPS tag type for tuples.
193///
194/// A blob tuple should be serialized by serializing each of the elements in
195/// sequence.
196template <typename... SPSTagTs> class SPSTuple {
197public:
198 /// Convenience typedef of the corresponding arg list.
199 typedef SPSArgList<SPSTagTs...> AsArgList;
200};
201
202/// SPS tag type for optionals.
203///
204/// SPSOptionals should be serialized as a bool with true indicating that an
205/// SPSTagT value is present, and false indicating that there is no value.
206/// If the boolean is true then the serialized SPSTagT will follow immediately
207/// after it.
208template <typename SPSTagT> class SPSOptional {};
209
210/// SPS tag type for sequences.
211///
212/// SPSSequences should be serialized as a uint64_t sequence length,
213/// followed by the serialization of each of the elements.
214template <typename SPSElementTagT> class SPSSequence;
215
216/// SPS tag type for strings, which are equivalent to sequences of chars.
218
219/// SPS tag type for maps.
220///
221/// SPS maps are just sequences of (Key, Value) tuples.
222template <typename SPSTagT1, typename SPSTagT2>
224
225/// Serialization for SPSEmpty type.
227public:
228 static size_t size(const SPSEmpty &EP) { return 0; }
229 static bool serialize(SPSOutputBuffer &OB, const SPSEmpty &BE) {
230 return true;
231 }
232 static bool deserialize(SPSInputBuffer &IB, SPSEmpty &BE) { return true; }
233};
234
235/// Specialize this to implement 'trivial' sequence serialization for
236/// a concrete sequence type.
237///
238/// Trivial sequence serialization uses the sequence's 'size' member to get the
239/// length of the sequence, and uses a range-based for loop to iterate over the
240/// elements.
241///
242/// Specializing this template class means that you do not need to provide a
243/// specialization of SPSSerializationTraits for your type.
244template <typename SPSElementTagT, typename ConcreteSequenceT>
246public:
247 static constexpr bool available = false;
248};
249
250/// Specialize this to implement 'trivial' sequence deserialization for
251/// a concrete sequence type.
252///
253/// Trivial deserialization calls a static 'reserve(SequenceT&)' method on your
254/// specialization (you must implement this) to reserve space, and then calls
255/// a static 'append(SequenceT&, ElementT&) method to append each of the
256/// deserialized elements.
257///
258/// Specializing this template class means that you do not need to provide a
259/// specialization of SPSSerializationTraits for your type.
260template <typename SPSElementTagT, typename ConcreteSequenceT>
262public:
263 static constexpr bool available = false;
264};
265
266/// Trivial std::string -> SPSSequence<char> serialization.
268public:
269 static constexpr bool available = true;
270};
271
272/// Trivial SPSSequence<char> -> std::string deserialization.
274public:
275 static constexpr bool available = true;
276
278
279 static void reserve(std::string &S, uint64_t Size) { S.reserve(Size); }
280 static bool append(std::string &S, char C) {
281 S.push_back(C);
282 return true;
283 }
284};
285
286/// Trivial std::vector<T> -> SPSSequence<SPSElementTagT> serialization.
287template <typename SPSElementTagT, typename T>
288class TrivialSPSSequenceSerialization<SPSElementTagT, std::vector<T>> {
289public:
290 static constexpr bool available = true;
291};
292
293/// Trivial SPSSequence<SPSElementTagT> -> std::vector<T> deserialization.
294template <typename SPSElementTagT, typename T>
295class TrivialSPSSequenceDeserialization<SPSElementTagT, std::vector<T>> {
296public:
297 static constexpr bool available = true;
298
299 using element_type = typename std::vector<T>::value_type;
300
301 static void reserve(std::vector<T> &V, uint64_t Size) { V.reserve(Size); }
302 static bool append(std::vector<T> &V, T E) {
303 V.push_back(std::move(E));
304 return true;
305 }
306};
307
308/// Trivial SmallVectorImpl<T> -> SPSSequence<char> serialization.
309template <typename SPSElementTagT, typename T>
311public:
312 static constexpr bool available = true;
313};
314
315/// Trivial SPSSequence<SPSElementTagT> -> SmallVectorImpl<T> deserialization.
316template <typename SPSElementTagT, typename T>
318public:
319 static constexpr bool available = true;
320
322
323 static void reserve(SmallVectorImpl<T> &V, uint64_t Size) { V.reserve(Size); }
324 static bool append(SmallVectorImpl<T> &V, T E) {
325 V.push_back(std::move(E));
326 return true;
327 }
328};
329
330/// Trivial SmallVectorImpl<T> -> SPSSequence<char> serialization.
331template <typename SPSElementTagT, typename T, unsigned N>
333 : public TrivialSPSSequenceSerialization<SPSElementTagT,
334 SmallVectorImpl<T>> {};
335
336/// Trivial SPSSequence<SPSElementTagT> -> SmallVectorImpl<T> deserialization.
337template <typename SPSElementTagT, typename T, unsigned N>
339 : public TrivialSPSSequenceDeserialization<SPSElementTagT,
340 SmallVectorImpl<T>> {};
341
342/// Trivial ArrayRef<T> -> SPSSequence<SPSElementTagT> serialization.
343template <typename SPSElementTagT, typename T>
345public:
346 static constexpr bool available = true;
347};
348
349/// Specialized SPSSequence<char> -> ArrayRef<char> serialization.
350///
351/// On deserialize, points directly into the input buffer.
353public:
354 static size_t size(const ArrayRef<char> &A) {
355 return SPSArgList<uint64_t>::size(static_cast<uint64_t>(A.size())) +
356 A.size();
357 }
358
359 static bool serialize(SPSOutputBuffer &OB, const ArrayRef<char> &A) {
360 if (!SPSArgList<uint64_t>::serialize(OB, static_cast<uint64_t>(A.size())))
361 return false;
362 if (A.empty()) // Empty ArrayRef may have null data, so bail out early.
363 return true;
364 return OB.write(A.data(), A.size());
365 }
366
370 return false;
371 if (Size > std::numeric_limits<size_t>::max())
372 return false;
373 A = {Size ? IB.data() : nullptr, static_cast<size_t>(Size)};
374 return IB.skip(Size);
375 }
376};
377
378/// 'Trivial' sequence serialization: Sequence is serialized as a uint64_t size
379/// followed by a for-earch loop over the elements of the sequence to serialize
380/// each of them.
381template <typename SPSElementTagT, typename SequenceT>
382class SPSSerializationTraits<SPSSequence<SPSElementTagT>, SequenceT,
383 std::enable_if_t<TrivialSPSSequenceSerialization<
384 SPSElementTagT, SequenceT>::available>> {
385public:
386 static size_t size(const SequenceT &S) {
387 size_t Size = SPSArgList<uint64_t>::size(static_cast<uint64_t>(S.size()));
388 for (const auto &E : S)
390 return Size;
391 }
392
393 static bool serialize(SPSOutputBuffer &OB, const SequenceT &S) {
394 if (!SPSArgList<uint64_t>::serialize(OB, static_cast<uint64_t>(S.size())))
395 return false;
396 for (const auto &E : S)
398 return false;
399 return true;
400 }
401
402 static bool deserialize(SPSInputBuffer &IB, SequenceT &S) {
406 return false;
407 TBSD::reserve(S, Size);
408 for (size_t I = 0; I != Size; ++I) {
409 typename TBSD::element_type E;
411 return false;
412 if (!TBSD::append(S, std::move(E)))
413 return false;
414 }
415 return true;
416 }
417};
418
419/// SPSTuple serialization for std::tuple.
420template <typename... SPSTagTs, typename... Ts>
421class SPSSerializationTraits<SPSTuple<SPSTagTs...>, std::tuple<Ts...>> {
422private:
423 using TupleArgList = typename SPSTuple<SPSTagTs...>::AsArgList;
424 using ArgIndices = std::make_index_sequence<sizeof...(Ts)>;
425
426 template <std::size_t... I>
427 static size_t size(const std::tuple<Ts...> &T, std::index_sequence<I...>) {
428 return TupleArgList::size(std::get<I>(T)...);
429 }
430
431 template <std::size_t... I>
432 static bool serialize(SPSOutputBuffer &OB, const std::tuple<Ts...> &T,
433 std::index_sequence<I...>) {
434 return TupleArgList::serialize(OB, std::get<I>(T)...);
435 }
436
437 template <std::size_t... I>
438 static bool deserialize(SPSInputBuffer &IB, std::tuple<Ts...> &T,
439 std::index_sequence<I...>) {
440 return TupleArgList::deserialize(IB, std::get<I>(T)...);
441 }
442
443public:
444 static size_t size(const std::tuple<Ts...> &T) {
445 return size(T, ArgIndices{});
446 }
447
448 static bool serialize(SPSOutputBuffer &OB, const std::tuple<Ts...> &T) {
449 return serialize(OB, T, ArgIndices{});
450 }
451
452 static bool deserialize(SPSInputBuffer &IB, std::tuple<Ts...> &T) {
453 return deserialize(IB, T, ArgIndices{});
454 }
455};
456
457/// SPSTuple serialization for std::pair.
458template <typename SPSTagT1, typename SPSTagT2, typename T1, typename T2>
459class SPSSerializationTraits<SPSTuple<SPSTagT1, SPSTagT2>, std::pair<T1, T2>> {
460public:
461 static size_t size(const std::pair<T1, T2> &P) {
462 return SPSArgList<SPSTagT1>::size(P.first) +
464 }
465
466 static bool serialize(SPSOutputBuffer &OB, const std::pair<T1, T2> &P) {
467 return SPSArgList<SPSTagT1>::serialize(OB, P.first) &&
469 }
470
471 static bool deserialize(SPSInputBuffer &IB, std::pair<T1, T2> &P) {
472 return SPSArgList<SPSTagT1>::deserialize(IB, P.first) &&
474 }
475};
476
477/// SPSOptional serialization for std::optional.
478template <typename SPSTagT, typename T>
479class SPSSerializationTraits<SPSOptional<SPSTagT>, std::optional<T>> {
480public:
481 static size_t size(const std::optional<T> &Value) {
483 if (Value)
485 return Size;
486 }
487
488 static bool serialize(SPSOutputBuffer &OB, const std::optional<T> &Value) {
490 return false;
491 if (Value)
493 return true;
494 }
495
496 static bool deserialize(SPSInputBuffer &IB, std::optional<T> &Value) {
497 bool HasValue;
499 return false;
500 if (HasValue) {
501 Value = T();
503 } else
504 Value = std::optional<T>();
505 return true;
506 }
507};
508
509/// Serialization for StringRefs.
510///
511/// Serialization is as for regular strings. Deserialization points directly
512/// into the blob.
514public:
515 static size_t size(const StringRef &S) {
516 return SPSArgList<uint64_t>::size(static_cast<uint64_t>(S.size())) +
517 S.size();
518 }
519
520 static bool serialize(SPSOutputBuffer &OB, StringRef S) {
521 if (!SPSArgList<uint64_t>::serialize(OB, static_cast<uint64_t>(S.size())))
522 return false;
523 if (S.empty()) // Empty StringRef may have null data, so bail out early.
524 return true;
525 return OB.write(S.data(), S.size());
526 }
527
528 static bool deserialize(SPSInputBuffer &IB, StringRef &S) {
529 const char *Data = nullptr;
532 return false;
533 Data = IB.data();
534 if (!IB.skip(Size))
535 return false;
536 S = StringRef(Size ? Data : nullptr, Size);
537 return true;
538 }
539};
540
541/// Serialization for StringMap<ValueT>s.
542template <typename SPSValueT, typename ValueT>
544 StringMap<ValueT>> {
545public:
546 static size_t size(const StringMap<ValueT> &M) {
547 size_t Sz = SPSArgList<uint64_t>::size(static_cast<uint64_t>(M.size()));
548 for (auto &E : M)
549 Sz += SPSArgList<SPSString, SPSValueT>::size(E.first(), E.second);
550 return Sz;
551 }
552
553 static bool serialize(SPSOutputBuffer &OB, const StringMap<ValueT> &M) {
554 if (!SPSArgList<uint64_t>::serialize(OB, static_cast<uint64_t>(M.size())))
555 return false;
556
557 for (auto &E : M)
558 if (!SPSArgList<SPSString, SPSValueT>::serialize(OB, E.first(), E.second))
559 return false;
560
561 return true;
562 }
563
566 assert(M.empty() && "M already contains elements");
567
569 return false;
570
571 while (Size--) {
572 StringRef S;
573 ValueT V;
575 return false;
576 if (!M.insert(std::make_pair(S, V)).second)
577 return false;
578 }
579
580 return true;
581 }
582};
583
584/// SPS tag type for errors.
585class SPSError;
586
587/// SPS tag type for expecteds, which are either a T or a string representing
588/// an error.
589template <typename SPSTagT> class SPSExpected;
590
591namespace detail {
592
593/// Helper type for serializing Errors.
594///
595/// llvm::Errors are move-only, and not inspectable except by consuming them.
596/// This makes them unsuitable for direct serialization via
597/// SPSSerializationTraits, which needs to inspect values twice (once to
598/// determine the amount of space to reserve, and then again to serialize).
599///
600/// The SPSSerializableError type is a helper that can be
601/// constructed from an llvm::Error, but inspected more than once.
603 bool HasError = false;
604 std::string ErrMsg;
605};
606
607/// Helper type for serializing Expected<T>s.
608///
609/// See SPSSerializableError for more details.
610///
611// FIXME: Use std::variant for storage once we have c++17.
612template <typename T> struct SPSSerializableExpected {
613 bool HasValue = false;
615 std::string ErrMsg;
616};
617
619 if (Err)
620 return {true, toString(std::move(Err))};
621 return {false, {}};
622}
623
625 if (BSE.HasError)
626 return make_error<StringError>(BSE.ErrMsg, inconvertibleErrorCode());
627 return Error::success();
628}
629
630template <typename T>
632 if (E)
633 return {true, std::move(*E), {}};
634 else
635 return {false, T(), toString(E.takeError())};
636}
637
638template <typename T>
640 if (BSE.HasValue)
641 return std::move(BSE.Value);
642 else
643 return make_error<StringError>(BSE.ErrMsg, inconvertibleErrorCode());
644}
645
646} // end namespace detail
647
648/// Serialize to a SPSError from a detail::SPSSerializableError.
649template <>
650class SPSSerializationTraits<SPSError, detail::SPSSerializableError> {
651public:
652 static size_t size(const detail::SPSSerializableError &BSE) {
654 if (BSE.HasError)
656 return Size;
657 }
658
659 static bool serialize(SPSOutputBuffer &OB,
660 const detail::SPSSerializableError &BSE) {
662 return false;
663 if (BSE.HasError)
665 return false;
666 return true;
667 }
668
672 return false;
673
674 if (!BSE.HasError)
675 return true;
676
678 }
679};
680
681/// Serialize to a SPSExpected<SPSTagT> from a
682/// detail::SPSSerializableExpected<T>.
683template <typename SPSTagT, typename T>
685 detail::SPSSerializableExpected<T>> {
686public:
687 static size_t size(const detail::SPSSerializableExpected<T> &BSE) {
689 if (BSE.HasValue)
691 else
693 return Size;
694 }
695
696 static bool serialize(SPSOutputBuffer &OB,
699 return false;
700
701 if (BSE.HasValue)
703
705 }
706
710 return false;
711
712 if (BSE.HasValue)
714
716 }
717};
718
719/// Serialize to a SPSExpected<SPSTagT> from a detail::SPSSerializableError.
720template <typename SPSTagT>
722 detail::SPSSerializableError> {
723public:
724 static size_t size(const detail::SPSSerializableError &BSE) {
725 assert(BSE.HasError && "Cannot serialize expected from a success value");
726 return SPSArgList<bool>::size(false) +
728 }
729
730 static bool serialize(SPSOutputBuffer &OB,
731 const detail::SPSSerializableError &BSE) {
732 assert(BSE.HasError && "Cannot serialize expected from a success value");
733 if (!SPSArgList<bool>::serialize(OB, false))
734 return false;
736 }
737};
738
739/// Serialize to a SPSExpected<SPSTagT> from a T.
740template <typename SPSTagT, typename T>
742public:
743 static size_t size(const T &Value) {
745 }
746
747 static bool serialize(SPSOutputBuffer &OB, const T &Value) {
748 if (!SPSArgList<bool>::serialize(OB, true))
749 return false;
751 }
752};
753
754} // end namespace shared
755} // end namespace orc
756} // end namespace llvm
757
758#endif // LLVM_EXECUTIONENGINE_ORC_SHARED_SIMPLEPACKEDSERIALIZATION_H
This file defines the StringMap class.
AMDGPU promote alloca to vector or false DEBUG_TYPE to vector
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
uint64_t Size
#define I(x, y, z)
Definition: MD5.cpp:58
#define T
#define P(N)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file contains some templates that are useful if you are working with the STL at all.
This file defines the SmallVector class.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
Lightweight error class with error context and mandatory checking.
Definition: Error.h:160
static ErrorSuccess success()
Create a success value.
Definition: Error.h:337
Tagged union holding either a T or a Error.
Definition: Error.h:481
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:573
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1196
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
Definition: StringMap.h:128
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:51
constexpr bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:147
constexpr size_t size() const
size - Get the string size.
Definition: StringRef.h:150
constexpr const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
Definition: StringRef.h:144
LLVM Value Representation.
Definition: Value.h:74
static bool deserialize(SPSInputBuffer &IB, ArgT &Arg, ArgTs &...Args)
static bool serialize(SPSOutputBuffer &OB, const ArgT &Arg, const ArgTs &...Args)
static size_t size(const ArgT &Arg, const ArgTs &...Args)
static bool deserializeFromSmallVector(const SmallVectorImpl< char > &V)
static bool serializeToSmallVector(SmallVectorImpl< char > &V)
static bool serialize(SPSOutputBuffer &OB)
static bool deserialize(SPSInputBuffer &IB)
A utility class for serializing to a blob from a variadic list.
SPS tag type for expecteds, which are either a T or a string representing an error.
Input char buffer with underflow check.
SPSInputBuffer(const char *Buffer, size_t Remaining)
bool read(char *Data, size_t Size)
Output char buffer with overflow check.
bool write(const char *Data, size_t Size)
SPSOutputBuffer(char *Buffer, size_t Remaining)
static bool serialize(SPSOutputBuffer &OB, const SPSEmpty &BE)
static bool deserialize(SPSInputBuffer &IB, detail::SPSSerializableError &BSE)
static bool serialize(SPSOutputBuffer &OB, const detail::SPSSerializableError &BSE)
static bool serialize(SPSOutputBuffer &OB, const detail::SPSSerializableExpected< T > &BSE)
static bool serialize(SPSOutputBuffer &OB, const detail::SPSSerializableError &BSE)
static bool serialize(SPSOutputBuffer &OB, const std::optional< T > &Value)
Specialize to describe how to serialize/deserialize to/from the given concrete type.
SPSArgList< SPSTagTs... > AsArgList
Convenience typedef of the corresponding arg list.
Specialize this to implement 'trivial' sequence deserialization for a concrete sequence type.
Specialize this to implement 'trivial' sequence serialization for a concrete sequence type.
@ C
The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
SPSSerializableError toSPSSerializable(Error Err)
Error fromSPSSerializable(SPSSerializableError BSE)
constexpr bool IsBigEndianHost
Definition: SwapByteOrder.h:26
void swapByteOrder(T &Value)
Definition: SwapByteOrder.h:61
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
Definition: STLExtras.h:1697
std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
Definition: Error.cpp:98
detail::ValueMatchesPoly< M > HasValue(M Matcher)
Definition: Error.h:221
const char * toString(DWARFSectionKind Kind)
Implement std::hash so that hash_code can be used in STL containers.
Definition: BitVector.h:858
#define N