Quellcode durchsuchen

gcc: Add the `heap_allocated' attribute.

* gcc-plugin/src/starpu.c (heap_allocated_attribute_name): New variable.
  (handle_heap_allocated_attribute): New function.
  (register_task_attributes): Register it.

* gcc-plugin/tests/Makefile.am (gcc_tests): Add	`heap-allocated.c' and
  `heap-allocated-errors.c'.

* gcc-plugin/tests/heap-allocated-errors.c,
  gcc-plugin/tests/heap-allocated.c: New files.

* gcc-plugin/tests/mocks.h (malloc_calls, free_calls,
  expected_malloc_argument, expected_free_argument): New variables.
  (starpu_malloc, _starpu_free_unref): New functions.

* include/starpu_data.h [STARPU_GCC_PLUGIN](_starpu_free_unref): New
  declaration.

* src/util/malloc.c (_starpu_free_unref): New function.
Ludovic Courtès vor 13 Jahren
Ursprung
Commit
3a97eae379

+ 1 - 0
.gitignore

@@ -186,3 +186,4 @@ starpu.log
 /gcc-plugin/tests/lib-user
 /gcc-plugin/examples/matrix-mult
 /gcc-plugin/src/c-expr.c
+/gcc-plugin/tests/heap-allocated

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

@@ -67,6 +67,7 @@ static const char plugin_name[] = "starpu";
 /* Names of public attributes.  */
 static const char task_attribute_name[] = "task";
 static const char task_implementation_attribute_name[] = "task_implementation";
+static const char heap_allocated_attribute_name[] = "heap_allocated";
 
 /* Names of attributes used internally.  */
 static const char task_codelet_attribute_name[] = ".codelet";
@@ -798,6 +799,67 @@ handle_task_implementation_attribute (tree *node, tree name, tree args,
   return NULL_TREE;
 }
 
+/* Handle the `heap_allocated' attribute on variable *NODE.  */
+
+static tree
+handle_heap_allocated_attribute (tree *node, tree name, tree args,
+				 int flags, bool *no_add_attrs)
+{
+  location_t loc;
+  tree var = *node;
+
+  loc = DECL_SOURCE_LOCATION (var);
+
+  if (DECL_EXTERNAL (var))
+    error_at (loc, "attribute %<heap_allocated%> cannot be used "
+	      "on external declarations");
+  else if (TREE_PUBLIC (var) || TREE_STATIC (var))
+    {
+      error_at (loc, "attribute %<heap_allocated%> cannot be used "
+		"on global variables");
+      TREE_TYPE (var) = error_mark_node;
+    }
+  else if (TREE_CODE (TREE_TYPE (var)) != ARRAY_TYPE)
+    {
+      error_at (loc, "variable %qE must have an array type",
+		DECL_NAME (var));
+      TREE_TYPE (var) = error_mark_node;
+    }
+  else if (TYPE_SIZE (TREE_TYPE (var)) == NULL_TREE)
+    {
+      error_at (loc, "variable %qE has an incomplete array type",
+		DECL_NAME (var));
+      TREE_TYPE (var) = error_mark_node;
+    }
+  else
+    {
+      tree array_type = TREE_TYPE (var);
+      tree pointer_type = build_pointer_type (array_type);
+
+      TREE_TYPE (var) = pointer_type;
+      DECL_SIZE (var) = TYPE_SIZE (pointer_type);
+      DECL_SIZE_UNIT (var) = TYPE_SIZE_UNIT (pointer_type);
+      DECL_MODE (var) = TYPE_MODE (pointer_type);
+
+      tree malloc_fn = lookup_name (get_identifier ("starpu_malloc"));
+      gcc_assert (malloc_fn != NULL_TREE);
+
+      add_stmt (build_call_expr (malloc_fn, 2,
+				 build_addr (var, current_function_decl),
+				 TYPE_SIZE_UNIT (array_type)));
+
+      /* Add a destructor for VAR.
+	 TODO: Provide a way to disable this.  */
+      DECL_ATTRIBUTES (var) =
+	tree_cons (get_identifier ("cleanup"),
+		   lookup_name (get_identifier ("_starpu_free_unref")),
+		   DECL_ATTRIBUTES (var));
+    }
+
+  return NULL_TREE;
+}
+
+
 /* Return the declaration of the `starpu_codelet' variable associated with
    TASK_DECL.  */
 
@@ -952,8 +1014,15 @@ register_task_attributes (void *gcc_data, void *user_data)
       handle_task_implementation_attribute
     };
 
