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