DaPorkchop_ created this revision. DaPorkchop_ added a project: clang. Herald added a project: All. DaPorkchop_ requested review of this revision. Herald added a subscriber: cfe-commits.
This makes __builtin_bit_cast support converting to and from vector types in a constexpr context. Without this patch, attempting to use `std::bit_cast` with a vector type will fail to compile with a message such as: `constexpr bit_cast involving type '__attribute__((__vector_size__(4 * sizeof(int)))) int const' (vector of 4 'int' values) is not yet supported` Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D157825 Files: clang/lib/AST/ExprConstant.cpp clang/test/SemaCXX/constexpr-builtin-bit-cast.cpp Index: clang/test/SemaCXX/constexpr-builtin-bit-cast.cpp =================================================================== --- clang/test/SemaCXX/constexpr-builtin-bit-cast.cpp +++ clang/test/SemaCXX/constexpr-builtin-bit-cast.cpp @@ -463,3 +463,19 @@ 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), ""); + +} Index: clang/lib/AST/ExprConstant.cpp =================================================================== --- clang/lib/AST/ExprConstant.cpp +++ clang/lib/AST/ExprConstant.cpp @@ -6990,10 +6990,11 @@ 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. @@ -7080,6 +7081,21 @@ 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(); @@ -7289,6 +7305,22 @@ 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)); }
Index: clang/test/SemaCXX/constexpr-builtin-bit-cast.cpp =================================================================== --- clang/test/SemaCXX/constexpr-builtin-bit-cast.cpp +++ clang/test/SemaCXX/constexpr-builtin-bit-cast.cpp @@ -463,3 +463,19 @@ 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), ""); + +} Index: clang/lib/AST/ExprConstant.cpp =================================================================== --- clang/lib/AST/ExprConstant.cpp +++ clang/lib/AST/ExprConstant.cpp @@ -6990,10 +6990,11 @@ 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. @@ -7080,6 +7081,21 @@ 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(); @@ -7289,6 +7305,22 @@ 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)); }
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits