[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