diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -2930,8 +2930,10 @@ "vector size not an integral multiple of component size">; def err_attribute_zero_size : Error<"zero %0 size">; def err_attribute_size_too_large : Error<"%0 size too large">; -def err_typecheck_vector_not_convertable_sizeless : Error< - "cannot convert between a fixed-length and a sizeless vector (%0 and %1)">; +def err_typecheck_sve_ambiguous : Error< + "cannot combine fixed-length and sizeless SVE vectors in expression, result is ambiguous (%0 and %1)">; +def err_typecheck_sve_gnu_ambiguous : Error< + "cannot combine GNU and SVE vectors in expression, result is ambiguous (%0 and %1)">; def err_typecheck_vector_not_convertable_implict_truncation : Error< "cannot convert between %select{scalar|vector}0 type %1 and vector type" " %2 as implicit conversion would cause truncation">; diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -8514,7 +8514,11 @@ First->getVectorKind() != VectorType::AltiVecPixel && First->getVectorKind() != VectorType::AltiVecBool && Second->getVectorKind() != VectorType::AltiVecPixel && - Second->getVectorKind() != VectorType::AltiVecBool) + Second->getVectorKind() != VectorType::AltiVecBool && + First->getVectorKind() != VectorType::SveFixedLengthDataVector && + First->getVectorKind() != VectorType::SveFixedLengthPredicateVector && + Second->getVectorKind() != VectorType::SveFixedLengthDataVector && + Second->getVectorKind() != VectorType::SveFixedLengthPredicateVector) return true; return false; diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -9844,6 +9844,44 @@ } } + // Expressions containing fixed-length and sizeless SVE vectors are invalid + // since the ambiguity can affect the ABI. + auto IsSveConversion = [](QualType FirstType, QualType SecondType) { + const VectorType *VecType = SecondType->getAs(); + return FirstType->isSizelessBuiltinType() && VecType && + (VecType->getVectorKind() == VectorType::SveFixedLengthDataVector || + VecType->getVectorKind() == + VectorType::SveFixedLengthPredicateVector); + }; + + if (IsSveConversion(LHSType, RHSType) || IsSveConversion(RHSType, LHSType)) { + Diag(Loc, diag::err_typecheck_sve_ambiguous) << LHSType << RHSType; + return QualType(); + } + + // Expressions containing GNU and SVE (fixed or sizeless) vectors are invalid + // since the ambiguity can affect the ABI. + auto IsSveGnuConversion = [](QualType FirstType, QualType SecondType) { + const VectorType *FirstVecType = FirstType->getAs(); + const VectorType *SecondVecType = SecondType->getAs(); + + if (FirstVecType && SecondVecType) + return FirstVecType->getVectorKind() == VectorType::GenericVector && + (SecondVecType->getVectorKind() == + VectorType::SveFixedLengthDataVector || + SecondVecType->getVectorKind() == + VectorType::SveFixedLengthPredicateVector); + + return FirstType->isSizelessBuiltinType() && SecondVecType && + SecondVecType->getVectorKind() == VectorType::GenericVector; + }; + + if (IsSveGnuConversion(LHSType, RHSType) || + IsSveGnuConversion(RHSType, LHSType)) { + Diag(Loc, diag::err_typecheck_sve_gnu_ambiguous) << LHSType << RHSType; + return QualType(); + } + // If there's a vector type and a scalar, try to convert the scalar to // the vector element type and splat. unsigned DiagID = diag::err_typecheck_vector_not_convertable; @@ -9900,22 +9938,6 @@ // Okay, the expression is invalid. - // Returns true if the operands are SVE VLA and VLS types. - auto IsSveConversion = [](QualType FirstType, QualType SecondType) { - const VectorType *VecType = SecondType->getAs(); - return FirstType->isSizelessBuiltinType() && VecType && - (VecType->getVectorKind() == VectorType::SveFixedLengthDataVector || - VecType->getVectorKind() == - VectorType::SveFixedLengthPredicateVector); - }; - - // If there's a sizeless and fixed-length operand, diagnose that. - if (IsSveConversion(LHSType, RHSType) || IsSveConversion(RHSType, LHSType)) { - Diag(Loc, diag::err_typecheck_vector_not_convertable_sizeless) - << LHSType << RHSType; - return QualType(); - } - // If there's a non-vector, non-real operand, diagnose that. if ((!RHSVecType && !RHSType->isRealType()) || (!LHSVecType && !LHSType->isRealType())) { diff --git a/clang/test/Sema/attr-arm-sve-vector-bits.c b/clang/test/Sema/attr-arm-sve-vector-bits.c --- a/clang/test/Sema/attr-arm-sve-vector-bits.c +++ b/clang/test/Sema/attr-arm-sve-vector-bits.c @@ -123,13 +123,56 @@ void f(int c) { fixed_int8_t fs8; svint8_t ss8; + gnu_int8_t gs8; + // Check conditional expressions where the result is ambiguous are + // ill-formed. void *sel __attribute__((unused)); - sel = c ? ss8 : fs8; // expected-error {{cannot convert between a fixed-length and a sizeless vector}} - sel = c ? fs8 : ss8; // expected-error {{cannot convert between a fixed-length and a sizeless vector}} + sel = c ? ss8 : fs8; // expected-error {{cannot combine fixed-length and sizeless SVE vectors in expression, result is ambiguous}} + sel = c ? fs8 : ss8; // expected-error {{cannot combine fixed-length and sizeless SVE vectors in expression, result is ambiguous}} - sel = fs8 + ss8; // expected-error {{cannot convert between a fixed-length and a sizeless vector}} - sel = ss8 + fs8; // expected-error {{cannot convert between a fixed-length and a sizeless vector}} + sel = c ? gs8 : ss8; // expected-error {{cannot combine GNU and SVE vectors in expression, result is ambiguous}} + sel = c ? ss8 : gs8; // expected-error {{cannot combine GNU and SVE vectors in expression, result is ambiguous}} + + sel = c ? gs8 : fs8; // expected-error {{cannot combine GNU and SVE vectors in expression, result is ambiguous}} + sel = c ? fs8 : gs8; // expected-error {{cannot combine GNU and SVE vectors in expression, result is ambiguous}} + + // Check binary expressions where the result is ambiguous are ill-formed. + ss8 = ss8 + fs8; // expected-error {{cannot combine fixed-length and sizeless SVE vectors in expression, result is ambiguous}} + ss8 = ss8 + gs8; // expected-error {{cannot combine GNU and SVE vectors in expression, result is ambiguous}} + + fs8 = fs8 + ss8; // expected-error {{cannot combine fixed-length and sizeless SVE vectors in expression, result is ambiguous}} + fs8 = fs8 + gs8; // expected-error {{cannot combine GNU and SVE vectors in expression, result is ambiguous}} + + gs8 = gs8 + ss8; // expected-error {{cannot combine GNU and SVE vectors in expression, result is ambiguous}} + gs8 = gs8 + fs8; // expected-error {{cannot combine GNU and SVE vectors in expression, result is ambiguous}} + + ss8 += fs8; // expected-error {{cannot combine fixed-length and sizeless SVE vectors in expression, result is ambiguous}} + ss8 += gs8; // expected-error {{cannot combine GNU and SVE vectors in expression, result is ambiguous}} + + fs8 += ss8; // expected-error {{cannot combine fixed-length and sizeless SVE vectors in expression, result is ambiguous}} + fs8 += gs8; // expected-error {{cannot combine GNU and SVE vectors in expression, result is ambiguous}} + + gs8 += ss8; // expected-error {{cannot combine GNU and SVE vectors in expression, result is ambiguous}} + gs8 += fs8; // expected-error {{cannot combine GNU and SVE vectors in expression, result is ambiguous}} + + ss8 = ss8 == fs8; // expected-error {{cannot combine fixed-length and sizeless SVE vectors in expression, result is ambiguous}} + ss8 = ss8 == gs8; // expected-error {{cannot combine GNU and SVE vectors in expression, result is ambiguous}} + + fs8 = fs8 == ss8; // expected-error {{cannot combine fixed-length and sizeless SVE vectors in expression, result is ambiguous}} + fs8 = fs8 == gs8; // expected-error {{cannot combine GNU and SVE vectors in expression, result is ambiguous}} + + gs8 = gs8 == ss8; // expected-error {{cannot combine GNU and SVE vectors in expression, result is ambiguous}} + gs8 = gs8 == fs8; // expected-error {{cannot combine GNU and SVE vectors in expression, result is ambiguous}} + + ss8 = ss8 & fs8; // expected-error {{invalid operands to binary expression}} + ss8 = ss8 & gs8; // expected-error {{invalid operands to binary expression}} + + fs8 = fs8 & ss8; // expected-error {{invalid operands to binary expression}} + fs8 = fs8 & gs8; // expected-error {{cannot combine GNU and SVE vectors in expression, result is ambiguous}} + + gs8 = gs8 & ss8; // expected-error {{invalid operands to binary expression}} + gs8 = gs8 & fs8; // expected-error {{cannot combine GNU and SVE vectors in expression, result is ambiguous}} } // --------------------------------------------------------------------------// @@ -268,3 +311,78 @@ TEST_CALL(int32) TEST_CALL(float64) TEST_CALL(bool) + +// --------------------------------------------------------------------------// +// Vector initialization + +#if __ARM_FEATURE_SVE_BITS == 256 + +typedef svint32_t int32x8 __attribute__((arm_sve_vector_bits(N))); +typedef svfloat64_t float64x4 __attribute__((arm_sve_vector_bits(N))); + +int32x8 foo = {1, 2, 3, 4, 5, 6, 7, 8}; +int32x8 foo2 = {1, 2, 3, 4, 5, 6, 7, 8, 9}; // expected-warning{{excess elements in vector initializer}} + +float64x4 bar = {1.0, 2.0, 3.0, 4.0}; +float64x4 bar2 = {1.0, 2.0, 3.0, 4.0, 5.0}; // expected-warning{{excess elements in vector initializer}} + +#endif + +// --------------------------------------------------------------------------// +// Vector ops + +#define TEST_BINARY(TYPE, NAME, OP) \ + TYPE NAME##_##TYPE(TYPE op1, TYPE op2) { \ + return op1 OP op2; \ + } \ + TYPE compound##NAME##_##TYPE(TYPE op1, TYPE op2) { \ + op1 OP##= op2; \ + return op1; \ + } + +#define TEST_COMPARISON(TYPE, NAME, OP) \ + TYPE NAME##_##TYPE(TYPE op1, TYPE op2) { \ + return op1 OP op2; \ + } + +#define TEST_UNARY(TYPE, NAME, OP) \ + TYPE NAME##_##TYPE(TYPE op1) { \ + return OP op1; \ + } + +#define TEST_OPS(TYPE) \ + TEST_BINARY(TYPE, add, +) \ + TEST_BINARY(TYPE, sub, -) \ + TEST_BINARY(TYPE, mul, *) \ + TEST_BINARY(TYPE, div, /) \ + TEST_COMPARISON(TYPE, eq, ==) \ + TEST_COMPARISON(TYPE, ne, !=) \ + TEST_COMPARISON(TYPE, lt, <) \ + TEST_COMPARISON(TYPE, gt, >) \ + TEST_COMPARISON(TYPE, lte, <=) \ + TEST_COMPARISON(TYPE, gte, >=) \ + TEST_UNARY(TYPE, nop, +) \ + TEST_UNARY(TYPE, neg, -) + +#define TEST_INT_OPS(TYPE) \ + TEST_OPS(TYPE) \ + TEST_BINARY(TYPE, mod, %) \ + TEST_BINARY(TYPE, and, &) \ + TEST_BINARY(TYPE, or, |) \ + TEST_BINARY(TYPE, xor, ^) \ + TEST_BINARY(TYPE, shl, <<) \ + TEST_BINARY(TYPE, shr, <<) \ + TEST_UNARY(TYPE, not, ~) + +TEST_INT_OPS(fixed_int8_t) +TEST_INT_OPS(fixed_int16_t) +TEST_INT_OPS(fixed_int32_t) +TEST_INT_OPS(fixed_int64_t) +TEST_INT_OPS(fixed_uint8_t) +TEST_INT_OPS(fixed_uint16_t) +TEST_INT_OPS(fixed_uint32_t) +TEST_INT_OPS(fixed_uint64_t) + +TEST_OPS(fixed_float16_t) +TEST_OPS(fixed_float32_t) +TEST_OPS(fixed_float64_t)