]> granicus.if.org Git - clang/commitdiff
Parse: add support for parsing CUDA kernel calls
authorPeter Collingbourne <peter@pcc.me.uk>
Wed, 9 Feb 2011 21:12:02 +0000 (21:12 +0000)
committerPeter Collingbourne <peter@pcc.me.uk>
Wed, 9 Feb 2011 21:12:02 +0000 (21:12 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@125219 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticParseKinds.td
lib/Parse/ParseExpr.cpp
lib/Parse/Parser.cpp
test/PCH/cuda-kernel-call.cu [new file with mode: 0644]
test/Parser/cuda-kernel-call.cu [new file with mode: 0644]
test/SemaCUDA/cuda.h
test/SemaCUDA/kernel-call.cu [new file with mode: 0644]

index 4142fcca65aa401939c7904f53193ca20acfa928..0b14ed70241228c40e92629903a9a35d0fd0f513 100644 (file)
@@ -95,6 +95,7 @@ def err_expected_lsquare : Error<"expected '['">;
 def err_expected_rsquare : Error<"expected ']'">;
 def err_expected_rbrace : Error<"expected '}'">;
 def err_expected_greater : Error<"expected '>'">;
+def err_expected_ggg : Error<"expected '>>>'">;
 def err_expected_semi_declaration : Error<
   "expected ';' at end of declaration">;
 def err_expected_semi_decl_list : Error<
index 5928871987f8ebdd1504e5252d8208049198052a..55d2ba222f59660de67212baf5a1a7d8a792b317 100644 (file)
@@ -1093,24 +1093,68 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
       break;
     }
 
-    case tok::l_paren: {   // p-e: p-e '(' argument-expression-list[opt] ')'
+    case tok::l_paren:         // p-e: p-e '(' argument-expression-list[opt] ')'
+    case tok::lesslessless: {  // p-e: p-e '<<<' argument-expression-list '>>>'
+                               //   '(' argument-expression-list[opt] ')'
+      tok::TokenKind OpKind = Tok.getKind();
       InMessageExpressionRAIIObject InMessage(*this, false);
       
+      Expr *ExecConfig = 0;
+
+      if (OpKind == tok::lesslessless) {
+        ExprVector ExecConfigExprs(Actions);
+        CommaLocsTy ExecConfigCommaLocs;
+        SourceLocation LLLLoc, GGGLoc;
+
+        LLLLoc = ConsumeToken();
+
+        if (ParseExpressionList(ExecConfigExprs, ExecConfigCommaLocs)) {
+          LHS = ExprError();
+        }
+
+        if (LHS.isInvalid()) {
+          SkipUntil(tok::greatergreatergreater);
+        } else if (Tok.isNot(tok::greatergreatergreater)) {
+          MatchRHSPunctuation(tok::greatergreatergreater, LLLLoc);
+          LHS = ExprError();
+        } else {
+          GGGLoc = ConsumeToken();
+        }
+
+        if (!LHS.isInvalid()) {
+          if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen, ""))
+            LHS = ExprError();
+          else
+            Loc = PrevTokLocation;
+        }
+
+        if (!LHS.isInvalid()) {
+          ExprResult ECResult = Actions.ActOnCUDAExecConfigExpr(getCurScope(),
+                                     LLLLoc, move_arg(ExecConfigExprs), GGGLoc);
+          if (ECResult.isInvalid())
+            LHS = ExprError();
+          else
+            ExecConfig = ECResult.get();
+        }
+      } else {
+        Loc = ConsumeParen();
+      }
+
       ExprVector ArgExprs(Actions);
       CommaLocsTy CommaLocs;
-
-      Loc = ConsumeParen();
       
       if (Tok.is(tok::code_completion)) {
         Actions.CodeCompleteCall(getCurScope(), LHS.get(), 0, 0);
         ConsumeCodeCompletionToken();
       }
