瀏覽代碼

gcc: Raise an error when a task implementation invokes a task.

* gcc-plugin/src/starpu.c (validate_task_implementation): New function.
  (lower_starpu): Use it.

* gcc-plugin/tests/task-errors.c (my_external_task,
  my_task_that_invokes_task, my_task_that_invokes_task_cpu): New
  function declarations.
Ludovic Courtès 13 年之前
父節點
當前提交
4b20e7f846
共有 2 個文件被更改,包括 48 次插入0 次删除
  1. 33 0
      gcc-plugin/src/starpu.c
  2. 15 0
      gcc-plugin/tests/task-errors.c

+ 33 - 0
gcc-plugin/src/starpu.c

@@ -1618,6 +1618,34 @@ build_task_body (const_tree task_decl)
 				  insert_task_fn, args);
 }
 
+/* Raise an error when IMPL doesn't satisfy the constraints of a task
+   implementations, such as not invoking another task.  */
+
+static void
+validate_task_implementation (tree impl)
+{
+  gcc_assert (task_implementation_p (impl));
+
+  const struct cgraph_node *cgraph;
+  const struct cgraph_edge *callee;
+
+  cgraph = cgraph_get_node (impl);
+  for (callee = cgraph->callees;
+       callee != NULL;
+       callee = callee->next_callee)
+    {
+      if (task_p (callee->callee->decl))
+	{
+	  location_t loc;
+
+	  loc = gimple_location (callee->call_stmt);
+	  error_at (loc, "task %qE cannot be invoked from task implementation %qE",
+		    DECL_NAME (callee->callee->decl),
+		    DECL_NAME (impl));
+	}
+    }
+}
+
 static unsigned int
 lower_starpu (void)
 {
@@ -1630,6 +1658,11 @@ lower_starpu (void)
 
   if (task_p (fndecl))
     {
+      /* Make sure the task implementations are valid.  */
+
+      for_each (validate_task_implementation,
+		task_implementation_list (fndecl));
+
       /* Generate a `struct starpu_codelet' structure and a wrapper function for
 	 each implementation of TASK_DECL.  This cannot be done earlier
 	 because we need to have a complete list of task implementations.  */

+ 15 - 0
gcc-plugin/tests/task-errors.c

@@ -16,6 +16,8 @@
 
 /* Test error handling for the `task' and `task_implementation' attributes.  */
 
+extern void my_external_task (int foo, char *bar) __attribute__ ((task));
+
 static void my_task (int foo, char *bar) __attribute__ ((task));
 static void my_task_cpu (int foo, float *bar)    /* (error "type differs") */
   __attribute__ ((task_implementation ("cpu", my_task)));
@@ -52,6 +54,12 @@ static void my_task_with_a_body (int foo, char *bar)
 extern int my_task_not_void (int foo) /* (error "return type") */
   __attribute__ ((task));
 
+void my_task_that_invokes_task (int x, char *y)
+  __attribute__ ((task));
+
+void my_task_that_invokes_task_cpu (int x, char *y)
+  __attribute__ ((task_implementation ("cpu", my_task_that_invokes_task)));
+
 
 static void
 my_task_cpu (int foo, float *bar)
@@ -92,3 +100,10 @@ static void
 my_task_with_a_body (int foo, char *bar)  /* (error "must not have a body") */
 {
 }
+
+void
+my_task_that_invokes_task_cpu (int x, char *y)
+{
+  my_external_task (x, y); /* (error "cannot be invoked from task implementation") */
+}
+