Implement TARGET_IRA_CHANGE_PSEUDO_ALLOCNO_CLASS hook.
[official-gcc.git] / gcc / c-family / cilk.c
blob4957ade7e0f6523bb696c9c722cb3e490554bf14
1 /* This file is part of the Intel(R) Cilk(TM) Plus support
2 This file contains the CilkPlus Intrinsics
3 Copyright (C) 2013-2015 Free Software Foundation, Inc.
4 Contributed by Balaji V. Iyer <balaji.v.iyer@intel.com>,
5 Intel Corporation
7 This file is part of GCC.
9 GCC is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3, or (at your option)
12 any later version.
14 GCC is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3. If not see
21 <http://www.gnu.org/licenses/>. */
23 #include "config.h"
24 #include "system.h"
25 #include "coretypes.h"
26 #include "input.h"
27 #include "alias.h"
28 #include "symtab.h"
29 #include "options.h"
30 #include "tree.h"
31 #include "fold-const.h"
32 #include "stringpool.h"
33 #include "calls.h"
34 #include "langhooks.h"
35 #include "gimple-expr.h"
36 #include "gimplify.h"
37 #include "tree-iterator.h"
38 #include "tree-inline.h"
39 #include "c-family/c-common.h"
40 #include "toplev.h"
41 #include "is-a.h"
42 #include "plugin-api.h"
43 #include "tm.h"
44 #include "hard-reg-set.h"
45 #include "input.h"
46 #include "function.h"
47 #include "ipa-ref.h"
48 #include "cgraph.h"
49 #include "diagnostic.h"
50 #include "cilk.h"
52 enum add_variable_type {
53 /* Reference to previously-defined variable. */
54 ADD_READ,
55 /* Definition of a new variable in inner-scope. */
56 ADD_BIND,
57 /* Write to possibly previously-defined variable. */
58 ADD_WRITE
61 enum cilk_block_type {
62 /* Indicates a _Cilk_spawn block. 30 was an arbitary number picked for
63 ease of debugging. */
64 CILK_BLOCK_SPAWN = 30,
65 /* Indicates _Cilk_for statement block. */
66 CILK_BLOCK_FOR
69 struct wrapper_data
71 /* Kind of function to be created. */
72 enum cilk_block_type type;
73 /* Signature of helper function. */
74 tree fntype;
75 /* Containing function. */
76 tree context;
77 /* Disposition of all variables in the inner statement. */
78 hash_map<tree, tree> *decl_map;
79 /* True if this function needs a static chain. */
80 bool nested;
81 /* Arguments to be passed to wrapper function, currently a list. */
82 tree arglist;
83 /* Argument types, a list. */
84 tree argtypes;
85 /* Incoming parameters. */
86 tree parms;
87 /* Outer BLOCK object. */
88 tree block;
91 static void extract_free_variables (tree, struct wrapper_data *,
92 enum add_variable_type);
93 static HOST_WIDE_INT cilk_wrapper_count;
95 /* Marks the CALL_EXPR or FUNCTION_DECL, FCALL, as a spawned function call
96 and the current function as a spawner. Emit error if the function call
97 is outside a function or if a non function-call is spawned. */
99 inline bool
100 cilk_set_spawn_marker (location_t loc, tree fcall)
102 if (!current_function_decl)
104 error_at (loc, "%<_Cilk_spawn%> may only be used inside a function");
105 return false;
107 else if (fcall == error_mark_node)
108 /* Error reporting here is not necessary here since if FCALL is an
109 error_mark_node, the function marking it as error would have reported
110 it. */
111 return false;
112 else if (TREE_CODE (fcall) != CALL_EXPR
113 /* In C++, TARGET_EXPR is generated when we have an overloaded
114 '=' operator. */
115 && TREE_CODE (fcall) != TARGET_EXPR)
117 error_at (loc, "only function calls can be spawned");
118 return false;
120 else
122 cfun->calls_cilk_spawn = true;
123 return true;
127 /* This function will output the exit conditions for a spawn call. */
129 tree
130 create_cilk_function_exit (tree frame, bool detaches, bool needs_sync)
132 tree epi = alloc_stmt_list ();
134 if (needs_sync)
135 append_to_statement_list (build_cilk_sync (), &epi);
136 tree func_ptr = build1 (ADDR_EXPR, cilk_frame_ptr_type_decl, frame);
137 tree pop_frame = build_call_expr (cilk_pop_fndecl, 1, func_ptr);
138 tree worker = cilk_dot (frame, CILK_TI_FRAME_WORKER, 0);
139 tree current = cilk_arrow (worker, CILK_TI_WORKER_CUR, 0);
140 tree parent = cilk_dot (frame, CILK_TI_FRAME_PARENT, 0);
141 tree set_current = build2 (MODIFY_EXPR, void_type_node, current, parent);
142 append_to_statement_list (set_current, &epi);
143 append_to_statement_list (pop_frame, &epi);
144 tree call = build_call_expr (cilk_leave_fndecl, 1, func_ptr);
145 if (!detaches)
147 tree flags = cilk_dot (frame, CILK_TI_FRAME_FLAGS, false);
148 tree flags_cmp_expr = fold_build2 (NE_EXPR, TREE_TYPE (flags), flags,
149 build_int_cst (TREE_TYPE (flags),
150 CILK_FRAME_VERSION));
151 call = fold_build3 (COND_EXPR, void_type_node, flags_cmp_expr,
152 call, build_empty_stmt (EXPR_LOCATION (flags)));
154 append_to_statement_list (call, &epi);
155 return epi;
158 /* Trying to get the correct cfun for the FUNCTION_DECL indicated by OUTER. */
160 static void
161 pop_cfun_to (tree outer)
163 pop_cfun ();
164 current_function_decl = outer;
165 gcc_assert (cfun == DECL_STRUCT_FUNCTION (current_function_decl));
166 gcc_assert (cfun->decl == current_function_decl);
169 /* This function does whatever is necessary to make the compiler emit a newly
170 generated function, FNDECL. */
172 static void
173 call_graph_add_fn (tree fndecl)
175 const tree outer = current_function_decl;
176 struct function *f = DECL_STRUCT_FUNCTION (fndecl);
177 gcc_assert (TREE_CODE (fndecl) == FUNCTION_DECL);
179 f->is_cilk_function = 1;
180 f->curr_properties = cfun->curr_properties;
181 gcc_assert (cfun == DECL_STRUCT_FUNCTION (outer));
182 gcc_assert (cfun->decl == outer);
184 push_cfun (f);
185 cgraph_node::create (fndecl);
186 pop_cfun_to (outer);
189 /* Return true if this is a tree which is allowed to contain a spawn as
190 operand 0.
191 A spawn call may be wrapped in a series of unary operations such
192 as conversions. These conversions need not be "useless"
193 to be disregarded because they are retained in the spawned
194 statement. They are bypassed only to look for a spawn
195 within.
196 A comparison to constant is simple enough to allow, and
197 is used to convert to bool. */
199 static bool
200 cilk_ignorable_spawn_rhs_op (tree exp)
202 enum tree_code code = TREE_CODE (exp);
203 switch (TREE_CODE_CLASS (code))
205 case tcc_expression:
206 return code == ADDR_EXPR;
207 case tcc_comparison:
208 /* We need the spawn as operand 0 for now. That's where it
209 appears in the only case we really care about, conversion
210 to bool. */
211 return (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST);
212 case tcc_unary:
213 case tcc_reference:
214 return true;
215 default:
216 return false;
220 /* Helper function for walk_tree. If *TP is a CILK_SPAWN_STMT, then unwrap
221 this "wrapper." The function returns NULL_TREE regardless. */
223 static tree
224 unwrap_cilk_spawn_stmt (tree *tp, int *walk_subtrees, void *)
226 if (TREE_CODE (*tp) == CILK_SPAWN_STMT)
228 *tp = CILK_SPAWN_FN (*tp);
229 *walk_subtrees = 0;
231 return NULL_TREE;
234 /* Returns true when EXP is a CALL_EXPR with _Cilk_spawn in front. Unwraps
235 CILK_SPAWN_STMT wrapper from the CALL_EXPR in *EXP0 statement. */
237 static bool
238 recognize_spawn (tree exp, tree *exp0)
240 bool spawn_found = false;
241 if (TREE_CODE (exp) == CILK_SPAWN_STMT)
243 /* Remove the CALL_EXPR from CILK_SPAWN_STMT wrapper. */
244 exp = CILK_SPAWN_FN (exp);
245 walk_tree (exp0, unwrap_cilk_spawn_stmt, NULL, NULL);
246 spawn_found = true;
248 /* _Cilk_spawn can't be wrapped in expression such as PLUS_EXPR. */
249 else if (contains_cilk_spawn_stmt (exp))
250 error_at (EXPR_LOCATION (exp), "invalid use of %<_Cilk_spawn%>");
251 return spawn_found;
254 /* Returns true if *EXP0 is a recognized form of spawn. Recognized forms are,
255 after conversion to void, a call expression at outer level or an assignment
256 at outer level with the right hand side being a spawned call.
257 In addition to this, it also unwraps the CILK_SPAWN_STMT cover from the
258 CALL_EXPR that is being spawned.
259 Note that `=' in C++ may turn into a CALL_EXPR rather than a MODIFY_EXPR. */
261 bool
262 cilk_detect_spawn_and_unwrap (tree *exp0)
264 tree exp = *exp0;
266 if (!TREE_SIDE_EFFECTS (exp))
267 return false;
269 /* Strip off any conversion to void. It does not affect whether spawn
270 is supported here. */
271 if (TREE_CODE (exp) == CONVERT_EXPR && VOID_TYPE_P (TREE_TYPE (exp)))
272 exp = TREE_OPERAND (exp, 0);
274 if (TREE_CODE (exp) == MODIFY_EXPR || TREE_CODE (exp) == INIT_EXPR)
275 exp = TREE_OPERAND (exp, 1);
277 while (cilk_ignorable_spawn_rhs_op (exp))
278 exp = TREE_OPERAND (exp, 0);
280 if (TREE_CODE (exp) == TARGET_EXPR)
281 if (TARGET_EXPR_INITIAL (exp)
282 && TREE_CODE (TARGET_EXPR_INITIAL (exp)) != AGGR_INIT_EXPR)
283 exp = TARGET_EXPR_INITIAL (exp);
285 /* Happens with C++ TARGET_EXPR. */
286 if (exp == NULL_TREE)
287 return false;
289 while (TREE_CODE (exp) == CLEANUP_POINT_EXPR || TREE_CODE (exp) == EXPR_STMT)
290 exp = TREE_OPERAND (exp, 0);
292 /* Now we should have a CALL_EXPR with a CILK_SPAWN_STMT wrapper around
293 it, or return false. */
294 if (recognize_spawn (exp, exp0))
295 return true;
296 return false;
299 /* This function will build and return a FUNCTION_DECL using information
300 from *WD. */
302 static tree
303 create_cilk_helper_decl (struct wrapper_data *wd)
305 char name[20];
306 if (wd->type == CILK_BLOCK_FOR)
307 sprintf (name, "_cilk_for_" HOST_WIDE_INT_PRINT_DEC, cilk_wrapper_count++);
308 else if (wd->type == CILK_BLOCK_SPAWN)
309 sprintf (name, "_cilk_spn_" HOST_WIDE_INT_PRINT_DEC, cilk_wrapper_count++);
310 else
311 gcc_unreachable ();
313 clean_symbol_name (name);
314 tree fndecl = build_decl (UNKNOWN_LOCATION, FUNCTION_DECL,
315 get_identifier (name), wd->fntype);
317 TREE_PUBLIC (fndecl) = 0;
318 TREE_STATIC (fndecl) = 1;
319 TREE_USED (fndecl) = 1;
320 DECL_ARTIFICIAL (fndecl) = 0;
321 DECL_IGNORED_P (fndecl) = 0;
322 DECL_EXTERNAL (fndecl) = 0;
324 DECL_CONTEXT (fndecl) = wd->context;
325 tree block = make_node (BLOCK);
326 DECL_INITIAL (fndecl) = block;
327 TREE_USED (block) = 1;
328 BLOCK_SUPERCONTEXT (block) = fndecl;
329 gcc_assert (!DECL_SAVED_TREE (fndecl));
331 /* Inlining would defeat the purpose of this wrapper.
332 Either it secretly switches stack frames or it allocates
333 a stable stack frame to hold function arguments even if
334 the parent stack frame is stolen. */
335 DECL_UNINLINABLE (fndecl) = 1;
337 tree result_decl = build_decl (UNKNOWN_LOCATION, RESULT_DECL, NULL_TREE,
338 void_type_node);
339 DECL_ARTIFICIAL (result_decl) = 0;
340 DECL_IGNORED_P (result_decl) = 1;
341 DECL_CONTEXT (result_decl) = fndecl;
342 DECL_RESULT (fndecl) = result_decl;
344 return fndecl;
347 struct cilk_decls
349 tree key;
350 tree *val;
353 /* A function used by traversal to fill vector of decls for further work. */
355 bool
356 fill_decls_vec (tree const &key0, tree *val0, auto_vec<struct cilk_decls> *v)
358 tree t1 = key0;
359 struct cilk_decls dp;
361 if (DECL_P (t1))
363 dp.key = t1;
364 dp.val = val0;
365 v->safe_push (dp);
367 return true;
370 /* Function that actually creates necessary parm lists. */
372 static void
373 create_parm_list (struct wrapper_data *wd, tree *val0, tree arg)
375 tree val = *val0;
376 tree parm;
378 if (val == error_mark_node || val == arg)
379 return;
381 if (TREE_CODE (val) == PAREN_EXPR)
383 /* We should not reach here with a register receiver.
384 We may see a register variable modified in the
385 argument list. Because register variables are
386 worker-local we don't need to work hard to support
387 them in code that spawns. */
388 if ((TREE_CODE (arg) == VAR_DECL) && DECL_HARD_REGISTER (arg))
390 error_at (EXPR_LOCATION (arg),
391 "explicit register variable %qD may not be modified in "
392 "spawn", arg);
393 arg = null_pointer_node;
395 else
396 arg = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (arg)), arg);
398 val = TREE_OPERAND (val, 0);
399 *val0 = val;
400 gcc_assert (TREE_CODE (val) == INDIRECT_REF);
401 parm = TREE_OPERAND (val, 0);
402 STRIP_NOPS (parm);
404 else
405 parm = val;
406 TREE_CHAIN (parm) = wd->parms;
407 wd->parms = parm;
408 wd->argtypes = tree_cons (NULL_TREE, TREE_TYPE (parm), wd->argtypes);
409 wd->arglist = tree_cons (NULL_TREE, arg, wd->arglist);
412 /* Sorting decls in a vector. */
414 static int
415 compare_decls (const void *a, const void *b)
417 const struct cilk_decls *t1 = (const struct cilk_decls *) a;
418 const struct cilk_decls *t2 = (const struct cilk_decls *) b;
420 if (DECL_UID (t1->key) > DECL_UID (t2->key))
421 return 1;
422 else if (DECL_UID (t1->key) < DECL_UID (t2->key))
423 return -1;
424 else
425 return 0;
428 /* This function is used to build a wrapper of a certain type. */
430 static void
431 build_wrapper_type (struct wrapper_data *wd)
433 unsigned int j;
434 struct cilk_decls * c;
435 auto_vec<struct cilk_decls> vd;
436 wd->arglist = NULL_TREE;
437 wd->parms = NULL_TREE;
438 wd->argtypes = void_list_node;
440 gcc_assert (wd->type != CILK_BLOCK_FOR);
441 wd->decl_map->traverse<auto_vec<struct cilk_decls> *, fill_decls_vec> (&vd);
442 vd.qsort (compare_decls);
444 FOR_EACH_VEC_ELT (vd, j, c)
445 create_parm_list (wd, c->val, c->key);
447 /* Now build a function.
448 Its return type is void (all side effects are via explicit parameters).
449 Its parameters are WRAPPER_PARMS with type WRAPPER_TYPES.
450 Actual arguments in the caller are WRAPPER_ARGS. */
451 wd->fntype = build_function_type (void_type_node, wd->argtypes);
454 /* This function checks all the CALL_EXPRs in *TP found by cilk_outline. */
456 static tree
457 check_outlined_calls (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
458 void *data)
460 bool *throws = (bool *) data;
461 tree t = *tp;
462 int flags;
464 if (TREE_CODE (t) != CALL_EXPR)
465 return 0;
466 flags = call_expr_flags (t);
468 if (!(flags & ECF_NOTHROW) && flag_exceptions)
469 *throws = true;
470 if (flags & ECF_RETURNS_TWICE)
471 error_at (EXPR_LOCATION (t),
472 "cannot spawn call to function that returns twice");
473 return 0;
476 /* Each DECL in the source code (spawned statement) is passed to this function
477 once. Each instance of the DECL is replaced with the result of this
478 function.
480 The parameters of the wrapper should have been entered into the map already.
481 This function only deals with variables with scope limited to the
482 spawned expression. */
484 static tree
485 copy_decl_for_cilk (tree decl, copy_body_data *id)
487 switch (TREE_CODE (decl))
489 case VAR_DECL:
490 return copy_decl_no_change (decl, id);
492 case LABEL_DECL:
493 error_at (EXPR_LOCATION (decl), "invalid use of label %q+D in "
494 "%<_Cilk_spawn%>",
495 decl);
496 return error_mark_node;
498 case RESULT_DECL:
499 case PARM_DECL:
500 /* RESULT_DECL and PARM_DECL has already been entered into the map. */
501 default:
502 gcc_unreachable ();
503 return error_mark_node;
507 /* Alter a tree STMT from OUTER_FN to form the body of INNER_FN. */
509 void
510 cilk_outline (tree inner_fn, tree *stmt_p, void *w)
512 struct wrapper_data *wd = (struct wrapper_data *) w;
513 const tree outer_fn = wd->context;
514 const bool nested = (wd->type == CILK_BLOCK_FOR);
515 copy_body_data id;
516 bool throws;
517 auto_vec<struct cilk_decls> vd;
518 unsigned int j;
519 struct cilk_decls * c;
521 DECL_STATIC_CHAIN (outer_fn) = 1;
523 memset (&id, 0, sizeof (id));
524 /* Copy from the function containing the spawn... */
525 id.src_fn = outer_fn;
527 /* ...to the wrapper. */
528 id.dst_fn = inner_fn;
529 id.src_cfun = DECL_STRUCT_FUNCTION (outer_fn);
531 /* There shall be no RETURN in spawn helper. */
532 id.retvar = 0;
533 id.decl_map = wd->decl_map;
534 id.copy_decl = nested ? copy_decl_no_change : copy_decl_for_cilk;
535 id.block = DECL_INITIAL (inner_fn);
536 id.transform_lang_insert_block = NULL;
538 id.transform_new_cfg = true;
539 id.transform_call_graph_edges = CB_CGE_MOVE;
540 id.remap_var_for_cilk = true;
541 id.regimplify = true; /* unused? */
543 insert_decl_map (&id, wd->block, DECL_INITIAL (inner_fn));
545 wd->decl_map->traverse<auto_vec<struct cilk_decls> *, fill_decls_vec> (&vd);
546 vd.qsort (compare_decls);
547 /* We don't want the private variables any more. */
548 FOR_EACH_VEC_ELT (vd, j, c)
549 if (*(c->val) == error_mark_node)
550 *(c->val) = nested ? copy_decl_no_change (c->key, &id)
551 : copy_decl_for_cilk (c->key, &id);
553 walk_tree (stmt_p, copy_tree_body_r, (void *) &id, NULL);
555 /* See if this function can throw or calls something that should
556 not be spawned. The exception part is only necessary if
557 flag_exceptions && !flag_non_call_exceptions. */
558 throws = false ;
559 (void) walk_tree_without_duplicates (stmt_p, check_outlined_calls, &throws);
562 /* Generate the body of a wrapper function that assigns the
563 result of the expression RHS into RECEIVER. RECEIVER must
564 be NULL if this is not a spawn -- the wrapper will return
565 a value. If this is a spawn, the wrapper will return void. */
567 static tree
568 create_cilk_wrapper_body (tree stmt, struct wrapper_data *wd)
570 const tree outer = current_function_decl;
571 tree fndecl;
572 tree p;
574 /* Build the type of the wrapper and its argument list from the
575 variables that it requires. */
576 build_wrapper_type (wd);
578 /* Emit a function that takes WRAPPER_PARMS incoming and applies ARGS
579 (modified) to the wrapped function. Return the wrapper and modified ARGS
580 to the caller to generate a function call. */
581 fndecl = create_cilk_helper_decl (wd);
582 push_struct_function (fndecl);
583 if (wd->nested && (wd->type == CILK_BLOCK_FOR))
585 gcc_assert (TREE_VALUE (wd->arglist) == NULL_TREE);
586 TREE_VALUE (wd->arglist) = build2 (FDESC_EXPR, ptr_type_node,
587 fndecl, integer_one_node);
589 DECL_ARGUMENTS (fndecl) = wd->parms;
591 for (p = wd->parms; p; p = TREE_CHAIN (p))
592 DECL_CONTEXT (p) = fndecl;
594 gcc_assert (!DECL_SAVED_TREE (fndecl));
595 cilk_install_body_with_frame_cleanup (fndecl, stmt, (void *) wd);
596 gcc_assert (DECL_SAVED_TREE (fndecl));
598 pop_cfun_to (outer);
600 /* Recognize the new function. */
601 call_graph_add_fn (fndecl);
602 return fndecl;
605 /* Initializes the wrapper data structure. */
607 static void
608 init_wd (struct wrapper_data *wd, enum cilk_block_type type)
610 wd->type = type;
611 wd->fntype = NULL_TREE;
612 wd->context = current_function_decl;
613 wd->decl_map = new hash_map<tree, tree>;
614 /* _Cilk_for bodies are always nested. Others start off as
615 normal functions. */
616 wd->nested = (type == CILK_BLOCK_FOR);
617 wd->arglist = NULL_TREE;
618 wd->argtypes = NULL_TREE;
619 wd->block = NULL_TREE;
622 /* Clears the wrapper data structure. */
624 static void
625 free_wd (struct wrapper_data *wd)
627 delete wd->decl_map;
628 wd->nested = false;
629 wd->arglist = NULL_TREE;
630 wd->argtypes = NULL_TREE;
631 wd->parms = NULL_TREE;
635 /* Given a variable in an expression to be extracted into
636 a helper function, declare the helper function parameter
637 to receive it.
639 On entry the value of the (key, value) pair may be
641 (*, error_mark_node) -- Variable is private to helper function,
642 do nothing.
644 (var, var) -- Reference to outer scope (function or global scope).
646 (var, integer 0) -- Capture by value, save newly-declared PARM_DECL
647 for value in value slot.
649 (var, integer 1) -- Capture by reference, declare pointer to type
650 as new PARM_DECL and store (spawn_stmt (indirect_ref (parm)).
652 (var, ???) -- Pure output argument, handled similarly to above.
655 bool
656 declare_one_free_variable (tree var0, tree *map0)
658 const_tree var = var0;
659 tree map = *map0;
660 tree var_type = TREE_TYPE (var), arg_type;
661 bool by_reference;
662 tree parm;
664 gcc_assert (DECL_P (var));
666 /* Ignore truly local variables. */
667 if (map == error_mark_node)
668 return true;
669 /* Ignore references to the parent function. */
670 if (map == var)
671 return true;
673 gcc_assert (TREE_CODE (map) == INTEGER_CST);
675 /* A value is passed by reference if:
677 1. It is addressable, so that a copy may not be made.
678 2. It is modified in the spawned statement.
679 In the future this function may want to arrange
680 a warning if the spawned statement is a loop body
681 because an output argument would indicate a race.
682 Note: Earlier passes must have marked the variable addressable.
683 3. It is expensive to copy. */
684 by_reference =
685 (TREE_ADDRESSABLE (var_type)
686 /* Arrays must be passed by reference. This is required for C
687 semantics -- arrays are not first class objects. Other
688 aggregate types can and should be passed by reference if
689 they are not passed to the spawned function. We aren't yet
690 distinguishing safe uses in argument calculation from unsafe
691 uses as outgoing function arguments, so we make a copy to
692 stabilize the value. */
693 || TREE_CODE (var_type) == ARRAY_TYPE
694 || (tree) map == integer_one_node);
696 if (by_reference)
697 var_type = build_qualified_type (build_pointer_type (var_type),
698 TYPE_QUAL_RESTRICT);
699 gcc_assert (!TREE_ADDRESSABLE (var_type));
701 /* Maybe promote to int. */
702 if (INTEGRAL_TYPE_P (var_type) && COMPLETE_TYPE_P (var_type)
703 && tree_int_cst_lt (TYPE_SIZE (var_type), TYPE_SIZE (integer_type_node)))
704 arg_type = integer_type_node;
705 else
706 arg_type = var_type;
708 parm = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL_TREE, var_type);
709 DECL_ARG_TYPE (parm) = arg_type;
710 DECL_ARTIFICIAL (parm) = 0;
711 TREE_READONLY (parm) = 1;
713 if (by_reference)
715 parm = build1 (INDIRECT_REF, TREE_TYPE (var_type), parm);
716 parm = build1 (PAREN_EXPR, void_type_node, parm);
718 *map0 = parm;
719 return true;
722 /* Returns a wrapper function for a _Cilk_spawn. */
724 static tree
725 create_cilk_wrapper (tree exp, tree *args_out)
727 struct wrapper_data wd;
728 tree fndecl;
729 unsigned int j;
730 struct cilk_decls * c;
731 auto_vec<struct cilk_decls> vd;
733 init_wd (&wd, CILK_BLOCK_SPAWN);
735 if (TREE_CODE (exp) == CONVERT_EXPR)
736 exp = TREE_OPERAND (exp, 0);
738 /* Special handling for top level INIT_EXPR. Usually INIT_EXPR means the
739 variable is defined in the spawned expression and can be private to the
740 spawn helper. A top level INIT_EXPR defines a variable to be initialized
741 by spawn and the variable must remain in the outer function. */
742 if (TREE_CODE (exp) == INIT_EXPR)
744 extract_free_variables (TREE_OPERAND (exp, 0), &wd, ADD_WRITE);
745 extract_free_variables (TREE_OPERAND (exp, 1), &wd, ADD_READ);
746 /* TREE_TYPE should be void. Be defensive. */
747 if (TREE_TYPE (exp) != void_type_node)
748 extract_free_variables (TREE_TYPE (exp), &wd, ADD_READ);
750 else
751 extract_free_variables (exp, &wd, ADD_READ);
752 wd.decl_map->traverse<auto_vec<struct cilk_decls> *, fill_decls_vec> (&vd);
753 vd.qsort (compare_decls);
754 FOR_EACH_VEC_ELT (vd, j, c)
755 declare_one_free_variable (c->key, c->val);
757 wd.block = TREE_BLOCK (exp);
758 if (!wd.block)
759 wd.block = DECL_INITIAL (current_function_decl);
761 /* Now fvars maps the old variable to incoming variable. Update
762 the expression and arguments to refer to the new names. */
763 fndecl = create_cilk_wrapper_body (exp, &wd);
764 *args_out = wd.arglist;
766 free_wd (&wd);
768 return fndecl;
771 /* Transform *SPAWN_P, a spawned CALL_EXPR, to gimple. *SPAWN_P can be a
772 CALL_EXPR, INIT_EXPR or MODIFY_EXPR. Returns GS_OK if everything is fine,
773 and GS_UNHANDLED, otherwise. */
776 gimplify_cilk_spawn (tree *spawn_p)
778 tree expr = *spawn_p;
779 tree function, call1, call2, new_args;
780 tree ii_args = NULL_TREE;
781 int total_args = 0, ii = 0;
782 tree *arg_array;
783 tree setjmp_cond_expr = NULL_TREE;
784 tree setjmp_expr, spawn_expr, setjmp_value = NULL_TREE;
786 cfun->calls_cilk_spawn = 1;
787 cfun->is_cilk_function = 1;
789 /* Remove CLEANUP_POINT_EXPR and EXPR_STMT from *spawn_p. */
790 while (TREE_CODE (expr) == CLEANUP_POINT_EXPR
791 || TREE_CODE (expr) == EXPR_STMT)
792 expr = TREE_OPERAND (expr, 0);
794 new_args = NULL;
795 function = create_cilk_wrapper (expr, &new_args);
797 /* This should give the number of parameters. */
798 total_args = list_length (new_args);
799 if (total_args)
800 arg_array = XNEWVEC (tree, total_args);
801 else
802 arg_array = NULL;
804 ii_args = new_args;
805 for (ii = 0; ii < total_args; ii++)
807 arg_array[ii] = TREE_VALUE (ii_args);
808 ii_args = TREE_CHAIN (ii_args);
811 TREE_USED (function) = 1;
812 rest_of_decl_compilation (function, 0, 0);
814 call1 = cilk_call_setjmp (cfun->cilk_frame_decl);
816 if (arg_array == NULL || *arg_array == NULL_TREE)
817 call2 = build_call_expr (function, 0);
818 else
819 call2 = build_call_expr_loc_array (EXPR_LOCATION (*spawn_p), function,
820 total_args, arg_array);
821 *spawn_p = alloc_stmt_list ();
822 tree f_ptr_type = build_pointer_type (TREE_TYPE (cfun->cilk_frame_decl));
823 tree frame_ptr = build1 (ADDR_EXPR, f_ptr_type, cfun->cilk_frame_decl);
824 tree save_fp = build_call_expr (cilk_save_fp_fndecl, 1, frame_ptr);
825 append_to_statement_list (save_fp, spawn_p);
826 setjmp_value = create_tmp_var (TREE_TYPE (call1));
827 setjmp_expr = fold_build2 (MODIFY_EXPR, void_type_node, setjmp_value, call1);
829 append_to_statement_list_force (setjmp_expr, spawn_p);
831 setjmp_cond_expr = fold_build2 (EQ_EXPR, TREE_TYPE (call1), setjmp_value,
832 build_int_cst (TREE_TYPE (call1), 0));
833 spawn_expr = fold_build3 (COND_EXPR, void_type_node, setjmp_cond_expr,
834 call2, build_empty_stmt (EXPR_LOCATION (call1)));
835 append_to_statement_list (spawn_expr, spawn_p);
837 return GS_OK;
840 /* Make the frames necessary for a spawn call. */
842 tree
843 make_cilk_frame (tree fn)
845 struct function *f = DECL_STRUCT_FUNCTION (fn);
846 tree decl;
848 if (f->cilk_frame_decl)
849 return f->cilk_frame_decl;
851 decl = build_decl (EXPR_LOCATION (fn), VAR_DECL, NULL_TREE,
852 cilk_frame_type_decl);
853 DECL_CONTEXT (decl) = fn;
854 DECL_SEEN_IN_BIND_EXPR_P (decl) = 1;
855 f->cilk_frame_decl = decl;
856 return decl;
859 /* Returns a STATEMENT_LIST with all the pedigree operations required for
860 install body with frame cleanup functions. FRAME_PTR is the pointer to
861 __cilkrts_stack_frame created by make_cilk_frame. */
863 tree
864 cilk_install_body_pedigree_operations (tree frame_ptr)
866 tree body_list = alloc_stmt_list ();
867 tree enter_frame = build_call_expr (cilk_enter_fast_fndecl, 1, frame_ptr);
868 append_to_statement_list (enter_frame, &body_list);
870 tree parent = cilk_arrow (frame_ptr, CILK_TI_FRAME_PARENT, 0);
871 tree worker = cilk_arrow (frame_ptr, CILK_TI_FRAME_WORKER, 0);
873 tree pedigree = cilk_arrow (frame_ptr, CILK_TI_FRAME_PEDIGREE, 0);
874 tree pedigree_rank = cilk_dot (pedigree, CILK_TI_PEDIGREE_RANK, 0);
875 tree parent_pedigree = cilk_dot (pedigree, CILK_TI_PEDIGREE_PARENT, 0);
876 tree pedigree_parent = cilk_arrow (parent, CILK_TI_FRAME_PEDIGREE, 0);
877 tree pedigree_parent_rank = cilk_dot (pedigree_parent,
878 CILK_TI_PEDIGREE_RANK, 0);
879 tree pedigree_parent_parent = cilk_dot (pedigree_parent,
880 CILK_TI_PEDIGREE_PARENT, 0);
881 tree worker_pedigree = cilk_arrow (worker, CILK_TI_WORKER_PEDIGREE, 1);
882 tree w_pedigree_rank = cilk_dot (worker_pedigree, CILK_TI_PEDIGREE_RANK, 0);
883 tree w_pedigree_parent = cilk_dot (worker_pedigree,
884 CILK_TI_PEDIGREE_PARENT, 0);
886 /* sf.pedigree.rank = worker->pedigree.rank. */
887 tree exp1 = build2 (MODIFY_EXPR, void_type_node, pedigree_rank,
888 w_pedigree_rank);
889 append_to_statement_list (exp1, &body_list);
891 /* sf.pedigree.parent = worker->pedigree.parent. */
892 exp1 = build2 (MODIFY_EXPR, void_type_node, parent_pedigree,
893 w_pedigree_parent);
894 append_to_statement_list (exp1, &body_list);
896 /* sf.call_parent->pedigree.rank = worker->pedigree.rank. */
897 exp1 = build2 (MODIFY_EXPR, void_type_node, pedigree_parent_rank,
898 w_pedigree_rank);
899 append_to_statement_list (exp1, &body_list);
901 /* sf.call_parent->pedigree.parent = worker->pedigree.parent. */
902 exp1 = build2 (MODIFY_EXPR, void_type_node, pedigree_parent_parent,
903 w_pedigree_parent);
904 append_to_statement_list (exp1, &body_list);
906 /* sf->worker.pedigree.rank = 0. */
907 exp1 = build2 (MODIFY_EXPR, void_type_node, w_pedigree_rank,
908 build_zero_cst (uint64_type_node));
909 append_to_statement_list (exp1, &body_list);
911 /* sf->pedigree.parent = &sf->pedigree. */
912 exp1 = build2 (MODIFY_EXPR, void_type_node, w_pedigree_parent,
913 build1 (ADDR_EXPR,
914 build_pointer_type (cilk_pedigree_type_decl),
915 pedigree));
916 append_to_statement_list (exp1, &body_list);
917 return body_list;
920 /* Add a new variable, VAR to a variable list in WD->DECL_MAP. HOW indicates
921 whether the variable is previously defined, currently defined, or a variable
922 that is being written to. */
924 static void
925 add_variable (struct wrapper_data *wd, tree var, enum add_variable_type how)
927 tree *valp = wd->decl_map->get (var);
928 if (valp)
930 tree val = (tree) *valp;
931 /* If the variable is local, do nothing. */
932 if (val == error_mark_node)
933 return;
934 /* If the variable was entered with itself as value,
935 meaning it belongs to an outer scope, do not alter
936 the value. */
937 if (val == var)
938 return;
939 /* A statement expression may cause a variable to be
940 bound twice, once in BIND_EXPR and again in a
941 DECL_EXPR. That case caused a return in the
942 test above. Any other duplicate definition is
943 an error. */
944 gcc_assert (how != ADD_BIND);
945 if (how != ADD_WRITE)
946 return;
947 /* This variable might have been entered as read but is now written. */
948 *valp = var;
949 wd->nested = true;
950 return;
952 else
954 tree val = NULL_TREE;
956 /* Nested function rewriting silently discards hard register
957 assignments for function scope variables, and they wouldn't
958 work anyway. Warn here. This misses one case: if the
959 register variable is used as the loop bound or increment it
960 has already been added to the map. */
961 if ((how != ADD_BIND) && (TREE_CODE (var) == VAR_DECL)
962 && !DECL_EXTERNAL (var) && DECL_HARD_REGISTER (var))
963 warning (0, "register assignment ignored for %qD used in Cilk block",
964 var);
966 switch (how)
968 /* ADD_BIND means always make a fresh new variable. */
969 case ADD_BIND:
970 val = error_mark_node;
971 break;
972 /* ADD_READ means
973 1. For cilk_for, refer to the outer scope definition as-is
974 2. For a spawned block, take a scalar in an rgument
975 and otherwise refer to the outer scope definition as-is.
976 3. For a spawned call, take a scalar in an argument. */
977 case ADD_READ:
978 switch (wd->type)
980 case CILK_BLOCK_FOR:
981 val = var;
982 break;
983 case CILK_BLOCK_SPAWN:
984 if (TREE_ADDRESSABLE (var))
986 val = var;
987 wd->nested = true;
988 break;
990 val = integer_zero_node;
991 break;
993 break;
994 case ADD_WRITE:
995 switch (wd->type)
997 case CILK_BLOCK_FOR:
998 val = var;
999 wd->nested = true;
1000 break;
1001 case CILK_BLOCK_SPAWN:
1002 if (TREE_ADDRESSABLE (var))
1003 val = integer_one_node;
1004 else
1006 val = var;
1007 wd->nested = true;
1009 break;
1012 wd->decl_map->put (var, val);
1016 /* Find the variables referenced in an expression T. This does not avoid
1017 duplicates because a variable may be read in one context and written in
1018 another. HOW describes the context in which the reference is seen. If
1019 NESTED is true a nested function is being generated and variables in the
1020 original context should not be remapped. */
1022 static void
1023 extract_free_variables (tree t, struct wrapper_data *wd,
1024 enum add_variable_type how)
1026 if (t == NULL_TREE)
1027 return;
1029 enum tree_code code = TREE_CODE (t);
1030 bool is_expr = IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code));
1032 if (is_expr)
1033 extract_free_variables (TREE_TYPE (t), wd, ADD_READ);
1035 switch (code)
1037 case ERROR_MARK:
1038 case IDENTIFIER_NODE:
1039 case VOID_CST:
1040 case INTEGER_CST:
1041 case REAL_CST:
1042 case FIXED_CST:
1043 case STRING_CST:
1044 case BLOCK:
1045 case PLACEHOLDER_EXPR:
1046 case FIELD_DECL:
1047 case VOID_TYPE:
1048 case REAL_TYPE:
1049 /* These do not contain variable references. */
1050 return;
1052 case SSA_NAME:
1053 /* Currently we don't see SSA_NAME. */
1054 extract_free_variables (SSA_NAME_VAR (t), wd, how);
1055 return;
1057 case LABEL_DECL:
1058 /* This might be a reference to a label outside the Cilk block,
1059 which is an error, or a reference to a label in the Cilk block
1060 that we haven't seen yet. We can't tell. Ignore it. An
1061 invalid use will cause an error later in copy_decl_for_cilk. */
1062 return;
1064 case RESULT_DECL:
1065 if (wd->type != CILK_BLOCK_SPAWN)
1066 TREE_ADDRESSABLE (t) = 1;
1067 case VAR_DECL:
1068 case PARM_DECL:
1069 if (!TREE_STATIC (t) && !DECL_EXTERNAL (t))
1070 add_variable (wd, t, how);
1071 return;
1073 case NON_LVALUE_EXPR:
1074 case CONVERT_EXPR:
1075 case NOP_EXPR:
1076 extract_free_variables (TREE_OPERAND (t, 0), wd, ADD_READ);
1077 return;
1079 case VEC_INIT_EXPR:
1080 case INIT_EXPR:
1081 extract_free_variables (TREE_OPERAND (t, 0), wd, ADD_BIND);
1082 extract_free_variables (TREE_OPERAND (t, 1), wd, ADD_READ);
1083 return;
1085 case MODIFY_EXPR:
1086 case PREDECREMENT_EXPR:
1087 case PREINCREMENT_EXPR:
1088 case POSTDECREMENT_EXPR:
1089 case POSTINCREMENT_EXPR:
1090 /* These write their result. */
1091 extract_free_variables (TREE_OPERAND (t, 0), wd, ADD_WRITE);
1092 extract_free_variables (TREE_OPERAND (t, 1), wd, ADD_READ);
1093 return;
1095 case ADDR_EXPR:
1096 /* This might modify its argument, and the value needs to be
1097 passed by reference in any case to preserve identity and
1098 type if is a promoting type. In the case of a nested loop
1099 just notice that we touch the variable. It will already
1100 be addressable, and marking it modified will cause a spurious
1101 warning about writing the control variable. */
1102 if (wd->type != CILK_BLOCK_SPAWN)
1103 extract_free_variables (TREE_OPERAND (t, 0), wd, ADD_READ);
1104 else
1105 extract_free_variables (TREE_OPERAND (t, 0), wd, ADD_WRITE);
1106 return;
1108 case ARRAY_REF:
1109 /* Treating ARRAY_REF and BIT_FIELD_REF identically may
1110 mark the array as written but the end result is correct
1111 because the array is passed by pointer anyway. */
1112 case BIT_FIELD_REF:
1113 /* Propagate the access type to the object part of which
1114 is being accessed here. As for ADDR_EXPR, don't do this
1115 in a nested loop, unless the access is to a fixed index. */
1116 if (wd->type != CILK_BLOCK_FOR || TREE_CONSTANT (TREE_OPERAND (t, 1)))
1117 extract_free_variables (TREE_OPERAND (t, 0), wd, how);
1118 else
1119 extract_free_variables (TREE_OPERAND (t, 0), wd, ADD_READ);
1120 extract_free_variables (TREE_OPERAND (t, 1), wd, ADD_READ);
1121 extract_free_variables (TREE_OPERAND (t, 2), wd, ADD_READ);
1122 return;
1124 case TREE_LIST:
1125 extract_free_variables (TREE_PURPOSE (t), wd, ADD_READ);
1126 extract_free_variables (TREE_VALUE (t), wd, ADD_READ);
1127 extract_free_variables (TREE_CHAIN (t), wd, ADD_READ);
1128 return;
1130 case TREE_VEC:
1132 int len = TREE_VEC_LENGTH (t);
1133 int i;
1134 for (i = 0; i < len; i++)
1135 extract_free_variables (TREE_VEC_ELT (t, i), wd, ADD_READ);
1136 return;
1139 case VECTOR_CST:
1141 unsigned ii = 0;
1142 for (ii = 0; ii < VECTOR_CST_NELTS (t); ii++)
1143 extract_free_variables (VECTOR_CST_ELT (t, ii), wd, ADD_READ);
1144 break;
1147 case COMPLEX_CST:
1148 extract_free_variables (TREE_REALPART (t), wd, ADD_READ);
1149 extract_free_variables (TREE_IMAGPART (t), wd, ADD_READ);
1150 return;
1152 case BIND_EXPR:
1154 tree decl;
1155 for (decl = BIND_EXPR_VARS (t); decl; decl = TREE_CHAIN (decl))
1157 add_variable (wd, decl, ADD_BIND);
1158 /* A self-referential initialization is no problem because
1159 we already entered the variable into the map as local. */
1160 extract_free_variables (DECL_INITIAL (decl), wd, ADD_READ);
1161 extract_free_variables (DECL_SIZE (decl), wd, ADD_READ);
1162 extract_free_variables (DECL_SIZE_UNIT (decl), wd, ADD_READ);
1164 extract_free_variables (BIND_EXPR_BODY (t), wd, ADD_READ);
1165 return;
1168 case STATEMENT_LIST:
1170 tree_stmt_iterator i;
1171 for (i = tsi_start (t); !tsi_end_p (i); tsi_next (&i))
1172 extract_free_variables (*tsi_stmt_ptr (i), wd, ADD_READ);
1173 return;
1176 case TARGET_EXPR:
1178 extract_free_variables (TREE_OPERAND (t, 0), wd, ADD_BIND);
1179 extract_free_variables (TREE_OPERAND (t, 1), wd, ADD_READ);
1180 extract_free_variables (TREE_OPERAND (t, 2), wd, ADD_READ);
1181 if (TREE_OPERAND (t, 3) != TREE_OPERAND (t, 1))
1182 extract_free_variables (TREE_OPERAND (t, 3), wd, ADD_READ);
1183 return;
1186 case RETURN_EXPR:
1187 if (TREE_NO_WARNING (t))
1189 gcc_assert (errorcount);
1190 return;
1192 return;
1194 case DECL_EXPR:
1195 if (TREE_CODE (DECL_EXPR_DECL (t)) != TYPE_DECL)
1196 extract_free_variables (DECL_EXPR_DECL (t), wd, ADD_BIND);
1197 return;
1199 case INTEGER_TYPE:
1200 case ENUMERAL_TYPE:
1201 case BOOLEAN_TYPE:
1202 extract_free_variables (TYPE_MIN_VALUE (t), wd, ADD_READ);
1203 extract_free_variables (TYPE_MAX_VALUE (t), wd, ADD_READ);
1204 return;
1206 case POINTER_TYPE:
1207 extract_free_variables (TREE_TYPE (t), wd, ADD_READ);
1208 break;
1210 case ARRAY_TYPE:
1211 extract_free_variables (TREE_TYPE (t), wd, ADD_READ);
1212 extract_free_variables (TYPE_DOMAIN (t), wd, ADD_READ);
1213 return;
1215 case RECORD_TYPE:
1216 extract_free_variables (TYPE_FIELDS (t), wd, ADD_READ);
1217 return;
1219 case METHOD_TYPE:
1220 extract_free_variables (TYPE_ARG_TYPES (t), wd, ADD_READ);
1221 extract_free_variables (TYPE_METHOD_BASETYPE (t), wd, ADD_READ);
1222 return;
1224 case AGGR_INIT_EXPR:
1225 case CALL_EXPR:
1227 int len = 0;
1228 int ii = 0;
1229 if (TREE_CODE (TREE_OPERAND (t, 0)) == INTEGER_CST)
1231 len = TREE_INT_CST_LOW (TREE_OPERAND (t, 0));
1233 for (ii = 0; ii < len; ii++)
1234 extract_free_variables (TREE_OPERAND (t, ii), wd, ADD_READ);
1235 extract_free_variables (TREE_TYPE (t), wd, ADD_READ);
1237 break;
1240 case CONSTRUCTOR:
1242 unsigned HOST_WIDE_INT idx = 0;
1243 constructor_elt *ce;
1244 for (idx = 0; vec_safe_iterate (CONSTRUCTOR_ELTS (t), idx, &ce); idx++)
1245 extract_free_variables (ce->value, wd, ADD_READ);
1246 break;
1249 default:
1250 if (is_expr)
1252 int i, len;
1254 /* Walk over all the sub-trees of this operand. */
1255 len = TREE_CODE_LENGTH (code);
1257 /* Go through the subtrees. We need to do this in forward order so
1258 that the scope of a FOR_EXPR is handled properly. */
1259 for (i = 0; i < len; ++i)
1260 extract_free_variables (TREE_OPERAND (t, i), wd, ADD_READ);
1265 /* Add appropriate frames needed for a Cilk spawned function call, FNDECL.
1266 Returns the __cilkrts_stack_frame * variable. */
1268 tree
1269 insert_cilk_frame (tree fndecl)
1271 tree addr, body, enter, out, orig_body;
1272 location_t loc = EXPR_LOCATION (fndecl);
1274 if (!cfun || cfun->decl != fndecl)
1275 push_cfun (DECL_STRUCT_FUNCTION (fndecl));
1277 tree decl = cfun->cilk_frame_decl;
1278 if (!decl)
1280 tree *saved_tree = &DECL_SAVED_TREE (fndecl);
1281 decl = make_cilk_frame (fndecl);
1282 add_local_decl (cfun, decl);
1284 addr = build1 (ADDR_EXPR, cilk_frame_ptr_type_decl, decl);
1285 enter = build_call_expr (cilk_enter_fndecl, 1, addr);
1286 out = create_cilk_function_exit (cfun->cilk_frame_decl, false, true);
1288 /* The new body will be:
1289 __cilkrts_enter_frame_1 (&sf);
1290 try {
1291 orig_body;
1293 finally {
1294 __cilkrts_pop_frame (&sf);
1295 __cilkrts_leave_frame (&sf);
1296 } */
1298 body = alloc_stmt_list ();
1299 orig_body = *saved_tree;
1301 if (TREE_CODE (orig_body) == BIND_EXPR)
1302 orig_body = BIND_EXPR_BODY (orig_body);
1304 append_to_statement_list (enter, &body);
1305 append_to_statement_list (build_stmt (loc, TRY_FINALLY_EXPR, orig_body,
1306 out), &body);
1307 if (TREE_CODE (*saved_tree) == BIND_EXPR)
1308 BIND_EXPR_BODY (*saved_tree) = body;
1309 else
1310 *saved_tree = body;
1312 return decl;
1315 /* Wraps CALL, a CALL_EXPR, into a CILK_SPAWN_STMT tree and returns it. */
1317 tree
1318 build_cilk_spawn (location_t loc, tree call)
1320 if (!cilk_set_spawn_marker (loc, call))
1321 return error_mark_node;
1322 tree spawn_stmt = build1 (CILK_SPAWN_STMT, TREE_TYPE (call), call);
1323 TREE_SIDE_EFFECTS (spawn_stmt) = 1;
1324 return spawn_stmt;
1327 /* Returns a tree of type CILK_SYNC_STMT. */
1329 tree
1330 build_cilk_sync (void)
1332 tree sync = build0 (CILK_SYNC_STMT, void_type_node);
1333 TREE_SIDE_EFFECTS (sync) = 1;
1334 return sync;
1337 /* Helper for contains_cilk_spawn_stmt, callback for walk_tree. Return
1338 non-null tree if TP contains CILK_SPAWN_STMT. */
1340 static tree
1341 contains_cilk_spawn_stmt_walker (tree *tp, int *, void *)
1343 if (TREE_CODE (*tp) == CILK_SPAWN_STMT)
1344 return *tp;
1345 else
1346 return NULL_TREE;
1349 /* Returns true if EXPR or any of its subtrees contain CILK_SPAWN_STMT
1350 node. */
1352 bool
1353 contains_cilk_spawn_stmt (tree expr)
1355 return walk_tree (&expr, contains_cilk_spawn_stmt_walker, NULL, NULL)
1356 != NULL_TREE;
1359 /* Return a error location for EXPR if LOC is not set. */
1361 static location_t
1362 get_error_location (tree expr, location_t loc)
1364 if (loc == UNKNOWN_LOCATION)
1366 if (TREE_CODE (expr) == MODIFY_EXPR)
1367 expr = TREE_OPERAND (expr, 0);
1368 loc = EXPR_LOCATION (expr);
1370 return loc;
1373 /* Check that no array notation or spawn statement is in EXPR.
1374 If not true generate an error at LOC for ARRAY_GMSGID or
1375 SPAWN_MSGID. */
1377 bool
1378 check_no_cilk (tree expr, const char *array_msgid, const char *spawn_msgid,
1379 location_t loc)
1381 if (!flag_cilkplus)
1382 return false;
1383 if (contains_array_notation_expr (expr))
1385 loc = get_error_location (expr, loc);
1386 error_at (loc, array_msgid);
1387 return true;
1389 if (walk_tree (&expr, contains_cilk_spawn_stmt_walker, NULL, NULL))
1391 loc = get_error_location (expr, loc);
1392 error_at (loc, spawn_msgid);
1393 return true;
1395 return false;