From 7ef9f729f3e5b750e773d134e5e7c820d984b3a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Fri, 27 Sep 2024 17:58:22 +0200 Subject: [PATCH] [llvm] Add serialization to uint32_t for FixedPointSemantics FixedPointSemantics is exactly 32bits and this static_assert'ed after its declaration. Add support for converting it to and from a uint32_t. --- llvm/include/llvm/ADT/APFixedPoint.h | 9 +++++++ llvm/lib/Support/APFixedPoint.cpp | 10 ++++++++ llvm/unittests/ADT/APFixedPointTest.cpp | 31 +++++++++++++++++++++++++ 3 files changed, 50 insertions(+) diff --git a/llvm/include/llvm/ADT/APFixedPoint.h b/llvm/include/llvm/ADT/APFixedPoint.h index ae40db96e4818..e4aa82d7a41c3 100644 --- a/llvm/include/llvm/ADT/APFixedPoint.h +++ b/llvm/include/llvm/ADT/APFixedPoint.h @@ -114,6 +114,15 @@ class FixedPointSemantics { } bool operator!=(FixedPointSemantics Other) const { return !(*this == Other); } + /// Convert the semantics to a 32-bit unsigned integer. + /// The result is dependent on the host endianness and not stable across LLVM + /// versions. See getFromOpaqueInt() to convert it back to a + /// FixedPointSemantics object. + uint32_t toOpaqueInt() const; + /// Create a FixedPointSemantics object from an integer created via + /// toOpaqueInt(). + static FixedPointSemantics getFromOpaqueInt(uint32_t); + private: unsigned Width : WidthBitWidth; signed int LsbWeight : LsbWeightBitWidth; diff --git a/llvm/lib/Support/APFixedPoint.cpp b/llvm/lib/Support/APFixedPoint.cpp index 249c4f1e2153d..f395919287b72 100644 --- a/llvm/lib/Support/APFixedPoint.cpp +++ b/llvm/lib/Support/APFixedPoint.cpp @@ -29,6 +29,16 @@ void FixedPointSemantics::print(llvm::raw_ostream &OS) const { OS << "IsSaturated=" << IsSaturated; } +uint32_t FixedPointSemantics::toOpaqueInt() const { + return llvm::bit_cast(*this); +} + +FixedPointSemantics FixedPointSemantics::getFromOpaqueInt(uint32_t I) { + FixedPointSemantics F(0, 0, false, false, false); + std::memcpy(&F, &I, sizeof(F)); + return F; +} + APFixedPoint APFixedPoint::convert(const FixedPointSemantics &DstSema, bool *Overflow) const { APSInt NewVal = Val; diff --git a/llvm/unittests/ADT/APFixedPointTest.cpp b/llvm/unittests/ADT/APFixedPointTest.cpp index ecb89fbf76c8b..e7aa58a832577 100644 --- a/llvm/unittests/ADT/APFixedPointTest.cpp +++ b/llvm/unittests/ADT/APFixedPointTest.cpp @@ -1274,4 +1274,35 @@ TEST(FixedPoint, div) { true, false, false))); } +TEST(FixedPoint, semanticsSerialization) { + auto roundTrip = [](FixedPointSemantics FPS) -> bool { + uint32_t I = FPS.toOpaqueInt(); + FixedPointSemantics FPS2 = FixedPointSemantics::getFromOpaqueInt(I); + return FPS == FPS2; + }; + + ASSERT_TRUE(roundTrip(getS32Pos2())); + ASSERT_TRUE(roundTrip(getU8Pos4())); + ASSERT_TRUE(roundTrip(getS16Neg18())); + ASSERT_TRUE(roundTrip(getU8Neg10())); + ASSERT_TRUE(roundTrip(getPadULFractSema())); + ASSERT_TRUE(roundTrip(getPadUFractSema())); + ASSERT_TRUE(roundTrip(getPadUSFractSema())); + ASSERT_TRUE(roundTrip(getPadULAccumSema())); + ASSERT_TRUE(roundTrip(getPadUAccumSema())); + ASSERT_TRUE(roundTrip(getPadUSAccumSema())); + ASSERT_TRUE(roundTrip(getULFractSema())); + ASSERT_TRUE(roundTrip(getUFractSema())); + ASSERT_TRUE(roundTrip(getUSFractSema())); + ASSERT_TRUE(roundTrip(getULAccumSema())); + ASSERT_TRUE(roundTrip(getUAccumSema())); + ASSERT_TRUE(roundTrip(getUSAccumSema())); + ASSERT_TRUE(roundTrip(getLFractSema())); + ASSERT_TRUE(roundTrip(getFractSema())); + ASSERT_TRUE(roundTrip(getSFractSema())); + ASSERT_TRUE(roundTrip(getLAccumSema())); + ASSERT_TRUE(roundTrip(getAccumSema())); + ASSERT_TRUE(roundTrip(getSAccumSema())); +} + } // namespace