1/* Tree lowering pass. This pass gimplifies the tree representation built 2 by the C-based front ends. The structure of gimplified, or 3 language-independent, trees is dictated by the grammar described in this 4 file. 5 Copyright (C) 2002-2022 Free Software Foundation, Inc. 6 Lowering of expressions contributed by Sebastian Pop <s.pop@laposte.net> 7 Re-written to support lowering of whole function trees, documentation 8 and miscellaneous cleanups by Diego Novillo <dnovillo@redhat.com> 9 10This file is part of GCC. 11 12GCC is free software; you can redistribute it and/or modify it under 13the terms of the GNU General Public License as published by the Free 14Software Foundation; either version 3, or (at your option) any later 15version. 16 17GCC is distributed in the hope that it will be useful, but WITHOUT ANY 18WARRANTY; without even the implied warranty of MERCHANTABILITY or 19FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 20for more details. 21 22You should have received a copy of the GNU General Public License 23along with GCC; see the file COPYING3. If not see 24<http://www.gnu.org/licenses/>. */ 25 26#include "config.h" 27#include "system.h" 28#include "coretypes.h" 29#include "tm.h" 30#include "function.h" 31#include "basic-block.h" 32#include "tree.h" 33#include "tree-iterator.h" 34#include "predict.h" 35#include "gimple.h" 36#include "cgraph.h" 37#include "c-pretty-print.h" 38#include "gimplify.h" 39#include "langhooks.h" 40#include "dumpfile.h" 41#include "c-ubsan.h" 42#include "tree-nested.h" 43 44/* The gimplification pass converts the language-dependent trees 45 (ld-trees) emitted by the parser into language-independent trees 46 (li-trees) that are the target of SSA analysis and transformations. 47 48 Language-independent trees are based on the SIMPLE intermediate 49 representation used in the McCAT compiler framework: 50 51 "Designing the McCAT Compiler Based on a Family of Structured 52 Intermediate Representations," 53 L. Hendren, C. Donawa, M. Emami, G. Gao, Justiani, and B. Sridharan, 54 Proceedings of the 5th International Workshop on Languages and 55 Compilers for Parallel Computing, no. 757 in Lecture Notes in 56 Computer Science, New Haven, Connecticut, pp. 406-420, 57 Springer-Verlag, August 3-5, 1992. 58 59 http://www-acaps.cs.mcgill.ca/info/McCAT/McCAT.html 60 61 Basically, we walk down gimplifying the nodes that we encounter. As we 62 walk back up, we check that they fit our constraints, and copy them 63 into temporaries if not. */ 64 65/* Callback for c_genericize. */ 66 67static tree 68ubsan_walk_array_refs_r (tree *tp, int *walk_subtrees, void *data) 69{ 70 hash_set<tree> *pset = (hash_set<tree> *) data; 71 72 if (TREE_CODE (*tp) == BIND_EXPR) 73 { 74 /* Since walk_tree doesn't call the callback function on the decls 75 in BIND_EXPR_VARS, we have to walk them manually, so we can avoid 76 instrumenting DECL_INITIAL of TREE_STATIC vars. */ 77 *walk_subtrees = 0; 78 for (tree decl = BIND_EXPR_VARS (*tp); decl; decl = DECL_CHAIN (decl)) 79 { 80 if (TREE_STATIC (decl)) 81 continue; 82 walk_tree (&DECL_INITIAL (decl), ubsan_walk_array_refs_r, pset, 83 pset); 84 walk_tree (&DECL_SIZE (decl), ubsan_walk_array_refs_r, pset, pset); 85 walk_tree (&DECL_SIZE_UNIT (decl), ubsan_walk_array_refs_r, pset, 86 pset); 87 } 88 walk_tree (&BIND_EXPR_BODY (*tp), ubsan_walk_array_refs_r, pset, pset); 89 } 90 else if (TREE_CODE (*tp) == ADDR_EXPR 91 && TREE_CODE (TREE_OPERAND (*tp, 0)) == ARRAY_REF) 92 { 93 ubsan_maybe_instrument_array_ref (&TREE_OPERAND (*tp, 0), true); 94 /* Make sure ubsan_maybe_instrument_array_ref is not called again 95 on the ARRAY_REF, the above call might not instrument anything 96 as the index might be constant or masked, so ensure it is not 97 walked again and walk its subtrees manually. */ 98 tree aref = TREE_OPERAND (*tp, 0); 99 pset->add (aref); 100 *walk_subtrees = 0; 101 walk_tree (&TREE_OPERAND (aref, 0), ubsan_walk_array_refs_r, pset, pset); 102 walk_tree (&TREE_OPERAND (aref, 1), ubsan_walk_array_refs_r, pset, pset); 103 walk_tree (&TREE_OPERAND (aref, 2), ubsan_walk_array_refs_r, pset, pset); 104 walk_tree (&TREE_OPERAND (aref, 3), ubsan_walk_array_refs_r, pset, pset); 105 } 106 else if (TREE_CODE (*tp) == ARRAY_REF) 107 ubsan_maybe_instrument_array_ref (tp, false); 108 else if (TREE_CODE (*tp) == MODIFY_EXPR) 109 { 110 /* Since r7-1900, we gimplify RHS before LHS. Consider 111 a[b] |= c; 112 wherein we can have a single shared tree a[b] in both LHS and RHS. 113 If we only instrument the LHS and the access is invalid, the program 114 could crash before emitting a UBSan error. So instrument the RHS 115 first. */ 116 *walk_subtrees = 0; 117 walk_tree (&TREE_OPERAND (*tp, 1), ubsan_walk_array_refs_r, pset, pset); 118 walk_tree (&TREE_OPERAND (*tp, 0), ubsan_walk_array_refs_r, pset, pset); 119 } 120 return NULL_TREE; 121} 122 123/* Gimplification of statement trees. */ 124 125/* Local declarations. */ 126 127enum bc_t { bc_break = 0, bc_continue = 1 }; 128 129/* Stack of labels which are targets for "break" or "continue", 130 linked through TREE_CHAIN. */ 131static tree bc_label[2]; 132 133/* Begin a scope which can be exited by a break or continue statement. BC 134 indicates which. 135 136 Just creates a label with location LOCATION and pushes it into the current 137 context. */ 138 139static tree 140begin_bc_block (enum bc_t bc, location_t location) 141{ 142 tree label = create_artificial_label (location); 143 DECL_CHAIN (label) = bc_label[bc]; 144 bc_label[bc] = label; 145 if (bc == bc_break) 146 LABEL_DECL_BREAK (label) = true; 147 else 148 LABEL_DECL_CONTINUE (label) = true; 149 return label; 150} 151 152/* Finish a scope which can be exited by a break or continue statement. 153 LABEL was returned from the most recent call to begin_bc_block. BLOCK is 154 an expression for the contents of the scope. 155 156 If we saw a break (or continue) in the scope, append a LABEL_EXPR to 157 BLOCK. Otherwise, just forget the label. */ 158 159static void 160finish_bc_block (tree *block, enum bc_t bc, tree label) 161{ 162 gcc_assert (label == bc_label[bc]); 163 164 if (TREE_USED (label)) 165 append_to_statement_list (build1 (LABEL_EXPR, void_type_node, label), 166 block); 167 168 bc_label[bc] = DECL_CHAIN (label); 169 DECL_CHAIN (label) = NULL_TREE; 170} 171 172/* Allow saving and restoring break/continue state. */ 173 174void 175save_bc_state (bc_state_t *state) 176{ 177 state->bc_label[bc_break] = bc_label[bc_break]; 178 state->bc_label[bc_continue] = bc_label[bc_continue]; 179 bc_label[bc_break] = NULL_TREE; 180 bc_label[bc_continue] = NULL_TREE; 181} 182 183void 184restore_bc_state (bc_state_t *state) 185{ 186 gcc_assert (bc_label[bc_break] == NULL); 187 gcc_assert (bc_label[bc_continue] == NULL); 188 bc_label[bc_break] = state->bc_label[bc_break]; 189 bc_label[bc_continue] = state->bc_label[bc_continue]; 190} 191 192/* Get the LABEL_EXPR to represent a break or continue statement 193 in the current block scope. BC indicates which. */ 194 195static tree 196get_bc_label (enum bc_t bc) 197{ 198 tree label = bc_label[bc]; 199 gcc_assert (label); 200 201 /* Mark the label used for finish_bc_block. */ 202 TREE_USED (label) = 1; 203 return label; 204} 205 206/* Return the location from EXPR, or OR_LOC if the former is unknown. */ 207 208location_t 209expr_loc_or_loc (const_tree expr, location_t or_loc) 210{ 211 tree t = CONST_CAST_TREE (expr); 212 location_t loc = UNKNOWN_LOCATION; 213 if (t) 214 loc = EXPR_LOCATION (t); 215 if (loc == UNKNOWN_LOCATION) 216 loc = or_loc; 217 return loc; 218} 219 220/* Build a generic representation of one of the C loop forms. COND is the 221 loop condition or NULL_TREE. BODY is the (possibly compound) statement 222 controlled by the loop. INCR is the increment expression of a for-loop, 223 or NULL_TREE. COND_IS_FIRST indicates whether the condition is 224 evaluated before the loop body as in while and for loops, or after the 225 loop body as in do-while loops. */ 226 227static void 228genericize_c_loop (tree *stmt_p, location_t start_locus, tree cond, tree body, 229 tree incr, bool cond_is_first, int *walk_subtrees, 230 void *data, walk_tree_fn func, walk_tree_lh lh) 231{ 232 tree blab, clab; 233 tree entry = NULL, exit = NULL, t; 234 tree stmt_list = NULL; 235 location_t cond_locus = expr_loc_or_loc (cond, start_locus); 236 location_t incr_locus = expr_loc_or_loc (incr, start_locus); 237 238 protected_set_expr_location_if_unset (incr, start_locus); 239 240 walk_tree_1 (&cond, func, data, NULL, lh); 241 walk_tree_1 (&incr, func, data, NULL, lh); 242 243 blab = begin_bc_block (bc_break, start_locus); 244 clab = begin_bc_block (bc_continue, start_locus); 245 246 walk_tree_1 (&body, func, data, NULL, lh); 247 *walk_subtrees = 0; 248 249 /* If condition is zero don't generate a loop construct. */ 250 if (cond && integer_zerop (cond)) 251 { 252 if (cond_is_first) 253 { 254 t = build1_loc (start_locus, GOTO_EXPR, void_type_node, 255 get_bc_label (bc_break)); 256 append_to_statement_list (t, &stmt_list); 257 } 258 } 259 else 260 { 261 /* Expand to gotos. */ 262 tree top = build1 (LABEL_EXPR, void_type_node, 263 create_artificial_label (start_locus)); 264 265 /* If we have an exit condition, then we build an IF with gotos either 266 out of the loop, or to the top of it. If there's no exit condition, 267 then we just build a jump back to the top. */ 268 exit = build1 (GOTO_EXPR, void_type_node, LABEL_EXPR_LABEL (top)); 269 270 if (cond && !integer_nonzerop (cond)) 271 { 272 /* Canonicalize the loop condition to the end. This means 273 generating a branch to the loop condition. Reuse the 274 continue label, if there is no incr expression. */ 275 if (cond_is_first) 276 { 277 if (incr) 278 { 279 entry = build1 (LABEL_EXPR, void_type_node, 280 create_artificial_label (start_locus)); 281 t = build1_loc (start_locus, GOTO_EXPR, void_type_node, 282 LABEL_EXPR_LABEL (entry)); 283 } 284 else 285 t = build1_loc (start_locus, GOTO_EXPR, void_type_node, 286 get_bc_label (bc_continue)); 287 append_to_statement_list (t, &stmt_list); 288 } 289 290 t = build1 (GOTO_EXPR, void_type_node, get_bc_label (bc_break)); 291 exit = fold_build3_loc (cond_locus, 292 COND_EXPR, void_type_node, cond, exit, t); 293 } 294 else 295 { 296 /* For the backward-goto's location of an unconditional loop 297 use the beginning of the body, or, if there is none, the 298 top of the loop. */ 299 location_t loc = expr_loc_or_loc (expr_first (body), 300 start_locus); 301 SET_EXPR_LOCATION (exit, loc); 302 } 303 append_to_statement_list (top, &stmt_list); 304 } 305 306 append_to_statement_list (body, &stmt_list); 307 finish_bc_block (&stmt_list, bc_continue, clab); 308 if (incr) 309 { 310 if (MAY_HAVE_DEBUG_MARKER_STMTS && incr_locus != UNKNOWN_LOCATION) 311 { 312 tree d = build0 (DEBUG_BEGIN_STMT, void_type_node); 313 SET_EXPR_LOCATION (d, expr_loc_or_loc (incr, start_locus)); 314 append_to_statement_list (d, &stmt_list); 315 } 316 append_to_statement_list (incr, &stmt_list); 317 } 318 append_to_statement_list (entry, &stmt_list); 319 320 if (MAY_HAVE_DEBUG_MARKER_STMTS && cond_locus != UNKNOWN_LOCATION) 321 { 322 tree d = build0 (DEBUG_BEGIN_STMT, void_type_node); 323 SET_EXPR_LOCATION (d, cond_locus); 324 append_to_statement_list (d, &stmt_list); 325 } 326 append_to_statement_list (exit, &stmt_list); 327 finish_bc_block (&stmt_list, bc_break, blab); 328 if (!stmt_list) 329 stmt_list = build_empty_stmt (start_locus); 330 331 *stmt_p = stmt_list; 332} 333 334/* Genericize a FOR_STMT node *STMT_P. */ 335 336static void 337genericize_for_stmt (tree *stmt_p, int *walk_subtrees, void *data, 338 walk_tree_fn func, walk_tree_lh lh) 339{ 340 tree stmt = *stmt_p; 341 tree expr = NULL; 342 tree loop; 343 tree init = FOR_INIT_STMT (stmt); 344 345 if (init) 346 { 347 walk_tree_1 (&init, func, data, NULL, lh); 348 append_to_statement_list (init, &expr); 349 } 350 351 genericize_c_loop (&loop, EXPR_LOCATION (stmt), FOR_COND (stmt), 352 FOR_BODY (stmt), FOR_EXPR (stmt), 1, walk_subtrees, 353 data, func, lh); 354 append_to_statement_list (loop, &expr); 355 if (expr == NULL_TREE) 356 expr = loop; 357 *stmt_p = expr; 358} 359 360/* Genericize a WHILE_STMT node *STMT_P. */ 361 362static void 363genericize_while_stmt (tree *stmt_p, int *walk_subtrees, void *data, 364 walk_tree_fn func, walk_tree_lh lh) 365{ 366 tree stmt = *stmt_p; 367 genericize_c_loop (stmt_p, EXPR_LOCATION (stmt), WHILE_COND (stmt), 368 WHILE_BODY (stmt), NULL_TREE, 1, walk_subtrees, 369 data, func, lh); 370} 371 372/* Genericize a DO_STMT node *STMT_P. */ 373 374static void 375genericize_do_stmt (tree *stmt_p, int *walk_subtrees, void *data, 376 walk_tree_fn func, walk_tree_lh lh) 377{ 378 tree stmt = *stmt_p; 379 genericize_c_loop (stmt_p, EXPR_LOCATION (stmt), DO_COND (stmt), 380 DO_BODY (stmt), NULL_TREE, 0, walk_subtrees, 381 data, func, lh); 382} 383 384/* Genericize a SWITCH_STMT node *STMT_P by turning it into a SWITCH_EXPR. */ 385 386static void 387genericize_switch_stmt (tree *stmt_p, int *walk_subtrees, void *data, 388 walk_tree_fn func, walk_tree_lh lh) 389{ 390 tree stmt = *stmt_p; 391 tree break_block, body, cond, type; 392 location_t stmt_locus = EXPR_LOCATION (stmt); 393 394 body = SWITCH_STMT_BODY (stmt); 395 if (!body) 396 body = build_empty_stmt (stmt_locus); 397 cond = SWITCH_STMT_COND (stmt); 398 type = SWITCH_STMT_TYPE (stmt); 399 400 walk_tree_1 (&cond, func, data, NULL, lh); 401 402 break_block = begin_bc_block (bc_break, stmt_locus); 403 404 walk_tree_1 (&body, func, data, NULL, lh); 405 walk_tree_1 (&type, func, data, NULL, lh); 406 *walk_subtrees = 0; 407 408 if (TREE_USED (break_block)) 409 SWITCH_BREAK_LABEL_P (break_block) = 1; 410 finish_bc_block (&body, bc_break, break_block); 411 *stmt_p = build2_loc (stmt_locus, SWITCH_EXPR, type, cond, body); 412 SWITCH_ALL_CASES_P (*stmt_p) = SWITCH_STMT_ALL_CASES_P (stmt); 413 gcc_checking_assert (!SWITCH_STMT_NO_BREAK_P (stmt) 414 || !TREE_USED (break_block)); 415} 416 417/* Genericize a CONTINUE_STMT node *STMT_P. */ 418 419static void 420genericize_continue_stmt (tree *stmt_p) 421{ 422 tree stmt_list = NULL; 423 tree pred = build_predict_expr (PRED_CONTINUE, NOT_TAKEN); 424 tree label = get_bc_label (bc_continue); 425 location_t location = EXPR_LOCATION (*stmt_p); 426 tree jump = build1_loc (location, GOTO_EXPR, void_type_node, label); 427 append_to_statement_list_force (pred, &stmt_list); 428 append_to_statement_list (jump, &stmt_list); 429 *stmt_p = stmt_list; 430} 431 432/* Genericize a BREAK_STMT node *STMT_P. */ 433 434static void 435genericize_break_stmt (tree *stmt_p) 436{ 437 tree label = get_bc_label (bc_break); 438 location_t location = EXPR_LOCATION (*stmt_p); 439 *stmt_p = build1_loc (location, GOTO_EXPR, void_type_node, label); 440} 441 442/* Genericize a OMP_FOR node *STMT_P. */ 443 444static void 445genericize_omp_for_stmt (tree *stmt_p, int *walk_subtrees, void *data, 446 walk_tree_fn func, walk_tree_lh lh) 447{ 448 tree stmt = *stmt_p; 449 location_t locus = EXPR_LOCATION (stmt); 450 tree clab = begin_bc_block (bc_continue, locus); 451 452 walk_tree_1 (&OMP_FOR_BODY (stmt), func, data, NULL, lh); 453 if (TREE_CODE (stmt) != OMP_TASKLOOP) 454 walk_tree_1 (&OMP_FOR_CLAUSES (stmt), func, data, NULL, lh); 455 walk_tree_1 (&OMP_FOR_INIT (stmt), func, data, NULL, lh); 456 walk_tree_1 (&OMP_FOR_COND (stmt), func, data, NULL, lh); 457 walk_tree_1 (&OMP_FOR_INCR (stmt), func, data, NULL, lh); 458 walk_tree_1 (&OMP_FOR_PRE_BODY (stmt), func, data, NULL, lh); 459 *walk_subtrees = 0; 460 461 finish_bc_block (&OMP_FOR_BODY (stmt), bc_continue, clab); 462} 463 464 465/* Lower structured control flow tree nodes, such as loops. The 466 STMT_P, WALK_SUBTREES, and DATA arguments are as for the walk_tree_fn 467 type. FUNC and LH are language-specific functions passed to walk_tree_1 468 for node visiting and traversal, respectively; they are used to do 469 subtree processing in a language-dependent way. */ 470 471tree 472c_genericize_control_stmt (tree *stmt_p, int *walk_subtrees, void *data, 473 walk_tree_fn func, walk_tree_lh lh) 474{ 475 tree stmt = *stmt_p; 476 477 switch (TREE_CODE (stmt)) 478 { 479 case FOR_STMT: 480 genericize_for_stmt (stmt_p, walk_subtrees, data, func, lh); 481 break; 482 483 case WHILE_STMT: 484 genericize_while_stmt (stmt_p, walk_subtrees, data, func, lh); 485 break; 486 487 case DO_STMT: 488 genericize_do_stmt (stmt_p, walk_subtrees, data, func, lh); 489 break; 490 491 case SWITCH_STMT: 492 genericize_switch_stmt (stmt_p, walk_subtrees, data, func, lh); 493 break; 494 495 case CONTINUE_STMT: 496 genericize_continue_stmt (stmt_p); 497 break; 498 499 case BREAK_STMT: 500 genericize_break_stmt (stmt_p); 501 break; 502 503 case OMP_FOR: 504 case OMP_SIMD: 505 case OMP_DISTRIBUTE: 506 case OMP_LOOP: 507 case OMP_TASKLOOP: 508 case OACC_LOOP: 509 genericize_omp_for_stmt (stmt_p, walk_subtrees, data, func, lh); 510 break; 511 512 case STATEMENT_LIST: 513 if (TREE_SIDE_EFFECTS (stmt)) 514 { 515 tree_stmt_iterator i; 516 int nondebug_stmts = 0; 517 bool clear_side_effects = true; 518 /* Genericization can clear TREE_SIDE_EFFECTS, e.g. when 519 transforming an IF_STMT into COND_EXPR. If such stmt 520 appears in a STATEMENT_LIST that contains only that 521 stmt and some DEBUG_BEGIN_STMTs, without -g where the 522 STATEMENT_LIST wouldn't be present at all the resulting 523 expression wouldn't have TREE_SIDE_EFFECTS set, so make sure 524 to clear it even on the STATEMENT_LIST in such cases. */ 525 hash_set<tree> *pset = (c_dialect_cxx () 526 ? nullptr 527 : static_cast<hash_set<tree> *>(data)); 528 for (i = tsi_start (stmt); !tsi_end_p (i); tsi_next (&i)) 529 { 530 tree t = tsi_stmt (i); 531 if (TREE_CODE (t) != DEBUG_BEGIN_STMT && nondebug_stmts < 2) 532 nondebug_stmts++; 533 walk_tree_1 (tsi_stmt_ptr (i), func, data, pset, lh); 534 if (TREE_CODE (t) != DEBUG_BEGIN_STMT 535 && (nondebug_stmts > 1 || TREE_SIDE_EFFECTS (tsi_stmt (i)))) 536 clear_side_effects = false; 537 } 538 if (clear_side_effects) 539 TREE_SIDE_EFFECTS (stmt) = 0; 540 *walk_subtrees = 0; 541 } 542 break; 543 544 default: 545 break; 546 } 547 548 return NULL; 549} 550 551 552/* Wrapper for c_genericize_control_stmt to allow it to be used as a walk_tree 553 callback. This is appropriate for C; C++ calls c_genericize_control_stmt 554 directly. */ 555 556static tree 557c_genericize_control_r (tree *stmt_p, int *walk_subtrees, void *data) 558{ 559 c_genericize_control_stmt (stmt_p, walk_subtrees, data, 560 c_genericize_control_r, NULL); 561 return NULL; 562} 563 564/* Convert the tree representation of FNDECL from C frontend trees to 565 GENERIC. */ 566 567void 568c_genericize (tree fndecl) 569{ 570 FILE *dump_orig; 571 dump_flags_t local_dump_flags; 572 struct cgraph_node *cgn; 573 574 if (flag_sanitize & SANITIZE_BOUNDS) 575 { 576 hash_set<tree> pset; 577 walk_tree (&DECL_SAVED_TREE (fndecl), ubsan_walk_array_refs_r, &pset, 578 &pset); 579 } 580 581 /* Genericize loops and other structured control constructs. The C++ 582 front end has already done this in lang-specific code. */ 583 if (!c_dialect_cxx ()) 584 { 585 bc_state_t save_state; 586 push_cfun (DECL_STRUCT_FUNCTION (fndecl)); 587 save_bc_state (&save_state); 588 hash_set<tree> pset; 589 walk_tree (&DECL_SAVED_TREE (fndecl), c_genericize_control_r, &pset, 590 &pset); 591 restore_bc_state (&save_state); 592 pop_cfun (); 593 } 594 595 if (warn_duplicated_branches) 596 walk_tree_without_duplicates (&DECL_SAVED_TREE (fndecl), 597 do_warn_duplicated_branches_r, NULL); 598 599 /* Dump the C-specific tree IR. */ 600 dump_orig = get_dump_info (TDI_original, &local_dump_flags); 601 if (dump_orig) 602 { 603 fprintf (dump_orig, "\n;; Function %s", 604 lang_hooks.decl_printable_name (fndecl, 2)); 605 fprintf (dump_orig, " (%s)\n", 606 (!DECL_ASSEMBLER_NAME_SET_P (fndecl) ? "null" 607 : IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl)))); 608 fprintf (dump_orig, ";; enabled by -%s\n", dump_flag_name (TDI_original)); 609 fprintf (dump_orig, "\n"); 610 611 if (local_dump_flags & TDF_RAW) 612 dump_node (DECL_SAVED_TREE (fndecl), 613 TDF_SLIM | local_dump_flags, dump_orig); 614 else 615 print_c_tree (dump_orig, DECL_SAVED_TREE (fndecl)); 616 fprintf (dump_orig, "\n"); 617 } 618 619 /* Dump all nested functions now. */ 620 cgn = cgraph_node::get_create (fndecl); 621 for (cgn = first_nested_function (cgn); 622 cgn; cgn = next_nested_function (cgn)) 623 c_genericize (cgn->decl); 624} 625 626static void 627add_block_to_enclosing (tree block) 628{ 629 unsigned i; 630 tree enclosing; 631 gbind *bind; 632 vec<gbind *> stack = gimple_bind_expr_stack (); 633 634 FOR_EACH_VEC_ELT (stack, i, bind) 635 if (gimple_bind_block (bind)) 636 break; 637 638 enclosing = gimple_bind_block (bind); 639 BLOCK_SUBBLOCKS (enclosing) = chainon (BLOCK_SUBBLOCKS (enclosing), block); 640} 641 642/* Genericize a scope by creating a new BIND_EXPR. 643 BLOCK is either a BLOCK representing the scope or a chain of _DECLs. 644 In the latter case, we need to create a new BLOCK and add it to the 645 BLOCK_SUBBLOCKS of the enclosing block. 646 BODY is a chain of C _STMT nodes for the contents of the scope, to be 647 genericized. */ 648 649tree 650c_build_bind_expr (location_t loc, tree block, tree body) 651{ 652 tree decls, bind; 653 654 if (block == NULL_TREE) 655 decls = NULL_TREE; 656 else if (TREE_CODE (block) == BLOCK) 657 decls = BLOCK_VARS (block); 658 else 659 { 660 decls = block; 661 if (DECL_ARTIFICIAL (decls)) 662 block = NULL_TREE; 663 else 664 { 665 block = make_node (BLOCK); 666 BLOCK_VARS (block) = decls; 667 add_block_to_enclosing (block); 668 } 669 } 670 671 if (!body) 672 body = build_empty_stmt (loc); 673 if (decls || block) 674 { 675 bind = build3 (BIND_EXPR, void_type_node, decls, body, block); 676 TREE_SIDE_EFFECTS (bind) = 1; 677 SET_EXPR_LOCATION (bind, loc); 678 } 679 else 680 bind = body; 681 682 return bind; 683} 684 685/* Gimplification of expression trees. */ 686 687/* Do C-specific gimplification on *EXPR_P. PRE_P and POST_P are as in 688 gimplify_expr. */ 689 690int 691c_gimplify_expr (tree *expr_p, gimple_seq *pre_p ATTRIBUTE_UNUSED, 692 gimple_seq *post_p ATTRIBUTE_UNUSED) 693{ 694 enum tree_code code = TREE_CODE (*expr_p); 695 696 switch (code) 697 { 698 case LSHIFT_EXPR: 699 case RSHIFT_EXPR: 700 case LROTATE_EXPR: 701 case RROTATE_EXPR: 702 { 703 /* We used to convert the right operand of a shift-expression 704 to an integer_type_node in the FEs. But it is unnecessary 705 and not desirable for diagnostics and sanitizers. We keep 706 this here to not pessimize the code, but we convert to an 707 unsigned type, because negative shift counts are undefined 708 anyway. 709 We should get rid of this conversion when we have a proper 710 type demotion/promotion pass. */ 711 tree *op1_p = &TREE_OPERAND (*expr_p, 1); 712 if (!VECTOR_TYPE_P (TREE_TYPE (*op1_p)) 713 && !types_compatible_p (TYPE_MAIN_VARIANT (TREE_TYPE (*op1_p)), 714 unsigned_type_node) 715 && !types_compatible_p (TYPE_MAIN_VARIANT (TREE_TYPE (*op1_p)), 716 integer_type_node)) 717 /* Make sure to unshare the result, tree sharing is invalid 718 during gimplification. */ 719 *op1_p = unshare_expr (convert (unsigned_type_node, *op1_p)); 720 break; 721 } 722 723 case PREINCREMENT_EXPR: 724 case PREDECREMENT_EXPR: 725 case POSTINCREMENT_EXPR: 726 case POSTDECREMENT_EXPR: 727 { 728 tree type = TREE_TYPE (TREE_OPERAND (*expr_p, 0)); 729 if (INTEGRAL_TYPE_P (type) && c_promoting_integer_type_p (type)) 730 { 731 if (!TYPE_OVERFLOW_WRAPS (type)) 732 type = unsigned_type_for (type); 733 return gimplify_self_mod_expr (expr_p, pre_p, post_p, 1, type); 734 } 735 break; 736 } 737 738 default:; 739 } 740 741 return GS_UNHANDLED; 742} 743