2017-03-17 Richard Biener <rguenther@suse.de>
[official-gcc.git] / gcc / c-family / cilk.c
blob43478fff9144178900cd8da575b0cb75d17d3009
1 /* This file is part of the Intel(R) Cilk(TM) Plus support
2 This file contains the CilkPlus Intrinsics
3 Copyright (C) 2013-2017 Free Software Foundation, Inc.
4 Contributed by Balaji V. Iyer <balaji.v.iyer@intel.com>,
5 Intel Corporation
7 This file is part of GCC.
9 GCC is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3, or (at your option)
12 any later version.
14 GCC is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3. If not see
21 <http://www.gnu.org/licenses/>. */
23 #include "config.h"
24 #include "system.h"
25 #include "coretypes.h"
26 #include "tm.h"
27 #include "function.h"
28 #include "c-family/c-common.h"
29 #include "gimple-expr.h"
30 #include "stringpool.h"
31 #include "cgraph.h"
32 #include "diagnostic.h"
33 #include "gimplify.h"
34 #include "tree-iterator.h"
35 #include "tree-inline.h"
36 #include "toplev.h"
37 #include "calls.h"
38 #include "cilk.h"
40 enum add_variable_type {
41 /* Reference to previously-defined variable. */
42 ADD_READ,
43 /* Definition of a new variable in inner-scope. */
44 ADD_BIND,
45 /* Write to possibly previously-defined variable. */
46 ADD_WRITE
49 enum cilk_block_type {
50 /* Indicates a _Cilk_spawn block. 30 was an arbitary number picked for
51 ease of debugging. */
52 CILK_BLOCK_SPAWN = 30,
53 /* Indicates _Cilk_for statement block. */
54 CILK_BLOCK_FOR
57 struct wrapper_data
59 /* Kind of function to be created. */
60 enum cilk_block_type type;
61 /* Signature of helper function. */
62 tree fntype;
63 /* Containing function. */
64 tree context;
65 /* Disposition of all variables in the inner statement. */
66 hash_map<tree, tree> *decl_map;
67 /* True if this function needs a static chain. */
68 bool nested;
69 /* Arguments to be passed to wrapper function, currently a list. */
70 tree arglist;
71 /* Argument types, a list. */
72 tree argtypes;
73 /* Incoming parameters. */
74 tree parms;
75 /* Outer BLOCK object. */
76 tree block;
79 static tree contains_cilk_spawn_stmt_walker (tree *tp, int *, void *);
80 static void extract_free_variables (tree, struct wrapper_data *,
81 enum add_variable_type);
82 static HOST_WIDE_INT cilk_wrapper_count;
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. */
88 inline bool
89 cilk_set_spawn_marker (location_t loc, tree fcall)
91 if (!current_function_decl)
93 error_at (loc, "%<_Cilk_spawn%> may only be used inside a function");
94 return false;
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)
106 error_at (loc, "only function calls can be spawned");
107 return false;
109 else
111 cfun->calls_cilk_spawn = true;
112 return true;
116 /* This function will output the exit conditions for a spawn call. */
118 tree
119 create_cilk_function_exit (tree frame, bool detaches, bool needs_sync)
121 tree epi = alloc_stmt_list ();
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)
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)));
143 append_to_statement_list (call, &epi);
144 return epi;
147 /* Trying to get the correct cfun for the FUNCTION_DECL indicated by OUTER. */
149 static void
150 pop_cfun_to (tree outer)
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);
158 /* This function does whatever is necessary to make the compiler emit a newly
159 generated function, FNDECL. */
161 static void
162 call_graph_add_fn (tree fndecl)
164 const tree outer = current_function_decl;
165 struct function *f = DECL_STRUCT_FUNCTION (fndecl);
166 gcc_assert (TREE_CODE (fndecl) == FUNCTION_DECL);
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);
173 push_cfun (f);
174 cgraph_node::create (fndecl);
175 pop_cfun_to (outer);
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. */
188 bool
189 cilk_ignorable_spawn_rhs_op (tree exp)
191 enum tree_code code = TREE_CODE (exp);
192 switch (TREE_CODE_CLASS (code))
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;
209 /* Helper function for walk_tree. If *TP is a CILK_SPAWN_STMT, then unwrap
210 this "wrapper." The function returns NULL_TREE regardless. */
212 static tree
213 unwrap_cilk_spawn_stmt (tree *tp, int *walk_subtrees, void *)
215 if (TREE_CODE (*tp) == CILK_SPAWN_STMT)
217 *tp = CILK_SPAWN_FN (*tp);
218 *walk_subtrees = 0;
220 return NULL_TREE;
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. */
226 bool
227 cilk_recognize_spawn (tree exp, tree *exp0)
229 bool spawn_found = false;
230 if (TREE_CODE (exp) == CILK_SPAWN_STMT)
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;
237 /* _Cilk_spawn can't be wrapped in expression such as PLUS_EXPR. */
238 else if (contains_cilk_spawn_stmt (exp))
240 location_t loc = EXPR_LOCATION (exp);
241 if (loc == UNKNOWN_LOCATION)
243 tree stmt = walk_tree (&exp,
244 contains_cilk_spawn_stmt_walker,
245 NULL,
246 NULL);
247 gcc_assert (stmt != NULL_TREE);
248 loc = EXPR_LOCATION (stmt);
250 error_at (loc, "invalid use of %<_Cilk_spawn%>");
252 return spawn_found;
255 /* Returns true if *EXP0 is a recognized form of spawn. Recognized forms are,
256 after conversion to void, a call expression at outer level or an assignment
257 at outer level with the right hand side being a spawned call.
258 In addition to this, it also unwraps the CILK_SPAWN_STMT cover from the
259 CALL_EXPR that is being spawned.
260 Note that `=' in C++ may turn into a CALL_EXPR rather than a MODIFY_EXPR. */
262 bool
263 cilk_detect_spawn_and_unwrap (tree *exp0)
265 tree exp = *exp0;
267 if (!TREE_SIDE_EFFECTS (exp))
268 return false;
270 /* Strip off any conversion to void. It does not affect whether spawn
271 is supported here. */
272 if (TREE_CODE (exp) == CONVERT_EXPR && VOID_TYPE_P (TREE_TYPE (exp)))
273 exp = TREE_OPERAND (exp, 0);
275 if (TREE_CODE (exp) == MODIFY_EXPR || TREE_CODE (exp) == INIT_EXPR)
276 exp = TREE_OPERAND (exp, 1);
278 while (cilk_ignorable_spawn_rhs_op (exp))
279 exp = TREE_OPERAND (exp, 0);
281 if (TREE_CODE (exp) == TARGET_EXPR)
282 if (TARGET_EXPR_INITIAL (exp)
283 && TREE_CODE (TARGET_EXPR_INITIAL (exp)) != AGGR_INIT_EXPR)
284 exp = TARGET_EXPR_INITIAL (exp);
286 /* Happens with C++ TARGET_EXPR. */
287 if (exp == NULL_TREE)
288 return false;
290 while (TREE_CODE (exp) == CLEANUP_POINT_EXPR || TREE_CODE (exp) == EXPR_STMT)
291 exp = TREE_OPERAND (exp, 0);
293 /* Now we should have a CALL_EXPR with a CILK_SPAWN_STMT wrapper around
294 it, or return false. */
295 if (cilk_recognize_spawn (exp, exp0))
296 return true;
297 return false;
300 /* This function will build and return a FUNCTION_DECL using information
301 from *WD. */
303 static tree
304 create_cilk_helper_decl (struct wrapper_data *wd)
306 char name[20];
307 if (wd->type == CILK_BLOCK_FOR)
308 sprintf (name, "_cilk_for_" HOST_WIDE_INT_PRINT_DEC, cilk_wrapper_count++);
309 else if (wd->type == CILK_BLOCK_SPAWN)
310 sprintf (name, "_cilk_spn_" HOST_WIDE_INT_PRINT_DEC, cilk_wrapper_count++);
311 else
312 gcc_unreachable ();
314 clean_symbol_name (name);
316 tree fndecl = build_decl (DECL_SOURCE_LOCATION (current_function_decl),
317 FUNCTION_DECL, get_identifier (name), wd->fntype);
319 TREE_PUBLIC (fndecl) = 0;
320 TREE_STATIC (fndecl) = 1;
321 TREE_USED (fndecl) = 1;
322 DECL_ARTIFICIAL (fndecl) = 0;
323 DECL_IGNORED_P (fndecl) = 0;
324 DECL_EXTERNAL (fndecl) = 0;
326 DECL_CONTEXT (fndecl) = wd->context;
327 tree block = make_node (BLOCK);
328 DECL_INITIAL (fndecl) = block;
329 TREE_USED (block) = 1;
330 BLOCK_SUPERCONTEXT (block) = fndecl;
331 gcc_assert (!DECL_SAVED_TREE (fndecl));
333 /* Inlining would defeat the purpose of this wrapper.
334 Either it secretly switches stack frames or it allocates
335 a stable stack frame to hold function arguments even if
336 the parent stack frame is stolen. */
337 DECL_UNINLINABLE (fndecl) = 1;
339 tree result_decl = build_decl (UNKNOWN_LOCATION, RESULT_DECL, NULL_TREE,
340 void_type_node);
341 DECL_ARTIFICIAL (result_decl) = 0;
342 DECL_IGNORED_P (result_decl) = 1;
343 DECL_CONTEXT (result_decl) = fndecl;
344 DECL_RESULT (fndecl) = result_decl;
346 return fndecl;
349 struct cilk_decls
351 tree key;
352 tree *val;
355 /* A function used by traversal to fill vector of decls for further work. */
357 bool
358 fill_decls_vec (tree const &key0, tree *val0, auto_vec<struct cilk_decls> *v)
360 tree t1 = key0;
361 struct cilk_decls dp;
363 if (DECL_P (t1))
365 dp.key = t1;
366 dp.val = val0;
367 v->safe_push (dp);
369 return true;
372 /* Function that actually creates necessary parm lists. */
374 static void
375 create_parm_list (struct wrapper_data *wd, tree *val0, tree arg)
377 tree val = *val0;
378 tree parm;
380 if (val == error_mark_node || val == arg)
381 return;
383 if (TREE_CODE (val) == PAREN_EXPR)
385 /* We should not reach here with a register receiver.
386 We may see a register variable modified in the
387 argument list. Because register variables are
388 worker-local we don't need to work hard to support
389 them in code that spawns. */
390 if (VAR_P (arg) && DECL_HARD_REGISTER (arg))
392 error_at (EXPR_LOCATION (arg),
393 "explicit register variable %qD may not be modified in "
394 "spawn", arg);
395 arg = null_pointer_node;
397 else
398 arg = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (arg)), arg);
400 val = TREE_OPERAND (val, 0);
401 *val0 = val;
402 gcc_assert (INDIRECT_REF_P (val));
403 parm = TREE_OPERAND (val, 0);
404 STRIP_NOPS (parm);
406 else
407 parm = val;
408 TREE_CHAIN (parm) = wd->parms;
409 wd->parms = parm;
410 wd->argtypes = tree_cons (NULL_TREE, TREE_TYPE (parm), wd->argtypes);
411 wd->arglist = tree_cons (NULL_TREE, arg, wd->arglist);
414 /* Sorting decls in a vector. */
416 static int
417 compare_decls (const void *a, const void *b)
419 const struct cilk_decls *t1 = (const struct cilk_decls *) a;
420 const struct cilk_decls *t2 = (const struct cilk_decls *) b;
422 if (DECL_UID (t1->key) > DECL_UID (t2->key))
423 return 1;
424 else if (DECL_UID (t1->key) < DECL_UID (t2->key))
425 return -1;
426 else
427 return 0;
430 /* This function is used to build a wrapper of a certain type. */
432 static void
433 build_wrapper_type (struct wrapper_data *wd)
435 unsigned int j;
436 struct cilk_decls * c;
437 auto_vec<struct cilk_decls> vd;
438 wd->arglist = NULL_TREE;
439 wd->parms = NULL_TREE;
440 wd->argtypes = void_list_node;
442 gcc_assert (wd->type != CILK_BLOCK_FOR);
443 wd->decl_map->traverse<auto_vec<struct cilk_decls> *, fill_decls_vec> (&vd);
444 vd.qsort (compare_decls);
446 FOR_EACH_VEC_ELT (vd, j, c)
447 create_parm_list (wd, c->val, c->key);
449 /* Now build a function.
450 Its return type is void (all side effects are via explicit parameters).
451 Its parameters are WRAPPER_PARMS with type WRAPPER_TYPES.
452 Actual arguments in the caller are WRAPPER_ARGS. */
453 wd->fntype = build_function_type (void_type_node, wd->argtypes);
456 /* This function checks all the CALL_EXPRs in *TP found by cilk_outline. */
458 static tree
459 check_outlined_calls (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
460 void *data)
462 bool *throws = (bool *) data;
463 tree t = *tp;
464 int flags;
466 if (TREE_CODE (t) != CALL_EXPR)
467 return 0;
468 flags = call_expr_flags (t);
470 if (!(flags & ECF_NOTHROW) && flag_exceptions)
471 *throws = true;
472 if (flags & ECF_RETURNS_TWICE)
473 error_at (EXPR_LOCATION (t),
474 "cannot spawn call to function that returns twice");
475 return 0;
478 /* Each DECL in the source code (spawned statement) is passed to this function
479 once. Each instance of the DECL is replaced with the result of this
480 function.
482 The parameters of the wrapper should have been entered into the map already.
483 This function only deals with variables with scope limited to the
484 spawned expression. */
486 static tree
487 copy_decl_for_cilk (tree decl, copy_body_data *id)
489 switch (TREE_CODE (decl))
491 case VAR_DECL:
492 return copy_decl_no_change (decl, id);
494 case LABEL_DECL:
495 error_at (EXPR_LOCATION (decl), "invalid use of label %q+D in "
496 "%<_Cilk_spawn%>",
497 decl);
498 return error_mark_node;
500 case RESULT_DECL:
501 case PARM_DECL:
502 /* RESULT_DECL and PARM_DECL has already been entered into the map. */
503 default:
504 gcc_unreachable ();
505 return error_mark_node;
509 /* Alter a tree STMT from OUTER_FN to form the body of INNER_FN. */
511 void
512 cilk_outline (tree inner_fn, tree *stmt_p, void *w)
514 struct wrapper_data *wd = (struct wrapper_data *) w;
515 const tree outer_fn = wd->context;
516 const bool nested = (wd->type == CILK_BLOCK_FOR);
517 copy_body_data id;
518 bool throws;
519 auto_vec<struct cilk_decls> vd;
520 unsigned int j;
521 struct cilk_decls * c;
523 DECL_STATIC_CHAIN (outer_fn) = 1;
525 memset (&id, 0, sizeof (id));
526 /* Copy from the function containing the spawn... */
527 id.src_fn = outer_fn;
529 /* ...to the wrapper. */
530 id.dst_fn = inner_fn;
531 id.src_cfun = DECL_STRUCT_FUNCTION (outer_fn);
533 /* There shall be no RETURN in spawn helper. */
534 id.retvar = 0;
535 id.decl_map = wd->decl_map;
536 id.copy_decl = nested ? copy_decl_no_change : copy_decl_for_cilk;
537 id.block = DECL_INITIAL (inner_fn);
538 id.transform_lang_insert_block = NULL;
540 id.transform_new_cfg = true;
541 id.transform_call_graph_edges = CB_CGE_MOVE;
542 id.remap_var_for_cilk = true;
543 id.regimplify = true; /* unused? */
545 insert_decl_map (&id, wd->block, DECL_INITIAL (inner_fn));
547 wd->decl_map->traverse<auto_vec<struct cilk_decls> *, fill_decls_vec> (&vd);
548 vd.qsort (compare_decls);
549 /* We don't want the private variables any more. */
550 FOR_EACH_VEC_ELT (vd, j, c)
551 if (*(c->val) == error_mark_node)
552 *(c->val) = nested ? copy_decl_no_change (c->key, &id)
553 : copy_decl_for_cilk (c->key, &id);
555 walk_tree (stmt_p, copy_tree_body_r, (void *) &id, NULL);
557 /* See if this function can throw or calls something that should
558 not be spawned. The exception part is only necessary if
559 flag_exceptions && !flag_non_call_exceptions. */
560 throws = false ;
561 (void) walk_tree_without_duplicates (stmt_p, check_outlined_calls, &throws);
564 /* Generate the body of a wrapper function that assigns the
565 result of the expression RHS into RECEIVER. RECEIVER must
566 be NULL if this is not a spawn -- the wrapper will return
567 a value. If this is a spawn, the wrapper will return void. */
569 static tree
570 create_cilk_wrapper_body (tree stmt, struct wrapper_data *wd)
572 const tree outer = current_function_decl;
573 tree fndecl;
574 tree p;
576 /* Build the type of the wrapper and its argument list from the
577 variables that it requires. */
578 build_wrapper_type (wd);
580 /* Emit a function that takes WRAPPER_PARMS incoming and applies ARGS
581 (modified) to the wrapped function. Return the wrapper and modified ARGS
582 to the caller to generate a function call. */
583 fndecl = create_cilk_helper_decl (wd);
584 push_struct_function (fndecl);
585 if (wd->nested && (wd->type == CILK_BLOCK_FOR))
587 gcc_assert (TREE_VALUE (wd->arglist) == NULL_TREE);
588 TREE_VALUE (wd->arglist) = build2 (FDESC_EXPR, ptr_type_node,
589 fndecl, integer_one_node);
591 DECL_ARGUMENTS (fndecl) = wd->parms;
593 for (p = wd->parms; p; p = TREE_CHAIN (p))
594 DECL_CONTEXT (p) = fndecl;
596 /* The statement containing the spawn expression might create temporaries with
597 destructors defined; if so we need to add a CLEANUP_POINT_EXPR to ensure
598 the expression is properly gimplified. */
599 stmt = fold_build_cleanup_point_expr (void_type_node, stmt);
601 gcc_assert (!DECL_SAVED_TREE (fndecl));
602 cilk_install_body_with_frame_cleanup (fndecl, stmt, (void *) wd);
603 gcc_assert (DECL_SAVED_TREE (fndecl));
605 pop_cfun_to (outer);
607 /* Recognize the new function. */
608 call_graph_add_fn (fndecl);
609 return fndecl;
612 /* Initializes the wrapper data structure. */
614 static void
615 init_wd (struct wrapper_data *wd, enum cilk_block_type type)
617 wd->type = type;
618 wd->fntype = NULL_TREE;
619 wd->context = current_function_decl;
620 wd->decl_map = new hash_map<tree, tree>;
621 /* _Cilk_for bodies are always nested. Others start off as
622 normal functions. */
623 wd->nested = (type == CILK_BLOCK_FOR);
624 wd->arglist = NULL_TREE;
625 wd->argtypes = NULL_TREE;
626 wd->block = NULL_TREE;
629 /* Clears the wrapper data structure. */
631 static void
632 free_wd (struct wrapper_data *wd)
634 delete wd->decl_map;
635 wd->nested = false;
636 wd->arglist = NULL_TREE;
637 wd->argtypes = NULL_TREE;
638 wd->parms = NULL_TREE;
642 /* Given a variable in an expression to be extracted into
643 a helper function, declare the helper function parameter
644 to receive it.
646 On entry the value of the (key, value) pair may be
648 (*, error_mark_node) -- Variable is private to helper function,
649 do nothing.
651 (var, var) -- Reference to outer scope (function or global scope).
653 (var, integer 0) -- Capture by value, save newly-declared PARM_DECL
654 for value in value slot.
656 (var, integer 1) -- Capture by reference, declare pointer to type
657 as new PARM_DECL and store (spawn_stmt (indirect_ref (parm)).
659 (var, ???) -- Pure output argument, handled similarly to above.
662 bool
663 declare_one_free_variable (tree var0, tree *map0)
665 const_tree var = var0;
666 tree map = *map0;
667 tree var_type = TREE_TYPE (var), arg_type;
668 bool by_reference;
669 tree parm;
671 gcc_assert (DECL_P (var));
673 /* Ignore truly local variables. */
674 if (map == error_mark_node)
675 return true;
676 /* Ignore references to the parent function. */
677 if (map == var)
678 return true;
680 gcc_assert (TREE_CODE (map) == INTEGER_CST);
682 /* A value is passed by reference if:
684 1. It is addressable, so that a copy may not be made.
685 2. It is modified in the spawned statement.
686 In the future this function may want to arrange
687 a warning if the spawned statement is a loop body
688 because an output argument would indicate a race.
689 Note: Earlier passes must have marked the variable addressable.
690 3. It is expensive to copy. */
691 by_reference =
692 (TREE_ADDRESSABLE (var_type)
693 /* Arrays must be passed by reference. This is required for C
694 semantics -- arrays are not first class objects. Other
695 aggregate types can and should be passed by reference if
696 they are not passed to the spawned function. We aren't yet
697 distinguishing safe uses in argument calculation from unsafe
698 uses as outgoing function arguments, so we make a copy to
699 stabilize the value. */
700 || TREE_CODE (var_type) == ARRAY_TYPE
701 || (tree) map == integer_one_node);
703 if (by_reference)
704 var_type = build_qualified_type (build_pointer_type (var_type),
705 TYPE_QUAL_RESTRICT);
706 gcc_assert (!TREE_ADDRESSABLE (var_type));
708 /* Maybe promote to int. */
709 if (INTEGRAL_TYPE_P (var_type) && COMPLETE_TYPE_P (var_type)
710 && tree_int_cst_lt (TYPE_SIZE (var_type), TYPE_SIZE (integer_type_node)))
711 arg_type = integer_type_node;
712 else
713 arg_type = var_type;
715 parm = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL_TREE, var_type);
716 DECL_ARG_TYPE (parm) = arg_type;
717 DECL_ARTIFICIAL (parm) = 0;
718 TREE_READONLY (parm) = 1;
720 if (by_reference)
722 parm = build1 (INDIRECT_REF, TREE_TYPE (var_type), parm);
723 parm = build1 (PAREN_EXPR, void_type_node, parm);
725 *map0 = parm;
726 return true;
729 /* Returns a wrapper function for a _Cilk_spawn. */
731 static tree
732 create_cilk_wrapper (tree exp, tree *args_out)
734 struct wrapper_data wd;
735 tree fndecl;
736 unsigned int j;
737 struct cilk_decls * c;
738 auto_vec<struct cilk_decls> vd;
740 init_wd (&wd, CILK_BLOCK_SPAWN);
742 if (TREE_CODE (exp) == CONVERT_EXPR)
743 exp = TREE_OPERAND (exp, 0);
745 /* Special handling for top level INIT_EXPR. Usually INIT_EXPR means the
746 variable is defined in the spawned expression and can be private to the
747 spawn helper. A top level INIT_EXPR defines a variable to be initialized
748 by spawn and the variable must remain in the outer function. */
749 if (TREE_CODE (exp) == INIT_EXPR)
751 extract_free_variables (TREE_OPERAND (exp, 0), &wd, ADD_WRITE);
752 extract_free_variables (TREE_OPERAND (exp, 1), &wd, ADD_READ);
753 /* TREE_TYPE should be void. Be defensive. */
754 if (TREE_TYPE (exp) != void_type_node)
755 extract_free_variables (TREE_TYPE (exp), &wd, ADD_READ);
757 else
758 extract_free_variables (exp, &wd, ADD_READ);
759 wd.decl_map->traverse<auto_vec<struct cilk_decls> *, fill_decls_vec> (&vd);
760 vd.qsort (compare_decls);
761 FOR_EACH_VEC_ELT (vd, j, c)
762 declare_one_free_variable (c->key, c->val);
764 wd.block = TREE_BLOCK (exp);
765 if (!wd.block)
766 wd.block = DECL_INITIAL (current_function_decl);
768 /* Now fvars maps the old variable to incoming variable. Update
769 the expression and arguments to refer to the new names. */
770 fndecl = create_cilk_wrapper_body (exp, &wd);
771 *args_out = wd.arglist;
773 free_wd (&wd);
775 return fndecl;
778 /* Gimplify all the parameters for the Spawned function. *EXPR_P can be a
779 CALL_EXPR, INIT_EXPR, MODIFY_EXPR or TARGET_EXPR. *PRE_P and *POST_P are
780 gimple sequences from the caller of gimplify_cilk_spawn. */
782 void
783 cilk_gimplify_call_params_in_spawned_fn (tree *expr_p, gimple_seq *pre_p)
785 int ii = 0;
786 tree *fix_parm_expr = expr_p;
788 /* Remove CLEANUP_POINT_EXPR and EXPR_STMT from *spawn_p. */
789 while (TREE_CODE (*fix_parm_expr) == CLEANUP_POINT_EXPR
790 || TREE_CODE (*fix_parm_expr) == EXPR_STMT)
791 *fix_parm_expr = TREE_OPERAND (*fix_parm_expr, 0);
793 if ((TREE_CODE (*expr_p) == INIT_EXPR)
794 || (TREE_CODE (*expr_p) == TARGET_EXPR)
795 || (TREE_CODE (*expr_p) == MODIFY_EXPR))
796 fix_parm_expr = &TREE_OPERAND (*expr_p, 1);
798 if (TREE_CODE (*fix_parm_expr) == CALL_EXPR)
800 /* Cilk outlining assumes GENERIC bodies, avoid leaking SSA names
801 via parameters. */
802 for (ii = 0; ii < call_expr_nargs (*fix_parm_expr); ii++)
803 gimplify_arg (&CALL_EXPR_ARG (*fix_parm_expr, ii), pre_p,
804 EXPR_LOCATION (*fix_parm_expr), false);
809 /* Transform *SPAWN_P, a spawned CALL_EXPR, to gimple. *SPAWN_P can be a
810 CALL_EXPR, INIT_EXPR or MODIFY_EXPR. Returns GS_OK if everything is fine,
811 and GS_UNHANDLED, otherwise. */
814 gimplify_cilk_spawn (tree *spawn_p)
816 tree expr = *spawn_p;
817 tree function, call1, call2, new_args;
818 tree ii_args = NULL_TREE;
819 int total_args = 0, ii = 0;
820 tree *arg_array;
821 tree setjmp_cond_expr = NULL_TREE;
822 tree setjmp_expr, spawn_expr, setjmp_value = NULL_TREE;
824 cfun->calls_cilk_spawn = 1;
825 cfun->is_cilk_function = 1;
826 new_args = NULL;
827 function = create_cilk_wrapper (expr, &new_args);
829 /* This should give the number of parameters. */
830 total_args = list_length (new_args);
831 if (total_args)
832 arg_array = XNEWVEC (tree, total_args);
833 else
834 arg_array = NULL;
836 ii_args = new_args;
837 for (ii = 0; ii < total_args; ii++)
839 arg_array[ii] = TREE_VALUE (ii_args);
840 ii_args = TREE_CHAIN (ii_args);
843 TREE_USED (function) = 1;
844 rest_of_decl_compilation (function, 0, 0);
846 call1 = cilk_call_setjmp (cfun->cilk_frame_decl);
848 if (arg_array == NULL || *arg_array == NULL_TREE)
849 call2 = build_call_expr (function, 0);
850 else
851 call2 = build_call_expr_loc_array (EXPR_LOCATION (*spawn_p), function,
852 total_args, arg_array);
853 *spawn_p = alloc_stmt_list ();
854 tree f_ptr_type = build_pointer_type (TREE_TYPE (cfun->cilk_frame_decl));
855 tree frame_ptr = build1 (ADDR_EXPR, f_ptr_type, cfun->cilk_frame_decl);
856 tree save_fp = build_call_expr (cilk_save_fp_fndecl, 1, frame_ptr);
857 append_to_statement_list (save_fp, spawn_p);
858 setjmp_value = create_tmp_var (TREE_TYPE (call1));
859 setjmp_expr = fold_build2 (MODIFY_EXPR, void_type_node, setjmp_value, call1);
861 append_to_statement_list_force (setjmp_expr, spawn_p);
863 setjmp_cond_expr = fold_build2 (EQ_EXPR, TREE_TYPE (call1), setjmp_value,
864 build_int_cst (TREE_TYPE (call1), 0));
865 spawn_expr = fold_build3 (COND_EXPR, void_type_node, setjmp_cond_expr,
866 call2, build_empty_stmt (EXPR_LOCATION (call1)));
867 append_to_statement_list (spawn_expr, spawn_p);
869 free (arg_array);
870 return GS_OK;
873 /* Make the frames necessary for a spawn call. */
875 tree
876 make_cilk_frame (tree fn)
878 struct function *f = DECL_STRUCT_FUNCTION (fn);
879 tree decl;
881 if (f->cilk_frame_decl)
882 return f->cilk_frame_decl;
884 decl = build_decl (EXPR_LOCATION (fn), VAR_DECL, NULL_TREE,
885 cilk_frame_type_decl);
886 DECL_CONTEXT (decl) = fn;
887 DECL_SEEN_IN_BIND_EXPR_P (decl) = 1;
888 f->cilk_frame_decl = decl;
889 return decl;
892 /* Returns a STATEMENT_LIST with all the pedigree operations required for
893 install body with frame cleanup functions. FRAME_PTR is the pointer to
894 __cilkrts_stack_frame created by make_cilk_frame. */
896 tree
897 cilk_install_body_pedigree_operations (tree frame_ptr)
899 tree body_list = alloc_stmt_list ();
900 tree enter_frame = build_call_expr (cilk_enter_fast_fndecl, 1, frame_ptr);
901 append_to_statement_list (enter_frame, &body_list);
903 tree parent = cilk_arrow (frame_ptr, CILK_TI_FRAME_PARENT, 0);
904 tree worker = cilk_arrow (frame_ptr, CILK_TI_FRAME_WORKER, 0);
906 tree pedigree = cilk_arrow (frame_ptr, CILK_TI_FRAME_PEDIGREE, 0);
907 tree pedigree_rank = cilk_dot (pedigree, CILK_TI_PEDIGREE_RANK, 0);
908 tree parent_pedigree = cilk_dot (pedigree, CILK_TI_PEDIGREE_PARENT, 0);
909 tree pedigree_parent = cilk_arrow (parent, CILK_TI_FRAME_PEDIGREE, 0);
910 tree pedigree_parent_rank = cilk_dot (pedigree_parent,
911 CILK_TI_PEDIGREE_RANK, 0);
912 tree pedigree_parent_parent = cilk_dot (pedigree_parent,
913 CILK_TI_PEDIGREE_PARENT, 0);
914 tree worker_pedigree = cilk_arrow (worker, CILK_TI_WORKER_PEDIGREE, 1);
915 tree w_pedigree_rank = cilk_dot (worker_pedigree, CILK_TI_PEDIGREE_RANK, 0);
916 tree w_pedigree_parent = cilk_dot (worker_pedigree,
917 CILK_TI_PEDIGREE_PARENT, 0);
919 /* sf.pedigree.rank = worker->pedigree.rank. */
920 tree exp1 = build2 (MODIFY_EXPR, void_type_node, pedigree_rank,
921 w_pedigree_rank);
922 append_to_statement_list (exp1, &body_list);
924 /* sf.pedigree.parent = worker->pedigree.parent. */
925 exp1 = build2 (MODIFY_EXPR, void_type_node, parent_pedigree,
926 w_pedigree_parent);
927 append_to_statement_list (exp1, &body_list);
929 /* sf.call_parent->pedigree.rank = worker->pedigree.rank. */
930 exp1 = build2 (MODIFY_EXPR, void_type_node, pedigree_parent_rank,
931 w_pedigree_rank);
932 append_to_statement_list (exp1, &body_list);
934 /* sf.call_parent->pedigree.parent = worker->pedigree.parent. */
935 exp1 = build2 (MODIFY_EXPR, void_type_node, pedigree_parent_parent,
936 w_pedigree_parent);
937 append_to_statement_list (exp1, &body_list);
939 /* sf->worker.pedigree.rank = 0. */
940 exp1 = build2 (MODIFY_EXPR, void_type_node, w_pedigree_rank,
941 build_zero_cst (uint64_type_node));
942 append_to_statement_list (exp1, &body_list);
944 /* sf->pedigree.parent = &sf->pedigree. */
945 exp1 = build2 (MODIFY_EXPR, void_type_node, w_pedigree_parent,
946 build1 (ADDR_EXPR,
947 build_pointer_type (cilk_pedigree_type_decl),
948 pedigree));
949 append_to_statement_list (exp1, &body_list);
950 return body_list;
953 /* Add a new variable, VAR to a variable list in WD->DECL_MAP. HOW indicates
954 whether the variable is previously defined, currently defined, or a variable
955 that is being written to. */
957 static void
958 add_variable (struct wrapper_data *wd, tree var, enum add_variable_type how)
960 tree *valp = wd->decl_map->get (var);
961 if (valp)
963 tree val = (tree) *valp;
964 /* If the variable is local, do nothing. */
965 if (val == error_mark_node)
966 return;
967 /* If the variable was entered with itself as value,
968 meaning it belongs to an outer scope, do not alter
969 the value. */
970 if (val == var)
971 return;
972 /* A statement expression may cause a variable to be
973 bound twice, once in BIND_EXPR and again in a
974 DECL_EXPR. That case caused a return in the
975 test above. Any other duplicate definition is
976 an error. */
977 gcc_assert (how != ADD_BIND);
978 if (how != ADD_WRITE)
979 return;
980 /* This variable might have been entered as read but is now written. */
981 *valp = var;
982 wd->nested = true;
983 return;
985 else
987 tree val = NULL_TREE;
989 /* Nested function rewriting silently discards hard register
990 assignments for function scope variables, and they wouldn't
991 work anyway. Warn here. This misses one case: if the
992 register variable is used as the loop bound or increment it
993 has already been added to the map. */
994 if ((how != ADD_BIND) && VAR_P (var)
995 && !DECL_EXTERNAL (var) && DECL_HARD_REGISTER (var))
996 warning (0, "register assignment ignored for %qD used in Cilk block",
997 var);
999 switch (how)
1001 /* ADD_BIND means always make a fresh new variable. */
1002 case ADD_BIND:
1003 val = error_mark_node;
1004 break;
1005 /* ADD_READ means
1006 1. For cilk_for, refer to the outer scope definition as-is
1007 2. For a spawned block, take a scalar in an rgument
1008 and otherwise refer to the outer scope definition as-is.
1009 3. For a spawned call, take a scalar in an argument. */
1010 case ADD_READ:
1011 switch (wd->type)
1013 case CILK_BLOCK_FOR:
1014 val = var;
1015 break;
1016 case CILK_BLOCK_SPAWN:
1017 if (TREE_ADDRESSABLE (var))
1019 val = var;
1020 wd->nested = true;
1021 break;
1023 val = integer_zero_node;
1024 break;
1026 break;
1027 case ADD_WRITE:
1028 switch (wd->type)
1030 case CILK_BLOCK_FOR:
1031 val = var;
1032 wd->nested = true;
1033 break;
1034 case CILK_BLOCK_SPAWN:
1035 if (TREE_ADDRESSABLE (var))
1036 val = integer_one_node;
1037 else
1039 val = var;
1040 wd->nested = true;
1042 break;
1045 wd->decl_map->put (var, val);
1049 /* Find the variables referenced in an expression T. This does not avoid
1050 duplicates because a variable may be read in one context and written in
1051 another. HOW describes the context in which the reference is seen. If
1052 NESTED is true a nested function is being generated and variables in the
1053 original context should not be remapped. */
1055 static void
1056 extract_free_variables (tree t, struct wrapper_data *wd,
1057 enum add_variable_type how)
1059 if (t == NULL_TREE)
1060 return;
1062 enum tree_code code = TREE_CODE (t);
1063 bool is_expr = IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code));
1065 if (is_expr)
1066 extract_free_variables (TREE_TYPE (t), wd, ADD_READ);
1068 switch (code)
1070 case ERROR_MARK:
1071 case IDENTIFIER_NODE:
1072 case VOID_CST:
1073 case INTEGER_CST:
1074 case REAL_CST:
1075 case FIXED_CST:
1076 case STRING_CST:
1077 case BLOCK:
1078 case PLACEHOLDER_EXPR:
1079 case FIELD_DECL:
1080 case VOID_TYPE:
1081 case REAL_TYPE:
1082 /* These do not contain variable references. */
1083 return;
1085 case SSA_NAME:
1086 /* Currently we don't see SSA_NAME. */
1087 extract_free_variables (SSA_NAME_VAR (t), wd, how);
1088 return;
1090 case LABEL_DECL:
1091 /* This might be a reference to a label outside the Cilk block,
1092 which is an error, or a reference to a label in the Cilk block
1093 that we haven't seen yet. We can't tell. Ignore it. An
1094 invalid use will cause an error later in copy_decl_for_cilk. */
1095 return;
1097 case RESULT_DECL:
1098 if (wd->type != CILK_BLOCK_SPAWN)
1099 TREE_ADDRESSABLE (t) = 1;
1100 /* FALLTHRU */
1101 case VAR_DECL:
1102 case PARM_DECL:
1103 if (!is_global_var (t))
1104 add_variable (wd, t, how);
1105 return;
1107 case NON_LVALUE_EXPR:
1108 case CONVERT_EXPR:
1109 case NOP_EXPR:
1110 extract_free_variables (TREE_OPERAND (t, 0), wd, ADD_READ);
1111 return;
1113 case VEC_INIT_EXPR:
1114 case INIT_EXPR:
1115 extract_free_variables (TREE_OPERAND (t, 0), wd, ADD_BIND);
1116 extract_free_variables (TREE_OPERAND (t, 1), wd, ADD_READ);
1117 return;
1119 case MODIFY_EXPR:
1120 case PREDECREMENT_EXPR:
1121 case PREINCREMENT_EXPR:
1122 case POSTDECREMENT_EXPR:
1123 case POSTINCREMENT_EXPR:
1124 /* These write their result. */
1125 extract_free_variables (TREE_OPERAND (t, 0), wd, ADD_WRITE);
1126 extract_free_variables (TREE_OPERAND (t, 1), wd, ADD_READ);
1127 return;
1129 case ADDR_EXPR:
1130 /* This might modify its argument, and the value needs to be
1131 passed by reference in any case to preserve identity and
1132 type if is a promoting type. In the case of a nested loop
1133 just notice that we touch the variable. It will already
1134 be addressable, and marking it modified will cause a spurious
1135 warning about writing the control variable. */
1136 if (wd->type != CILK_BLOCK_SPAWN)
1137 extract_free_variables (TREE_OPERAND (t, 0), wd, ADD_READ);
1138 else
1139 extract_free_variables (TREE_OPERAND (t, 0), wd, ADD_WRITE);
1140 return;
1142 case ARRAY_REF:
1143 /* Treating ARRAY_REF and BIT_FIELD_REF identically may
1144 mark the array as written but the end result is correct
1145 because the array is passed by pointer anyway. */
1146 case BIT_FIELD_REF:
1147 /* Propagate the access type to the object part of which
1148 is being accessed here. As for ADDR_EXPR, don't do this
1149 in a nested loop, unless the access is to a fixed index. */
1150 if (wd->type != CILK_BLOCK_FOR || TREE_CONSTANT (TREE_OPERAND (t, 1)))
1151 extract_free_variables (TREE_OPERAND (t, 0), wd, how);
1152 else
1153 extract_free_variables (TREE_OPERAND (t, 0), wd, ADD_READ);
1154 extract_free_variables (TREE_OPERAND (t, 1), wd, ADD_READ);
1155 extract_free_variables (TREE_OPERAND (t, 2), wd, ADD_READ);
1156 return;
1158 case TREE_LIST:
1159 extract_free_variables (TREE_PURPOSE (t), wd, ADD_READ);
1160 extract_free_variables (TREE_VALUE (t), wd, ADD_READ);
1161 extract_free_variables (TREE_CHAIN (t), wd, ADD_READ);
1162 return;
1164 case TREE_VEC:
1166 int len = TREE_VEC_LENGTH (t);
1167 int i;
1168 for (i = 0; i < len; i++)
1169 extract_free_variables (TREE_VEC_ELT (t, i), wd, ADD_READ);
1170 return;
1173 case VECTOR_CST:
1175 unsigned ii = 0;
1176 for (ii = 0; ii < VECTOR_CST_NELTS (t); ii++)
1177 extract_free_variables (VECTOR_CST_ELT (t, ii), wd, ADD_READ);
1178 break;
1181 case COMPLEX_CST:
1182 extract_free_variables (TREE_REALPART (t), wd, ADD_READ);
1183 extract_free_variables (TREE_IMAGPART (t), wd, ADD_READ);
1184 return;
1186 case BIND_EXPR:
1188 tree decl;
1189 for (decl = BIND_EXPR_VARS (t); decl; decl = TREE_CHAIN (decl))
1191 add_variable (wd, decl, ADD_BIND);
1192 /* A self-referential initialization is no problem because
1193 we already entered the variable into the map as local. */
1194 extract_free_variables (DECL_INITIAL (decl), wd, ADD_READ);
1195 extract_free_variables (DECL_SIZE (decl), wd, ADD_READ);
1196 extract_free_variables (DECL_SIZE_UNIT (decl), wd, ADD_READ);
1198 extract_free_variables (BIND_EXPR_BODY (t), wd, ADD_READ);
1199 return;
1202 case STATEMENT_LIST:
1204 tree_stmt_iterator i;
1205 for (i = tsi_start (t); !tsi_end_p (i); tsi_next (&i))
1206 extract_free_variables (*tsi_stmt_ptr (i), wd, ADD_READ);
1207 return;
1210 case TARGET_EXPR:
1212 extract_free_variables (TREE_OPERAND (t, 0), wd, ADD_BIND);
1213 extract_free_variables (TREE_OPERAND (t, 1), wd, ADD_READ);
1214 extract_free_variables (TREE_OPERAND (t, 2), wd, ADD_READ);
1215 if (TREE_OPERAND (t, 3) != TREE_OPERAND (t, 1))
1216 extract_free_variables (TREE_OPERAND (t, 3), wd, ADD_READ);
1217 return;
1220 case RETURN_EXPR:
1221 if (TREE_NO_WARNING (t))
1223 gcc_assert (errorcount);
1224 return;
1226 return;
1228 case DECL_EXPR:
1229 if (TREE_CODE (DECL_EXPR_DECL (t)) != TYPE_DECL)
1230 extract_free_variables (DECL_EXPR_DECL (t), wd, ADD_BIND);
1231 return;
1233 case INTEGER_TYPE:
1234 case ENUMERAL_TYPE:
1235 case BOOLEAN_TYPE:
1236 extract_free_variables (TYPE_MIN_VALUE (t), wd, ADD_READ);
1237 extract_free_variables (TYPE_MAX_VALUE (t), wd, ADD_READ);
1238 return;
1240 case POINTER_TYPE:
1241 extract_free_variables (TREE_TYPE (t), wd, ADD_READ);
1242 break;
1244 case ARRAY_TYPE:
1245 extract_free_variables (TREE_TYPE (t), wd, ADD_READ);
1246 extract_free_variables (TYPE_DOMAIN (t), wd, ADD_READ);
1247 return;
1249 case RECORD_TYPE:
1250 extract_free_variables (TYPE_FIELDS (t), wd, ADD_READ);
1251 return;
1253 case METHOD_TYPE:
1254 extract_free_variables (TYPE_ARG_TYPES (t), wd, ADD_READ);
1255 extract_free_variables (TYPE_METHOD_BASETYPE (t), wd, ADD_READ);
1256 return;
1258 case AGGR_INIT_EXPR:
1260 int len = 0;
1261 int ii = 0;
1262 extract_free_variables (TREE_OPERAND (t, 1), wd, ADD_READ);
1263 if (TREE_CODE (TREE_OPERAND (t, 0)) == INTEGER_CST)
1265 len = TREE_INT_CST_LOW (TREE_OPERAND (t, 0));
1267 for (ii = 3; ii < len; ii++)
1268 extract_free_variables (TREE_OPERAND (t, ii), wd, ADD_READ);
1269 extract_free_variables (TREE_TYPE (t), wd, ADD_READ);
1271 break;
1274 case CALL_EXPR:
1276 int len = 0;
1277 int ii = 0;
1278 if (TREE_CODE (TREE_OPERAND (t, 0)) == INTEGER_CST)
1280 len = TREE_INT_CST_LOW (TREE_OPERAND (t, 0));
1282 for (ii = 0; ii < len; ii++)
1283 extract_free_variables (TREE_OPERAND (t, ii), wd, ADD_READ);
1284 extract_free_variables (TREE_TYPE (t), wd, ADD_READ);
1286 break;
1289 case CONSTRUCTOR:
1291 unsigned HOST_WIDE_INT idx = 0;
1292 constructor_elt *ce;
1293 for (idx = 0; vec_safe_iterate (CONSTRUCTOR_ELTS (t), idx, &ce); idx++)
1294 extract_free_variables (ce->value, wd, ADD_READ);
1295 break;
1298 default:
1299 if (is_expr)
1301 int i, len;
1303 /* Walk over all the sub-trees of this operand. */
1304 len = TREE_CODE_LENGTH (code);
1306 /* Go through the subtrees. We need to do this in forward order so
1307 that the scope of a FOR_EXPR is handled properly. */
1308 for (i = 0; i < len; ++i)
1309 extract_free_variables (TREE_OPERAND (t, i), wd, ADD_READ);
1314 /* Add appropriate frames needed for a Cilk spawned function call, FNDECL.
1315 Returns the __cilkrts_stack_frame * variable. */
1317 tree
1318 insert_cilk_frame (tree fndecl)
1320 tree addr, body, enter, out, orig_body;
1321 location_t loc = EXPR_LOCATION (fndecl);
1323 if (!cfun || cfun->decl != fndecl)
1324 push_cfun (DECL_STRUCT_FUNCTION (fndecl));
1326 tree decl = cfun->cilk_frame_decl;
1327 if (!decl)
1329 tree *saved_tree = &DECL_SAVED_TREE (fndecl);
1330 decl = make_cilk_frame (fndecl);
1331 add_local_decl (cfun, decl);
1333 addr = build1 (ADDR_EXPR, cilk_frame_ptr_type_decl, decl);
1334 enter = build_call_expr (cilk_enter_fndecl, 1, addr);
1335 out = create_cilk_function_exit (cfun->cilk_frame_decl, false, true);
1337 /* The new body will be:
1338 __cilkrts_enter_frame_1 (&sf);
1339 try {
1340 orig_body;
1342 finally {
1343 __cilkrts_pop_frame (&sf);
1344 __cilkrts_leave_frame (&sf);
1345 } */
1347 body = alloc_stmt_list ();
1348 orig_body = *saved_tree;
1350 if (TREE_CODE (orig_body) == BIND_EXPR)
1351 orig_body = BIND_EXPR_BODY (orig_body);
1353 append_to_statement_list (enter, &body);
1354 append_to_statement_list (build_stmt (loc, TRY_FINALLY_EXPR, orig_body,
1355 out), &body);
1356 if (TREE_CODE (*saved_tree) == BIND_EXPR)
1357 BIND_EXPR_BODY (*saved_tree) = body;
1358 else
1359 *saved_tree = body;
1361 return decl;
1364 /* Wraps CALL, a CALL_EXPR, into a CILK_SPAWN_STMT tree and returns it. */
1366 tree
1367 build_cilk_spawn (location_t loc, tree call)
1369 if (!cilk_set_spawn_marker (loc, call))
1370 return error_mark_node;
1371 tree spawn_stmt = build1 (CILK_SPAWN_STMT, TREE_TYPE (call), call);
1372 TREE_SIDE_EFFECTS (spawn_stmt) = 1;
1373 return spawn_stmt;
1376 /* Returns a tree of type CILK_SYNC_STMT. */
1378 tree
1379 build_cilk_sync (void)
1381 tree sync = build0 (CILK_SYNC_STMT, void_type_node);
1382 TREE_SIDE_EFFECTS (sync) = 1;
1383 return sync;
1386 /* Helper for contains_cilk_spawn_stmt, callback for walk_tree. Return
1387 non-null tree if TP contains CILK_SPAWN_STMT. */
1389 static tree
1390 contains_cilk_spawn_stmt_walker (tree *tp, int *, void *)
1392 if (TREE_CODE (*tp) == CILK_SPAWN_STMT)
1393 return *tp;
1394 else
1395 return NULL_TREE;
1398 /* Returns true if EXPR or any of its subtrees contain CILK_SPAWN_STMT
1399 node. */
1401 bool
1402 contains_cilk_spawn_stmt (tree expr)
1404 return walk_tree (&expr, contains_cilk_spawn_stmt_walker, NULL, NULL)
1405 != NULL_TREE;
1408 /* Return a error location for EXPR if LOC is not set. */
1410 static location_t
1411 get_error_location (tree expr, location_t loc)
1413 if (loc == UNKNOWN_LOCATION)
1415 if (TREE_CODE (expr) == MODIFY_EXPR)
1416 expr = TREE_OPERAND (expr, 0);
1417 loc = EXPR_LOCATION (expr);
1419 return loc;
1422 /* Check that no array notation or spawn statement is in EXPR.
1423 If not true generate an error at LOC for ARRAY_GMSGID or
1424 SPAWN_MSGID. */
1426 bool
1427 check_no_cilk (tree expr, const char *array_msgid, const char *spawn_msgid,
1428 location_t loc)
1430 if (!flag_cilkplus)
1431 return false;
1432 if (contains_array_notation_expr (expr))
1434 loc = get_error_location (expr, loc);
1435 error_at (loc, array_msgid);
1436 return true;
1438 if (walk_tree (&expr, contains_cilk_spawn_stmt_walker, NULL, NULL))
1440 loc = get_error_location (expr, loc);
1441 error_at (loc, spawn_msgid);
1442 return true;
1444 return false;