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