warn-unregistered.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. /* GCC-StarPU
  2. Copyright (C) 2012 Inria
  3. GCC-StarPU is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation, either version 3 of the License, or
  6. (at your option) any later version.
  7. GCC-StarPU is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with GCC-StarPU. If not, see <http://www.gnu.org/licenses/>. */
  13. /* Use extensions of the GNU C Library. */
  14. #define _GNU_SOURCE 1
  15. #include <starpu-gcc/config.h>
  16. /* We must include starpu.h here, otherwise gcc will complain about a poisoned
  17. malloc in xmmintrin.h. */
  18. #include <starpu.h>
  19. #include <gcc-plugin.h>
  20. #include <plugin-version.h>
  21. #include <plugin.h>
  22. #include <cpplib.h>
  23. #include <tree.h>
  24. #include <tree-pass.h>
  25. #include <gimple.h>
  26. #include <diagnostic.h>
  27. #include <cgraph.h>
  28. #include <starpu-gcc/utils.h>
  29. #include <starpu-gcc/tasks.h>
  30. /* Return true if there exists a `starpu_vector_data_register' call for VAR
  31. before GSI in its basic block. */
  32. static bool
  33. registration_in_bb_p (gimple_stmt_iterator gsi, tree var)
  34. {
  35. gcc_assert (SSA_VAR_P (var));
  36. tree register_fn_name;
  37. register_fn_name = get_identifier ("starpu_vector_data_register");
  38. local_define (bool, registration_function_p, (const_tree obj))
  39. {
  40. /* TODO: Compare against the real fndecl. */
  41. return (obj != NULL_TREE
  42. && TREE_CODE (obj) == FUNCTION_DECL
  43. && DECL_NAME (obj) == register_fn_name);
  44. };
  45. bool found;
  46. for (found = false;
  47. !gsi_end_p (gsi) && !found;
  48. gsi_prev (&gsi))
  49. {
  50. gimple stmt;
  51. stmt = gsi_stmt (gsi);
  52. if (is_gimple_call (stmt))
  53. {
  54. tree fn = gimple_call_fndecl (stmt);
  55. if (registration_function_p (fn))
  56. {
  57. tree arg = gimple_call_arg (stmt, 2);
  58. if (is_gimple_address (arg))
  59. arg = TREE_OPERAND (arg, 0);
  60. if (((TREE_CODE (arg) == VAR_DECL
  61. || TREE_CODE (arg) == VAR_DECL)
  62. && refs_may_alias_p (arg, var))
  63. /* Both VAR and ARG should be SSA names, otherwise, if ARG
  64. is a VAR_DECL, `ptr_derefs_may_alias_p' will
  65. conservatively assume that they may alias. */
  66. || (TREE_CODE (var) == SSA_NAME
  67. && TREE_CODE (arg) != VAR_DECL
  68. && ptr_derefs_may_alias_p (arg, var)))
  69. {
  70. if (verbose_output_p)
  71. {
  72. var = TREE_CODE (var) == SSA_NAME ? SSA_NAME_VAR (var) : var;
  73. inform (gimple_location (stmt),
  74. "found registration of variable %qE",
  75. DECL_NAME (var));
  76. }
  77. found = true;
  78. }
  79. }
  80. }
  81. }
  82. return found;
  83. }
  84. /* Return true if BB is dominated by a registration of VAR. */
  85. static bool
  86. dominated_by_registration (gimple_stmt_iterator gsi, tree var)
  87. {
  88. /* Is there a registration call for VAR in GSI's basic block? */
  89. if (registration_in_bb_p (gsi, var))
  90. return true;
  91. edge e;
  92. edge_iterator ei;
  93. bool found = false;
  94. /* If every incoming edge is dominated by a registration, then we're
  95. fine.
  96. FIXME: This triggers false positives when registration is done in a
  97. loop, because there's always an edge through which no registration
  98. happens--the edge corresponding to the case where the loop is not
  99. entered. */
  100. FOR_EACH_EDGE (e, ei, gsi_bb (gsi)->preds)
  101. {
  102. if (!dominated_by_registration (gsi_last_bb (e->src), var))
  103. return false;
  104. else
  105. found = true;
  106. }
  107. return found;
  108. }
  109. /* Return true if NAME aliases a global variable or a PARM_DECL. Note that,
  110. for the former, `ptr_deref_may_alias_global_p' is way too conservative,
  111. hence this approach. */
  112. static bool
  113. ssa_name_aliases_global_or_parm_p (const_tree name)
  114. {
  115. gcc_assert (TREE_CODE (name) == SSA_NAME);
  116. if (TREE_CODE (SSA_NAME_VAR (name)) == PARM_DECL)
  117. return true;
  118. else
  119. {
  120. gimple def_stmt;
  121. def_stmt = SSA_NAME_DEF_STMT (name);
  122. if (is_gimple_assign (def_stmt))
  123. {
  124. tree rhs = gimple_assign_rhs1 (def_stmt);
  125. if (TREE_CODE (rhs) == VAR_DECL
  126. && (DECL_EXTERNAL (rhs) || TREE_STATIC (rhs)))
  127. return true;
  128. }
  129. }
  130. return false;
  131. }
  132. /* Validate the arguments passed to tasks in FN's body. */
  133. static void
  134. validate_task_invocations (tree fn)
  135. {
  136. gcc_assert (TREE_CODE (fn) == FUNCTION_DECL);
  137. const struct cgraph_node *cgraph;
  138. const struct cgraph_edge *callee;
  139. cgraph = cgraph_get_node (fn);
  140. /* When a definition of IMPL is available, check its callees. */
  141. if (cgraph != NULL)
  142. for (callee = cgraph->callees;
  143. callee != NULL;
  144. callee = callee->next_callee)
  145. {
  146. if (task_p (callee->callee->decl))
  147. {
  148. unsigned i;
  149. gimple call_stmt = callee->call_stmt;
  150. for (i = 0; i < gimple_call_num_args (call_stmt); i++)
  151. {
  152. tree arg = gimple_call_arg (call_stmt, i);
  153. if (TREE_CODE (arg) == ADDR_EXPR
  154. && TREE_CODE (TREE_OPERAND (arg, 0)) == VAR_DECL
  155. && (TREE_CODE (TREE_TYPE (TREE_OPERAND (arg, 0)))
  156. == ARRAY_TYPE))
  157. /* This is a "pointer-to-array" of a variable, so what we
  158. really care about is the variable itself. */
  159. arg = TREE_OPERAND (arg, 0);
  160. if ((POINTER_TYPE_P (TREE_TYPE (arg))
  161. || (TREE_CODE (TREE_TYPE (arg)) == ARRAY_TYPE))
  162. && ((TREE_CODE (arg) == VAR_DECL
  163. && !TREE_STATIC (arg)
  164. && !DECL_EXTERNAL (arg)
  165. && !TREE_NO_WARNING (arg))
  166. || (TREE_CODE (arg) == SSA_NAME
  167. && !ssa_name_aliases_global_or_parm_p (arg))))
  168. {
  169. if (!dominated_by_registration (gsi_for_stmt (call_stmt),
  170. arg))
  171. {
  172. if (TREE_CODE (arg) == SSA_NAME)
  173. {
  174. tree var = SSA_NAME_VAR (arg);
  175. if (DECL_NAME (var) != NULL)
  176. arg = var;
  177. /* TODO: Check whether we can get the original
  178. variable name via ARG's DEF_STMT. */
  179. }
  180. if (TREE_CODE (arg) == VAR_DECL
  181. && DECL_NAME (arg) != NULL_TREE)
  182. warning_at (gimple_location (call_stmt), 0,
  183. "variable %qE may be used unregistered",
  184. DECL_NAME (arg));
  185. else
  186. warning_at (gimple_location (call_stmt), 0,
  187. "argument %i may be used unregistered",
  188. i);
  189. }
  190. }
  191. }
  192. }
  193. }
  194. }
  195. /* A pass to warn about possibly unregistered task arguments. */
  196. static unsigned int
  197. warn_starpu_unregistered (void)
  198. {
  199. tree fndecl;
  200. fndecl = current_function_decl;
  201. gcc_assert (TREE_CODE (fndecl) == FUNCTION_DECL);
  202. if (!task_p (fndecl))
  203. validate_task_invocations (fndecl);
  204. return 0;
  205. }
  206. struct opt_pass pass_warn_starpu_unregistered =
  207. {
  208. designated_field_init (type, GIMPLE_PASS),
  209. designated_field_init (name, "warn_starpu_unregistered"),
  210. designated_field_init (gate, NULL),
  211. designated_field_init (execute, warn_starpu_unregistered),
  212. /* The rest is zeroed. */
  213. };