diff --git a/compiler-rt/lib/orc/simple_packed_serialization.h b/compiler-rt/lib/orc/simple_packed_serialization.h index a5948ec650fd5..9cebbeadee026 100644 --- a/compiler-rt/lib/orc/simple_packed_serialization.h +++ b/compiler-rt/lib/orc/simple_packed_serialization.h @@ -39,6 +39,7 @@ #include "error.h" #include "stl_extras.h" +#include #include #include #include @@ -189,6 +190,14 @@ template class SPSTuple { typedef SPSArgList AsArgList; }; +/// 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 class SPSOptional {}; + /// SPS tag type for sequences. /// /// SPSSequences should be serialized as a uint64_t sequence length, @@ -396,6 +405,38 @@ class SPSSerializationTraits, std::pair> { } }; +/// SPSOptional serialization for std::optional. +template +class SPSSerializationTraits, std::optional> { +public: + static size_t size(const std::optional &Value) { + size_t Size = SPSArgList::size(!!Value); + if (Value) + Size += SPSArgList::size(*Value); + return Size; + } + + static bool serialize(SPSOutputBuffer &OB, const std::optional &Value) { + if (!SPSArgList::serialize(OB, !!Value)) + return false; + if (Value) + return SPSArgList::serialize(OB, *Value); + return true; + } + + static bool deserialize(SPSInputBuffer &IB, std::optional &Value) { + bool HasValue; + if (!SPSArgList::deserialize(IB, HasValue)) + return false; + if (HasValue) { + Value = T(); + return SPSArgList::deserialize(IB, *Value); + } else + Value = std::optional(); + return true; + } +}; + /// Serialization for string_views. /// /// Serialization is as for regular strings. Deserialization points directly diff --git a/compiler-rt/lib/orc/tests/unit/simple_packed_serialization_test.cpp b/compiler-rt/lib/orc/tests/unit/simple_packed_serialization_test.cpp index 3ecc20f8992b2..5577ef919fc6a 100644 --- a/compiler-rt/lib/orc/tests/unit/simple_packed_serialization_test.cpp +++ b/compiler-rt/lib/orc/tests/unit/simple_packed_serialization_test.cpp @@ -160,6 +160,16 @@ TEST(SimplePackedSerializationTest, StdPairSerialization) { std::pair>(P); } +TEST(SimplePackedSerializationTest, StdOptionalNoValueSerialization) { + std::optional NoValue; + blobSerializationRoundTrip>(NoValue); +} + +TEST(SimplePackedSerializationTest, StdOptionalValueSerialization) { + std::optional Value(42); + blobSerializationRoundTrip>(Value); +} + TEST(SimplePackedSerializationTest, ArgListSerialization) { using BAL = SPSArgList; diff --git a/llvm/include/llvm/ExecutionEngine/Orc/Shared/SimplePackedSerialization.h b/llvm/include/llvm/ExecutionEngine/Orc/Shared/SimplePackedSerialization.h index c388259482088..8a55d5fb17955 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/Shared/SimplePackedSerialization.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/Shared/SimplePackedSerialization.h @@ -40,6 +40,7 @@ #include "llvm/Support/SwapByteOrder.h" #include +#include #include #include #include @@ -198,6 +199,14 @@ template class SPSTuple { typedef SPSArgList AsArgList; }; +/// 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 class SPSOptional {}; + /// SPS tag type for sequences. /// /// SPSSequences should be serialized as a uint64_t sequence length, @@ -465,6 +474,38 @@ class SPSSerializationTraits, std::pair> { } }; +/// SPSOptional serialization for std::optional. +template +class SPSSerializationTraits, std::optional> { +public: + static size_t size(const std::optional &Value) { + size_t Size = SPSArgList::size(!!Value); + if (Value) + Size += SPSArgList::size(*Value); + return Size; + } + + static bool serialize(SPSOutputBuffer &OB, const std::optional &Value) { + if (!SPSArgList::serialize(OB, !!Value)) + return false; + if (Value) + return SPSArgList::serialize(OB, *Value); + return true; + } + + static bool deserialize(SPSInputBuffer &IB, std::optional &Value) { + bool HasValue; + if (!SPSArgList::deserialize(IB, HasValue)) + return false; + if (HasValue) { + Value = T(); + return SPSArgList::deserialize(IB, *Value); + } else + Value = std::optional(); + return true; + } +}; + /// Serialization for StringRefs. /// /// Serialization is as for regular strings. Deserialization points directly diff --git a/llvm/unittests/ExecutionEngine/Orc/SimplePackedSerializationTest.cpp b/llvm/unittests/ExecutionEngine/Orc/SimplePackedSerializationTest.cpp index 6c441a31882a6..ff37d2368ab38 100644 --- a/llvm/unittests/ExecutionEngine/Orc/SimplePackedSerializationTest.cpp +++ b/llvm/unittests/ExecutionEngine/Orc/SimplePackedSerializationTest.cpp @@ -137,6 +137,16 @@ TEST(SimplePackedSerializationTest, StdPairSerialization) { spsSerializationRoundTrip>(P); } +TEST(SimplePackedSerializationTest, StdOptionalNoValueSerialization) { + std::optional NoValue; + spsSerializationRoundTrip>(NoValue); +} + +TEST(SimplePackedSerializationTest, StdOptionalValueSerialization) { + std::optional Value(42); + spsSerializationRoundTrip>(Value); +} + TEST(SimplePackedSerializationTest, ArgListSerialization) { using BAL = SPSArgList;