Skip to content

Commit

Permalink
[AArch64] Add aarch64_vector_pcs function attribute to Clang
Browse files Browse the repository at this point in the history
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
  • Loading branch information
sdesmalen-arm committed Nov 26, 2018
1 parent 10a7ee7 commit 44a2253
Show file tree
Hide file tree
Showing 16 changed files with 110 additions and 9 deletions.
1 change: 1 addition & 0 deletions clang/include/clang-c/Index.h
Expand Up @@ -3336,6 +3336,7 @@ enum CXCallingConv {
CXCallingConv_Swift = 13,
CXCallingConv_PreserveMost = 14,
CXCallingConv_PreserveAll = 15,
CXCallingConv_AArch64VectorCall = 16,

CXCallingConv_Invalid = 100,
CXCallingConv_Unexposed = 200
Expand Down
5 changes: 5 additions & 0 deletions clang/include/clang/Basic/Attr.td
Expand Up @@ -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];
Expand Down
25 changes: 25 additions & 0 deletions clang/include/clang/Basic/AttrDocs.td
Expand Up @@ -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 = [{
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Basic/Specifiers.h
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions clang/lib/AST/ItaniumMangle.cpp
Expand Up @@ -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:
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/AST/Type.cpp
Expand Up @@ -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";
Expand Down Expand Up @@ -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:
Expand Down
5 changes: 4 additions & 1 deletion clang/lib/AST/TypePrinter.cpp
Expand Up @@ -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;
Expand Down Expand Up @@ -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";
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Basic/Targets/AArch64.cpp
Expand Up @@ -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:
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/CodeGen/CGCall.cpp
Expand Up @@ -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;
Expand Down Expand Up @@ -214,6 +215,9 @@ static CallingConv getCallingConventionForDecl(const Decl *D, bool IsWindows) {
if (PcsAttr *PCS = D->getAttr<PcsAttr>())
return (PCS->getPCS() == PcsAttr::AAPCS ? CC_AAPCS : CC_AAPCS_VFP);

if (D->hasAttr<AArch64VectorPcsAttr>())
return CC_AArch64VectorCall;

if (D->hasAttr<IntelOclBiccAttr>())
return CC_IntelOclBicc;

Expand Down
1 change: 1 addition & 0 deletions clang/lib/CodeGen/CGDebugInfo.cpp
Expand Up @@ -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;
Expand Down
25 changes: 17 additions & 8 deletions clang/lib/Sema/SemaDeclAttr.cpp
Expand Up @@ -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,
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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()));
}

Expand Down Expand Up @@ -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:
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Sema/SemaType.cpp
Expand Up @@ -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: \
Expand Down Expand Up @@ -6653,6 +6654,8 @@ static Attr *getCCTypeAttr(ASTContext &Ctx, ParsedAttr &Attr) {
return createSimpleAttr<SwiftCallAttr>(Ctx, Attr);
case ParsedAttr::AT_VectorCall:
return createSimpleAttr<VectorCallAttr>(Ctx, Attr);
case ParsedAttr::AT_AArch64VectorPcs:
return createSimpleAttr<AArch64VectorPcsAttr>(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,
Expand Down
23 changes: 23 additions & 0 deletions 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);
}
19 changes: 19 additions & 0 deletions 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}}
}
2 changes: 2 additions & 0 deletions clang/test/Sema/callingconv.c
Expand Up @@ -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() {}
Expand Down
1 change: 1 addition & 0 deletions clang/tools/libclang/CXType.cpp
Expand Up @@ -651,6 +651,7 @@ CXCallingConv clang_getFunctionTypeCallingConv(CXType X) {
TCALLINGCONV(X86Pascal);
TCALLINGCONV(X86RegCall);
TCALLINGCONV(X86VectorCall);
TCALLINGCONV(AArch64VectorCall);
TCALLINGCONV(Win64);
TCALLINGCONV(X86_64SysV);
TCALLINGCONV(AAPCS);
Expand Down

0 comments on commit 44a2253

Please sign in to comment.