https://github.com/DaMatrix updated https://github.com/llvm/llvm-project/pull/66894
>From 99d894e132468a7008e89aaab4847e16b4743bc7 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 | 77 ++++++++++++++++++- .../SemaCXX/constexpr-builtin-bit-cast.cpp | 35 +++++++++ 2 files changed, 111 insertions(+), 1 deletion(-) diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index fea06b97259fe31..e84d6214b99d818 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,40 @@ class APValueToBufferConverter { return true; } + bool visitVector(const APValue &Val, QualType Ty, CharUnits Offset) { + const auto *VT = Ty->castAs<VectorType>(); + unsigned VectorLength = Val.getVectorLength(); + + if (VT->isExtVectorBoolType()) { + // Special handling for OpenCL bool vectors: we need to pack the vector + // of 1-bit unsigned integers into a single integer with the corresponding + // bits set, then write out the resulting integer. + + CharUnits VecWidthBits = Info.Ctx.getTypeSizeInChars(VT) * 8; + + APSInt Bits(VecWidthBits.getQuantity()); + for (unsigned I = 0; I != VectorLength; ++I) { + const APValue &SubObj = Val.getVectorElt(I); + assert(SubObj.isInt() && "Bool vector element isn't an int?"); + Bits.setBitVal(I, !SubObj.getInt().isZero()); + } + return visit( + APValue(Bits), + Info.Ctx.getIntTypeForBitwidth(Bits.getBitWidth(), Bits.isSigned()), + Offset); + } + + CharUnits ElemWidth = Info.Ctx.getTypeSizeInChars(VT->getElementType()); + // 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 +7339,46 @@ class BufferToAPValueConverter { return ArrayValue; } + std::optional<APValue> visit(const VectorType *Ty, CharUnits Offset) { + unsigned NumElements = Ty->getNumElements(); + + SmallVector<APValue, 4> Elts; + Elts.reserve(NumElements); + + if (Ty->isExtVectorBoolType()) { + // Special handling for OpenCL bool vectors: we need to read + // the individual bits and then unpack them into a vector of 1-bit + // unsigned integers. + + CharUnits VecWidthBits = Info.Ctx.getTypeSizeInChars(Ty) * 8; + std::optional<APValue> BitsValue = visitType( + Info.Ctx.getIntTypeForBitwidth(VecWidthBits.getQuantity(), false), + Offset); + if (!BitsValue) + return std::nullopt; + + const APSInt &Bits = BitsValue->getInt(); + for (unsigned I = 0; I != NumElements; ++I) { + APSInt Bit(1); + Bit = Bits.intersects(APInt::getOneBitSet(Bits.getBitWidth(), I)); + Elts.emplace_back(std::move(Bit)); + } + } else { + CharUnits ElementWidth = + Info.Ctx.getTypeSizeInChars(Ty->getElementType()); + + for (unsigned 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..fe7aa51c167fa67 100644 --- a/clang/test/SemaCXX/constexpr-builtin-bit-cast.cpp +++ b/clang/test/SemaCXX/constexpr-builtin-bit-cast.cpp @@ -463,3 +463,38 @@ 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), ""); + +typedef bool bool8 __attribute__((ext_vector_type(8))); +typedef bool bool9 __attribute__((ext_vector_type(9))); +typedef bool bool17 __attribute__((ext_vector_type(17))); +typedef bool bool32 __attribute__((ext_vector_type(32))); + +static_assert(bit_cast<unsigned char>(bool8{1,0,1,0,1,0,1,0}) == 0x55, ""); +static_assert(round_trip<bool8>(static_cast<unsigned char>(0)), ""); +static_assert(round_trip<bool8>(static_cast<unsigned char>(1)), ""); +static_assert(round_trip<bool8>(static_cast<unsigned char>(0x55)), ""); + +static_assert(bit_cast<unsigned short>(bool9{1,1,0,1,0,1,0,1,0}) == 0xAB, ""); +static_assert(round_trip<bool9>(static_cast<unsigned short>(0)), ""); +static_assert(round_trip<bool9>(static_cast<unsigned short>(1)), ""); +static_assert(round_trip<bool9>(static_cast<unsigned short>(0x00AB)), ""); +static_assert(round_trip<bool9>(static_cast<unsigned short>(0x01AB)), ""); + +static_assert(round_trip<bool17>(static_cast<unsigned int>(0x0001CAFE)), ""); +static_assert(round_trip<bool32>(static_cast<unsigned int>(0xCAFEBABE)), ""); + +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits