Author: Matt Devereau Date: 2022-05-11T13:33:56Z New Revision: 75bb815231f6967bd5f4e24143141b9fe69d01f8
URL: https://github.com/llvm/llvm-project/commit/75bb815231f6967bd5f4e24143141b9fe69d01f8 DIFF: https://github.com/llvm/llvm-project/commit/75bb815231f6967bd5f4e24143141b9fe69d01f8.diff LOG: [AArch64][SVE] Add aarch64_sve_pcs attribute to Clang Enable function attribute aarch64_sve_pcs at the C level, which correspondes to aarch64_sve_vector_pcs at the LLVM IR level. This requirement was created by this addition to the ARM C Language Extension: https://github.com/ARM-software/acle/pull/194 Differential Revision: https://reviews.llvm.org/D124998 Added: clang/test/CodeGen/aarch64-svepcs.c clang/test/Sema/aarch64-svepcs.c Modified: clang/include/clang-c/Index.h clang/include/clang/Basic/Attr.td clang/include/clang/Basic/AttrDocs.td clang/include/clang/Basic/Specifiers.h clang/lib/AST/ItaniumMangle.cpp clang/lib/AST/Type.cpp clang/lib/AST/TypePrinter.cpp clang/lib/Basic/Targets/AArch64.cpp clang/lib/CodeGen/CGCall.cpp clang/lib/CodeGen/CGDebugInfo.cpp clang/lib/Sema/SemaDeclAttr.cpp clang/lib/Sema/SemaType.cpp clang/test/Sema/callingconv.c clang/tools/libclang/CXType.cpp Removed: ################################################################################ diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h index f28601c37d8ef..c4da7df6595d1 100644 --- a/clang/include/clang-c/Index.h +++ b/clang/include/clang-c/Index.h @@ -3445,6 +3445,7 @@ enum CXCallingConv { CXCallingConv_PreserveAll = 15, CXCallingConv_AArch64VectorCall = 16, CXCallingConv_SwiftAsync = 17, + CXCallingConv_AArch64SVEPCS = 18, CXCallingConv_Invalid = 100, CXCallingConv_Unexposed = 200 diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 39359f414ae78..3c41edb474e89 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -2313,6 +2313,11 @@ def AArch64VectorPcs: DeclOrTypeAttr { let Documentation = [AArch64VectorPcsDocs]; } +def AArch64SVEPcs: DeclOrTypeAttr { + let Spellings = [Clang<"aarch64_sve_pcs">]; + let Documentation = [AArch64SVEPcsDocs]; +} + def Pure : InheritableAttr { let Spellings = [GCC<"pure">]; let Documentation = [Undocumented]; diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index c7ef52f67afa3..b389ff9c02c45 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -2551,6 +2551,32 @@ the Arm Developer website. }]; } +def AArch64SVEPcsDocs : Documentation { + let Category = DocCatCallingConvs; + let Content = [{ +On AArch64 targets, this attribute changes the calling convention of a +function to preserve additional Scalable Vector registers and Scalable +Predicate registers relative to the default calling convention used for +AArch64. + +This means it is more efficient to call such functions from code that performs +extensive scalable vector and scalable predicate calculations, because fewer +live SVE registers need to be saved. This property makes it well-suited for SVE +math library functions, which are typically leaf functions that require a small +number of registers. + +However, using this attribute also means that it is more expensive to call +a function that adheres to the default calling convention from within such +a function. Therefore, it is recommended that this attribute is only used +for leaf functions. + +For more information, see the documentation for `aarch64_sve_pcs` in the +ARM C Language Extension (ACLE) documentation. + +.. _`aarch64_sve_pcs`: https://github.com/ARM-software/acle/blob/main/main/acle.md#scalable-vector-extension-procedure-call-standard-attribute + }]; +} + def RegparmDocs : Documentation { let Category = DocCatCallingConvs; let Content = [{ diff --git a/clang/include/clang/Basic/Specifiers.h b/clang/include/clang/Basic/Specifiers.h index 52ca7cce9d961..7a727e7088deb 100644 --- a/clang/include/clang/Basic/Specifiers.h +++ b/clang/include/clang/Basic/Specifiers.h @@ -280,6 +280,7 @@ namespace clang { CC_PreserveMost, // __attribute__((preserve_most)) CC_PreserveAll, // __attribute__((preserve_all)) CC_AArch64VectorCall, // __attribute__((aarch64_vector_pcs)) + CC_AArch64SVEPCS, // __attribute__((aarch64_sve_pcs)) }; /// Checks whether the given calling convention supports variadic diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index 8d90575385fc4..1be70487c1b4e 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -3149,6 +3149,7 @@ StringRef CXXNameMangler::getCallingConvQualifierName(CallingConv CC) { case CC_AAPCS: case CC_AAPCS_VFP: case CC_AArch64VectorCall: + case CC_AArch64SVEPCS: case CC_IntelOclBicc: case CC_SpirFunction: case CC_OpenCLKernel: diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index 92450e8f5f2f5..200a129437ed5 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -3185,6 +3185,7 @@ StringRef FunctionType::getNameForCallConv(CallingConv CC) { case CC_AAPCS: return "aapcs"; case CC_AAPCS_VFP: return "aapcs-vfp"; case CC_AArch64VectorCall: return "aarch64_vector_pcs"; + case CC_AArch64SVEPCS: return "aarch64_sve_pcs"; case CC_IntelOclBicc: return "intel_ocl_bicc"; case CC_SpirFunction: return "spir_function"; case CC_OpenCLKernel: return "opencl_kernel"; @@ -3620,6 +3621,7 @@ bool AttributedType::isCallingConv() const { case attr::SwiftAsyncCall: case attr::VectorCall: case attr::AArch64VectorPcs: + case attr::AArch64SVEPcs: case attr::Pascal: case attr::MSABI: case attr::SysVABI: diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp index 43183e1e5dd65..7bca45b5f5601 100644 --- a/clang/lib/AST/TypePrinter.cpp +++ b/clang/lib/AST/TypePrinter.cpp @@ -961,6 +961,9 @@ void TypePrinter::printFunctionAfter(const FunctionType::ExtInfo &Info, case CC_AArch64VectorCall: OS << "__attribute__((aarch64_vector_pcs))"; break; + case CC_AArch64SVEPCS: + OS << "__attribute__((aarch64_sve_pcs))"; + break; case CC_IntelOclBicc: OS << " __attribute__((intel_ocl_bicc))"; break; @@ -1750,6 +1753,7 @@ void TypePrinter::printAttributedAfter(const AttributedType *T, break; } case attr::AArch64VectorPcs: OS << "aarch64_vector_pcs"; break; + case attr::AArch64SVEPcs: OS << "aarch64_sve_pcs"; break; case attr::IntelOclBicc: OS << "inteloclbicc"; break; case attr::PreserveMost: OS << "preserve_most"; diff --git a/clang/lib/Basic/Targets/AArch64.cpp b/clang/lib/Basic/Targets/AArch64.cpp index f4aecd3675b1d..38862056227f1 100644 --- a/clang/lib/Basic/Targets/AArch64.cpp +++ b/clang/lib/Basic/Targets/AArch64.cpp @@ -676,6 +676,7 @@ AArch64TargetInfo::checkCallingConvention(CallingConv CC) const { case CC_PreserveAll: case CC_OpenCLKernel: case CC_AArch64VectorCall: + case CC_AArch64SVEPCS: case CC_Win64: return CCCR_OK; default: diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index d69455d650f43..a35e3d811862d 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -62,6 +62,7 @@ unsigned CodeGenTypes::ClangCallConvToLLVMCallConv(CallingConv CC) { // TODO: Add support for __vectorcall to LLVM. case CC_X86VectorCall: return llvm::CallingConv::X86_VectorCall; case CC_AArch64VectorCall: return llvm::CallingConv::AArch64_VectorCall; + case CC_AArch64SVEPCS: return llvm::CallingConv::AArch64_SVE_VectorCall; case CC_SpirFunction: return llvm::CallingConv::SPIR_FUNC; case CC_OpenCLKernel: return CGM.getTargetCodeGenInfo().getOpenCLKernelCallingConv(); case CC_PreserveMost: return llvm::CallingConv::PreserveMost; @@ -228,6 +229,9 @@ static CallingConv getCallingConventionForDecl(const ObjCMethodDecl *D, if (D->hasAttr<AArch64VectorPcsAttr>()) return CC_AArch64VectorCall; + if (D->hasAttr<AArch64SVEPcsAttr>()) + return CC_AArch64SVEPCS; + if (D->hasAttr<IntelOclBiccAttr>()) return CC_IntelOclBicc; diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index a6ea2c0f31abf..3d73bfb8ce793 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -1326,6 +1326,7 @@ static unsigned getDwarfCC(CallingConv CC) { return llvm::dwarf::DW_CC_LLVM_X86_64SysV; case CC_AAPCS: case CC_AArch64VectorCall: + case CC_AArch64SVEPCS: return llvm::dwarf::DW_CC_LLVM_AAPCS; case CC_AAPCS_VFP: return llvm::dwarf::DW_CC_LLVM_AAPCS_VFP; diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 21001f8542477..c4a3b18ce2564 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -5024,6 +5024,9 @@ static void handleCallConvAttr(Sema &S, Decl *D, const ParsedAttr &AL) { case ParsedAttr::AT_AArch64VectorPcs: D->addAttr(::new (S.Context) AArch64VectorPcsAttr(S.Context, AL)); return; + case ParsedAttr::AT_AArch64SVEPcs: + D->addAttr(::new (S.Context) AArch64SVEPcsAttr(S.Context, AL)); + return; case ParsedAttr::AT_IntelOclBicc: D->addAttr(::new (S.Context) IntelOclBiccAttr(S.Context, AL)); return; @@ -5181,6 +5184,9 @@ bool Sema::CheckCallingConvAttr(const ParsedAttr &Attrs, CallingConv &CC, case ParsedAttr::AT_AArch64VectorPcs: CC = CC_AArch64VectorCall; break; + case ParsedAttr::AT_AArch64SVEPcs: + CC = CC_AArch64SVEPCS; + break; case ParsedAttr::AT_RegCall: CC = CC_X86RegCall; break; @@ -8793,6 +8799,7 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case ParsedAttr::AT_PreserveMost: case ParsedAttr::AT_PreserveAll: case ParsedAttr::AT_AArch64VectorPcs: + case ParsedAttr::AT_AArch64SVEPcs: handleCallConvAttr(S, D, AL); break; case ParsedAttr::AT_Suppress: diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 15f7d36840bad..0bb352e914a8c 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -121,6 +121,7 @@ static void diagnoseBadTypeAttribute(Sema &S, const ParsedAttr &attr, case ParsedAttr::AT_SwiftAsyncCall: \ case ParsedAttr::AT_VectorCall: \ case ParsedAttr::AT_AArch64VectorPcs: \ + case ParsedAttr::AT_AArch64SVEPcs: \ case ParsedAttr::AT_MSABI: \ case ParsedAttr::AT_SysVABI: \ case ParsedAttr::AT_Pcs: \ @@ -7481,6 +7482,8 @@ static Attr *getCCTypeAttr(ASTContext &Ctx, ParsedAttr &Attr) { return createSimpleAttr<VectorCallAttr>(Ctx, Attr); case ParsedAttr::AT_AArch64VectorPcs: return createSimpleAttr<AArch64VectorPcsAttr>(Ctx, Attr); + case ParsedAttr::AT_AArch64SVEPcs: + return createSimpleAttr<AArch64SVEPcsAttr>(Ctx, Attr); case ParsedAttr::AT_Pcs: { // The attribute may have had a fixit applied where we treated an // identifier as a string literal. The contents of the string are valid, diff --git a/clang/test/CodeGen/aarch64-svepcs.c b/clang/test/CodeGen/aarch64-svepcs.c new file mode 100644 index 0000000000000..1d4e2f302e3f7 --- /dev/null +++ b/clang/test/CodeGen/aarch64-svepcs.c @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -triple aarch64-linux-gnu -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECKC +// RUN: %clang_cc1 -triple aarch64-linux-gnu -emit-llvm -x c++ -o - %s | FileCheck %s -check-prefix=CHECKCXX +// RUN: %clang_cc1 -triple i686-pc-linux-gnu -verify %s + +void __attribute__((aarch64_sve_pcs)) f(int *); // expected-warning {{'aarch64_sve_pcs' calling convention is not supported for this target}} + +// CHECKC: define{{.*}} void @g( +// CHECKCXX: define{{.*}} void @_Z1gPi( +void g(int *a) { + + // CHECKC: call aarch64_sve_vector_pcs void @f( + // CHECKCXX: call aarch64_sve_vector_pcs void @_Z1fPi + f(a); +} + +// CHECKC: declare aarch64_sve_vector_pcs void @f( +// CHECKCXX: declare aarch64_sve_vector_pcs void @_Z1fPi + +void __attribute__((aarch64_sve_pcs)) h(int *a) { // expected-warning {{'aarch64_sve_pcs' calling convention is not supported for this target}} + // CHECKC: define{{.*}} aarch64_sve_vector_pcs void @h( + // CHECKCXX: define{{.*}} aarch64_sve_vector_pcs void @_Z1hPi( + f(a); +} diff --git a/clang/test/Sema/aarch64-svepcs.c b/clang/test/Sema/aarch64-svepcs.c new file mode 100644 index 0000000000000..96661c80767fa --- /dev/null +++ b/clang/test/Sema/aarch64-svepcs.c @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -triple aarch64-linux-gnu -target-feature +sve -verify %s + +typedef __attribute__((aarch64_sve_pcs)) int invalid_typedef; // expected-warning {{'aarch64_sve_pcs' only applies to function types; type here is 'int'}} + +void __attribute__((aarch64_sve_pcs(0))) foo0(void); // expected-error {{'aarch64_sve_pcs' attribute takes no arguments}} + +void __attribute__((aarch64_sve_pcs, preserve_all)) foo1(void); // expected-error {{not compatible}} + +void __attribute__((cdecl)) foo2(void); // expected-note {{previous declaration is here}} +void __attribute__((aarch64_sve_pcs)) foo2(void) {} // expected-error {{function declared 'aarch64_sve_pcs' here was previously declared 'cdecl'}} + +void foo3(void); // expected-note {{previous declaration is here}} +void __attribute__((aarch64_sve_pcs)) foo3(void) {} // expected-error {{function declared 'aarch64_sve_pcs' here was previously declared without calling convention}} + +typedef int (*fn_ty)(void); +typedef int __attribute__((aarch64_sve_pcs)) (*aasvepcs_fn_ty)(void); +void foo4(fn_ty ptr1, aasvepcs_fn_ty ptr2) { + ptr1 = ptr2; // expected-warning {{incompatible function pointer types}} +} diff --git a/clang/test/Sema/callingconv.c b/clang/test/Sema/callingconv.c index ed8e60bc6c0b1..675200cc9cfc7 100644 --- a/clang/test/Sema/callingconv.c +++ b/clang/test/Sema/callingconv.c @@ -52,6 +52,7 @@ int __attribute__((pcs("aapcs-vfp"))) pcs6(void); // expected-warning {{'pcs' ca int __attribute__((pcs("foo"))) pcs7(void); // expected-error {{invalid PCS type}} int __attribute__((aarch64_vector_pcs)) aavpcs(void); // expected-warning {{'aarch64_vector_pcs' calling convention is not supported for this target}} +int __attribute__((aarch64_sve_pcs)) aasvepcs(void); // expected-warning {{'aarch64_sve_pcs' calling convention is not supported for this target}} // PR6361 void ctest3(); diff --git a/clang/tools/libclang/CXType.cpp b/clang/tools/libclang/CXType.cpp index 31a89426ec359..4aee32210df1f 100644 --- a/clang/tools/libclang/CXType.cpp +++ b/clang/tools/libclang/CXType.cpp @@ -666,6 +666,7 @@ CXCallingConv clang_getFunctionTypeCallingConv(CXType X) { TCALLINGCONV(X86RegCall); TCALLINGCONV(X86VectorCall); TCALLINGCONV(AArch64VectorCall); + TCALLINGCONV(AArch64SVEPCS); TCALLINGCONV(Win64); TCALLINGCONV(X86_64SysV); TCALLINGCONV(AAPCS); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits