From: Sander de Smalen Date: Mon, 26 Nov 2018 16:38:37 +0000 (+0000) Subject: [AArch64] Add aarch64_vector_pcs function attribute to Clang X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=44a2253a54f5e98bee2e12ffb2d09eacd45991e8;p=platform%2Fupstream%2Fllvm.git [AArch64] Add aarch64_vector_pcs function attribute to Clang This is the Clang patch to complement the following LLVM patches: https://reviews.llvm.org/D51477 https://reviews.llvm.org/D51479 More information describing the vector ABI and procedure call standard can be found here: https://developer.arm.com/products/software-development-tools/\ hpc/arm-compiler-for-hpc/vector-function-abi Patch by Kerry McLaughlin. Reviewed By: rjmccall Differential Revision: https://reviews.llvm.org/D54425 llvm-svn: 347571 --- diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h index aaacb8d..c51dfb1 100644 --- a/clang/include/clang-c/Index.h +++ b/clang/include/clang-c/Index.h @@ -3336,6 +3336,7 @@ enum CXCallingConv { CXCallingConv_Swift = 13, CXCallingConv_PreserveMost = 14, CXCallingConv_PreserveAll = 15, + CXCallingConv_AArch64VectorCall = 16, CXCallingConv_Invalid = 100, CXCallingConv_Unexposed = 200 diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index aadf2fc..a6be48c 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -1785,6 +1785,11 @@ def Pcs : DeclOrTypeAttr { let Documentation = [PcsDocs]; } +def AArch64VectorPcs: DeclOrTypeAttr { + let Spellings = [Clang<"aarch64_vector_pcs">]; + let Documentation = [AArch64VectorPcsDocs]; +} + 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 02eac41..e38c557 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -1742,6 +1742,31 @@ similar to ``stdcall`` on x86. Valid parameter values are "aapcs" and }]; } +def AArch64VectorPcsDocs : Documentation { + let Category = DocCatCallingConvs; + let Content = [{ +On AArch64 targets, this attribute changes the calling convention of a +function to preserve additional floating-point and Advanced SIMD 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 floating-point and vector calculations, because fewer live SIMD and FP +registers need to be saved. This property makes it well-suited for e.g. +floating-point or vector 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_vector_pcs`_ on +the Arm Developer website. + +.. _`aarch64_vector_pcs`: https://developer.arm.com/products/software-development-tools/hpc/arm-compiler-for-hpc/vector-function-abi + }]; +} + 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 cd8213f..0af01e4 100644 --- a/clang/include/clang/Basic/Specifiers.h +++ b/clang/include/clang/Basic/Specifiers.h @@ -251,6 +251,7 @@ namespace clang { CC_Swift, // __attribute__((swiftcall)) CC_PreserveMost, // __attribute__((preserve_most)) CC_PreserveAll, // __attribute__((preserve_all)) + CC_AArch64VectorCall, // __attribute__((aarch64_vector_pcs)) }; /// Checks whether the given calling convention supports variadic diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index 83682a4..a651bdb 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -2659,6 +2659,7 @@ StringRef CXXNameMangler::getCallingConvQualifierName(CallingConv CC) { case CC_X86RegCall: case CC_AAPCS: case CC_AAPCS_VFP: + case CC_AArch64VectorCall: case CC_IntelOclBicc: case CC_SpirFunction: case CC_OpenCLKernel: diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index 86e1b8c..bfb08c0 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -2824,6 +2824,7 @@ StringRef FunctionType::getNameForCallConv(CallingConv CC) { case CC_X86RegCall : return "regcall"; case CC_AAPCS: return "aapcs"; case CC_AAPCS_VFP: return "aapcs-vfp"; + case CC_AArch64VectorCall: return "aarch64_vector_pcs"; case CC_IntelOclBicc: return "intel_ocl_bicc"; case CC_SpirFunction: return "spir_function"; case CC_OpenCLKernel: return "opencl_kernel"; @@ -3216,6 +3217,7 @@ bool AttributedType::isCallingConv() const { case attr::RegCall: case attr::SwiftCall: case attr::VectorCall: + case attr::AArch64VectorPcs: case attr::Pascal: case attr::MSABI: case attr::SysVABI: diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp index fe05127..365f84c 100644 --- a/clang/lib/AST/TypePrinter.cpp +++ b/clang/lib/AST/TypePrinter.cpp @@ -861,6 +861,9 @@ void TypePrinter::printFunctionAfter(const FunctionType::ExtInfo &Info, case CC_AAPCS_VFP: OS << " __attribute__((pcs(\"aapcs-vfp\")))"; break; + case CC_AArch64VectorCall: + OS << "__attribute__((aarch64_vector_pcs))"; + break; case CC_IntelOclBicc: OS << " __attribute__((intel_ocl_bicc))"; break; @@ -1492,7 +1495,7 @@ void TypePrinter::printAttributedAfter(const AttributedType *T, OS << ')'; break; } - + case attr::AArch64VectorPcs: OS << "aarch64_vector_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 1f91214..e64eb21 100644 --- a/clang/lib/Basic/Targets/AArch64.cpp +++ b/clang/lib/Basic/Targets/AArch64.cpp @@ -273,6 +273,7 @@ AArch64TargetInfo::checkCallingConvention(CallingConv CC) const { case CC_PreserveMost: case CC_PreserveAll: case CC_OpenCLKernel: + case CC_AArch64VectorCall: case CC_Win64: return CCCR_OK; default: diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 729884a..0ec5c7f 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -59,6 +59,7 @@ unsigned CodeGenTypes::ClangCallConvToLLVMCallConv(CallingConv CC) { case CC_X86Pascal: return llvm::CallingConv::C; // 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_SpirFunction: return llvm::CallingConv::SPIR_FUNC; case CC_OpenCLKernel: return CGM.getTargetCodeGenInfo().getOpenCLKernelCallingConv(); case CC_PreserveMost: return llvm::CallingConv::PreserveMost; @@ -214,6 +215,9 @@ static CallingConv getCallingConventionForDecl(const Decl *D, bool IsWindows) { if (PcsAttr *PCS = D->getAttr()) return (PCS->getPCS() == PcsAttr::AAPCS ? CC_AAPCS : CC_AAPCS_VFP); + if (D->hasAttr()) + return CC_AArch64VectorCall; + if (D->hasAttr()) return CC_IntelOclBicc; diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index 16d3324..dbceaa7 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -1102,6 +1102,7 @@ static unsigned getDwarfCC(CallingConv CC) { case CC_X86_64SysV: return llvm::dwarf::DW_CC_LLVM_X86_64SysV; case CC_AAPCS: + case CC_AArch64VectorCall: 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 b77b77d..9f5325d 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -4291,6 +4291,11 @@ static void handleCallConvAttr(Sema &S, Decl *D, const ParsedAttr &AL) { AL.getAttributeSpellingListIndex())); return; } + case ParsedAttr::AT_AArch64VectorPcs: + D->addAttr(::new(S.Context) + AArch64VectorPcsAttr(AL.getRange(), S.Context, + AL.getAttributeSpellingListIndex())); + return; case ParsedAttr::AT_IntelOclBicc: D->addAttr(::new (S.Context) IntelOclBiccAttr(AL.getRange(), S.Context, @@ -4368,6 +4373,9 @@ bool Sema::CheckCallingConvAttr(const ParsedAttr &Attrs, CallingConv &CC, case ParsedAttr::AT_VectorCall: CC = CC_X86VectorCall; break; + case ParsedAttr::AT_AArch64VectorPcs: + CC = CC_AArch64VectorCall; + break; case ParsedAttr::AT_RegCall: CC = CC_X86RegCall; break; @@ -5840,14 +5848,14 @@ static void handleDeprecatedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (AL.isDeclspecAttribute() || AL.isCXX11Attribute()) checkAttributeAtMostNumArgs(S, AL, 1); else if (AL.isArgExpr(1) && AL.getArgAsExpr(1) && - !S.checkStringLiteralArgumentAttr(AL, 1, Replacement)) - return; - - if (!S.getLangOpts().CPlusPlus14 && AL.isCXX11Attribute() && !AL.isGNUScope()) - S.Diag(AL.getLoc(), diag::ext_cxx14_attr) << AL; - - D->addAttr(::new (S.Context) - DeprecatedAttr(AL.getRange(), S.Context, Str, Replacement, + !S.checkStringLiteralArgumentAttr(AL, 1, Replacement)) + return; + + if (!S.getLangOpts().CPlusPlus14 && AL.isCXX11Attribute() && !AL.isGNUScope()) + S.Diag(AL.getLoc(), diag::ext_cxx14_attr) << AL; + + D->addAttr(::new (S.Context) + DeprecatedAttr(AL.getRange(), S.Context, Str, Replacement, AL.getAttributeSpellingListIndex())); } @@ -6493,6 +6501,7 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case ParsedAttr::AT_IntelOclBicc: case ParsedAttr::AT_PreserveMost: case ParsedAttr::AT_PreserveAll: + case ParsedAttr::AT_AArch64VectorPcs: handleCallConvAttr(S, D, AL); break; case ParsedAttr::AT_Suppress: diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index d99d493..99ea2d1 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -116,6 +116,7 @@ static void diagnoseBadTypeAttribute(Sema &S, const ParsedAttr &attr, case ParsedAttr::AT_Pascal: \ case ParsedAttr::AT_SwiftCall: \ case ParsedAttr::AT_VectorCall: \ + case ParsedAttr::AT_AArch64VectorPcs: \ case ParsedAttr::AT_MSABI: \ case ParsedAttr::AT_SysVABI: \ case ParsedAttr::AT_Pcs: \ @@ -6653,6 +6654,8 @@ static Attr *getCCTypeAttr(ASTContext &Ctx, ParsedAttr &Attr) { return createSimpleAttr(Ctx, Attr); case ParsedAttr::AT_VectorCall: return createSimpleAttr(Ctx, Attr); + case ParsedAttr::AT_AArch64VectorPcs: + return createSimpleAttr(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-vpcs.c b/clang/test/CodeGen/aarch64-vpcs.c new file mode 100644 index 0000000..0fc2e96 --- /dev/null +++ b/clang/test/CodeGen/aarch64-vpcs.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_vector_pcs)) f(int *); // expected-warning {{calling convention 'aarch64_vector_pcs' ignored for this target}} + +// CHECKC: define void @g( +// CHECKCXX: define void @_Z1gPi( +void g(int *a) { + +// CHECKC: call aarch64_vector_pcs void @f( +// CHECKCXX: call aarch64_vector_pcs void @_Z1fPi + f(a); +} + +// CHECKC: declare aarch64_vector_pcs void @f( +// CHECKCXX: declare aarch64_vector_pcs void @_Z1fPi + +void __attribute__((aarch64_vector_pcs)) h(int *a){ // expected-warning {{calling convention 'aarch64_vector_pcs' ignored for this target}} +// CHECKC: define aarch64_vector_pcs void @h( +// CHECKCXX: define aarch64_vector_pcs void @_Z1hPi( + f(a); +} diff --git a/clang/test/Sema/aarch64-vpcs.c b/clang/test/Sema/aarch64-vpcs.c new file mode 100644 index 0000000..93ad003 --- /dev/null +++ b/clang/test/Sema/aarch64-vpcs.c @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -triple aarch64-linux-gnu -verify %s + +typedef __attribute__((aarch64_vector_pcs)) int invalid_typedef; // expected-warning {{'aarch64_vector_pcs' only applies to function types; type here is 'int'}} + +void __attribute__((aarch64_vector_pcs(0))) foo0(void); // expected-error {{'aarch64_vector_pcs' attribute takes no arguments}} + +void __attribute__((aarch64_vector_pcs, preserve_all)) foo1(void); // expected-error {{not compatible}} + +void __attribute__((cdecl)) foo2(void); // expected-note {{previous declaration is here}} +void __attribute__((aarch64_vector_pcs)) foo2(void) {} // expected-error {{function declared 'aarch64_vector_pcs' here was previously declared 'cdecl'}} + +void foo3(void); // expected-note {{previous declaration is here}} +void __attribute__((aarch64_vector_pcs)) foo3(void) {} // expected-error {{function declared 'aarch64_vector_pcs' here was previously declared without calling convention}} + +typedef int (*fn_ty)(void); +typedef int __attribute__((aarch64_vector_pcs)) (*aavpcs_fn_ty)(void); +void foo4(fn_ty ptr1, aavpcs_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 c7a4821..8b64bee 100644 --- a/clang/test/Sema/callingconv.c +++ b/clang/test/Sema/callingconv.c @@ -51,6 +51,8 @@ int __attribute__((pcs("aapcs"))) pcs5(void); // expected-warning {{calling conv int __attribute__((pcs("aapcs-vfp"))) pcs6(void); // expected-warning {{calling convention 'pcs' ignored for this target}} int __attribute__((pcs("foo"))) pcs7(void); // expected-error {{invalid PCS type}} +int __attribute__((aarch64_vector_pcs)) aavpcs(void); // expected-warning {{calling convention 'aarch64_vector_pcs' ignored for this target}} + // PR6361 void ctest3(); void __attribute__((cdecl)) ctest3() {} diff --git a/clang/tools/libclang/CXType.cpp b/clang/tools/libclang/CXType.cpp index aaf4e7a..b511046 100644 --- a/clang/tools/libclang/CXType.cpp +++ b/clang/tools/libclang/CXType.cpp @@ -651,6 +651,7 @@ CXCallingConv clang_getFunctionTypeCallingConv(CXType X) { TCALLINGCONV(X86Pascal); TCALLINGCONV(X86RegCall); TCALLINGCONV(X86VectorCall); + TCALLINGCONV(AArch64VectorCall); TCALLINGCONV(Win64); TCALLINGCONV(X86_64SysV); TCALLINGCONV(AAPCS);