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