bool isSizelessType() const;
bool isSizelessBuiltinType() const;
+ /// Returns true for SVE scalable vector types.
+ bool isSVESizelessBuiltinType() const;
+
/// Determines if this is a sizeless type supported by the
/// 'arm_sve_vector_bits' type attribute, which can be applied to a single
/// SVE vector or predicate, excluding tuple types such as svint32x4_t.
def err_attribute_arm_feature_sve_bits_unsupported : Error<
"%0 is only supported when '-msve-vector-bits=<bits>' is specified with a "
"value of 128, 256, 512, 1024 or 2048.">;
+def err_sve_vector_in_non_sve_target : Error<
+ "SVE vector type %0 cannot be used in a target without sve">;
def err_attribute_requires_positive_integer : Error<
"%0 attribute requires a %select{positive|non-negative}1 "
"integral compile time constant expression">;
bool Type::isSizelessType() const { return isSizelessBuiltinType(); }
+bool Type::isSVESizelessBuiltinType() const {
+ if (const BuiltinType *BT = getAs<BuiltinType>()) {
+ switch (BT->getKind()) {
+ // SVE Types
+#define SVE_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
+#include "clang/Basic/AArch64SVEACLETypes.def"
+ return true;
+ default:
+ return false;
+ }
+ }
+ return false;
+}
+
bool Type::isVLSTBuiltinType() const {
if (const BuiltinType *BT = getAs<BuiltinType>()) {
switch (BT->getKind()) {
if (D)
targetDiag(D->getLocation(), diag::note_defined_here, FD) << D;
}
+
+ // Don't allow SVE types in functions without a SVE target.
+ if (Ty->isSVESizelessBuiltinType() && FD && FD->hasBody()) {
+ llvm::StringMap<bool> CallerFeatureMap;
+ Context.getFunctionFeatureMap(CallerFeatureMap, FD);
+ if (!Builtin::evaluateRequiredTargetFeatures(
+ "sve", CallerFeatureMap))
+ Diag(D->getLocation(), diag::err_sve_vector_in_non_sve_target) << Ty;
+ }
};
CheckType(Ty);
NewVD->setInvalidDecl();
return;
}
+
+ // Check that SVE types are only used in functions with SVE available.
+ if (T->isSVESizelessBuiltinType() && CurContext->isFunctionOrMethod()) {
+ const FunctionDecl *FD = cast<FunctionDecl>(CurContext);
+ llvm::StringMap<bool> CallerFeatureMap;
+ Context.getFunctionFeatureMap(CallerFeatureMap, FD);
+ if (!Builtin::evaluateRequiredTargetFeatures(
+ "sve", CallerFeatureMap)) {
+ Diag(NewVD->getLocation(), diag::err_sve_vector_in_non_sve_target) << T;
+ NewVD->setInvalidDecl();
+ return;
+ }
+ }
}
/// Perform semantic checking on a newly-created variable
return svadd_s8_z(pg, op1, op2);
}
-svint8_t test_errors(svbool_t pg, svint8_t op1, svint8_t op2)
+void test_errors()
{
#ifdef HAS8
// expected-error@+2{{always_inline function '__crc32cd' requires target feature 'crc'}}
#endif
__crc32cd(1, 1);
#if defined(HAS8) || defined(HAS81)
-// expected-error@+2{{'svadd_s8_z' needs target feature sve}}
+// expected-error@+2{{'svundef_s8' needs target feature sve}}
#endif
- return svadd_s8_z(pg, op1, op2);
+ svundef_s8();
}
--- /dev/null
+// RUN: %clang_cc1 -fsyntax-only -verify -DNONEON -std=c++11 -triple aarch64-arm-none-eabi %s
+
+// A target without sve should not be able to use sve types.
+
+void test_var() {
+ __SVFloat32_t x; // expected-error {{SVE vector type '__SVFloat32_t' cannot be used in a target without sve}}
+}
+
+__attribute__((target("sve")))
+void test_var_target() {
+ __SVFloat32_t x;
+}
+
+__attribute__((target("sve2")))
+void test_var_target2() {
+ __SVFloat32_t x;
+}
+
+__attribute__((target("sve2-bitperm")))
+void test_var_target3() {
+ __SVFloat32_t x;
+}
+
+__SVFloat32_t other_ret();
+__SVFloat32_t test_ret() { // expected-error {{SVE vector type '__SVFloat32_t' cannot be used in a target without sve}}
+ return other_ret();
+}
+
+__attribute__((target("sve")))
+__SVFloat32_t test_ret_target() {
+ return other_ret();
+}
+
+void test_arg(__SVFloat32_t arg) { // expected-error {{SVE vector type '__SVFloat32_t' cannot be used in a target without sve}}
+}
+
+__attribute__((target("sve")))
+void test_arg_target(__SVFloat32_t arg) {
+}
+
+__clang_svint32x4_t test4x() { // expected-error {{SVE vector type '__clang_svint32x4_t' cannot be used in a target without sve}}
+ __clang_svint32x4_t x; // expected-error {{SVE vector type '__clang_svint32x4_t' cannot be used in a target without sve}}
+ return x;
+}
+
+__attribute__((target("sve")))
+__clang_svint32x4_t test4x_target() {
+ __clang_svint32x4_t x;
+ return x;
+}
+
+// Pointers are still valid to pass around.
+void foo(__SVFloat32_t *&ptrA, __SVFloat32_t* &ptrB) {
+ ptrA = ptrB;
+}
+
+__SVFloat32_t* foo(int x, __SVFloat32_t *ptrA) {
+ return ptrA;
+}
+