-      
-      if (Tok.isNot(tok::r_paren)) {
-        if (ParseExpressionList(ArgExprs, CommaLocs, &Sema::CodeCompleteCall,
-                                LHS.get())) {
-          SkipUntil(tok::r_paren);
-          LHS = ExprError();
+
+      if (OpKind == tok::l_paren || !LHS.isInvalid()) {
+        if (Tok.isNot(tok::r_paren)) {
+          if (ParseExpressionList(ArgExprs, CommaLocs, &Sema::CodeCompleteCall,
+                                  LHS.get())) {
+            SkipUntil(tok::r_paren);
+            LHS = ExprError();
+          }
         }
       }
 
@@ -1125,7 +1169,8 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
                 ArgExprs.size()-1 == CommaLocs.size())&&
                "Unexpected number of commas!");
         LHS = Actions.ActOnCallExpr(getCurScope(), LHS.take(), Loc,
-                                    move_arg(ArgExprs), Tok.getLocation());
+                                    move_arg(ArgExprs), Tok.getLocation(),
+                                    ExecConfig);
         ConsumeParen();
       }
 
index 820f703068c49d8b40f619bf2dd0445e2255f100..bb0966111ebb68ef1b39c0ab087343b5e715e5ab 100644 (file)
@@ -126,6 +126,8 @@ SourceLocation Parser::MatchRHSPunctuation(tok::TokenKind RHSTok,
   case tok::r_brace : LHSName = "{"; DID = diag::err_expected_rbrace; break;
   case tok::r_square: LHSName = "["; DID = diag::err_expected_rsquare; break;
   case tok::greater:  LHSName = "<"; DID = diag::err_expected_greater; break;
+  case tok::greatergreatergreater:
+                      LHSName = "<<<"; DID = diag::err_expected_ggg; break;
   }
   Diag(Tok, DID);
   Diag(LHSLoc, diag::note_matching) << LHSName;
diff --git a/test/PCH/cuda-kernel-call.cu b/test/PCH/cuda-kernel-call.cu
new file mode 100644 (file)
index 0000000..ef12c59
--- /dev/null
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -emit-pch -o %t %s
+// RUN: %clang_cc1 -include-pch %t -fsyntax-only %s 
+
+#ifndef HEADER
+#define HEADER
+// Header.
+
+#include "../SemaCUDA/cuda.h"
+
+void kcall(void (*kp)()) {
+  kp<<<1, 1>>>();
+}
+
+__global__ void kern() {
+}
+
+#else
+// Using the header.
+
+void test() {
+  kcall(kern);
+  kern<<<1, 1>>>();
+}
+
+#endif
diff --git a/test/Parser/cuda-kernel-call.cu b/test/Parser/cuda-kernel-call.cu
new file mode 100644 (file)
index 0000000..f95ae9e
--- /dev/null
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+void foo(void) {
+  foo<<<1;      // expected-error {{expected '>>>'}} expected-note {{to match this '<<<'}}
+
+  foo<<<1,1>>>; // expected-error {{expected '('}}
+
+  foo<<<>>>();  // expected-error {{expected expression}}
+}
index c5037478200782b70281347bc5dfacb4eb344fd6..e3aeb99ed2205beb4c1c4e39177d13f4c5441253 100644 (file)
@@ -1,7 +1,19 @@
 /* Minimal declarations for CUDA support.  Testing purposes only. */
 
+#include <stddef.h>
+
 #define __constant__ __attribute__((constant))
 #define __device__ __attribute__((device))
 #define __global__ __attribute__((global))
 #define __host__ __attribute__((host))
 #define __shared__ __attribute__((shared))
+
+struct dim3 {
+  unsigned x, y, z;
+  dim3(unsigned x, unsigned y = 1, unsigned z = 1) : x(x), y(y), z(z) {}
+};
+
+typedef struct cudaStream *cudaStream_t;
+
+int cudaConfigureCall(dim3 gridSize, dim3 blockSize, size_t sharedSize = 0,
+                      cudaStream_t stream = 0);
diff --git a/test/SemaCUDA/kernel-call.cu b/test/SemaCUDA/kernel-call.cu
new file mode 100644 (file)
index 0000000..6d51695
--- /dev/null
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+#include "cuda.h"
+
+__global__ void g1(int x) {}
+
+template <typename T> void t1(T arg) {
+  g1<<<arg, arg>>>(1);
+}
+
+int main(void) {
+  g1<<<1, 1>>>(42);
+
+  t1(1);
+}