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_ <daporkc...@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), ""); + +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits