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