c-rhodes created this revision.
c-rhodes added reviewers: sdesmalen, rsandifo-arm, efriedma, ctetreau, 
cameron.mcinally.
Herald added subscribers: danielkiss, kristof.beyls, tschuett.
Herald added a reviewer: rengolin.
Herald added a reviewer: aaron.ballman.
Herald added a project: clang.

This patch implements parsing support for the 'arm_sve_vector_bits' type
attribute, defined by the Arm C Language Extensions (ACLE, version 00bet5,
section 3.7.3) for SVE [1].

The purpose of this attribute is to define fixed-length (VLST) versions
of existing sizeless types (VLAT). For example:

  #if __ARM_FEATURE_SVE_BITS==512
  typedef svint32_t fixed_svint32_t __attribute__((arm_sve_vector_bits(512)));
  #endif

Creates a type 'fixed_svint32_t' that is a fixed-length version of
'svint32_t' that is normal-sized (rather than sizeless) and contains
exactly 512 bits. Unlike 'svint32_t', this type can be used in places
such as structs and arrays where sizeless types can't.

Implemented in this patch is the following:

- Defined and tested attribute taking single argument.
- Checks the argument is an integer constant expression.
- Attribute can only be attached to a single SVE vector or predicate type, 
excluding tuple types such as svint32x4_t.
- Validates N == __ARM_FEATURE_SVE_BITS, where N is the number of bits passed 
to the attribute.
- Basic validation of the __ARM_FEATURE_SVE_BITS macro.

The __ARM_FEATURE_SVE_BITS macro will be enabled by the
-msve-vector-bits=<bits> flag in the final patch of the series.

[1] https://developer.arm.com/documentation/100987/latest


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D83550

Files:
  clang/include/clang/AST/Type.h
  clang/include/clang/Basic/Attr.td
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/lib/AST/Type.cpp
  clang/lib/AST/TypePrinter.cpp
  clang/lib/Sema/SemaType.cpp
  clang/test/Sema/arm-feature-sve-bits-macro.c
  clang/test/Sema/attr-arm-sve-vector-bits.c

Index: clang/test/Sema/attr-arm-sve-vector-bits.c
===================================================================
--- /dev/null
+++ clang/test/Sema/attr-arm-sve-vector-bits.c
@@ -0,0 +1,43 @@
+// RUN: %clang_cc1 -triple aarch64 -target-feature +sve -target-feature +bf16 -fsyntax-only -verify -D__ARM_FEATURE_SVE_BITS=128 -fallow-half-arguments-and-returns %s
+// RUN: %clang_cc1 -triple aarch64 -target-feature +sve -target-feature +bf16 -fsyntax-only -verify -D__ARM_FEATURE_SVE_BITS=256 -fallow-half-arguments-and-returns %s
+// RUN: %clang_cc1 -triple aarch64 -target-feature +sve -target-feature +bf16 -fsyntax-only -verify -D__ARM_FEATURE_SVE_BITS=512 -fallow-half-arguments-and-returns %s
+// RUN: %clang_cc1 -triple aarch64 -target-feature +sve -target-feature +bf16 -fsyntax-only -verify -D__ARM_FEATURE_SVE_BITS=1024 -fallow-half-arguments-and-returns %s
+// RUN: %clang_cc1 -triple aarch64 -target-feature +sve -target-feature +bf16 -fsyntax-only -verify -D__ARM_FEATURE_SVE_BITS=2048 -fallow-half-arguments-and-returns %s
+
+#include <arm_sve.h>
+
+#define N __ARM_FEATURE_SVE_BITS
+
+// Define valid fixed-width SVE types
+typedef svint8_t fixed_int8_t __attribute__((arm_sve_vector_bits(N)));
+typedef svint16_t fixed_int16_t __attribute__((arm_sve_vector_bits(N)));
+typedef svint32_t fixed_int32_t __attribute__((arm_sve_vector_bits(N)));
+typedef svint64_t fixed_int64_t __attribute__((arm_sve_vector_bits(N)));
+
+typedef svuint8_t fixed_uint8_t __attribute__((arm_sve_vector_bits(N)));
+typedef svuint16_t fixed_uint16_t __attribute__((arm_sve_vector_bits(N)));
+typedef svuint32_t fixed_uint32_t __attribute__((arm_sve_vector_bits(N)));
+typedef svuint64_t fixed_uint64_t __attribute__((arm_sve_vector_bits(N)));
+
+typedef svfloat16_t fixed_float16_t __attribute__((arm_sve_vector_bits(N)));
+typedef svfloat32_t fixed_float32_t __attribute__((arm_sve_vector_bits(N)));
+typedef svfloat64_t fixed_float64_t __attribute__((arm_sve_vector_bits(N)));
+
+typedef svbfloat16_t fixed_bfloat16_t __attribute__((arm_sve_vector_bits(N)));
+
+typedef svbool_t fixed_bool_t __attribute__((arm_sve_vector_bits(N)));
+
+// Attribute must have a single argument
+typedef svint8_t no_argument __attribute__((arm_sve_vector_bits));         // expected-error {{'arm_sve_vector_bits' attribute takes one argument}}
+typedef svint8_t two_arguments __attribute__((arm_sve_vector_bits(2, 4))); // expected-error {{'arm_sve_vector_bits' attribute takes one argument}}
+
+// The number of SVE vector bits must be an integer constant expression
+typedef svint8_t non_int_size1 __attribute__((arm_sve_vector_bits(2.0)));   // expected-error {{'arm_sve_vector_bits' attribute requires an integer constant}}
+typedef svint8_t non_int_size2 __attribute__((arm_sve_vector_bits("256"))); // expected-error {{'arm_sve_vector_bits' attribute requires an integer constant}}
+
+// Attribute must be attached to a single SVE vector or predicate type.
+typedef void *badtype1 __attribute__((arm_sve_vector_bits(N))); // expected-error {{'arm_sve_vector_bits' attribute applied to non-SVE type 'void *'}}
+typedef int badtype2 __attribute__((arm_sve_vector_bits(N)));   // expected-error {{'arm_sve_vector_bits' attribute applied to non-SVE type 'int'}}
+typedef float badtype3 __attribute__((arm_sve_vector_bits(N))); // expected-error {{'arm_sve_vector_bits' attribute applied to non-SVE type 'float'}}
+typedef svint8x2_t badtype4 __attribute__((arm_sve_vector_bits(N))); // expected-error {{'arm_sve_vector_bits' attribute applied to non-SVE type 'svint8x2_t' (aka '__clang_svint8x2_t')}}
+typedef svfloat32x3_t badtype5 __attribute__((arm_sve_vector_bits(N))); // expected-error {{'arm_sve_vector_bits' attribute applied to non-SVE type 'svfloat32x3_t' (aka '__clang_svfloat32x3_t')}}
Index: clang/test/Sema/arm-feature-sve-bits-macro.c
===================================================================
--- /dev/null
+++ clang/test/Sema/arm-feature-sve-bits-macro.c
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -triple aarch64 -target-feature +sve -fsyntax-only -verify -D__ARM_FEATURE_SVE_BITS=512 -D__ARM_FEATURE_SVE -fallow-half-arguments-and-returns %s
+
+#include <arm_sve.h>
+
+#define N 512
+
+// __ARM_FEATURE_SVE_BITS macro must be defined for attribute to have any effect
+#undef __ARM_FEATURE_SVE_BITS
+typedef svint8_t macro_undefined __attribute__((arm_sve_vector_bits(N))); // expected-error {{__ARM_FEATURE_SVE_BITS is not defined}}
+
+// __ARM_FEATURE_SVE_BITS macro must have a single argument
+#define __ARM_FEATURE_SVE_BITS
+typedef svint8_t macro_no_argument __attribute__((arm_sve_vector_bits(N))); // expected-error {{__ARM_FEATURE_SVE_BITS takes one argument}}
+#undef __ARM_FEATURE_SVE_BITS
+
+// __ARM_FEATURE_SVE_BITS macro must be an integer constant
+#define __ARM_FEATURE_SVE_BITS "512"
+typedef svint8_t macro_non_int_size __attribute__((arm_sve_vector_bits(N))); // expected-error {{__ARM_FEATURE_SVE_BITS requires an integer constant}}
+#undef __ARM_FEATURE_SVE_BITS
+
+// SVE vector bits must equal __ARM_FEATURE_SVE_BITS
+#define __ARM_FEATURE_SVE_BITS 512
+typedef svint8_t badsize __attribute__((arm_sve_vector_bits(256))); // expected-error {{unsupported SVE vector size '256'}}
Index: clang/lib/Sema/SemaType.cpp
===================================================================
--- clang/lib/Sema/SemaType.cpp
+++ clang/lib/Sema/SemaType.cpp
@@ -7748,6 +7748,88 @@
   CurType = S.Context.getVectorType(CurType, numElts, VecKind);
 }
 
+/// HandleArmSveVectorBitsTypeAttr - The "arm_sve_vector_bits" attribute is
+/// used to create fixed-length versions of sizeless SVE types defined by
+/// the ACLE, such as svint32_t and svbool_t.
+static void HandleArmSveVectorBitsTypeAttr(QualType &CurType,
+                                           const ParsedAttr &Attr, Sema &S) {
+  // Target must have SVE.
+  if (!S.Context.getTargetInfo().hasFeature("sve")) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_unsupported) << Attr;
+    Attr.setInvalid();
+    return;
+  }
+
+  // Check the attribute arguments.
+  if (Attr.getNumArgs() != 1) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
+        << Attr << 1;
+    Attr.setInvalid();
+    return;
+  }
+
+  // The vector size must be an integer constant expression.
+  Expr *VecSizeExpr = static_cast<Expr *>(Attr.getArgAsExpr(0));
+  llvm::APSInt SveVectorSizeInBits(32);
+  if (VecSizeExpr->isTypeDependent() || VecSizeExpr->isValueDependent() ||
+      !VecSizeExpr->isIntegerConstantExpr(SveVectorSizeInBits, S.Context)) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_argument_type)
+        << Attr << AANT_ArgumentIntegerConstant
+        << VecSizeExpr->getSourceRange();
+    Attr.setInvalid();
+    return;
+  }
+
+  // The __ARM_FEATURE_SVE_BITS macro must be defined when using this attribute.
+  auto &PP = S.getPreprocessor();
+  if (!PP.isMacroDefined("__ARM_FEATURE_SVE_BITS")) {
+    S.Diag(Attr.getLoc(),
+           diag::err_attribute_arm_feature_sve_bits_macro_not_defined);
+    Attr.setInvalid();
+    return;
+  }
+
+  const auto *II = PP.getIdentifierInfo("__ARM_FEATURE_SVE_BITS");
+  const auto *MI = PP.getMacroInfo(II);
+  if (!MI)
+    llvm_unreachable("Bad macro!");
+
+  // Check the macro arguments
+  if (MI->getNumTokens() != 1) {
+    S.Diag(Attr.getLoc(),
+           diag::err_attribute_arm_feature_sve_bits_macro_wrong_num_arguments);
+    Attr.setInvalid();
+    return;
+  }
+
+  // The __ARM_FEATURE_SVE_BITS macro must be an integer constant expression.
+  Token ArmFeatureSveBitsTok = MI->tokens().front();
+  if (ArmFeatureSveBitsTok.isNot(tok::numeric_constant)) {
+    S.Diag(Attr.getLoc(),
+           diag::err_attribute_arm_feature_sve_bits_macro_argument_type);
+    Attr.setInvalid();
+    return;
+  }
+
+  // The attribute vector size must equal __ARM_FEATURE_SVE_BITS.
+  ExprResult ExprRes = S.ActOnNumericConstant(ArmFeatureSveBitsTok);
+  const auto *ArmSveFeatureBits = dyn_cast<IntegerLiteral>(ExprRes.get());
+  unsigned VecSize = static_cast<unsigned>(SveVectorSizeInBits.getZExtValue());
+  if (ArmSveFeatureBits->getValue() != VecSize) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_bad_sve_vector_size) << VecSize;
+    Attr.setInvalid();
+    return;
+  }
+
+  // Attribute can only be attached to a single SVE vector or predicate type.
+  if (!CurType->isVLSTBuiltinType()) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_invalid_sve_type)
+        << Attr << CurType;
+    Attr.setInvalid();
+    return;
+  }
+}
+
 static void HandleArmMveStrictPolymorphismAttr(TypeProcessingState &State,
                                                QualType &CurType,
                                                ParsedAttr &Attr) {
@@ -8011,6 +8093,10 @@
                                VectorType::NeonPolyVector);
       attr.setUsedAsTypeAttr();
       break;
