[PATCH][OPENCL][SPIR] introduce SPIR calling conventions

Sameer Sahasrabuddhe sameer.sahasrabuddhe at amd.com
Wed Jan 14 19:28:16 PST 2015


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.

Note that the patch modifies how ASTContext determines the default 
calling convention. This *may* need a closer look, but it does pass lit 
tests on all targets.

Sameer.
-------------- next part --------------
commit 07b973291f687a53af9eb84ab416eb10df14a84b
Author: Sameer Sahasrabuddhe <sameer.sahasrabuddhe at amd.com>
Date:   Thu Jan 15 08:08:47 2015 +0530

    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.

diff --git a/include/clang/Basic/Specifiers.h b/include/clang/Basic/Specifiers.h
index a968d00..180785b 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 6b864d0..66eafda 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -8041,7 +8041,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 e4f364d..5a39ca0 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 e36fc17..b874dd0 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 4c64a02..ee57d88 100644
--- a/lib/Basic/Targets.cpp
+++ b/lib/Basic/Targets.cpp
@@ -6335,6 +6335,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 6403fa9..4e20c6a 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 0f96a1c..9d7e1a0 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 0000000..4d96d83
--- /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 81cff5a..04778dd 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
   }


More information about the cfe-commits mailing list