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