Hello Everyone, This patch is for Cilk Plus branch affecting mainly the C compiler. It checks to see if the gotos and increment expressions inside cilk_for are valid and report errors otherwise.
Thanks, Balaji V. Iyer.
Index: gcc/c-family/c-cilk.c =================================================================== --- gcc/c-family/c-cilk.c (revision 194366) +++ gcc/c-family/c-cilk.c (working copy) @@ -1292,8 +1292,9 @@ them in code that spawns. */ if ((TREE_CODE (arg) == VAR_DECL) && DECL_HARD_REGISTER (arg)) { - error ("explicit register variable %qD may not be modified in spawn", - arg); + error_at (EXPR_LOCATION (arg), + "explicit register variable %qD may not be modified in " + "spawn", arg); arg = null_pointer_node; } else @@ -1464,7 +1465,8 @@ return copy_decl_no_change (decl, id); case LABEL_DECL: - error ("Invalid use of label %q+D in spawn", decl); + error_at (EXPR_LOCATION (decl), + "Invalid use of label %q+D in spawn", decl); return error_mark_node; case RESULT_DECL: @@ -1544,7 +1546,8 @@ if (! (flags & ECF_NOTHROW) && flag_exceptions) *throws = true; if (flags & ECF_RETURNS_TWICE) - error ("Can not spawn call to function that returns twice"); + error_at (EXPR_LOCATION (t), + "Can not spawn call to function that returns twice"); return 0; } @@ -1761,6 +1764,7 @@ tree cond = FOR_COND (loop); tree init = CILK_FOR_INIT (loop); tree incr = cilk_simplify_tree (FOR_EXPR (loop)); + tree orig_incr = cilk_simplify_tree (FOR_EXPR (loop)); /* Copy for LOC. */ tree grain = CILK_FOR_GRAIN (loop); tree body = FOR_BODY (loop); @@ -1937,9 +1941,12 @@ exactly_one = incr_direction == -1; } else - gcc_unreachable (); + { + error_at (EXPR_LOCATION (orig_incr), + "Invalid loop increment operation."); + cfd->invalid = true; + } break; - default: gcc_unreachable (); } @@ -2865,3 +2872,6 @@ } return decl; } + + + Index: gcc/c-family/ChangeLog.cilkplus =================================================================== --- gcc/c-family/ChangeLog.cilkplus (revision 194366) +++ gcc/c-family/ChangeLog.cilkplus (working copy) @@ -1,3 +1,11 @@ +2012-12-12 Balaji V. Iyer <balaji.v.i...@intel.com> + + * c-typeck.c (c_finish_cilk_loop) Added location for error reporting. + * c-cilk.c (wrapper_parm_cb): Likewise. + (copy_decl_for_cilk): Likewise. + (check_outlined_calls): Likewise. + (extract_for_fields): Reported an error instead of gcc_unreachable (). + 2012-12-10 Balaji V. Iyer <balaji.v.i...@intel.com> * c-cpp-elem-function.c: New file. Index: gcc/c/c-typeck.c =================================================================== --- gcc/c/c-typeck.c (revision 194366) +++ gcc/c/c-typeck.c (working copy) @@ -10982,19 +10982,19 @@ if (!cond) { - error ("cilk_for missing condition"); + error ("_Cilk_for missing condition"); return; } if (!incr) { - error ("cilk_for missing increment"); + error ("_Cilk_for missing increment"); return; } /* If the condition is zero don't generate a loop construct. */ if (TREE_CONSTANT (cond)) { - error ("cilk_for has constant condition"); + error_at (EXPR_LOCATION (cond), "_Cilk_for has constant condition"); return; } if (!cvar) @@ -11004,7 +11004,7 @@ } if (clab) { - error ("cilk_for has continue"); + error_at (EXPR_LOCATION (clab), "_Cilk_for has continue"); return; } Index: gcc/c/c-objc-common.h =================================================================== --- gcc/c/c-objc-common.h (revision 194366) +++ gcc/c/c-objc-common.h (working copy) @@ -120,4 +120,7 @@ #undef LANG_HOOKS_ELEM_FN_CREATE_FN #define LANG_HOOKS_ELEM_FN_CREATE_FN elem_fn_create_fn + +#undef LANG_HOOKS_CILK_CHECK_CTRL_FLOW +#define LANG_HOOKS_CILK_CHECK_CTRL_FLOW cilk_check_ctrl_flow #endif /* GCC_C_OBJC_COMMON */ Index: gcc/testsuite/gcc.dg/cilk-plus/cilk_keywords_test/errors/cilk_for_incr_errors.c =================================================================== --- gcc/testsuite/gcc.dg/cilk-plus/cilk_keywords_test/errors/cilk_for_incr_errors.c (revision 0) +++ gcc/testsuite/gcc.dg/cilk-plus/cilk_keywords_test/errors/cilk_for_incr_errors.c (revision 0) @@ -0,0 +1,22 @@ +#define ARRAY_SIZE 100000 + +int main(void) +{ + int ii = 0; + int array[ARRAY_SIZE]; + + _Cilk_for (ii = 0; ii < 10; ii <<= 2) /* { dg-error "Invalid loop increment operation." } */ + array[ii] = 5; + + _Cilk_for (ii = 0; ii < 10; ii *= 2) /* { dg-error "Invalid loop increment operation." } */ + array[ii] = 5; + + _Cilk_for (ii = 0; ii < 10; ii /= 2) /* { dg-error "Invalid loop increment operation." } */ + array[ii] = 5; + + _Cilk_for (ii = 0; ii < 10; ii = 5) /* { dg-error "Invalid loop increment operation." } */ + array[ii] = 5; + + _Cilk_for (ii = 0; ii < 10; ii >>= 2) /* { dg-error "Invalid loop increment operation." } */ + array[ii] = 5; +} Index: gcc/testsuite/gcc.dg/cilk-plus/cilk_keywords_test/errors/errors.exp =================================================================== --- gcc/testsuite/gcc.dg/cilk-plus/cilk_keywords_test/errors/errors.exp (revision 0) +++ gcc/testsuite/gcc.dg/cilk-plus/cilk_keywords_test/errors/errors.exp (revision 0) @@ -0,0 +1,59 @@ +# Copyright (C) 2012 Free Software Foundation, Inc. + +# This program 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. +# +# This program 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; see the file COPYING3. If not see +# <http://www.gnu.org/licenses/>. + +# Written by Balaji V. Iyer <balaji.v.i...@intel.com> + +if { ![istarget i?86*-*-*] && ![istarget x86_64-*-*] } then { + return +} + + +load_lib gcc-dg.exp + +dg-init +dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cS\]]] " -ldl -lcilkrts -I $srcdir/../../libcilkrts/include -std=c99 -fcilkplus -O0" " " +dg-finish + +dg-init +dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cS\]]] " -ldl -lcilkrts -I $srcdir/../../libcilkrts/include -std=c99 -fcilkplus -O1" " " +dg-finish + +dg-init +dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cS\]]] " -ldl -lcilkrts -I $srcdir/../../libcilkrts/include -std=c99 -fcilkplus -O2" " " +dg-finish + +dg-init +dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cS\]]] " -ldl -lcilkrts -I $srcdir/../../libcilkrts/include -std=c99 -fcilkplus -O3" " " +dg-finish + +dg-init +dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cS\]]] " -ldl -lcilkrts -I $srcdir/../../libcilkrts/include -std=c99 -fcilkplus -O0 -g" " " +dg-finish + +dg-init +dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cS\]]] " -ldl -lcilkrts -I $srcdir/../../libcilkrts/include -std=c99 -fcilkplus -O1 -g" " " +dg-finish + +dg-init +dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cS\]]] " -ldl -lcilkrts -I $srcdir/../../libcilkrts/include -std=c99 -fcilkplus -O2 -g" " " +dg-finish + +dg-init +dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cS\]]] " -ldl -lcilkrts -I $srcdir/../../libcilkrts/include -std=c99 -fcilkplus -O3 -g" " " +dg-finish + +dg-finish + Index: gcc/testsuite/gcc.dg/cilk-plus/cilk_keywords_test/errors/goto_inside_cilkfor.c =================================================================== --- gcc/testsuite/gcc.dg/cilk-plus/cilk_keywords_test/errors/goto_inside_cilkfor.c (revision 0) +++ gcc/testsuite/gcc.dg/cilk-plus/cilk_keywords_test/errors/goto_inside_cilkfor.c (revision 0) @@ -0,0 +1,49 @@ +/* Checks goto inside cilk_for and outside of cilk_for. */ + +#define ARRAY_SIZE 10000 +int a[ARRAY_SIZE], b[ARRAY_SIZE][ARRAY_SIZE]; +int main (int argc, char **argv) +{ + int i = 0, q = 0, j = 0; + _Cilk_for (i = 0; i < ARRAY_SIZE; i++) + { +l1: + a[i] = i; +l2: + if (i%2) + q+=2; + } + goto l1; /* { dg-error "Goto label is inside a _Cilk_for while the goto itself is outside." } */ + if(a[(ARRAY_SIZE / 2)] == (ARRAY_SIZE / 2)) + goto l2; /* { dg-error "Goto label is inside a _Cilk_for while the goto itself is outside." } */ + + _Cilk_for (i = 0; i < ARRAY_SIZE; i++) + { + /* Goto jumps into another Cilk_for. */ + goto l2; /* { dg-error "goto destination is outside the _Cilk_for scope." } */ + a[i] = i; +l3: + goto l3; /* This is OK! */ + } + if(a[(ARRAY_SIZE / 2)] == (ARRAY_SIZE / 2)) + goto l4; /* This is OK! */ + else + goto l3; /* { dg-error "Goto label is inside a _Cilk_for while the goto itself is outside." } */ + + _Cilk_for (i = 0; i < ARRAY_SIZE; i++) { +l5: + if (i % 5) { + _Cilk_for (j = 0; j < ARRAY_SIZE; j++) { + goto l5; /* { dg-error "goto destination is outside the _Cilk_for scope." } */ + b[i][j] = (i+j); +l6: + q++; + goto l6; /* This is OK! */ + } + goto l6; /* { dg-error "goto destination is outside the _Cilk_for scope." } */ + } + } + +l4: + return 0; +} Index: gcc/testsuite/ChangeLog.cilkplus =================================================================== --- gcc/testsuite/ChangeLog.cilkplus (revision 194366) +++ gcc/testsuite/ChangeLog.cilkplus (working copy) @@ -1,3 +1,11 @@ +2012-12-12 Balaji V. Iyer <balaji.v.i...@intel.com> + + * gcc.dg/cilk-plus/cilk_keywords_test/errors/goto_inside_cilkfor.c: + New test. + * gcc.dg/cilk-plus/cilk_keywords_test/errors/cilk_for_incr_errors.c: + Likewise. + * gcc.dg/cilk-plus/cilk_keywords_test/errors/errors.exp: New script. + 2012-12-10 Balaji V. Iyer <balaji.v.i...@intel.com> * gcc.dg/cilk-plus/elem_fn_tests/test1.c: Remove. Index: gcc/cilk.c =================================================================== --- gcc/cilk.c (revision 194366) +++ gcc/cilk.c (working copy) @@ -37,6 +37,16 @@ #include "output.h" #include "dwarf2out.h" + +/* The only reason why we have this struct is that we need a void * to pass + into the walk_tree function. */ + +struct label_list_struct +{ + vec <tree, va_gc> *labels; +}; + + tree cilk_trees[(int) CILK_TI_MAX]; static HOST_WIDE_INT worker_tail_offset; @@ -1406,3 +1416,150 @@ return true; return false; } + + +/* Helper function for walk_trees. *WALK_SUBTREES is seto to zero if it + encounters a CILK_FOR, LABEL_DECL or GOTO in *TP. If LABEL_DECL is found + then the value is pushed into the list pointed by DATA. */ + +static tree +store_labels (tree *tp, int *walk_subtrees, void *data) +{ + struct label_list_struct *label_list = (struct label_list_struct *)data; + + if (!tp || !*tp) + return NULL_TREE; + else if (TREE_CODE (*tp) == CILK_FOR_STMT + || TREE_CODE (*tp) == GOTO_EXPR) + *walk_subtrees = 0; + else if (TREE_CODE (*tp) == LABEL_DECL) + { + *walk_subtrees = 0; + vec_safe_push (label_list->labels, *tp); + } + else + *walk_subtrees = 1; + return NULL_TREE; +} + +/* Finds all the labels in STMT that is not inside a CILK_FOR. */ + +static struct label_list_struct +find_all_labels (tree stmt) +{ + struct label_list_struct label_list; + + label_list.labels = NULL; + walk_tree (&stmt, store_labels, (void *)&label_list, NULL); + return label_list; +} + +/* Helper function for walk_trees. If the *TP is GOTO_EXPR it will check if + its destination label is in the list in *DATA. *WALK_SUBTREES is always + set to one. */ + +static tree +check_goto_labels_inside_cilk_for_body (tree *tp, int *walk_subtrees, + void *data) +{ + size_t ii = 0; + tree ii_t = NULL_TREE; + bool label_ok = false; + struct label_list_struct *label_list = (struct label_list_struct *)data; + if (!tp || !*tp) + return NULL_TREE; + + if (TREE_CODE (*tp) == GOTO_EXPR) + { + tree goto_label = GOTO_DESTINATION (*tp); + for (ii = 0; vec_safe_iterate (label_list->labels, ii, &ii_t); ii++) + if (ii_t == goto_label) + label_ok = true; + + if (!label_ok) + { + error_at (EXPR_LOCATION (*tp), "goto destination is outside the " + "_Cilk_for scope."); + *tp = error_mark_node; + } + } + else if (TREE_CODE (*tp) == CILK_FOR_STMT) + *walk_subtrees = 0; + else + *walk_subtrees = 1; + return NULL_TREE; +} + +/* Helper function for walk_tree. If *TP is a CILK_FOR_STMT, then it will find + all the labels in it and then walks through the body to see if the gotos in + it are using the local labels. */ + +static tree +check_gotos_inside_cilk_for (tree *tp, int *walk_subtrees, + void *data ATTRIBUTE_UNUSED) +{ + struct label_list_struct label_list; + if (!tp || !*tp) + return NULL_TREE; + + if (TREE_CODE (*tp) == CILK_FOR_STMT) + { + label_list = find_all_labels (FOR_BODY (*tp)); + walk_tree (&FOR_BODY (*tp), check_goto_labels_inside_cilk_for_body, + (void *) &label_list, NULL); + } + *walk_subtrees = 1; + return NULL_TREE; +} + +/* Helper function for walk_tree. */ + +static tree +check_gotos_outside_cilk_for (tree *tp, int *walk_subtrees, + void *data) +{ + tree ii_t = NULL_TREE; + size_t ii = 0; + bool label_ok = false; + struct label_list_struct *label_list = (struct label_list_struct *) data; + if (!tp || !*tp) + return NULL_TREE; + + if (TREE_CODE (*tp) == GOTO_EXPR) + { + tree goto_label = GOTO_DESTINATION (*tp); + *walk_subtrees = 0; + for (ii = 0; vec_safe_iterate (label_list->labels, ii, &ii_t); ii++) + if (ii_t == goto_label) + label_ok = true; + + if (!label_ok) + { + error_at (EXPR_LOCATION (*tp), "Goto label is inside a _Cilk_for " + "while the goto itself is outside."); + *tp = error_mark_node; + } + } + else if (TREE_CODE (*tp) == CILK_FOR_STMT) + *walk_subtrees = 0; + else + *walk_subtrees = 1; + + return NULL_TREE; +} + +/* Checks some of the control flow changing statements (e.g. goto) in *FNBODY + are valid. */ + +void +cilk_check_ctrl_flow (tree *fnbody) +{ + struct label_list_struct label_list; + if (!fnbody) + return; + walk_tree (fnbody, check_gotos_inside_cilk_for, NULL, NULL); + + label_list = find_all_labels (*fnbody); + walk_tree (fnbody, check_gotos_outside_cilk_for, (void *) &label_list, NULL); + return; +} Index: gcc/cilk.h =================================================================== --- gcc/cilk.h (revision 194366) +++ gcc/cilk.h (working copy) @@ -296,6 +296,7 @@ void gimplify_cilk_spawn (tree *, gimple_seq *, gimple_seq *); void gimplify_cilk_sync (tree *, gimple_seq *); void gimplify_cilk_for (tree *, gimple_seq *, gimple_seq *); +void cilk_check_ctrl_flow (tree *); extern tree cilk_call_setjmp (tree); extern tree make_cilk_frame (tree); extern tree build_cilk_function_exit (tree, bool, bool); Index: gcc/ChangeLog.cilkplus =================================================================== --- gcc/ChangeLog.cilkplus (revision 194366) +++ gcc/ChangeLog.cilkplus (working copy) @@ -1,3 +1,18 @@ +2012-12-12 Balaji V. Iyer <balaji.v.i...@intel.com> + + * c/c-objc-common.h (LANG_HOOKS_CILK_CHECK_CTRL_FLOW): New define. + * cilk.c (store_labels): New function. + (find_all_labels): Likewise. + (check_goto_labels_inside_cilk_for_body): Likewise. + (check_gotos_inside_cilk_for): Likewise. + (check_gotos_outside_cilk_for): Likewise. + (check_cilk_ctrl_flow): Likewise. + * langhooks.c (lhd_cilk_check_ctrl_flow): Likewise. + * langhooks.h (struct lang_hooks_for_cilkplus): New function pointer. + * gimplify.c (gimplify_function_tree): Called cilk_check_ctrl_flow + function that is part of lang_hooks. + * langhooks-def.h (LANG_HOOKS_CILK): New field added. + 2012-12-10 Balaji V. Iyer <balaji.v.i...@intel.com> * doc/tm.texi (TARGET_CILKPLUS_BUILTIN_MAP_PROCESSOR_TO_ATTR): Added Index: gcc/langhooks.c =================================================================== --- gcc/langhooks.c (revision 194366) +++ gcc/langhooks.c (working copy) @@ -730,3 +730,8 @@ { return; } + +void lhd_cilk_check_ctrl_flow (tree *x ATTRIBUTE_UNUSED) +{ + return; +} Index: gcc/langhooks.h =================================================================== --- gcc/langhooks.h (revision 194366) +++ gcc/langhooks.h (working copy) @@ -235,6 +235,7 @@ void (*gimplify_cilk_spawn) (tree *, gimple_seq *, gimple_seq *); void (*gimplify_cilk_for) (tree *, gimple_seq *, gimple_seq *); void (*gimplify_cilk_sync) (tree *, gimple_seq *); + void (*cilk_check_ctrl_flow) (tree *); void (*elem_fn_create_fn) (tree); }; Index: gcc/gimplify.c =================================================================== --- gcc/gimplify.c (revision 194366) +++ gcc/gimplify.c (working copy) @@ -8415,6 +8415,8 @@ gcc_assert (!gimple_body (fndecl)); + if (flag_enable_cilk) + lang_hooks.cilkplus.cilk_check_ctrl_flow (&DECL_SAVED_TREE (fndecl)); /* Here we check to see if we have a function with the attribute "vector." If so, then we must clone it to masked/unmasked when apropriate. */ Index: gcc/langhooks-def.h =================================================================== --- gcc/langhooks-def.h (revision 194366) +++ gcc/langhooks-def.h (working copy) @@ -217,6 +217,7 @@ void lhd_gimplify_cilk_for (tree *, gimple_seq *, gimple_seq *); void lhd_gimplify_cilk_sync (tree *, gimple_seq *); void lhd_elem_fn_create_fn (tree); +void lhd_cilk_check_ctrl_flow (tree *); #define LANG_HOOKS_CILK_RECOGNIZE_SPAWN hook_bool_tree_false #define LANG_HOOKS_CILK_VALID_CTOR hook_bool_tree_false #define LANG_HOOKS_CILK_VALID_SPAWN lhd_cilk_valid_spawn @@ -224,6 +225,7 @@ #define LANG_HOOKS_GIMPLIFY_CILK_FOR lhd_gimplify_cilk_for #define LANG_HOOKS_GIMPLIFY_CILK_SYNC lhd_gimplify_cilk_sync #define LANG_HOOKS_ELEM_FN_CREATE_FN lhd_elem_fn_create_fn +#define LANG_HOOKS_CILK_CHECK_CTRL_FLOW lhd_cilk_check_ctrl_flow #define LANG_HOOKS_CILK { \ LANG_HOOKS_CILK_RECOGNIZE_SPAWN, \ LANG_HOOKS_CILK_VALID_CTOR, \ @@ -231,6 +233,7 @@ LANG_HOOKS_GIMPLIFY_CILK_SPAWN, \ LANG_HOOKS_GIMPLIFY_CILK_FOR, \ LANG_HOOKS_GIMPLIFY_CILK_SYNC, \ + LANG_HOOKS_CILK_CHECK_CTRL_FLOW, \ LANG_HOOKS_ELEM_FN_CREATE_FN \ }