+    case ParsedAttr::AT_ArmSveVectorBits:
+      HandleArmSveVectorBitsTypeAttr(type, attr, state.getSema());
+      attr.setUsedAsTypeAttr();
+      break;
     case ParsedAttr::AT_ArmMveStrictPolymorphism: {
       HandleArmMveStrictPolymorphismAttr(state, type, attr);
       attr.setUsedAsTypeAttr();
Index: clang/lib/AST/TypePrinter.cpp
===================================================================
--- clang/lib/AST/TypePrinter.cpp
+++ clang/lib/AST/TypePrinter.cpp
@@ -1632,6 +1632,9 @@
   case attr::ArmMveStrictPolymorphism:
     OS << "__clang_arm_mve_strict_polymorphism";
     break;
+  case attr::ArmSveVectorBits:
+    OS << "arm_sve_vector_bits";
+    break;
   }
   OS << "))";
 }
Index: clang/lib/AST/Type.cpp
===================================================================
--- clang/lib/AST/Type.cpp
+++ clang/lib/AST/Type.cpp
@@ -2294,6 +2294,30 @@
 
 bool Type::isSizelessType() const { return isSizelessBuiltinType(); }
 
+bool Type::isVLSTBuiltinType() const {
+  if (const BuiltinType *BT = getAs<BuiltinType>()) {
+    switch (BT->getKind()) {
+    case BuiltinType::SveInt8:
+    case BuiltinType::SveInt16:
+    case BuiltinType::SveInt32:
+    case BuiltinType::SveInt64:
+    case BuiltinType::SveUint8:
+    case BuiltinType::SveUint16:
+    case BuiltinType::SveUint32:
+    case BuiltinType::SveUint64:
+    case BuiltinType::SveFloat16:
+    case BuiltinType::SveFloat32:
+    case BuiltinType::SveFloat64:
+    case BuiltinType::SveBFloat16:
+    case BuiltinType::SveBool:
+      return true;
+    default:
+      return false;
+    }
+  }
+  return false;
+}
+
 bool QualType::isPODType(const ASTContext &Context) const {
   // C++11 has a more relaxed definition of POD.
   if (Context.getLangOpts().CPlusPlus11)
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2800,6 +2800,16 @@
 def err_attribute_invalid_matrix_type : Error<"invalid matrix element type %0">;
 def err_attribute_bad_neon_vector_size : Error<
   "Neon vector size must be 64 or 128 bits">;
+def err_attribute_invalid_sve_type : Error<
+  "%0 attribute applied to non-SVE type %1">;
+def err_attribute_bad_sve_vector_size : Error<
+  "unsupported SVE vector size '%0'">;
+def err_attribute_arm_feature_sve_bits_macro_not_defined : Error<
+  "__ARM_FEATURE_SVE_BITS is not defined">;
+def err_attribute_arm_feature_sve_bits_macro_wrong_num_arguments : Error<
+  "__ARM_FEATURE_SVE_BITS takes one argument">;
+def err_attribute_arm_feature_sve_bits_macro_argument_type : Error<
+  "__ARM_FEATURE_SVE_BITS requires an integer constant">;
 def err_attribute_requires_positive_integer : Error<
   "%0 attribute requires a %select{positive|non-negative}1 "
   "integral compile time constant expression">;
Index: clang/include/clang/Basic/Attr.td
===================================================================
--- clang/include/clang/Basic/Attr.td
+++ clang/include/clang/Basic/Attr.td
@@ -1532,6 +1532,12 @@
   let ASTNode = 0;
 }
 
+def ArmSveVectorBits : TypeAttr {
+  let Spellings = [GNU<"arm_sve_vector_bits">];
+  let Args = [IntArgument<"NumBits">];
+  let Documentation = [Undocumented];
+}
+
 def ArmMveStrictPolymorphism : TypeAttr, TargetSpecificAttr<TargetARM> {
   let Spellings = [Clang<"__clang_arm_mve_strict_polymorphism">];
   let Documentation = [ArmMveStrictPolymorphismDocs];
Index: clang/include/clang/AST/Type.h
===================================================================
--- clang/include/clang/AST/Type.h
+++ clang/include/clang/AST/Type.h
@@ -1925,6 +1925,11 @@
   bool isSizelessType() const;
   bool isSizelessBuiltinType() 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.
+  bool isVLSTBuiltinType() const;
+
   /// Types are partitioned into 3 broad categories (C99 6.2.5p1):
   /// object types, function types, and incomplete types.
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to