From: Sameer Sahasrabuddhe Date: Tue, 20 Jan 2015 06:44:32 +0000 (+0000) Subject: Introduce SPIR calling conventions. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3a9971b5b8b35e17514c22a3dbbfd78f96d4d96a;p=clang Introduce SPIR calling conventions. This implements Section 3.7 from the SPIR 1.2 spec: SPIR kernels should use "spir_kernel" calling convention. Non-kernel functions use "spir_func" calling convention. All other calling conventions are disallowed. The patch works only for OpenCL source. Any other uses will need to ensure that kernels are assigned the spir_kernel calling convention correctly. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@226548 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/Specifiers.h b/include/clang/Basic/Specifiers.h index a968d00d20..180785b352 100644 --- a/include/clang/Basic/Specifiers.h +++ b/include/clang/Basic/Specifiers.h @@ -210,7 +210,9 @@ namespace clang { CC_AAPCS, // __attribute__((pcs("aapcs"))) CC_AAPCS_VFP, // __attribute__((pcs("aapcs-vfp"))) CC_PnaclCall, // __attribute__((pnaclcall)) - CC_IntelOclBicc // __attribute__((intel_ocl_bicc)) + CC_IntelOclBicc, // __attribute__((intel_ocl_bicc)) + CC_SpirFunction, // default for OpenCL functions on SPIR target + CC_SpirKernel // inferred for OpenCL kernels on SPIR target }; /// \brief Checks whether the given calling convention supports variadic @@ -222,6 +224,8 @@ namespace clang { case CC_X86ThisCall: case CC_X86Pascal: case CC_X86VectorCall: + case CC_SpirFunction: + case CC_SpirKernel: return false; default: return true; diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 7f17fe8b8c..c1bbc5f085 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -8043,7 +8043,9 @@ CallingConv ASTContext::getDefaultCallingConvention(bool IsVariadic, if (IsCXXMethod) return ABI->getDefaultMethodCallConv(IsVariadic); - return (LangOpts.MRTD && !IsVariadic) ? CC_X86StdCall : CC_C; + if (LangOpts.MRTD && !IsVariadic) return CC_X86StdCall; + + return Target->getDefaultCallingConv(TargetInfo::CCMT_Unknown); } bool ASTContext::isNearlyEmpty(const CXXRecordDecl *RD) const { diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index e4f364d04f..5a39ca0c6b 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -1588,6 +1588,8 @@ StringRef FunctionType::getNameForCallConv(CallingConv CC) { case CC_AAPCS_VFP: return "aapcs-vfp"; case CC_PnaclCall: return "pnaclcall"; case CC_IntelOclBicc: return "intel_ocl_bicc"; + case CC_SpirFunction: return "spir_function"; + case CC_SpirKernel: return "spir_kernel"; } llvm_unreachable("Invalid calling convention."); diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp index e36fc175c4..b874dd0b4c 100644 --- a/lib/AST/TypePrinter.cpp +++ b/lib/AST/TypePrinter.cpp @@ -697,6 +697,10 @@ void TypePrinter::printFunctionProtoAfter(const FunctionProtoType *T, case CC_X86_64SysV: OS << " __attribute__((sysv_abi))"; break; + case CC_SpirFunction: + case CC_SpirKernel: + // Do nothing. These CCs are not available as attributes. + break; } } diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp index 9aac3b7864..476217146e 100644 --- a/lib/Basic/Targets.cpp +++ b/lib/Basic/Targets.cpp @@ -6346,6 +6346,15 @@ namespace { BuiltinVaListKind getBuiltinVaListKind() const override { return TargetInfo::VoidPtrBuiltinVaList; } + + CallingConvCheckResult checkCallingConvention(CallingConv CC) const override { + return (CC == CC_SpirFunction || + CC == CC_SpirKernel) ? CCCR_OK : CCCR_Warning; + } + + CallingConv getDefaultCallingConv(CallingConvMethodType MT) const override { + return CC_SpirFunction; + } }; diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp index f9b26b6210..cb035d39c5 100644 --- a/lib/CodeGen/CGCall.cpp +++ b/lib/CodeGen/CGCall.cpp @@ -51,6 +51,8 @@ static unsigned 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_SpirFunction: return llvm::CallingConv::SPIR_FUNC; + case CC_SpirKernel: return llvm::CallingConv::SPIR_KERNEL; } } diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 7116973cf8..5624f709c9 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -2476,8 +2476,24 @@ getCCForDeclaratorChunk(Sema &S, Declarator &D, } } - return S.Context.getDefaultCallingConvention(FTI.isVariadic, - IsCXXInstanceMethod); + CallingConv CC = S.Context.getDefaultCallingConvention(FTI.isVariadic, + IsCXXInstanceMethod); + + // Attribute AT_OpenCLKernel affects the calling convention only on + // the SPIR target, hence it cannot be treated as a calling + // convention attribute. This is the simplest place to infer + // "spir_kernel" for OpenCL kernels on SPIR. + if (CC == CC_SpirFunction) { + for (const AttributeList *Attr = D.getDeclSpec().getAttributes().getList(); + Attr; Attr = Attr->getNext()) { + if (Attr->getKind() == AttributeList::AT_OpenCLKernel) { + CC = CC_SpirKernel; + break; + } + } + } + + return CC; } static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, diff --git a/test/CodeGenOpenCL/spir-calling-conv.cl b/test/CodeGenOpenCL/spir-calling-conv.cl new file mode 100644 index 0000000000..4d96d83552 --- /dev/null +++ b/test/CodeGenOpenCL/spir-calling-conv.cl @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 %s -triple "spir-unknown-unknown" -emit-llvm -o - | FileCheck %s + +int get_dummy_id(int D); + +kernel void bar(global int *A); + +kernel void foo(global int *A) +// CHECK: define spir_kernel void @foo(i32 addrspace(1)* %A) +{ + int id = get_dummy_id(0); + // CHECK: %call = tail call spir_func i32 @get_dummy_id(i32 0) + A[id] = id; + bar(A); + // CHECK: tail call spir_kernel void @bar(i32 addrspace(1)* %A) +} + +// CHECK: declare spir_func i32 @get_dummy_id(i32) +// CHECK: declare spir_kernel void @bar(i32 addrspace(1)*) diff --git a/tools/libclang/CXType.cpp b/tools/libclang/CXType.cpp index 81cff5abb4..04778ddfbb 100644 --- a/tools/libclang/CXType.cpp +++ b/tools/libclang/CXType.cpp @@ -527,6 +527,9 @@ CXCallingConv clang_getFunctionTypeCallingConv(CXType X) { TCALLINGCONV(AAPCS_VFP); TCALLINGCONV(PnaclCall); TCALLINGCONV(IntelOclBicc); + case CC_SpirFunction: return CXCallingConv_Unexposed; + case CC_SpirKernel: return CXCallingConv_Unexposed; + break; } #undef TCALLINGCONV }