]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/c-family/cilk.c
convert many uses of pointer_map to hash_map
[thirdparty/gcc.git] / gcc / c-family / cilk.c
1 /* This file is part of the Intel(R) Cilk(TM) Plus support
2 This file contains the CilkPlus Intrinsics
3 Copyright (C) 2013-2014 Free Software Foundation, Inc.
4 Contributed by Balaji V. Iyer <balaji.v.iyer@intel.com>,
5 Intel Corporation
6
7 This file is part of GCC.
8
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.
13
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.
18
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/>. */
22
23 #include "config.h"
24 #include "system.h"
25 #include "coretypes.h"
26 #include "tree.h"
27 #include "stringpool.h"
28 #include "calls.h"
29 #include "langhooks.h"
30 #include "pointer-set.h"
31 #include "gimple-expr.h"
32 #include "gimplify.h"
33 #include "tree-iterator.h"
34 #include "tree-inline.h"
35 #include "c-family/c-common.h"
36 #include "toplev.h"
37 #include "cgraph.h"
38 #include "diagnostic.h"
39 #include "cilk.h"
40
41 enum add_variable_type {
42 /* Reference to previously-defined variable. */
43 ADD_READ,
44 /* Definition of a new variable in inner-scope. */
45 ADD_BIND,
46 /* Write to possibly previously-defined variable. */
47 ADD_WRITE
48 };
49
50 enum cilk_block_type {
51 /* Indicates a _Cilk_spawn block. 30 was an arbitary number picked for
52 ease of debugging. */
53 CILK_BLOCK_SPAWN = 30,
54 /* Indicates _Cilk_for statement block. */
55 CILK_BLOCK_FOR
56 };
57
58 struct wrapper_data
59 {
60 /* Kind of function to be created. */
61 enum cilk_block_type type;
62 /* Signature of helper function. */
63 tree fntype;
64 /* Containing function. */
65 tree context;
66 /* Disposition of all variables in the inner statement. */
67 hash_map<tree, tree> *decl_map;
68 /* True if this function needs a static chain. */
69 bool nested;
70 /* Arguments to be passed to wrapper function, currently a list. */
71 tree arglist;
72 /* Argument types, a list. */
73 tree argtypes;
74 /* Incoming parameters. */
75 tree parms;
76 /* Outer BLOCK object. */
77 tree block;
78 };
79
80 static void extract_free_variables (tree, struct wrapper_data *,
81 enum add_variable_type);
82 static HOST_WIDE_INT cilk_wrapper_count;
83
84 /* Marks the CALL_EXPR or FUNCTION_DECL, FCALL, as a spawned function call
85 and the current function as a spawner. Emit error if the function call
86 is outside a function or if a non function-call is spawned. */
87
88 inline bool
89 cilk_set_spawn_marker (location_t loc, tree fcall)
90 {
91 if (!current_function_decl)
92 {
93 error_at (loc, "%<_Cilk_spawn%> may only be used inside a function");
94 return false;
95 }
96 else if (fcall == error_mark_node)
97 /* Error reporting here is not necessary here since if FCALL is an
98 error_mark_node, the function marking it as error would have reported
99 it. */
100 return false;
101 else if (TREE_CODE (fcall) != CALL_EXPR
102 /* In C++, TARGET_EXPR is generated when we have an overloaded
103 '=' operator. */
104 && TREE_CODE (fcall) != TARGET_EXPR)
105 {
106 error_at (loc, "only function calls can be spawned");
107 return false;
108 }
109 else
110 {
111 cfun->calls_cilk_spawn = true;
112 return true;
113 }
114 }
115
116 /* This function will output the exit conditions for a spawn call. */
117
118 tree
119 create_cilk_function_exit (tree frame, bool detaches, bool needs_sync)
120 {
121 tree epi = alloc_stmt_list ();
122
123 if (needs_sync)
124 append_to_statement_list (build_cilk_sync (), &epi);
125 tree func_ptr = build1 (ADDR_EXPR, cilk_frame_ptr_type_decl, frame);
126 tree pop_frame = build_call_expr (cilk_pop_fndecl, 1, func_ptr);
127 tree worker = cilk_dot (frame, CILK_TI_FRAME_WORKER, 0);
128 tree current = cilk_arrow (worker, CILK_TI_WORKER_CUR, 0);
129 tree parent = cilk_dot (frame, CILK_TI_FRAME_PARENT, 0);
130 tree set_current = build2 (MODIFY_EXPR, void_type_node, current, parent);
131 append_to_statement_list (set_current, &epi);
132 append_to_statement_list (pop_frame, &epi);
133 tree call = build_call_expr (cilk_leave_fndecl, 1, func_ptr);
134 if (!detaches)
135 {
136 tree flags = cilk_dot (frame, CILK_TI_FRAME_FLAGS, false);
137 tree flags_cmp_expr = fold_build2 (NE_EXPR, TREE_TYPE (flags), flags,
138 build_int_cst (TREE_TYPE (flags),
139 CILK_FRAME_VERSION));
140 call = fold_build3 (COND_EXPR, void_type_node, flags_cmp_expr,
141 call, build_empty_stmt (EXPR_LOCATION (flags)));
142 }
143 append_to_statement_list (call, &epi);
144 return epi;
145 }
146
147 /* Trying to get the correct cfun for the FUNCTION_DECL indicated by OUTER. */
148
149 static void
150 pop_cfun_to (tree outer)
151 {
152 pop_cfun ();
153 current_function_decl = outer;
154 gcc_assert (cfun == DECL_STRUCT_FUNCTION (current_function_decl));
155 gcc_assert (cfun->decl == current_function_decl);
156 }
157
158 /* This function does whatever is necessary to make the compiler emit a newly
159 generated function, FNDECL. */
160
161 static void
162 call_graph_add_fn (tree fndecl)
163 {
164 const tree outer = current_function_decl;
165 struct function *f = DECL_STRUCT_FUNCTION (fndecl);
166 gcc_assert (TREE_CODE (fndecl) == FUNCTION_DECL);
167
168 f->is_cilk_function = 1;
169 f->curr_properties = cfun->curr_properties;
170 gcc_assert (cfun == DECL_STRUCT_FUNCTION (outer));
171 gcc_assert (cfun->decl == outer);
172
173 push_cfun (f);
174 cgraph_node::create (fndecl);
175 pop_cfun_to (outer);
176 }
177
178 /* Return true if this is a tree which is allowed to contain a spawn as
179 operand 0.
180 A spawn call may be wrapped in a series of unary operations such
181 as conversions. These conversions need not be "useless"
182 to be disregarded because they are retained in the spawned
183 statement. They are bypassed only to look for a spawn
184 within.
185 A comparison to constant is simple enough to allow, and
186 is used to convert to bool. */
187
188 static bool
189 cilk_ignorable_spawn_rhs_op (tree exp)
190 {
191 enum tree_code code = TREE_CODE (exp);
192 switch (TREE_CODE_CLASS (code))
193 {
194 case tcc_expression:
195 return code == ADDR_EXPR;
196 case tcc_comparison:
197 /* We need the spawn as operand 0 for now. That's where it
198 appears in the only case we really care about, conversion
199 to bool. */
200 return (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST);
201 case tcc_unary:
202 case tcc_reference:
203 return true;
204 default:
205 return false;
206 }
207 }
208
209 /* Helper function for walk_tree. If *TP is a CILK_SPAWN_STMT, then unwrap
210 this "wrapper." The function returns NULL_TREE regardless. */
211
212 static tree
213 unwrap_cilk_spawn_stmt (tree *tp, int *walk_subtrees, void *)
214 {
215 if (TREE_CODE (*tp) == CILK_SPAWN_STMT)
216 {
217 *tp = CILK_SPAWN_FN (*tp);
218 *walk_subtrees = 0;
219 }
220 return NULL_TREE;
221 }
222
223 /* Returns true when EXP is a CALL_EXPR with _Cilk_spawn in front. Unwraps
224 CILK_SPAWN_STMT wrapper from the CALL_EXPR in *EXP0 statement. */
225
226 static bool
227 recognize_spawn (tree exp, tree *exp0)
228 {
229 bool spawn_found = false;
230 if (TREE_CODE (exp) == CILK_SPAWN_STMT)
231 {
232 /* Remove the CALL_EXPR from CILK_SPAWN_STMT wrapper. */
233 exp = CILK_SPAWN_FN (exp);
234 walk_tree (exp0, unwrap_cilk_spawn_stmt, NULL, NULL);
235 spawn_found = true;
236 }
237 /* _Cilk_spawn can't be wrapped in expression such as PLUS_EXPR. */
238 else if (contains_cilk_spawn_stmt (exp))
239 error ("invalid use of %<_Cilk_spawn%>");
240 return spawn_found;
241 }
242
243 /* Returns true if *EXP0 is a recognized form of spawn. Recognized forms are,
244 after conversion to void, a call expression at outer level or an assignment
245 at outer level with the right hand side being a spawned call.
246 In addition to this, it also unwraps the CILK_SPAWN_STMT cover from the
247 CALL_EXPR that is being spawned.
248 Note that `=' in C++ may turn into a CALL_EXPR rather than a MODIFY_EXPR. */
249
250 bool
251 cilk_detect_spawn_and_unwrap (tree *exp0)
252 {
253 tree exp = *exp0;
254
255 if (!TREE_SIDE_EFFECTS (exp))
256 return false;
257
258 /* Strip off any conversion to void. It does not affect whether spawn
259 is supported here. */
260 if (TREE_CODE (exp) == CONVERT_EXPR && VOID_TYPE_P (TREE_TYPE (exp)))
261 exp = TREE_OPERAND (exp, 0);
262
263 if (TREE_CODE (exp) == MODIFY_EXPR || TREE_CODE (exp) == INIT_EXPR)
264 exp = TREE_OPERAND (exp, 1);
265
266 while (cilk_ignorable_spawn_rhs_op (exp))
267 exp = TREE_OPERAND (exp, 0);
268
269 if (TREE_CODE (exp) == TARGET_EXPR)
270 if (TARGET_EXPR_INITIAL (exp)
271 && TREE_CODE (TARGET_EXPR_INITIAL (exp)) != AGGR_INIT_EXPR)
272 exp = TARGET_EXPR_INITIAL (exp);
273
274 /* Happens with C++ TARGET_EXPR. */
275 if (exp == NULL_TREE)
276 return false;
277
278 while (TREE_CODE (exp) == CLEANUP_POINT_EXPR || TREE_CODE (exp) == EXPR_STMT)
279 exp = TREE_OPERAND (exp, 0);
280
281 /* Now we should have a CALL_EXPR with a CILK_SPAWN_STMT wrapper around
282 it, or return false. */
283 if (recognize_spawn (exp, exp0))
284 return true;
285 return false;
286 }
287
288 /* This function will build and return a FUNCTION_DECL using information
289 from *WD. */
290
291 static tree
292 create_cilk_helper_decl (struct wrapper_data *wd)
293 {
294 char name[20];
295 if (wd->type == CILK_BLOCK_FOR)
296 sprintf (name, "_cilk_for_" HOST_WIDE_INT_PRINT_DEC, cilk_wrapper_count++);
297 else if (wd->type == CILK_BLOCK_SPAWN)
298 sprintf (name, "_cilk_spn_" HOST_WIDE_INT_PRINT_DEC, cilk_wrapper_count++);
299 else
300 gcc_unreachable ();
301
302 clean_symbol_name (name);
303 tree fndecl = build_decl (UNKNOWN_LOCATION, FUNCTION_DECL,
304 get_identifier (name), wd->fntype);
305
306 TREE_PUBLIC (fndecl) = 0;
307 TREE_STATIC (fndecl) = 1;
308 TREE_USED (fndecl) = 1;
309 DECL_ARTIFICIAL (fndecl) = 0;
310 DECL_IGNORED_P (fndecl) = 0;
311 DECL_EXTERNAL (fndecl) = 0;
312
313 DECL_CONTEXT (fndecl) = wd->context;
314 tree block = make_node (BLOCK);
315 DECL_INITIAL (fndecl) = block;
316 TREE_USED (block) = 1;
317 BLOCK_SUPERCONTEXT (block) = fndecl;
318 gcc_assert (!DECL_SAVED_TREE (fndecl));
319
320 /* Inlining would defeat the purpose of this wrapper.
321 Either it secretly switches stack frames or it allocates
322 a stable stack frame to hold function arguments even if
323 the parent stack frame is stolen. */
324 DECL_UNINLINABLE (fndecl) = 1;
325
326 tree result_decl = build_decl (UNKNOWN_LOCATION, RESULT_DECL, NULL_TREE,
327 void_type_node);
328 DECL_ARTIFICIAL (result_decl) = 0;
329 DECL_IGNORED_P (result_decl) = 1;
330 DECL_CONTEXT (result_decl) = fndecl;
331 DECL_RESULT (fndecl) = result_decl;
332
333 return fndecl;
334 }
335
336 /* A function used by walk tree to find wrapper parms. */
337
338 bool
339 wrapper_parm_cb (tree const &key0, tree *val0, wrapper_data *wd)
340 {
341 tree arg = key0;
342 tree val = *val0;
343 tree parm;
344
345 if (val == error_mark_node || val == arg)
346 return true;
347
348 if (TREE_CODE (val) == PAREN_EXPR)
349 {
350 /* We should not reach here with a register receiver.
351 We may see a register variable modified in the
352 argument list. Because register variables are
353 worker-local we don't need to work hard to support
354 them in code that spawns. */
355 if ((TREE_CODE (arg) == VAR_DECL) && DECL_HARD_REGISTER (arg))
356 {
357 error_at (EXPR_LOCATION (arg),
358 "explicit register variable %qD may not be modified in "
359 "spawn", arg);
360 arg = null_pointer_node;
361 }
362 else
363 arg = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (arg)), arg);
364
365 val = TREE_OPERAND (val, 0);
366 *val0 = val;
367 gcc_assert (TREE_CODE (val) == INDIRECT_REF);
368 parm = TREE_OPERAND (val, 0);
369 STRIP_NOPS (parm);
370 }
371 else
372 parm = val;
373 TREE_CHAIN (parm) = wd->parms;
374 wd->parms = parm;
375 wd->argtypes = tree_cons (NULL_TREE, TREE_TYPE (parm), wd->argtypes);
376 wd->arglist = tree_cons (NULL_TREE, arg, wd->arglist);
377 return true;
378 }
379
380 /* This function is used to build a wrapper of a certain type. */
381
382 static void
383 build_wrapper_type (struct wrapper_data *wd)
384 {
385 wd->arglist = NULL_TREE;
386 wd->parms = NULL_TREE;
387 wd->argtypes = void_list_node;
388
389 wd->decl_map->traverse<wrapper_data *, wrapper_parm_cb> (wd);
390 gcc_assert (wd->type != CILK_BLOCK_FOR);
391
392 /* Now build a function.
393 Its return type is void (all side effects are via explicit parameters).
394 Its parameters are WRAPPER_PARMS with type WRAPPER_TYPES.
395 Actual arguments in the caller are WRAPPER_ARGS. */
396 wd->fntype = build_function_type (void_type_node, wd->argtypes);
397 }
398
399 /* This function checks all the CALL_EXPRs in *TP found by cilk_outline. */
400
401 static tree
402 check_outlined_calls (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
403 void *data)
404 {
405 bool *throws = (bool *) data;
406 tree t = *tp;
407 int flags;
408
409 if (TREE_CODE (t) != CALL_EXPR)
410 return 0;
411 flags = call_expr_flags (t);
412
413 if (!(flags & ECF_NOTHROW) && flag_exceptions)
414 *throws = true;
415 if (flags & ECF_RETURNS_TWICE)
416 error_at (EXPR_LOCATION (t),
417 "cannot spawn call to function that returns twice");
418 return 0;
419 }
420
421 /* Each DECL in the source code (spawned statement) is passed to this function
422 once. Each instance of the DECL is replaced with the result of this
423 function.
424
425 The parameters of the wrapper should have been entered into the map already.
426 This function only deals with variables with scope limited to the
427 spawned expression. */
428
429 static tree
430 copy_decl_for_cilk (tree decl, copy_body_data *id)
431 {
432 switch (TREE_CODE (decl))
433 {
434 case VAR_DECL:
435 return copy_decl_no_change (decl, id);
436
437 case LABEL_DECL:
438 error_at (EXPR_LOCATION (decl), "invalid use of label %q+D in "
439 "%<_Cilk_spawn%>",
440 decl);
441 return error_mark_node;
442
443 case RESULT_DECL:
444 case PARM_DECL:
445 /* RESULT_DECL and PARM_DECL has already been entered into the map. */
446 default:
447 gcc_unreachable ();
448 return error_mark_node;
449 }
450 }
451
452 /* Copy all local variables. */
453
454 bool
455 for_local_cb (tree const &k, tree *vp, copy_body_data *id)
456 {
457 tree v = *vp;
458
459 if (v == error_mark_node)
460 *vp = copy_decl_no_change (k, id);
461 return true;
462 }
463
464 /* Copy all local declarations from a _Cilk_spawned function's body. */
465
466 bool
467 wrapper_local_cb (tree const &key, tree *vp, copy_body_data *id)
468 {
469 tree val = *vp;
470
471 if (val == error_mark_node)
472 *vp = copy_decl_for_cilk (key, id);
473
474 return true;
475 }
476
477 /* Alter a tree STMT from OUTER_FN to form the body of INNER_FN. */
478
479 void
480 cilk_outline (tree inner_fn, tree *stmt_p, void *w)
481 {
482 struct wrapper_data *wd = (struct wrapper_data *) w;
483 const tree outer_fn = wd->context;
484 const bool nested = (wd->type == CILK_BLOCK_FOR);
485 copy_body_data id;
486 bool throws;
487
488 DECL_STATIC_CHAIN (outer_fn) = 1;
489
490 memset (&id, 0, sizeof (id));
491 /* Copy from the function containing the spawn... */
492 id.src_fn = outer_fn;
493
494 /* ...to the wrapper. */
495 id.dst_fn = inner_fn;
496 id.src_cfun = DECL_STRUCT_FUNCTION (outer_fn);
497
498 /* There shall be no RETURN in spawn helper. */
499 id.retvar = 0;
500 id.decl_map = wd->decl_map;
501 id.copy_decl = nested ? copy_decl_no_change : copy_decl_for_cilk;
502 id.block = DECL_INITIAL (inner_fn);
503 id.transform_lang_insert_block = NULL;
504
505 id.transform_new_cfg = true;
506 id.transform_call_graph_edges = CB_CGE_MOVE;
507 id.remap_var_for_cilk = true;
508 id.regimplify = true; /* unused? */
509
510 insert_decl_map (&id, wd->block, DECL_INITIAL (inner_fn));
511
512 /* We don't want the private variables any more. */
513 if (nested)
514 wd->decl_map->traverse<copy_body_data *, for_local_cb> (&id);
515 else
516 wd->decl_map->traverse<copy_body_data *, wrapper_local_cb> (&id);
517
518 walk_tree (stmt_p, copy_tree_body_r, (void *) &id, NULL);
519
520 /* See if this function can throw or calls something that should
521 not be spawned. The exception part is only necessary if
522 flag_exceptions && !flag_non_call_exceptions. */
523 throws = false ;
524 (void) walk_tree_without_duplicates (stmt_p, check_outlined_calls, &throws);
525 }
526
527 /* Generate the body of a wrapper function that assigns the
528 result of the expression RHS into RECEIVER. RECEIVER must
529 be NULL if this is not a spawn -- the wrapper will return
530 a value. If this is a spawn, the wrapper will return void. */
531
532 static tree
533 create_cilk_wrapper_body (tree stmt, struct wrapper_data *wd)
534 {
535 const tree outer = current_function_decl;
536 tree fndecl;
537 tree p;
538
539 /* Build the type of the wrapper and its argument list from the
540 variables that it requires. */
541 build_wrapper_type (wd);
542
543 /* Emit a function that takes WRAPPER_PARMS incoming and applies ARGS
544 (modified) to the wrapped function. Return the wrapper and modified ARGS
545 to the caller to generate a function call. */
546 fndecl = create_cilk_helper_decl (wd);
547 push_struct_function (fndecl);
548 if (wd->nested && (wd->type == CILK_BLOCK_FOR))
549 {
550 gcc_assert (TREE_VALUE (wd->arglist) == NULL_TREE);
551 TREE_VALUE (wd->arglist) = build2 (FDESC_EXPR, ptr_type_node,
552 fndecl, integer_one_node);
553 }
554 DECL_ARGUMENTS (fndecl) = wd->parms;
555
556 for (p = wd->parms; p; p = TREE_CHAIN (p))
557 DECL_CONTEXT (p) = fndecl;
558
559 gcc_assert (!DECL_SAVED_TREE (fndecl));
560 cilk_install_body_with_frame_cleanup (fndecl, stmt, (void *) wd);
561 gcc_assert (DECL_SAVED_TREE (fndecl));
562
563 pop_cfun_to (outer);
564
565 /* Recognize the new function. */
566 call_graph_add_fn (fndecl);
567 return fndecl;
568 }
569
570 /* Initializes the wrapper data structure. */
571
572 static void
573 init_wd (struct wrapper_data *wd, enum cilk_block_type type)
574 {
575 wd->type = type;
576 wd->fntype = NULL_TREE;
577 wd->context = current_function_decl;
578 wd->decl_map = new hash_map<tree, tree>;
579 /* _Cilk_for bodies are always nested. Others start off as
580 normal functions. */
581 wd->nested = (type == CILK_BLOCK_FOR);
582 wd->arglist = NULL_TREE;
583 wd->argtypes = NULL_TREE;
584 wd->block = NULL_TREE;
585 }
586
587 /* Clears the wrapper data structure. */
588
589 static void
590 free_wd (struct wrapper_data *wd)
591 {
592 delete wd->decl_map;
593 wd->nested = false;
594 wd->arglist = NULL_TREE;
595 wd->argtypes = NULL_TREE;
596 wd->parms = NULL_TREE;
597 }
598
599
600 /* Given a variable in an expression to be extracted into
601 a helper function, declare the helper function parameter
602 to receive it.
603
604 On entry the value of the (key, value) pair may be
605
606 (*, error_mark_node) -- Variable is private to helper function,
607 do nothing.
608
609 (var, var) -- Reference to outer scope (function or global scope).
610
611 (var, integer 0) -- Capture by value, save newly-declared PARM_DECL
612 for value in value slot.
613
614 (var, integer 1) -- Capture by reference, declare pointer to type
615 as new PARM_DECL and store (spawn_stmt (indirect_ref (parm)).
616
617 (var, ???) -- Pure output argument, handled similarly to above.
618 */
619
620 bool
621 declare_one_free_variable (tree const &var0, tree *map0, wrapper_data &)
622 {
623 const_tree var = var0;
624 tree map = *map0;
625 tree var_type = TREE_TYPE (var), arg_type;
626 bool by_reference;
627 tree parm;
628
629 gcc_assert (DECL_P (var));
630
631 /* Ignore truly local variables. */
632 if (map == error_mark_node)
633 return true;
634 /* Ignore references to the parent function. */
635 if (map == var)
636 return true;
637
638 gcc_assert (TREE_CODE (map) == INTEGER_CST);
639
640 /* A value is passed by reference if:
641
642 1. It is addressable, so that a copy may not be made.
643 2. It is modified in the spawned statement.
644 In the future this function may want to arrange
645 a warning if the spawned statement is a loop body
646 because an output argument would indicate a race.
647 Note: Earlier passes must have marked the variable addressable.
648 3. It is expensive to copy. */
649 by_reference =
650 (TREE_ADDRESSABLE (var_type)
651 /* Arrays must be passed by reference. This is required for C
652 semantics -- arrays are not first class objects. Other
653 aggregate types can and should be passed by reference if
654 they are not passed to the spawned function. We aren't yet
655 distinguishing safe uses in argument calculation from unsafe
656 uses as outgoing function arguments, so we make a copy to
657 stabilize the value. */
658 || TREE_CODE (var_type) == ARRAY_TYPE
659 || (tree) map == integer_one_node);
660
661 if (by_reference)
662 var_type = build_qualified_type (build_pointer_type (var_type),
663 TYPE_QUAL_RESTRICT);
664 gcc_assert (!TREE_ADDRESSABLE (var_type));
665
666 /* Maybe promote to int. */
667 if (INTEGRAL_TYPE_P (var_type) && COMPLETE_TYPE_P (var_type)
668 && tree_int_cst_lt (TYPE_SIZE (var_type), TYPE_SIZE (integer_type_node)))
669 arg_type = integer_type_node;
670 else
671 arg_type = var_type;
672
673 parm = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL_TREE, var_type);
674 DECL_ARG_TYPE (parm) = arg_type;
675 DECL_ARTIFICIAL (parm) = 0;
676 TREE_READONLY (parm) = 1;
677
678 if (by_reference)
679 {
680 parm = build1 (INDIRECT_REF, TREE_TYPE (var_type), parm);
681 parm = build1 (PAREN_EXPR, void_type_node, parm);
682 }
683 *map0 = parm;
684 return true;
685 }
686
687 /* Returns a wrapper function for a _Cilk_spawn. */
688
689 static tree
690 create_cilk_wrapper (tree exp, tree *args_out)
691 {
692 struct wrapper_data wd;
693 tree fndecl;
694
695 init_wd (&wd, CILK_BLOCK_SPAWN);
696
697 if (TREE_CODE (exp) == CONVERT_EXPR)
698 exp = TREE_OPERAND (exp, 0);
699
700 /* Special handling for top level INIT_EXPR. Usually INIT_EXPR means the
701 variable is defined in the spawned expression and can be private to the
702 spawn helper. A top level INIT_EXPR defines a variable to be initialized
703 by spawn and the variable must remain in the outer function. */
704 if (TREE_CODE (exp) == INIT_EXPR)
705 {
706 extract_free_variables (TREE_OPERAND (exp, 0), &wd, ADD_WRITE);
707 extract_free_variables (TREE_OPERAND (exp, 1), &wd, ADD_READ);
708 /* TREE_TYPE should be void. Be defensive. */
709 if (TREE_TYPE (exp) != void_type_node)
710 extract_free_variables (TREE_TYPE (exp), &wd, ADD_READ);
711 }
712 else
713 extract_free_variables (exp, &wd, ADD_READ);
714 wd.decl_map->traverse<wrapper_data &, declare_one_free_variable> (wd);
715 wd.block = TREE_BLOCK (exp);
716 if (!wd.block)
717 wd.block = DECL_INITIAL (current_function_decl);
718
719 /* Now fvars maps the old variable to incoming variable. Update
720 the expression and arguments to refer to the new names. */
721 fndecl = create_cilk_wrapper_body (exp, &wd);
722 *args_out = wd.arglist;
723
724 free_wd (&wd);
725
726 return fndecl;
727 }
728
729 /* Transform *SPAWN_P, a spawned CALL_EXPR, to gimple. *SPAWN_P can be a
730 CALL_EXPR, INIT_EXPR or MODIFY_EXPR. Returns GS_OK if everything is fine,
731 and GS_UNHANDLED, otherwise. */
732
733 int
734 gimplify_cilk_spawn (tree *spawn_p)
735 {
736 tree expr = *spawn_p;
737 tree function, call1, call2, new_args;
738 tree ii_args = NULL_TREE;
739 int total_args = 0, ii = 0;
740 tree *arg_array;
741 tree setjmp_cond_expr = NULL_TREE;
742 tree setjmp_expr, spawn_expr, setjmp_value = NULL_TREE;
743
744 cfun->calls_cilk_spawn = 1;
745 cfun->is_cilk_function = 1;
746
747 /* Remove CLEANUP_POINT_EXPR and EXPR_STMT from *spawn_p. */
748 while (TREE_CODE (expr) == CLEANUP_POINT_EXPR
749 || TREE_CODE (expr) == EXPR_STMT)
750 expr = TREE_OPERAND (expr, 0);
751
752 new_args = NULL;
753 function = create_cilk_wrapper (expr, &new_args);
754
755 /* This should give the number of parameters. */
756 total_args = list_length (new_args);
757 if (total_args)
758 arg_array = XNEWVEC (tree, total_args);
759 else
760 arg_array = NULL;
761
762 ii_args = new_args;
763 for (ii = 0; ii < total_args; ii++)
764 {
765 arg_array[ii] = TREE_VALUE (ii_args);
766 ii_args = TREE_CHAIN (ii_args);
767 }
768
769 TREE_USED (function) = 1;
770 rest_of_decl_compilation (function, 0, 0);
771
772 call1 = cilk_call_setjmp (cfun->cilk_frame_decl);
773
774 if (arg_array == NULL || *arg_array == NULL_TREE)
775 call2 = build_call_expr (function, 0);
776 else
777 call2 = build_call_expr_loc_array (EXPR_LOCATION (*spawn_p), function,
778 total_args, arg_array);
779 *spawn_p = alloc_stmt_list ();
780 tree f_ptr_type = build_pointer_type (TREE_TYPE (cfun->cilk_frame_decl));
781 tree frame_ptr = build1 (ADDR_EXPR, f_ptr_type, cfun->cilk_frame_decl);
782 tree save_fp = build_call_expr (cilk_save_fp_fndecl, 1, frame_ptr);
783 append_to_statement_list (save_fp, spawn_p);
784 setjmp_value = create_tmp_var (TREE_TYPE (call1), NULL);
785 setjmp_expr = fold_build2 (MODIFY_EXPR, void_type_node, setjmp_value, call1);
786
787 append_to_statement_list_force (setjmp_expr, spawn_p);
788
789 setjmp_cond_expr = fold_build2 (EQ_EXPR, TREE_TYPE (call1), setjmp_value,
790 build_int_cst (TREE_TYPE (call1), 0));
791 spawn_expr = fold_build3 (COND_EXPR, void_type_node, setjmp_cond_expr,
792 call2, build_empty_stmt (EXPR_LOCATION (call1)));
793 append_to_statement_list (spawn_expr, spawn_p);
794
795 return GS_OK;
796 }
797
798 /* Make the frames necessary for a spawn call. */
799
800 tree
801 make_cilk_frame (tree fn)
802 {
803 struct function *f = DECL_STRUCT_FUNCTION (fn);
804 tree decl;
805
806 if (f->cilk_frame_decl)
807 return f->cilk_frame_decl;
808
809 decl = build_decl (EXPR_LOCATION (fn), VAR_DECL, NULL_TREE,
810 cilk_frame_type_decl);
811 DECL_CONTEXT (decl) = fn;
812 DECL_SEEN_IN_BIND_EXPR_P (decl) = 1;
813 f->cilk_frame_decl = decl;
814 return decl;
815 }
816
817 /* Returns a STATEMENT_LIST with all the pedigree operations required for
818 install body with frame cleanup functions. FRAME_PTR is the pointer to
819 __cilkrts_stack_frame created by make_cilk_frame. */
820
821 tree
822 cilk_install_body_pedigree_operations (tree frame_ptr)
823 {
824 tree body_list = alloc_stmt_list ();
825 tree enter_frame = build_call_expr (cilk_enter_fast_fndecl, 1, frame_ptr);
826 append_to_statement_list (enter_frame, &body_list);
827
828 tree parent = cilk_arrow (frame_ptr, CILK_TI_FRAME_PARENT, 0);
829 tree worker = cilk_arrow (frame_ptr, CILK_TI_FRAME_WORKER, 0);
830
831 tree pedigree = cilk_arrow (frame_ptr, CILK_TI_FRAME_PEDIGREE, 0);
832 tree pedigree_rank = cilk_dot (pedigree, CILK_TI_PEDIGREE_RANK, 0);
833 tree parent_pedigree = cilk_dot (pedigree, CILK_TI_PEDIGREE_PARENT, 0);
834 tree pedigree_parent = cilk_arrow (parent, CILK_TI_FRAME_PEDIGREE, 0);
835 tree pedigree_parent_rank = cilk_dot (pedigree_parent,
836 CILK_TI_PEDIGREE_RANK, 0);
837 tree pedigree_parent_parent = cilk_dot (pedigree_parent,
838 CILK_TI_PEDIGREE_PARENT, 0);
839 tree worker_pedigree = cilk_arrow (worker, CILK_TI_WORKER_PEDIGREE, 1);
840 tree w_pedigree_rank = cilk_dot (worker_pedigree, CILK_TI_PEDIGREE_RANK, 0);
841 tree w_pedigree_parent = cilk_dot (worker_pedigree,
842 CILK_TI_PEDIGREE_PARENT, 0);
843
844 /* sf.pedigree.rank = worker->pedigree.rank. */
845 tree exp1 = build2 (MODIFY_EXPR, void_type_node, pedigree_rank,
846 w_pedigree_rank);
847 append_to_statement_list (exp1, &body_list);
848
849 /* sf.pedigree.parent = worker->pedigree.parent. */
850 exp1 = build2 (MODIFY_EXPR, void_type_node, parent_pedigree,
851 w_pedigree_parent);
852 append_to_statement_list (exp1, &body_list);
853
854 /* sf.call_parent->pedigree.rank = worker->pedigree.rank. */
855 exp1 = build2 (MODIFY_EXPR, void_type_node, pedigree_parent_rank,
856 w_pedigree_rank);
857 append_to_statement_list (exp1, &body_list);
858
859 /* sf.call_parent->pedigree.parent = worker->pedigree.parent. */
860 exp1 = build2 (MODIFY_EXPR, void_type_node, pedigree_parent_parent,
861 w_pedigree_parent);
862 append_to_statement_list (exp1, &body_list);
863
864 /* sf->worker.pedigree.rank = 0. */
865 exp1 = build2 (MODIFY_EXPR, void_type_node, w_pedigree_rank,
866 build_zero_cst (uint64_type_node));
867 append_to_statement_list (exp1, &body_list);
868
869 /* sf->pedigree.parent = &sf->pedigree. */
870 exp1 = build2 (MODIFY_EXPR, void_type_node, w_pedigree_parent,
871 build1 (ADDR_EXPR,
872 build_pointer_type (cilk_pedigree_type_decl),
873 pedigree));
874 append_to_statement_list (exp1, &body_list);
875 return body_list;
876 }
877
878 /* Add a new variable, VAR to a variable list in WD->DECL_MAP. HOW indicates
879 whether the variable is previously defined, currently defined, or a variable
880 that is being written to. */
881
882 static void
883 add_variable (struct wrapper_data *wd, tree var, enum add_variable_type how)
884 {
885 tree *valp = wd->decl_map->get (var);
886 if (valp)
887 {
888 tree val = (tree) *valp;
889 /* If the variable is local, do nothing. */
890 if (val == error_mark_node)
891 return;
892 /* If the variable was entered with itself as value,
893 meaning it belongs to an outer scope, do not alter
894 the value. */
895 if (val == var)
896 return;
897 /* A statement expression may cause a variable to be
898 bound twice, once in BIND_EXPR and again in a
899 DECL_EXPR. That case caused a return in the
900 test above. Any other duplicate definition is
901 an error. */
902 gcc_assert (how != ADD_BIND);
903 if (how != ADD_WRITE)
904 return;
905 /* This variable might have been entered as read but is now written. */
906 *valp = var;
907 wd->nested = true;
908 return;
909 }
910 else
911 {
912 tree val = NULL_TREE;
913
914 /* Nested function rewriting silently discards hard register
915 assignments for function scope variables, and they wouldn't
916 work anyway. Warn here. This misses one case: if the
917 register variable is used as the loop bound or increment it
918 has already been added to the map. */
919 if ((how != ADD_BIND) && (TREE_CODE (var) == VAR_DECL)
920 && !DECL_EXTERNAL (var) && DECL_HARD_REGISTER (var))
921 warning (0, "register assignment ignored for %qD used in Cilk block",
922 var);
923
924 switch (how)
925 {
926 /* ADD_BIND means always make a fresh new variable. */
927 case ADD_BIND:
928 val = error_mark_node;
929 break;
930 /* ADD_READ means
931 1. For cilk_for, refer to the outer scope definition as-is
932 2. For a spawned block, take a scalar in an rgument
933 and otherwise refer to the outer scope definition as-is.
934 3. For a spawned call, take a scalar in an argument. */
935 case ADD_READ:
936 switch (wd->type)
937 {
938 case CILK_BLOCK_FOR:
939 val = var;
940 break;
941 case CILK_BLOCK_SPAWN:
942 if (TREE_ADDRESSABLE (var))
943 {
944 val = var;
945 wd->nested = true;
946 break;
947 }
948 val = integer_zero_node;
949 break;
950 }
951 break;
952 case ADD_WRITE:
953 switch (wd->type)
954 {
955 case CILK_BLOCK_FOR:
956 val = var;
957 wd->nested = true;
958 break;
959 case CILK_BLOCK_SPAWN:
960 if (TREE_ADDRESSABLE (var))
961 val = integer_one_node;
962 else
963 {
964 val = var;
965 wd->nested = true;
966 }
967 break;
968 }
969 }
970 wd->decl_map->put (var, val);
971 }
972 }
973
974 /* Find the variables referenced in an expression T. This does not avoid
975 duplicates because a variable may be read in one context and written in
976 another. HOW describes the context in which the reference is seen. If
977 NESTED is true a nested function is being generated and variables in the
978 original context should not be remapped. */
979
980 static void
981 extract_free_variables (tree t, struct wrapper_data *wd,
982 enum add_variable_type how)
983 {
984 if (t == NULL_TREE)
985 return;
986
987 enum tree_code code = TREE_CODE (t);
988 bool is_expr = IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code));
989
990 if (is_expr)
991 extract_free_variables (TREE_TYPE (t), wd, ADD_READ);
992
993 switch (code)
994 {
995 case ERROR_MARK:
996 case IDENTIFIER_NODE:
997 case VOID_CST:
998 case INTEGER_CST:
999 case REAL_CST:
1000 case FIXED_CST:
1001 case STRING_CST:
1002 case BLOCK:
1003 case PLACEHOLDER_EXPR:
1004 case FIELD_DECL:
1005 case VOID_TYPE:
1006 case REAL_TYPE:
1007 /* These do not contain variable references. */
1008 return;
1009
1010 case SSA_NAME:
1011 /* Currently we don't see SSA_NAME. */
1012 extract_free_variables (SSA_NAME_VAR (t), wd, how);
1013 return;
1014
1015 case LABEL_DECL:
1016 /* This might be a reference to a label outside the Cilk block,
1017 which is an error, or a reference to a label in the Cilk block
1018 that we haven't seen yet. We can't tell. Ignore it. An
1019 invalid use will cause an error later in copy_decl_for_cilk. */
1020 return;
1021
1022 case RESULT_DECL:
1023 if (wd->type != CILK_BLOCK_SPAWN)
1024 TREE_ADDRESSABLE (t) = 1;
1025 case VAR_DECL:
1026 case PARM_DECL:
1027 if (!TREE_STATIC (t) && !DECL_EXTERNAL (t))
1028 add_variable (wd, t, how);
1029 return;
1030
1031 case NON_LVALUE_EXPR:
1032 case CONVERT_EXPR:
1033 case NOP_EXPR:
1034 extract_free_variables (TREE_OPERAND (t, 0), wd, ADD_READ);
1035 return;
1036
1037 case VEC_INIT_EXPR:
1038 case INIT_EXPR:
1039 extract_free_variables (TREE_OPERAND (t, 0), wd, ADD_BIND);
1040 extract_free_variables (TREE_OPERAND (t, 1), wd, ADD_READ);
1041 return;
1042
1043 case MODIFY_EXPR:
1044 case PREDECREMENT_EXPR:
1045 case PREINCREMENT_EXPR:
1046 case POSTDECREMENT_EXPR:
1047 case POSTINCREMENT_EXPR:
1048 /* These write their result. */
1049 extract_free_variables (TREE_OPERAND (t, 0), wd, ADD_WRITE);
1050 extract_free_variables (TREE_OPERAND (t, 1), wd, ADD_READ);
1051 return;
1052
1053 case ADDR_EXPR:
1054 /* This might modify its argument, and the value needs to be
1055 passed by reference in any case to preserve identity and
1056 type if is a promoting type. In the case of a nested loop
1057 just notice that we touch the variable. It will already
1058 be addressable, and marking it modified will cause a spurious
1059 warning about writing the control variable. */
1060 if (wd->type != CILK_BLOCK_SPAWN)
1061 extract_free_variables (TREE_OPERAND (t, 0), wd, ADD_READ);
1062 else
1063 extract_free_variables (TREE_OPERAND (t, 0), wd, ADD_WRITE);
1064 return;
1065
1066 case ARRAY_REF:
1067 /* Treating ARRAY_REF and BIT_FIELD_REF identically may
1068 mark the array as written but the end result is correct
1069 because the array is passed by pointer anyway. */
1070 case BIT_FIELD_REF:
1071 /* Propagate the access type to the object part of which
1072 is being accessed here. As for ADDR_EXPR, don't do this
1073 in a nested loop, unless the access is to a fixed index. */
1074 if (wd->type != CILK_BLOCK_FOR || TREE_CONSTANT (TREE_OPERAND (t, 1)))
1075 extract_free_variables (TREE_OPERAND (t, 0), wd, how);
1076 else
1077 extract_free_variables (TREE_OPERAND (t, 0), wd, ADD_READ);
1078 extract_free_variables (TREE_OPERAND (t, 1), wd, ADD_READ);
1079 extract_free_variables (TREE_OPERAND (t, 2), wd, ADD_READ);
1080 return;
1081
1082 case TREE_LIST:
1083 extract_free_variables (TREE_PURPOSE (t), wd, ADD_READ);
1084 extract_free_variables (TREE_VALUE (t), wd, ADD_READ);
1085 extract_free_variables (TREE_CHAIN (t), wd, ADD_READ);
1086 return;
1087
1088 case TREE_VEC:
1089 {
1090 int len = TREE_VEC_LENGTH (t);
1091 int i;
1092 for (i = 0; i < len; i++)
1093 extract_free_variables (TREE_VEC_ELT (t, i), wd, ADD_READ);
1094 return;
1095 }
1096
1097 case VECTOR_CST:
1098 {
1099 unsigned ii = 0;
1100 for (ii = 0; ii < VECTOR_CST_NELTS (t); ii++)
1101 extract_free_variables (VECTOR_CST_ELT (t, ii), wd, ADD_READ);
1102 break;
1103 }
1104
1105 case COMPLEX_CST:
1106 extract_free_variables (TREE_REALPART (t), wd, ADD_READ);
1107 extract_free_variables (TREE_IMAGPART (t), wd, ADD_READ);
1108 return;
1109
1110 case BIND_EXPR:
1111 {
1112 tree decl;
1113 for (decl = BIND_EXPR_VARS (t); decl; decl = TREE_CHAIN (decl))
1114 {
1115 add_variable (wd, decl, ADD_BIND);
1116 /* A self-referential initialization is no problem because
1117 we already entered the variable into the map as local. */
1118 extract_free_variables (DECL_INITIAL (decl), wd, ADD_READ);
1119 extract_free_variables (DECL_SIZE (decl), wd, ADD_READ);
1120 extract_free_variables (DECL_SIZE_UNIT (decl), wd, ADD_READ);
1121 }
1122 extract_free_variables (BIND_EXPR_BODY (t), wd, ADD_READ);
1123 return;
1124 }
1125
1126 case STATEMENT_LIST:
1127 {
1128 tree_stmt_iterator i;
1129 for (i = tsi_start (t); !tsi_end_p (i); tsi_next (&i))
1130 extract_free_variables (*tsi_stmt_ptr (i), wd, ADD_READ);
1131 return;
1132 }
1133
1134 case TARGET_EXPR:
1135 {
1136 extract_free_variables (TREE_OPERAND (t, 0), wd, ADD_BIND);
1137 extract_free_variables (TREE_OPERAND (t, 1), wd, ADD_READ);
1138 extract_free_variables (TREE_OPERAND (t, 2), wd, ADD_READ);
1139 if (TREE_OPERAND (t, 3) != TREE_OPERAND (t, 1))
1140 extract_free_variables (TREE_OPERAND (t, 3), wd, ADD_READ);
1141 return;
1142 }
1143
1144 case RETURN_EXPR:
1145 if (TREE_NO_WARNING (t))
1146 {
1147 gcc_assert (errorcount);
1148 return;
1149 }
1150 return;
1151
1152 case DECL_EXPR:
1153 if (TREE_CODE (DECL_EXPR_DECL (t)) != TYPE_DECL)
1154 extract_free_variables (DECL_EXPR_DECL (t), wd, ADD_BIND);
1155 return;
1156
1157 case INTEGER_TYPE:
1158 case ENUMERAL_TYPE:
1159 case BOOLEAN_TYPE:
1160 extract_free_variables (TYPE_MIN_VALUE (t), wd, ADD_READ);
1161 extract_free_variables (TYPE_MAX_VALUE (t), wd, ADD_READ);
1162 return;
1163
1164 case POINTER_TYPE:
1165 extract_free_variables (TREE_TYPE (t), wd, ADD_READ);
1166 break;
1167
1168 case ARRAY_TYPE:
1169 extract_free_variables (TREE_TYPE (t), wd, ADD_READ);
1170 extract_free_variables (TYPE_DOMAIN (t), wd, ADD_READ);
1171 return;
1172
1173 case RECORD_TYPE:
1174 extract_free_variables (TYPE_FIELDS (t), wd, ADD_READ);
1175 return;
1176
1177 case METHOD_TYPE:
1178 extract_free_variables (TYPE_ARG_TYPES (t), wd, ADD_READ);
1179 extract_free_variables (TYPE_METHOD_BASETYPE (t), wd, ADD_READ);
1180 return;
1181
1182 case AGGR_INIT_EXPR:
1183 case CALL_EXPR:
1184 {
1185 int len = 0;
1186 int ii = 0;
1187 if (TREE_CODE (TREE_OPERAND (t, 0)) == INTEGER_CST)
1188 {
1189 len = TREE_INT_CST_LOW (TREE_OPERAND (t, 0));
1190
1191 for (ii = 0; ii < len; ii++)
1192 extract_free_variables (TREE_OPERAND (t, ii), wd, ADD_READ);
1193 extract_free_variables (TREE_TYPE (t), wd, ADD_READ);
1194 }
1195 break;
1196 }
1197
1198 case CONSTRUCTOR:
1199 {
1200 unsigned HOST_WIDE_INT idx = 0;
1201 constructor_elt *ce;
1202 for (idx = 0; vec_safe_iterate (CONSTRUCTOR_ELTS (t), idx, &ce); idx++)
1203 extract_free_variables (ce->value, wd, ADD_READ);
1204 break;
1205 }
1206
1207 default:
1208 if (is_expr)
1209 {
1210 int i, len;
1211
1212 /* Walk over all the sub-trees of this operand. */
1213 len = TREE_CODE_LENGTH (code);
1214
1215 /* Go through the subtrees. We need to do this in forward order so
1216 that the scope of a FOR_EXPR is handled properly. */
1217 for (i = 0; i < len; ++i)
1218 extract_free_variables (TREE_OPERAND (t, i), wd, ADD_READ);
1219 }
1220 }
1221 }
1222
1223 /* Add appropriate frames needed for a Cilk spawned function call, FNDECL.
1224 Returns the __cilkrts_stack_frame * variable. */
1225
1226 tree
1227 insert_cilk_frame (tree fndecl)
1228 {
1229 tree addr, body, enter, out, orig_body;
1230 location_t loc = EXPR_LOCATION (fndecl);
1231
1232 if (!cfun || cfun->decl != fndecl)
1233 push_cfun (DECL_STRUCT_FUNCTION (fndecl));
1234
1235 tree decl = cfun->cilk_frame_decl;
1236 if (!decl)
1237 {
1238 tree *saved_tree = &DECL_SAVED_TREE (fndecl);
1239 decl = make_cilk_frame (fndecl);
1240 add_local_decl (cfun, decl);
1241
1242 addr = build1 (ADDR_EXPR, cilk_frame_ptr_type_decl, decl);
1243 enter = build_call_expr (cilk_enter_fndecl, 1, addr);
1244 out = create_cilk_function_exit (cfun->cilk_frame_decl, false, true);
1245
1246 /* The new body will be:
1247 __cilkrts_enter_frame_1 (&sf);
1248 try {
1249 orig_body;
1250 }
1251 finally {
1252 __cilkrts_pop_frame (&sf);
1253 __cilkrts_leave_frame (&sf);
1254 } */
1255
1256 body = alloc_stmt_list ();
1257 orig_body = *saved_tree;
1258
1259 if (TREE_CODE (orig_body) == BIND_EXPR)
1260 orig_body = BIND_EXPR_BODY (orig_body);
1261
1262 append_to_statement_list (enter, &body);
1263 append_to_statement_list (build_stmt (loc, TRY_FINALLY_EXPR, orig_body,
1264 out), &body);
1265 if (TREE_CODE (*saved_tree) == BIND_EXPR)
1266 BIND_EXPR_BODY (*saved_tree) = body;
1267 else
1268 *saved_tree = body;
1269 }
1270 return decl;
1271 }
1272
1273 /* Wraps CALL, a CALL_EXPR, into a CILK_SPAWN_STMT tree and returns it. */
1274
1275 tree
1276 build_cilk_spawn (location_t loc, tree call)
1277 {
1278 if (!cilk_set_spawn_marker (loc, call))
1279 return error_mark_node;
1280 tree spawn_stmt = build1 (CILK_SPAWN_STMT, TREE_TYPE (call), call);
1281 TREE_SIDE_EFFECTS (spawn_stmt) = 1;
1282 return spawn_stmt;
1283 }
1284
1285 /* Returns a tree of type CILK_SYNC_STMT. */
1286
1287 tree
1288 build_cilk_sync (void)
1289 {
1290 tree sync = build0 (CILK_SYNC_STMT, void_type_node);
1291 TREE_SIDE_EFFECTS (sync) = 1;
1292 return sync;
1293 }
1294
1295 /* Helper for contains_cilk_spawn_stmt, callback for walk_tree. Return
1296 non-null tree if TP contains CILK_SPAWN_STMT. */
1297
1298 static tree
1299 contains_cilk_spawn_stmt_walker (tree *tp, int *, void *)
1300 {
1301 if (TREE_CODE (*tp) == CILK_SPAWN_STMT)
1302 return *tp;
1303 else
1304 return NULL_TREE;
1305 }
1306
1307 /* Returns true if EXPR or any of its subtrees contain CILK_SPAWN_STMT
1308 node. */
1309
1310 bool
1311 contains_cilk_spawn_stmt (tree expr)
1312 {
1313 return walk_tree (&expr, contains_cilk_spawn_stmt_walker, NULL, NULL)
1314 != NULL_TREE;
1315 }