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