c-gimplify.cc revision 1.1 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