[clang] 753aca0 - [AArch64] Add an error if SVE scalable vector types are used in a context without sve

David Green via cfe-commits cfe-commits at lists.llvm.org
Thu Jan 12 10:21:34 PST 2023


Author: David Green
Date: 2023-01-12T18:21:28Z
New Revision: 753aca0a3ab0c1822ab3a95beaf8eaa91d7a157d

URL: https://github.com/llvm/llvm-project/commit/753aca0a3ab0c1822ab3a95beaf8eaa91d7a157d
DIFF: https://github.com/llvm/llvm-project/commit/753aca0a3ab0c1822ab3a95beaf8eaa91d7a157d.diff

LOG: [AArch64] Add an error if SVE scalable vector types are used in a context without sve

This adds an error message if the isSVESizelessBuiltinType like
__SVFloat32_t / __SVInt64_t / etc, which provide the backing for the
svfloat32_t / svint64_t / etc ACLE types, are used in a function without
SVE. The alternative is a crash in the backend, which is not capable of
handling scalable vector types.

When SVE is available, either through a -march=..+sve option or via a
target(sve) attribute, nothing should change. Without the sve feature,
this patch gives an error for any function arguments, return values and
variable declarations involving the scalable types. Struct/class members
and global variables already give an error. As this can be based on the
current function target attributes, the error sometimes needs to be
handled later than would otherwise if it was just based on the global
target.

Differential Revision: https://reviews.llvm.org/D131058

Added: 
    clang/test/Sema/arm-sve-target.cpp

Modified: 
    clang/include/clang/AST/Type.h
    clang/include/clang/Basic/DiagnosticSemaKinds.td
    clang/lib/AST/Type.cpp
    clang/lib/Sema/Sema.cpp
    clang/lib/Sema/SemaDecl.cpp
    clang/test/CodeGen/aarch64-targetattr-arch.c

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index c1650724f711..25d4cab59804 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -2026,6 +2026,9 @@ class alignas(8) Type : public ExtQualsTypeCommonBase {
   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.

diff  --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index e3d186807e17..02afb098b239 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3048,6 +3048,8 @@ def err_attribute_bad_sve_vector_size : Error<
 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">;

diff  --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index aec8e9596e42..1536faed23b0 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -2343,6 +2343,20 @@ bool Type::isSizelessBuiltinType() const {
 
 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()) {

diff  --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index ec13dc46e8c0..e856e5a4429c 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -2035,6 +2035,15 @@ void Sema::checkTypeSupport(QualType Ty, SourceLocation Loc, ValueDecl *D) {
       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);

diff  --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 026779e0bb9f..3dbd61c2c711 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -8690,6 +8690,19 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) {
     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

diff  --git a/clang/test/CodeGen/aarch64-targetattr-arch.c b/clang/test/CodeGen/aarch64-targetattr-arch.c
index c7fa8e878550..d70d68c6e6a2 100644
--- a/clang/test/CodeGen/aarch64-targetattr-arch.c
+++ b/clang/test/CodeGen/aarch64-targetattr-arch.c
@@ -22,14 +22,14 @@ svint8_t test_svadd_attr(svbool_t pg, svint8_t op1, svint8_t op2)
   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 at +2{{always_inline function '__crc32cd' requires target feature 'crc'}}
 #endif
   __crc32cd(1, 1);
 #if defined(HAS8) || defined(HAS81)
-// expected-error at +2{{'svadd_s8_z' needs target feature sve}}
+// expected-error at +2{{'svundef_s8' needs target feature sve}}
 #endif
-  return svadd_s8_z(pg, op1, op2);
+  svundef_s8();
 }

diff  --git a/clang/test/Sema/arm-sve-target.cpp b/clang/test/Sema/arm-sve-target.cpp
new file mode 100644
index 000000000000..2277c213bf86
--- /dev/null
+++ b/clang/test/Sema/arm-sve-target.cpp
@@ -0,0 +1,60 @@
+// 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;
+}
+


        


More information about the cfe-commits mailing list