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
10 This file is part of GCC.
11
12 GCC is free software; you can redistribute it and/or modify it under
13 the terms of the GNU General Public License as published by the Free
14 Software Foundation; either version 3, or (at your option) any later
15 version.
16
17 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
18 WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 for more details.
21
22 You should have received a copy of the GNU General Public License
23 along 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
67 static tree
ubsan_walk_array_refs_r(tree * tp,int * walk_subtrees,void * data)68 ubsan_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
127 enum 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. */
131 static 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
139 static tree
begin_bc_block(enum bc_t bc,location_t location)140 begin_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
159 static void
finish_bc_block(tree * block,enum bc_t bc,tree label)160 finish_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
174 void
save_bc_state(bc_state_t * state)175 save_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
183 void
restore_bc_state(bc_state_t * state)184 restore_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
195 static tree
get_bc_label(enum bc_t bc)196 get_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
208 location_t
expr_loc_or_loc(const_tree expr,location_t or_loc)209 expr_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
227 static void
genericize_c_loop(tree * stmt_p,location_t start_locus,tree cond,tree body,tree incr,bool cond_is_first,int * walk_subtrees,void * data,walk_tree_fn func,walk_tree_lh lh)228 genericize_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
336 static void
genericize_for_stmt(tree * stmt_p,int * walk_subtrees,void * data,walk_tree_fn func,walk_tree_lh lh)337 genericize_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
362 static void
genericize_while_stmt(tree * stmt_p,int * walk_subtrees,void * data,walk_tree_fn func,walk_tree_lh lh)363 genericize_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
374 static void
genericize_do_stmt(tree * stmt_p,int * walk_subtrees,void * data,walk_tree_fn func,walk_tree_lh lh)375 genericize_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
386 static void
genericize_switch_stmt(tree * stmt_p,int * walk_subtrees,void * data,walk_tree_fn func,walk_tree_lh lh)387 genericize_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
419 static void
genericize_continue_stmt(tree * stmt_p)420 genericize_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
434 static void
genericize_break_stmt(tree * stmt_p)435 genericize_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
444 static void
genericize_omp_for_stmt(tree * stmt_p,int * walk_subtrees,void * data,walk_tree_fn func,walk_tree_lh lh)445 genericize_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
471 tree
c_genericize_control_stmt(tree * stmt_p,int * walk_subtrees,void * data,walk_tree_fn func,walk_tree_lh lh)472 c_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
556 static tree
c_genericize_control_r(tree * stmt_p,int * walk_subtrees,void * data)557 c_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
567 void
c_genericize(tree fndecl)568 c_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
626 static void
add_block_to_enclosing(tree block)627 add_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
649 tree
c_build_bind_expr(location_t loc,tree block,tree body)650 c_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
690 int
c_gimplify_expr(tree * expr_p,gimple_seq * pre_p ATTRIBUTE_UNUSED,gimple_seq * post_p ATTRIBUTE_UNUSED)691 c_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