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