Branch data Line data Source code
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-2024 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 : : #include "context.h"
44 : : #include "tree-pass.h"
45 : : #include "internal-fn.h"
46 : :
47 : : /* The gimplification pass converts the language-dependent trees
48 : : (ld-trees) emitted by the parser into language-independent trees
49 : : (li-trees) that are the target of SSA analysis and transformations.
50 : :
51 : : Language-independent trees are based on the SIMPLE intermediate
52 : : representation used in the McCAT compiler framework:
53 : :
54 : : "Designing the McCAT Compiler Based on a Family of Structured
55 : : Intermediate Representations,"
56 : : L. Hendren, C. Donawa, M. Emami, G. Gao, Justiani, and B. Sridharan,
57 : : Proceedings of the 5th International Workshop on Languages and
58 : : Compilers for Parallel Computing, no. 757 in Lecture Notes in
59 : : Computer Science, New Haven, Connecticut, pp. 406-420,
60 : : Springer-Verlag, August 3-5, 1992.
61 : :
62 : : http://www-acaps.cs.mcgill.ca/info/McCAT/McCAT.html
63 : :
64 : : Basically, we walk down gimplifying the nodes that we encounter. As we
65 : : walk back up, we check that they fit our constraints, and copy them
66 : : into temporaries if not. */
67 : :
68 : : /* Callback for c_genericize. */
69 : :
70 : : static tree
71 : 997648 : ubsan_walk_array_refs_r (tree *tp, int *walk_subtrees, void *data)
72 : : {
73 : 997648 : hash_set<tree> *pset = (hash_set<tree> *) data;
74 : :
75 : 997648 : if (TREE_CODE (*tp) == BIND_EXPR)
76 : : {
77 : : /* Since walk_tree doesn't call the callback function on the decls
78 : : in BIND_EXPR_VARS, we have to walk them manually, so we can avoid
79 : : instrumenting DECL_INITIAL of TREE_STATIC vars. */
80 : 50183 : *walk_subtrees = 0;
81 : 63648 : for (tree decl = BIND_EXPR_VARS (*tp); decl; decl = DECL_CHAIN (decl))
82 : : {
83 : 13465 : if (TREE_STATIC (decl))
84 : 98 : continue;
85 : 13367 : walk_tree (&DECL_INITIAL (decl), ubsan_walk_array_refs_r, pset,
86 : : pset);
87 : 13367 : walk_tree (&DECL_SIZE (decl), ubsan_walk_array_refs_r, pset, pset);
88 : 13367 : walk_tree (&DECL_SIZE_UNIT (decl), ubsan_walk_array_refs_r, pset,
89 : : pset);
90 : : }
91 : 50183 : walk_tree (&BIND_EXPR_BODY (*tp), ubsan_walk_array_refs_r, pset, pset);
92 : : }
93 : 947465 : else if (TREE_CODE (*tp) == ADDR_EXPR
94 : 947465 : && TREE_CODE (TREE_OPERAND (*tp, 0)) == ARRAY_REF)
95 : : {
96 : 276 : ubsan_maybe_instrument_array_ref (&TREE_OPERAND (*tp, 0), true);
97 : : /* Make sure ubsan_maybe_instrument_array_ref is not called again
98 : : on the ARRAY_REF, the above call might not instrument anything
99 : : as the index might be constant or masked, so ensure it is not
100 : : walked again and walk its subtrees manually. */
101 : 276 : tree aref = TREE_OPERAND (*tp, 0);
102 : 276 : pset->add (aref);
103 : 276 : *walk_subtrees = 0;
104 : 276 : walk_tree (&TREE_OPERAND (aref, 0), ubsan_walk_array_refs_r, pset, pset);
105 : 276 : walk_tree (&TREE_OPERAND (aref, 1), ubsan_walk_array_refs_r, pset, pset);
106 : 276 : walk_tree (&TREE_OPERAND (aref, 2), ubsan_walk_array_refs_r, pset, pset);
107 : 276 : walk_tree (&TREE_OPERAND (aref, 3), ubsan_walk_array_refs_r, pset, pset);
108 : : }
109 : 947189 : else if (TREE_CODE (*tp) == ARRAY_REF)
110 : 3747 : ubsan_maybe_instrument_array_ref (tp, false);
111 : 943442 : else if (TREE_CODE (*tp) == MODIFY_EXPR)
112 : : {
113 : : /* Since r7-1900, we gimplify RHS before LHS. Consider
114 : : a[b] |= c;
115 : : wherein we can have a single shared tree a[b] in both LHS and RHS.
116 : : If we only instrument the LHS and the access is invalid, the program
117 : : could crash before emitting a UBSan error. So instrument the RHS
118 : : first. */
119 : 51562 : *walk_subtrees = 0;
120 : 51562 : walk_tree (&TREE_OPERAND (*tp, 1), ubsan_walk_array_refs_r, pset, pset);
121 : 51562 : walk_tree (&TREE_OPERAND (*tp, 0), ubsan_walk_array_refs_r, pset, pset);
122 : : }
123 : 997648 : return NULL_TREE;
124 : : }
125 : :
126 : : /* Gimplification of statement trees. */
127 : :
128 : : /* Local declarations. */
129 : :
130 : : enum bc_t { bc_break = 0, bc_continue = 1 };
131 : :
132 : : /* Stack of labels which are targets for "break" or "continue",
133 : : linked through TREE_CHAIN. */
134 : : static tree bc_label[2];
135 : :
136 : : /* Begin a scope which can be exited by a break or continue statement. BC
137 : : indicates which.
138 : :
139 : : Just creates a label with location LOCATION and pushes it into the current
140 : : context. */
141 : :
142 : : static tree
143 : 6652045 : begin_bc_block (enum bc_t bc, location_t location)
144 : : {
145 : 6652045 : tree label = create_artificial_label (location);
146 : 6652045 : DECL_CHAIN (label) = bc_label[bc];
147 : 6652045 : bc_label[bc] = label;
148 : 6652045 : if (bc == bc_break)
149 : 3452474 : LABEL_DECL_BREAK (label) = true;
150 : : else
151 : 3199571 : LABEL_DECL_CONTINUE (label) = true;
152 : 6652045 : return label;
153 : : }
154 : :
155 : : /* Finish a scope which can be exited by a break or continue statement.
156 : : LABEL was returned from the most recent call to begin_bc_block. BLOCK is
157 : : an expression for the contents of the scope.
158 : :
159 : : If we saw a break (or continue) in the scope, append a LABEL_EXPR to
160 : : BLOCK. Otherwise, just forget the label. */
161 : :
162 : : static void
163 : 6652045 : finish_bc_block (tree *block, enum bc_t bc, tree label)
164 : : {
165 : 6652045 : gcc_assert (label == bc_label[bc]);
166 : :
167 : 6652045 : if (TREE_USED (label))
168 : 2673794 : append_to_statement_list (build1 (LABEL_EXPR, void_type_node, label),
169 : : block);
170 : :
171 : 6652045 : bc_label[bc] = DECL_CHAIN (label);
172 : 6652045 : DECL_CHAIN (label) = NULL_TREE;
173 : 6652045 : }
174 : :
175 : : /* Allow saving and restoring break/continue state. */
176 : :
177 : : void
178 : 69610300 : save_bc_state (bc_state_t *state)
179 : : {
180 : 69610300 : state->bc_label[bc_break] = bc_label[bc_break];
181 : 69610300 : state->bc_label[bc_continue] = bc_label[bc_continue];
182 : 69610300 : bc_label[bc_break] = NULL_TREE;
183 : 69610300 : bc_label[bc_continue] = NULL_TREE;
184 : 69610300 : }
185 : :
186 : : void
187 : 69610300 : restore_bc_state (bc_state_t *state)
188 : : {
189 : 69610300 : gcc_assert (bc_label[bc_break] == NULL);
190 : 69610300 : gcc_assert (bc_label[bc_continue] == NULL);
191 : 69610300 : bc_label[bc_break] = state->bc_label[bc_break];
192 : 69610300 : bc_label[bc_continue] = state->bc_label[bc_continue];
193 : 69610300 : }
194 : :
195 : : /* Get the LABEL_EXPR to represent a break or continue statement
196 : : in the current block scope. BC indicates which. */
197 : :
198 : : static tree
199 : 3693776 : get_bc_label (enum bc_t bc)
200 : : {
201 : 3693776 : tree label = bc_label[bc];
202 : 3693776 : gcc_assert (label);
203 : :
204 : : /* Mark the label used for finish_bc_block. */
205 : 3693776 : TREE_USED (label) = 1;
206 : 3693776 : return label;
207 : : }
208 : :
209 : : /* Return the location from EXPR, or OR_LOC if the former is unknown. */
210 : :
211 : : location_t
212 : 7597768 : expr_loc_or_loc (const_tree expr, location_t or_loc)
213 : : {
214 : 7597768 : tree t = CONST_CAST_TREE (expr);
215 : 7597768 : location_t loc = UNKNOWN_LOCATION;
216 : 7597768 : if (t)
217 : 5822333 : loc = EXPR_LOCATION (t);
218 : 4751015 : if (loc == UNKNOWN_LOCATION)
219 : 4039923 : loc = or_loc;
220 : 7597768 : return loc;
221 : : }
222 : :
223 : : /* Build a generic representation of one of the C loop forms. COND is the
224 : : loop condition or NULL_TREE. BODY is the (possibly compound) statement
225 : : controlled by the loop. INCR is the increment expression of a for-loop,
226 : : or NULL_TREE. COND_IS_FIRST indicates whether the condition is
227 : : evaluated before the loop body as in while and for loops, or after the
228 : : loop body as in do-while loops. */
229 : :
230 : : static void
231 : 3157809 : genericize_c_loop (tree *stmt_p, location_t start_locus, tree cond, tree body,
232 : : tree incr, bool cond_is_first, int *walk_subtrees,
233 : : void *data, walk_tree_fn func, walk_tree_lh lh)
234 : : {
235 : 3157809 : tree blab, clab;
236 : 3157809 : tree entry = NULL, exit = NULL, t;
237 : 3157809 : tree stmt_list = NULL;
238 : 3157809 : location_t cond_locus = expr_loc_or_loc (cond, start_locus);
239 : 3157809 : location_t incr_locus = expr_loc_or_loc (incr, start_locus);
240 : :
241 : 3157809 : protected_set_expr_location_if_unset (incr, start_locus);
242 : :
243 : 3157809 : walk_tree_1 (&cond, func, data, NULL, lh);
244 : 3157809 : walk_tree_1 (&incr, func, data, NULL, lh);
245 : :
246 : 3157809 : blab = begin_bc_block (bc_break, start_locus);
247 : 3157809 : clab = begin_bc_block (bc_continue, start_locus);
248 : :
249 : 3157809 : walk_tree_1 (&body, func, data, NULL, lh);
250 : 3157809 : *walk_subtrees = 0;
251 : :
252 : : /* If condition is zero don't generate a loop construct. */
253 : 3157809 : if (cond && integer_zerop (cond))
254 : : {
255 : 1015480 : if (cond_is_first)
256 : : {
257 : 166 : t = build1_loc (start_locus, GOTO_EXPR, void_type_node,
258 : : get_bc_label (bc_break));
259 : 166 : append_to_statement_list (t, &stmt_list);
260 : : }
261 : : }
262 : : else
263 : : {
264 : : /* Expand to gotos. */
265 : 2142329 : tree top = build1 (LABEL_EXPR, void_type_node,
266 : : create_artificial_label (start_locus));
267 : :
268 : : /* If we have an exit condition, then we build an IF with gotos either
269 : : out of the loop, or to the top of it. If there's no exit condition,
270 : : then we just build a jump back to the top. */
271 : 2142329 : exit = build1 (GOTO_EXPR, void_type_node, LABEL_EXPR_LABEL (top));
272 : :
273 : 2142329 : if (cond && !integer_nonzerop (cond))
274 : : {
275 : : /* Canonicalize the loop condition to the end. This means
276 : : generating a branch to the loop condition. Reuse the
277 : : continue label, if there is no incr expression. */
278 : 2023265 : if (cond_is_first)
279 : : {
280 : 1878193 : if (incr)
281 : : {
282 : 1444379 : entry = build1 (LABEL_EXPR, void_type_node,
283 : : create_artificial_label (start_locus));
284 : 2888758 : t = build1_loc (start_locus, GOTO_EXPR, void_type_node,
285 : 1444379 : LABEL_EXPR_LABEL (entry));
286 : : }
287 : : else
288 : 433814 : t = build1_loc (start_locus, GOTO_EXPR, void_type_node,
289 : : get_bc_label (bc_continue));
290 : 1878193 : append_to_statement_list (t, &stmt_list);
291 : : }
292 : :
293 : 2023265 : t = build1 (GOTO_EXPR, void_type_node, get_bc_label (bc_break));
294 : 2023265 : exit = fold_build3_loc (cond_locus,
295 : : COND_EXPR, void_type_node, cond, exit, t);
296 : : }
297 : : else
298 : : {
299 : : /* For the backward-goto's location of an unconditional loop
300 : : use the beginning of the body, or, if there is none, the
301 : : top of the loop. */
302 : 119064 : location_t loc = expr_loc_or_loc (expr_first (body),
303 : : start_locus);
304 : 119064 : SET_EXPR_LOCATION (exit, loc);
305 : : }
306 : 2142329 : append_to_statement_list (top, &stmt_list);
307 : : }
308 : :
309 : 3157809 : append_to_statement_list (body, &stmt_list);
310 : 3157809 : if (c_dialect_cxx ()
311 : 2718893 : && stmt_list
312 : 2716982 : && TREE_CODE (stmt_list) == STATEMENT_LIST)
313 : : {
314 : 2716982 : tree_stmt_iterator tsi = tsi_last (stmt_list);
315 : 2716982 : if (!tsi_end_p (tsi))
316 : : {
317 : 2716982 : tree t = *tsi;
318 : 2716982 : while (TREE_CODE (t) == CLEANUP_POINT_EXPR
319 : : || TREE_CODE (t) == EXPR_STMT
320 : 4899319 : || CONVERT_EXPR_CODE_P (TREE_CODE (t)))
321 : 2182337 : t = TREE_OPERAND (t, 0);
322 : : /* For C++, if iteration statement body ends with fallthrough
323 : : statement, mark it such that we diagnose it even if next
324 : : statement would be labeled statement with case/default label. */
325 : 2716982 : if (TREE_CODE (t) == CALL_EXPR
326 : 95761 : && !CALL_EXPR_FN (t)
327 : 2716994 : && CALL_EXPR_IFN (t) == IFN_FALLTHROUGH)
328 : 12 : TREE_NOTHROW (t) = 1;
329 : : }
330 : : }
331 : 3157809 : finish_bc_block (&stmt_list, bc_continue, clab);
332 : 3157809 : if (incr)
333 : : {
334 : 1446876 : if (MAY_HAVE_DEBUG_MARKER_STMTS && incr_locus != UNKNOWN_LOCATION)
335 : : {
336 : 1163086 : tree d = build0 (DEBUG_BEGIN_STMT, void_type_node);
337 : 1163086 : SET_EXPR_LOCATION (d, expr_loc_or_loc (incr, start_locus));
338 : 1163086 : append_to_statement_list (d, &stmt_list);
339 : : }
340 : 1446876 : append_to_statement_list (incr, &stmt_list);
341 : : }
342 : 3157809 : append_to_statement_list (entry, &stmt_list);
343 : :
344 : 3157809 : if (MAY_HAVE_DEBUG_MARKER_STMTS && cond_locus != UNKNOWN_LOCATION)
345 : : {
346 : 2675103 : tree d = build0 (DEBUG_BEGIN_STMT, void_type_node);
347 : 2675103 : SET_EXPR_LOCATION (d, cond_locus);
348 : 2675103 : append_to_statement_list (d, &stmt_list);
349 : : }
350 : 3157809 : append_to_statement_list (exit, &stmt_list);
351 : 3157809 : finish_bc_block (&stmt_list, bc_break, blab);
352 : 3157809 : if (!stmt_list)
353 : 3583 : stmt_list = build_empty_stmt (start_locus);
354 : :
355 : 3157809 : *stmt_p = stmt_list;
356 : 3157809 : }
357 : :
358 : : /* Genericize a FOR_STMT node *STMT_P. */
359 : :
360 : : static void
361 : 1514169 : genericize_for_stmt (tree *stmt_p, int *walk_subtrees, void *data,
362 : : walk_tree_fn func, walk_tree_lh lh)
363 : : {
364 : 1514169 : tree stmt = *stmt_p;
365 : 1514169 : tree expr = NULL;
366 : 1514169 : tree loop;
367 : 1514169 : tree init = FOR_INIT_STMT (stmt);
368 : :
369 : 1514169 : if (init)
370 : : {
371 : 0 : walk_tree_1 (&init, func, data, NULL, lh);
372 : 0 : append_to_statement_list (init, &expr);
373 : : }
374 : :
375 : 3028338 : genericize_c_loop (&loop, EXPR_LOCATION (stmt), FOR_COND (stmt),
376 : 1514169 : FOR_BODY (stmt), FOR_EXPR (stmt), 1, walk_subtrees,
377 : : data, func, lh);
378 : 1514169 : append_to_statement_list (loop, &expr);
379 : 1514169 : if (expr == NULL_TREE)
380 : 0 : expr = loop;
381 : 1514169 : *stmt_p = expr;
382 : 1514169 : }
383 : :
384 : : /* Genericize a WHILE_STMT node *STMT_P. */
385 : :
386 : : static void
387 : 482868 : genericize_while_stmt (tree *stmt_p, int *walk_subtrees, void *data,
388 : : walk_tree_fn func, walk_tree_lh lh)
389 : : {
390 : 482868 : tree stmt = *stmt_p;
391 : 965736 : genericize_c_loop (stmt_p, EXPR_LOCATION (stmt), WHILE_COND (stmt),
392 : 482868 : WHILE_BODY (stmt), NULL_TREE, 1, walk_subtrees,
393 : : data, func, lh);
394 : 482868 : }
395 : :
396 : : /* Genericize a DO_STMT node *STMT_P. */
397 : :
398 : : static void
399 : 1160772 : genericize_do_stmt (tree *stmt_p, int *walk_subtrees, void *data,
400 : : walk_tree_fn func, walk_tree_lh lh)
401 : : {
402 : 1160772 : tree stmt = *stmt_p;
403 : 2321544 : genericize_c_loop (stmt_p, EXPR_LOCATION (stmt), DO_COND (stmt),
404 : 1160772 : DO_BODY (stmt), NULL_TREE, 0, walk_subtrees,
405 : : data, func, lh);
406 : 1160772 : }
407 : :
408 : : /* Genericize a SWITCH_STMT node *STMT_P by turning it into a SWITCH_EXPR. */
409 : :
410 : : static void
411 : 294665 : genericize_switch_stmt (tree *stmt_p, int *walk_subtrees, void *data,
412 : : walk_tree_fn func, walk_tree_lh lh)
413 : : {
414 : 294665 : tree stmt = *stmt_p;
415 : 294665 : tree break_block, body, cond, type;
416 : 294665 : location_t stmt_locus = EXPR_LOCATION (stmt);
417 : :
418 : 294665 : body = SWITCH_STMT_BODY (stmt);
419 : 294665 : if (!body)
420 : 0 : body = build_empty_stmt (stmt_locus);
421 : 294665 : cond = SWITCH_STMT_COND (stmt);
422 : 294665 : type = SWITCH_STMT_TYPE (stmt);
423 : :
424 : 294665 : walk_tree_1 (&cond, func, data, NULL, lh);
425 : :
426 : 294665 : break_block = begin_bc_block (bc_break, stmt_locus);
427 : :
428 : 294665 : walk_tree_1 (&body, func, data, NULL, lh);
429 : 294665 : walk_tree_1 (&type, func, data, NULL, lh);
430 : 294665 : *walk_subtrees = 0;
431 : :
432 : 294665 : if (TREE_USED (break_block))
433 : 139350 : SWITCH_BREAK_LABEL_P (break_block) = 1;
434 : 294665 : finish_bc_block (&body, bc_break, break_block);
435 : 294665 : *stmt_p = build2_loc (stmt_locus, SWITCH_EXPR, type, cond, body);
436 : 294665 : SWITCH_ALL_CASES_P (*stmt_p) = SWITCH_STMT_ALL_CASES_P (stmt);
437 : 294665 : gcc_checking_assert (!SWITCH_STMT_NO_BREAK_P (stmt)
438 : : || !TREE_USED (break_block));
439 : 294665 : }
440 : :
441 : : /* Genericize a CONTINUE_STMT node *STMT_P. */
442 : :
443 : : static void
444 : 22759 : genericize_continue_stmt (tree *stmt_p)
445 : : {
446 : 22759 : tree stmt_list = NULL;
447 : 22759 : tree pred = build_predict_expr (PRED_CONTINUE, NOT_TAKEN);
448 : 22759 : tree label = get_bc_label (bc_continue);
449 : 22759 : location_t location = EXPR_LOCATION (*stmt_p);
450 : 22759 : tree jump = build1_loc (location, GOTO_EXPR, void_type_node, label);
451 : 22759 : append_to_statement_list_force (pred, &stmt_list);
452 : 22759 : append_to_statement_list (jump, &stmt_list);
453 : 22759 : *stmt_p = stmt_list;
454 : 22759 : }
455 : :
456 : : /* Genericize a BREAK_STMT node *STMT_P. */
457 : :
458 : : static void
459 : 1213772 : genericize_break_stmt (tree *stmt_p)
460 : : {
461 : 1213772 : tree label = get_bc_label (bc_break);
462 : 1213772 : location_t location = EXPR_LOCATION (*stmt_p);
463 : 1213772 : *stmt_p = build1_loc (location, GOTO_EXPR, void_type_node, label);
464 : 1213772 : }
465 : :
466 : : /* Genericize a OMP_FOR node *STMT_P. */
467 : :
468 : : static void
469 : 41762 : genericize_omp_for_stmt (tree *stmt_p, int *walk_subtrees, void *data,
470 : : walk_tree_fn func, walk_tree_lh lh)
471 : : {
472 : 41762 : tree stmt = *stmt_p;
473 : 41762 : location_t locus = EXPR_LOCATION (stmt);
474 : 41762 : tree clab = begin_bc_block (bc_continue, locus);
475 : :
476 : 41762 : walk_tree_1 (&OMP_FOR_BODY (stmt), func, data, NULL, lh);
477 : 41762 : if (TREE_CODE (stmt) != OMP_TASKLOOP)
478 : 40250 : walk_tree_1 (&OMP_FOR_CLAUSES (stmt), func, data, NULL, lh);
479 : 41762 : walk_tree_1 (&OMP_FOR_INIT (stmt), func, data, NULL, lh);
480 : 41762 : walk_tree_1 (&OMP_FOR_COND (stmt), func, data, NULL, lh);
481 : 41762 : walk_tree_1 (&OMP_FOR_INCR (stmt), func, data, NULL, lh);
482 : 41762 : walk_tree_1 (&OMP_FOR_PRE_BODY (stmt), func, data, NULL, lh);
483 : 41762 : *walk_subtrees = 0;
484 : :
485 : 41762 : finish_bc_block (&OMP_FOR_BODY (stmt), bc_continue, clab);
486 : 41762 : }
487 : :
488 : :
489 : : /* Lower structured control flow tree nodes, such as loops. The
490 : : STMT_P, WALK_SUBTREES, and DATA arguments are as for the walk_tree_fn
491 : : type. FUNC and LH are language-specific functions passed to walk_tree_1
492 : : for node visiting and traversal, respectively; they are used to do
493 : : subtree processing in a language-dependent way. */
494 : :
495 : : tree
496 : 632329648 : c_genericize_control_stmt (tree *stmt_p, int *walk_subtrees, void *data,
497 : : walk_tree_fn func, walk_tree_lh lh)
498 : : {
499 : 632329648 : tree stmt = *stmt_p;
500 : :
501 : 632329648 : switch (TREE_CODE (stmt))
502 : : {
503 : 1514169 : case FOR_STMT:
504 : 1514169 : genericize_for_stmt (stmt_p, walk_subtrees, data, func, lh);
505 : 1514169 : break;
506 : :
507 : 482868 : case WHILE_STMT:
508 : 482868 : genericize_while_stmt (stmt_p, walk_subtrees, data, func, lh);
509 : 482868 : break;
510 : :
511 : 1160772 : case DO_STMT:
512 : 1160772 : genericize_do_stmt (stmt_p, walk_subtrees, data, func, lh);
513 : 1160772 : break;
514 : :
515 : 294665 : case SWITCH_STMT:
516 : 294665 : genericize_switch_stmt (stmt_p, walk_subtrees, data, func, lh);
517 : 294665 : break;
518 : :
519 : 22759 : case CONTINUE_STMT:
520 : 22759 : genericize_continue_stmt (stmt_p);
521 : 22759 : break;
522 : :
523 : 1213772 : case BREAK_STMT:
524 : 1213772 : genericize_break_stmt (stmt_p);
525 : 1213772 : break;
526 : :
527 : 41762 : case OMP_FOR:
528 : 41762 : case OMP_SIMD:
529 : 41762 : case OMP_DISTRIBUTE:
530 : 41762 : case OMP_LOOP:
531 : 41762 : case OMP_TASKLOOP:
532 : 41762 : case OACC_LOOP:
533 : 41762 : genericize_omp_for_stmt (stmt_p, walk_subtrees, data, func, lh);
534 : 41762 : break;
535 : :
536 : 48713294 : case STATEMENT_LIST:
537 : 48713294 : if (TREE_SIDE_EFFECTS (stmt))
538 : : {
539 : 46485772 : tree_stmt_iterator i;
540 : 46485772 : int nondebug_stmts = 0;
541 : 46485772 : bool clear_side_effects = true;
542 : : /* Genericization can clear TREE_SIDE_EFFECTS, e.g. when
543 : : transforming an IF_STMT into COND_EXPR. If such stmt
544 : : appears in a STATEMENT_LIST that contains only that
545 : : stmt and some DEBUG_BEGIN_STMTs, without -g where the
546 : : STATEMENT_LIST wouldn't be present at all the resulting
547 : : expression wouldn't have TREE_SIDE_EFFECTS set, so make sure
548 : : to clear it even on the STATEMENT_LIST in such cases. */
549 : 92971544 : hash_set<tree> *pset = (c_dialect_cxx ()
550 : 46485772 : ? nullptr
551 : : : static_cast<hash_set<tree> *>(data));
552 : 200636218 : for (i = tsi_start (stmt); !tsi_end_p (i); tsi_next (&i))
553 : : {
554 : 154150446 : tree t = tsi_stmt (i);
555 : 154150446 : if (TREE_CODE (t) != DEBUG_BEGIN_STMT && nondebug_stmts < 2)
556 : 71947326 : nondebug_stmts++;
557 : 154150446 : walk_tree_1 (tsi_stmt_ptr (i), func, data, pset, lh);
558 : 154150446 : if (TREE_CODE (t) != DEBUG_BEGIN_STMT
559 : 154150446 : && (nondebug_stmts > 1 || TREE_SIDE_EFFECTS (tsi_stmt (i))))
560 : : clear_side_effects = false;
561 : : }
562 : 46485772 : if (clear_side_effects)
563 : 2433 : TREE_SIDE_EFFECTS (stmt) = 0;
564 : 46485772 : *walk_subtrees = 0;
565 : : }
566 : : break;
567 : :
568 : : default:
569 : : break;
570 : : }
571 : :
572 : 632329648 : return NULL;
573 : : }
574 : :
575 : :
576 : : /* Wrapper for c_genericize_control_stmt to allow it to be used as a walk_tree
577 : : callback. This is appropriate for C; C++ calls c_genericize_control_stmt
578 : : directly. */
579 : :
580 : : static tree
581 : 583019773 : c_genericize_control_r (tree *stmt_p, int *walk_subtrees, void *data)
582 : : {
583 : 583019773 : c_genericize_control_stmt (stmt_p, walk_subtrees, data,
584 : : c_genericize_control_r, NULL);
585 : 583019773 : return NULL;
586 : : }
587 : :
588 : : /* Convert the tree representation of FNDECL from C frontend trees to
589 : : GENERIC. */
590 : :
591 : : void
592 : 69610300 : c_genericize (tree fndecl)
593 : : {
594 : 69610300 : dump_file_info *dfi;
595 : 69610300 : FILE *dump_orig;
596 : 69610300 : dump_flags_t local_dump_flags;
597 : 69610300 : struct cgraph_node *cgn;
598 : :
599 : 69610300 : if (flag_sanitize & SANITIZE_BOUNDS)
600 : : {
601 : 52644 : hash_set<tree> pset;
602 : 52644 : walk_tree (&DECL_SAVED_TREE (fndecl), ubsan_walk_array_refs_r, &pset,
603 : : &pset);
604 : 52644 : }
605 : :
606 : : /* Genericize loops and other structured control constructs. The C++
607 : : front end has already done this in lang-specific code. */
608 : 69610300 : if (!c_dialect_cxx ())
609 : : {
610 : 31771492 : bc_state_t save_state;
611 : 31771492 : push_cfun (DECL_STRUCT_FUNCTION (fndecl));
612 : 31771492 : save_bc_state (&save_state);
613 : 31771492 : hash_set<tree> pset;
614 : 31771492 : walk_tree (&DECL_SAVED_TREE (fndecl), c_genericize_control_r, &pset,
615 : : &pset);
616 : 31771492 : restore_bc_state (&save_state);
617 : 31771492 : pop_cfun ();
618 : 31771492 : }
619 : :
620 : 69610300 : if (warn_duplicated_branches)
621 : 163 : walk_tree_without_duplicates (&DECL_SAVED_TREE (fndecl),
622 : : do_warn_duplicated_branches_r, NULL);
623 : :
624 : : /* Dump the C-specific tree IR. */
625 : 69610300 : dfi = g->get_dumps ()->get_dump_file_info (TDI_original);
626 : 69610300 : dump_orig = dfi->pstream;
627 : 69610300 : local_dump_flags = dfi->pflags;
628 : 69610300 : if (dump_orig)
629 : : {
630 : 1170 : fprintf (dump_orig, "\n;; Function %s",
631 : 1170 : lang_hooks.decl_printable_name (fndecl, 2));
632 : 1170 : fprintf (dump_orig, " (%s)\n",
633 : 1170 : (!DECL_ASSEMBLER_NAME_SET_P (fndecl) ? "null"
634 : 3 : : IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl))));
635 : 1170 : fprintf (dump_orig, ";; enabled by -%s\n", dump_flag_name (TDI_original));
636 : 1170 : fprintf (dump_orig, "\n");
637 : :
638 : 1170 : if (local_dump_flags & TDF_RAW)
639 : 1 : dump_node (DECL_SAVED_TREE (fndecl),
640 : : TDF_SLIM | local_dump_flags, dump_orig);
641 : : else
642 : 1169 : print_c_tree (dump_orig, DECL_SAVED_TREE (fndecl));
643 : 1170 : fprintf (dump_orig, "\n");
644 : : }
645 : :
646 : : /* Dump all nested functions now. */
647 : 69610300 : cgn = cgraph_node::get_create (fndecl);
648 : 69611807 : for (cgn = first_nested_function (cgn);
649 : 69611807 : cgn; cgn = next_nested_function (cgn))
650 : 1507 : c_genericize (cgn->decl);
651 : 69610300 : }
652 : :
653 : : static void
654 : 0 : add_block_to_enclosing (tree block)
655 : : {
656 : 0 : unsigned i;
657 : 0 : tree enclosing;
658 : 0 : gbind *bind;
659 : 0 : vec<gbind *> stack = gimple_bind_expr_stack ();
660 : :
661 : 0 : FOR_EACH_VEC_ELT (stack, i, bind)
662 : 0 : if (gimple_bind_block (bind))
663 : : break;
664 : :
665 : 0 : enclosing = gimple_bind_block (bind);
666 : 0 : BLOCK_SUBBLOCKS (enclosing) = chainon (BLOCK_SUBBLOCKS (enclosing), block);
667 : 0 : }
668 : :
669 : : /* Genericize a scope by creating a new BIND_EXPR.
670 : : BLOCK is either a BLOCK representing the scope or a chain of _DECLs.
671 : : In the latter case, we need to create a new BLOCK and add it to the
672 : : BLOCK_SUBBLOCKS of the enclosing block.
673 : : BODY is a chain of C _STMT nodes for the contents of the scope, to be
674 : : genericized. */
675 : :
676 : : tree
677 : 121470041 : c_build_bind_expr (location_t loc, tree block, tree body)
678 : : {
679 : 121470041 : tree decls, bind;
680 : :
681 : 121470041 : if (block == NULL_TREE)
682 : : decls = NULL_TREE;
683 : 52102864 : else if (TREE_CODE (block) == BLOCK)
684 : 52102864 : decls = BLOCK_VARS (block);
685 : : else
686 : : {
687 : 0 : decls = block;
688 : 0 : if (DECL_ARTIFICIAL (decls))
689 : : block = NULL_TREE;
690 : : else
691 : : {
692 : 0 : block = make_node (BLOCK);
693 : 0 : BLOCK_VARS (block) = decls;
694 : 0 : add_block_to_enclosing (block);
695 : : }
696 : : }
697 : :
698 : 121470041 : if (!body)
699 : 0 : body = build_empty_stmt (loc);
700 : 121470041 : if (decls || block)
701 : : {
702 : 52102864 : bind = build3 (BIND_EXPR, void_type_node, decls, body, block);
703 : 52102864 : TREE_SIDE_EFFECTS (bind) = 1;
704 : 52102864 : SET_EXPR_LOCATION (bind, loc);
705 : : }
706 : : else
707 : : bind = body;
708 : :
709 : 121470041 : return bind;
710 : : }
711 : :
712 : : /* Helper for c_gimplify_expr: test if target supports fma-like FN. */
713 : :
714 : : static bool
715 : 0 : fma_supported_p (enum internal_fn fn, tree type)
716 : : {
717 : 0 : return direct_internal_fn_supported_p (fn, type, OPTIMIZE_FOR_BOTH);
718 : : }
719 : :
720 : : /* Gimplification of expression trees. */
721 : :
722 : : /* Do C-specific gimplification on *EXPR_P. PRE_P and POST_P are as in
723 : : gimplify_expr. */
724 : :
725 : : int
726 : 242819910 : c_gimplify_expr (tree *expr_p, gimple_seq *pre_p ATTRIBUTE_UNUSED,
727 : : gimple_seq *post_p ATTRIBUTE_UNUSED)
728 : : {
729 : 242819910 : enum tree_code code = TREE_CODE (*expr_p);
730 : :
731 : 242819910 : switch (code)
732 : : {
733 : 353454 : case LSHIFT_EXPR:
734 : 353454 : case RSHIFT_EXPR:
735 : 353454 : case LROTATE_EXPR:
736 : 353454 : case RROTATE_EXPR:
737 : 353454 : {
738 : : /* We used to convert the right operand of a shift-expression
739 : : to an integer_type_node in the FEs. But it is unnecessary
740 : : and not desirable for diagnostics and sanitizers. We keep
741 : : this here to not pessimize the code, but we convert to an
742 : : unsigned type, because negative shift counts are undefined
743 : : anyway.
744 : : We should get rid of this conversion when we have a proper
745 : : type demotion/promotion pass. */
746 : 353454 : tree *op1_p = &TREE_OPERAND (*expr_p, 1);
747 : 353454 : if (!VECTOR_TYPE_P (TREE_TYPE (*op1_p))
748 : 351757 : && !types_compatible_p (TYPE_MAIN_VARIANT (TREE_TYPE (*op1_p)),
749 : : unsigned_type_node)
750 : 651493 : && !types_compatible_p (TYPE_MAIN_VARIANT (TREE_TYPE (*op1_p)),
751 : : integer_type_node))
752 : : /* Make sure to unshare the result, tree sharing is invalid
753 : : during gimplification. */
754 : 21402 : *op1_p = unshare_expr (convert (unsigned_type_node, *op1_p));
755 : : break;
756 : : }
757 : :
758 : 1100170 : case PREINCREMENT_EXPR:
759 : 1100170 : case PREDECREMENT_EXPR:
760 : 1100170 : case POSTINCREMENT_EXPR:
761 : 1100170 : case POSTDECREMENT_EXPR:
762 : 1100170 : {
763 : 1100170 : tree type = TREE_TYPE (TREE_OPERAND (*expr_p, 0));
764 : 1100170 : if (INTEGRAL_TYPE_P (type) && c_promoting_integer_type_p (type))
765 : : {
766 : 5705 : if (!TYPE_OVERFLOW_WRAPS (type))
767 : 3199 : type = unsigned_type_for (type);
768 : 5705 : return gimplify_self_mod_expr (expr_p, pre_p, post_p, 1, type);
769 : : }
770 : : break;
771 : : }
772 : :
773 : 7165490 : case PLUS_EXPR:
774 : 7165490 : case MINUS_EXPR:
775 : 7165490 : {
776 : 7165490 : tree type = TREE_TYPE (*expr_p);
777 : : /* For -ffp-contract=on we need to attempt FMA contraction only
778 : : during initial gimplification. Late contraction across statement
779 : : boundaries would violate language semantics. */
780 : 7165490 : if (SCALAR_FLOAT_TYPE_P (type)
781 : 954989 : && flag_fp_contract_mode == FP_CONTRACT_ON
782 : 0 : && cfun && !(cfun->curr_properties & PROP_gimple_any)
783 : 7165490 : && fma_supported_p (IFN_FMA, type))
784 : : {
785 : 0 : bool neg_mul = false, neg_add = code == MINUS_EXPR;
786 : :
787 : 0 : tree *op0_p = &TREE_OPERAND (*expr_p, 0);
788 : 0 : tree *op1_p = &TREE_OPERAND (*expr_p, 1);
789 : :
790 : : /* Look for ±(x * y) ± z, swapping operands if necessary. */
791 : 0 : if (TREE_CODE (*op0_p) == NEGATE_EXPR
792 : 0 : && TREE_CODE (TREE_OPERAND (*op0_p, 0)) == MULT_EXPR)
793 : : /* '*EXPR_P' is '-(x * y) ± z'. This is fine. */;
794 : 0 : else if (TREE_CODE (*op0_p) != MULT_EXPR)
795 : : {
796 : : std::swap (op0_p, op1_p);
797 : : std::swap (neg_mul, neg_add);
798 : : }
799 : 0 : if (TREE_CODE (*op0_p) == NEGATE_EXPR)
800 : : {
801 : 0 : op0_p = &TREE_OPERAND (*op0_p, 0);
802 : 0 : neg_mul = !neg_mul;
803 : : }
804 : 0 : if (TREE_CODE (*op0_p) != MULT_EXPR)
805 : : break;
806 : 0 : auto_vec<tree, 3> ops (3);
807 : 0 : ops.quick_push (TREE_OPERAND (*op0_p, 0));
808 : 0 : ops.quick_push (TREE_OPERAND (*op0_p, 1));
809 : 0 : ops.quick_push (*op1_p);
810 : :
811 : 0 : enum internal_fn ifn = IFN_FMA;
812 : 0 : if (neg_mul)
813 : : {
814 : 0 : if (fma_supported_p (IFN_FNMA, type))
815 : : ifn = IFN_FNMA;
816 : : else
817 : 0 : ops[0] = build1 (NEGATE_EXPR, type, ops[0]);
818 : : }
819 : 0 : if (neg_add)
820 : : {
821 : 0 : enum internal_fn ifn2 = ifn == IFN_FMA ? IFN_FMS : IFN_FNMS;
822 : 0 : if (fma_supported_p (ifn2, type))
823 : : ifn = ifn2;
824 : : else
825 : 0 : ops[2] = build1 (NEGATE_EXPR, type, ops[2]);
826 : : }
827 : : /* Avoid gimplify_arg: it emits all side effects into *PRE_P. */
828 : 0 : for (auto &&op : ops)
829 : 0 : if (gimplify_expr (&op, pre_p, post_p, is_gimple_val, fb_rvalue)
830 : : == GS_ERROR)
831 : : return GS_ERROR;
832 : :
833 : 0 : gcall *call = gimple_build_call_internal_vec (ifn, ops);
834 : 0 : gimple_seq_add_stmt_without_update (pre_p, call);
835 : 0 : *expr_p = create_tmp_var (type);
836 : 0 : gimple_call_set_lhs (call, *expr_p);
837 : 0 : return GS_ALL_DONE;
838 : 0 : }
839 : : break;
840 : : }
841 : :
842 : 3651636 : case CALL_EXPR:
843 : 3651636 : {
844 : 3651636 : tree fndecl = get_callee_fndecl (*expr_p);
845 : 3651636 : if (fndecl
846 : 3421238 : && fndecl_built_in_p (fndecl, BUILT_IN_CLZG, BUILT_IN_CTZG)
847 : 61 : && call_expr_nargs (*expr_p) == 2
848 : 3651697 : && TREE_CODE (CALL_EXPR_ARG (*expr_p, 1)) != INTEGER_CST)
849 : : {
850 : 61 : tree a = save_expr (CALL_EXPR_ARG (*expr_p, 0));
851 : 61 : tree c = build_call_expr_loc (EXPR_LOCATION (*expr_p),
852 : : fndecl, 1, a);
853 : 122 : *expr_p = build3_loc (EXPR_LOCATION (*expr_p), COND_EXPR,
854 : : integer_type_node,
855 : 61 : build2_loc (EXPR_LOCATION (*expr_p),
856 : : NE_EXPR, boolean_type_node, a,
857 : 61 : build_zero_cst (TREE_TYPE (a))),
858 : 61 : c, CALL_EXPR_ARG (*expr_p, 1));
859 : 61 : return GS_OK;
860 : : }
861 : : break;
862 : : }
863 : :
864 : : default:;
865 : : }
866 : :
867 : : return GS_UNHANDLED;
868 : : }
|