[clang] [clang] Implement constexpr bit_cast for vectors (PR #66894)

via cfe-commits cfe-commits at lists.llvm.org
Wed Sep 20 04:44:05 PDT 2023


https://github.com/DaMatrix created https://github.com/llvm/llvm-project/pull/66894

This makes __builtin_bit_cast support converting to and from vector types in a constexpr context.

>From d4c7b67eff9997479712f1a25ebb162756d431c6 Mon Sep 17 00:00:00 2001
From: DaPorkchop_ <daporkchop at daporkchop.net>
Date: Sun, 13 Aug 2023 22:39:12 +0200
Subject: [PATCH] [clang] Implement constexpr bit_cast for vectors

---
 clang/lib/AST/ExprConstant.cpp                | 34 ++++++++++++++++++-
 .../SemaCXX/constexpr-builtin-bit-cast.cpp    | 16 +++++++++
 2 files changed, 49 insertions(+), 1 deletion(-)

diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index fea06b97259fe31..d58ff10604ee593 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -7005,10 +7005,11 @@ class APValueToBufferConverter {
       return visitArray(Val, Ty, Offset);
     case APValue::Struct:
       return visitRecord(Val, Ty, Offset);
+    case APValue::Vector:
+      return visitVector(Val, Ty, Offset);
 
     case APValue::ComplexInt:
     case APValue::ComplexFloat:
-    case APValue::Vector:
     case APValue::FixedPoint:
       // FIXME: We should support these.
 
@@ -7095,6 +7096,21 @@ class APValueToBufferConverter {
     return true;
   }
 
+  bool visitVector(const APValue &Val, QualType Ty, CharUnits Offset) {
+    const auto *VT = Ty->castAs<VectorType>();
+
+    CharUnits ElemWidth = Info.Ctx.getTypeSizeInChars(VT->getElementType());
+    unsigned VectorLength = Val.getVectorLength();
+    // Visit each of the vector elements
+    for (unsigned I = 0; I != VectorLength; ++I) {
+      const APValue &SubObj = Val.getVectorElt(I);
+      if (!visit(SubObj, VT->getElementType(), Offset + I * ElemWidth))
+        return false;
+    }
+
+    return true;
+  }
+
   bool visitInt(const APSInt &Val, QualType Ty, CharUnits Offset) {
     APSInt AdjustedVal = Val;
     unsigned Width = AdjustedVal.getBitWidth();
@@ -7304,6 +7320,22 @@ class BufferToAPValueConverter {
     return ArrayValue;
   }
 
+  std::optional<APValue> visit(const VectorType *Ty, CharUnits Offset) {
+    size_t NumElements = Ty->getNumElements();
+    CharUnits ElementWidth = Info.Ctx.getTypeSizeInChars(Ty->getElementType());
+
+    SmallVector<APValue, 4> Elts;
+    for (size_t I = 0; I != NumElements; ++I) {
+      std::optional<APValue> ElementValue =
+          visitType(Ty->getElementType(), Offset + I * ElementWidth);
+      if (!ElementValue)
+        return std::nullopt;
+      Elts.push_back(std::move(*ElementValue));
+    }
+
+    return APValue(Elts.data(), Elts.size());
+  }
+
   std::optional<APValue> visit(const Type *Ty, CharUnits Offset) {
     return unsupportedType(QualType(Ty, 0));
   }
diff --git a/clang/test/SemaCXX/constexpr-builtin-bit-cast.cpp b/clang/test/SemaCXX/constexpr-builtin-bit-cast.cpp
index a6ebe0572d063bb..7a45b8624d8011f 100644
--- a/clang/test/SemaCXX/constexpr-builtin-bit-cast.cpp
+++ b/clang/test/SemaCXX/constexpr-builtin-bit-cast.cpp
@@ -463,3 +463,19 @@ static_assert(bit_cast<long double>(ld539) == fivehundredandthirtynine, "");
 static_assert(round_trip<__int128_t>(34.0L));
 #endif
 }
+
+namespace test_vector {
+
+typedef unsigned uint2 __attribute__((vector_size(2 * sizeof(unsigned))));
+typedef char byte8 __attribute__((vector_size(sizeof(unsigned long long))));
+
+constexpr uint2 test_vector = { 0x0C05FEFE, 0xCAFEBABE };
+
+static_assert(bit_cast<unsigned long long>(test_vector) == (LITTLE_END
+                                                                ? 0xCAFEBABE0C05FEFE
+                                                                : 0x0C05FEFECAFEBABE), "");
+
+static_assert(round_trip<uint2>(0xCAFEBABE0C05FEFEULL), "");
+static_assert(round_trip<byte8>(0xCAFEBABE0C05FEFEULL), "");
+
+}



More information about the cfe-commits mailing list