diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -2029,6 +2029,9 @@ /// Returns true for SVE scalable vector types. bool isSVESizelessBuiltinType() const; + /// Returns true for RVV scalable vector types. + bool isRVVSizelessBuiltinType() const; + /// Check if this is a WebAssembly Reference Type. bool isWebAssemblyReferenceType() const; bool isWebAssemblyExternrefType() const; 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 @@ -3165,8 +3165,8 @@ def err_attribute_size_too_large : Error<"%0 size too large">; 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_sve_rvv_gnu_ambiguous : Error< + "cannot combine GNU and %select{SVE|RVV}0 vectors in expression, result is ambiguous (%1 and %2)">; 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/Type.cpp b/clang/lib/AST/Type.cpp --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -2372,6 +2372,19 @@ return false; } +bool Type::isRVVSizelessBuiltinType() const { + if (const BuiltinType *BT = getAs()) { + switch (BT->getKind()) { +#define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id: +#include "clang/Basic/RISCVVTypes.def" + return true; + default: + return false; + } + } + return false; +} + bool Type::isVLSTBuiltinType() const { if (const BuiltinType *BT = getAs()) { switch (BT->getKind()) { 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 @@ -10768,10 +10768,12 @@ // Expressions containing GNU and SVE (fixed or sizeless) vectors are invalid // since the ambiguity can affect the ABI. - auto IsSveGnuConversion = [](QualType FirstType, QualType SecondType) { + auto IsSveRVVGnuConversion = [](QualType FirstType, QualType SecondType, + unsigned &SVEorRVV) { const VectorType *FirstVecType = FirstType->getAs(); const VectorType *SecondVecType = SecondType->getAs(); + SVEorRVV = 0; if (FirstVecType && SecondVecType) return FirstVecType->getVectorKind() == VectorType::GenericVector && (SecondVecType->getVectorKind() == @@ -10779,13 +10781,24 @@ SecondVecType->getVectorKind() == VectorType::SveFixedLengthPredicateVector); - return FirstType->isSizelessBuiltinType() && SecondVecType && - SecondVecType->getVectorKind() == VectorType::GenericVector; + if (SecondVecType && + SecondVecType->getVectorKind() == VectorType::GenericVector) { + if (FirstType->isSVESizelessBuiltinType()) + return true; + if (FirstType->isRVVSizelessBuiltinType()) { + SVEorRVV = 1; + return true; + } + } + + return false; }; - if (IsSveGnuConversion(LHSType, RHSType) || - IsSveGnuConversion(RHSType, LHSType)) { - Diag(Loc, diag::err_typecheck_sve_gnu_ambiguous) << LHSType << RHSType; + unsigned SVEorRVV; + if (IsSveRVVGnuConversion(LHSType, RHSType, SVEorRVV) || + IsSveRVVGnuConversion(RHSType, LHSType, SVEorRVV)) { + Diag(Loc, diag::err_typecheck_sve_rvv_gnu_ambiguous) + << SVEorRVV << LHSType << RHSType; return QualType(); } diff --git a/clang/test/Sema/attr-riscv-rvv-vector-bits.c b/clang/test/Sema/attr-riscv-rvv-vector-bits.c new file mode 100644 --- /dev/null +++ b/clang/test/Sema/attr-riscv-rvv-vector-bits.c @@ -0,0 +1,62 @@ +// RUN: %clang_cc1 -triple riscv64-none-linux-gnu -target-feature +zve64x -ffreestanding -fsyntax-only -verify %s + +// TODO: Support for a arm_sve_vector_bits like attribute will come in the future. + +#include + +#define N 64 + +typedef __rvv_int8m1_t vint8m1_t; +typedef __rvv_uint8m1_t vuint8m1_t; +typedef __rvv_int16m1_t vint16m1_t; +typedef __rvv_uint16m1_t vuint16m1_t; +typedef __rvv_int32m1_t vint32m1_t; +typedef __rvv_uint32m1_t vuint32m1_t; +typedef __rvv_int64m1_t vint64m1_t; +typedef __rvv_uint64m1_t vuint64m1_t; +typedef __rvv_float32m1_t vfloat32m1_t; +typedef __rvv_float64m1_t vfloat64m1_t; + +// GNU vector types +typedef int8_t gnu_int8_t __attribute__((vector_size(N / 8))); +typedef int16_t gnu_int16_t __attribute__((vector_size(N / 8))); +typedef int32_t gnu_int32_t __attribute__((vector_size(N / 8))); +typedef int64_t gnu_int64_t __attribute__((vector_size(N / 8))); + +typedef uint8_t gnu_uint8_t __attribute__((vector_size(N / 8))); +typedef uint16_t gnu_uint16_t __attribute__((vector_size(N / 8))); +typedef uint32_t gnu_uint32_t __attribute__((vector_size(N / 8))); +typedef uint64_t gnu_uint64_t __attribute__((vector_size(N / 8))); + +typedef float gnu_float32_t __attribute__((vector_size(N / 8))); +typedef double gnu_float64_t __attribute__((vector_size(N / 8))); + + +void f(int c) { + vint8m1_t ss8; + gnu_int8_t gs8; + + // Check conditional expressions where the result is ambiguous are + // ill-formed. + void *sel __attribute__((unused)); + + sel = c ? gs8 : ss8; // expected-error {{cannot combine GNU and RVV vectors in expression, result is ambiguous}} + sel = c ? ss8 : gs8; // expected-error {{cannot combine GNU and RVV vectors in expression, result is ambiguous}} + + // Check binary expressions where the result is ambiguous are ill-formed. + ss8 = ss8 + gs8; // expected-error {{cannot combine GNU and RVV vectors in expression, result is ambiguous}} + + gs8 = gs8 + ss8; // expected-error {{cannot combine GNU and RVV vectors in expression, result is ambiguous}} + + ss8 += gs8; // expected-error {{cannot combine GNU and RVV vectors in expression, result is ambiguous}} + + gs8 += ss8; // expected-error {{cannot combine GNU and RVV vectors in expression, result is ambiguous}} + + ss8 = ss8 == gs8; // expected-error {{cannot combine GNU and RVV vectors in expression, result is ambiguous}} + + gs8 = gs8 == ss8; // expected-error {{cannot combine GNU and RVV vectors in expression, result is ambiguous}} + + ss8 = ss8 & gs8; // expected-error {{invalid operands to binary expression ('vint8m1_t' (aka '__rvv_int8m1_t') and 'gnu_int8_t' (vector of 8 'int8_t' values))}} + + gs8 = gs8 & ss8; // expected-error {{invalid operands to binary expression ('gnu_int8_t' (vector of 8 'int8_t' values) and 'vint8m1_t' (aka '__rvv_int8m1_t'))}} +}