}
}
+ // 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<VectorType>();
+ 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<VectorType>();
+ const VectorType *SecondVecType = SecondType->getAs<VectorType>();
+
+ 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;
// 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<VectorType>();
- 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())) {
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}}
}
// --------------------------------------------------------------------------//
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)