+  static const struct attribute_spec heap_allocated_attr =
+    {
+      heap_allocated_attribute_name, 0, 0, true, false, false,
+      handle_heap_allocated_attribute
+    };
+
   register_attribute (&task_attr);
   register_attribute (&task_implementation_attr);
+  register_attribute (&heap_allocated_attr);
 }
 
 

+ 2 - 0
gcc-plugin/tests/Makefile.am

@@ -29,6 +29,8 @@ gcc_tests =					\
   no-initialize.c				\
   lib-user.c					\
   wait-errors.c					\
+  heap-allocated.c				\
+  heap-allocated-errors.c			\
   shutdown-errors.c
 
 dist_noinst_HEADERS = mocks.h

+ 36 - 0
gcc-plugin/tests/heap-allocated-errors.c

@@ -0,0 +1,36 @@
+/* GCC-StarPU
+   Copyright (C) 2011 Institut National de Recherche en Informatique et Automatique
+
+   GCC-StarPU is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   GCC-StarPU is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC-StarPU.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* (instructions compile (cflags "-Wno-unused-variable")) */
+
+static int global[123]              /* (error "cannot be used") */
+  __attribute__ ((heap_allocated, used));
+
+extern int external[123]            /* (error "cannot be used") */
+  __attribute__ ((heap_allocated));
+
+void
+foo (size_t size)
+{
+  float scalar /* (error "must have an array type") */
+    __attribute__ ((heap_allocated));
+  float *ptr   /* (error "must have an array type") */
+    __attribute__ ((heap_allocated));
+  float incomp[]  /* (error "incomplete array type") */
+    __attribute__ ((heap_allocated));
+  float incomp2[size][3][]  /* (error "incomplete element type") */
+    __attribute__ ((heap_allocated));
+}

+ 44 - 0
gcc-plugin/tests/heap-allocated.c

@@ -0,0 +1,44 @@
+/* GCC-StarPU
+   Copyright (C) 2011 Institut National de Recherche en Informatique et Automatique
+
+   GCC-StarPU is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   GCC-StarPU is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC-StarPU.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#undef NDEBUG
+
+#include <mocks.h>
+
+static void
+foo (size_t size)
+{
+  expected_malloc_argument = size * 23 * sizeof (float);
+
+  float m[size][23] __attribute__ ((heap_allocated));
+
+  assert (malloc_calls == 1);
+
+  /* Freed when going out of scope.  */
+  expected_free_argument = m;
+}
+
+int
+main (int argc, char *argv[])
+{
+#pragma starpu initialize
+
+  foo (42 + argc);
+
+  assert (free_calls == 1);
+
+  return EXIT_SUCCESS;
+}

+ 27 - 0
gcc-plugin/tests/mocks.h

@@ -271,6 +271,33 @@ starpu_data_unregister (starpu_data_handle handle)
 }
 
 
+/* Heap allocation.  */
+
+/* Number of `starpu_malloc' and `starpu_free' calls.  */
+static unsigned int malloc_calls, free_calls;
+
+static size_t expected_malloc_argument;
+static void *expected_free_argument;
+
+int
+starpu_malloc (void **ptr, size_t size)
+{
+  assert (size == expected_malloc_argument);
+
+  *ptr = malloc (size);
+  malloc_calls++;
+
+  return 0;
+}
+
+void
+_starpu_free_unref (void *ptr)
+{
+  assert (* (void **) ptr == expected_free_argument);
+  free_calls++;
+}
+
+
 /* Initialization.  */
 
 static int initialized;

+ 4 - 0
include/starpu_data.h

@@ -75,6 +75,10 @@ void starpu_data_release(starpu_data_handle handle);
 int starpu_malloc(void **A, size_t dim);
 int starpu_free(void *A);
 
+#ifdef STARPU_GCC_PLUGIN
+void _starpu_free_unref(void *p);
+#endif
+
 /* XXX These macros are provided to avoid breaking old codes. But consider
  * these function names as deprecated. */
 #define starpu_data_malloc_pinned_if_possible	starpu_malloc

+ 7 - 0
src/util/malloc.c

@@ -215,3 +215,10 @@ int starpu_free(void *A)
 
 	return 0;
 }
+
+/* Internal convenience function, used by code generated by the GCC
+ * plug-in.  */
+void _starpu_free_unref(void *p)
+{
+	(void)starpu_free(* (void **)p);
+}