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-2026 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 : #include "omp-general.h"
47 :
48 : /* The gimplification pass converts the language-dependent trees
49 : (ld-trees) emitted by the parser into language-independent trees
50 : (li-trees) that are the target of SSA analysis and transformations.
51 :
52 : Language-independent trees are based on the SIMPLE intermediate
53 : representation used in the McCAT compiler framework:
54 :
55 : "Designing the McCAT Compiler Based on a Family of Structured
56 : Intermediate Representations,"
57 : L. Hendren, C. Donawa, M. Emami, G. Gao, Justiani, and B. Sridharan,
58 : Proceedings of the 5th International Workshop on Languages and
59 : Compilers for Parallel Computing, no. 757 in Lecture Notes in
60 : Computer Science, New Haven, Connecticut, pp. 406-420,
61 : Springer-Verlag, August 3-5, 1992.
62 :
63 : http://www-acaps.cs.mcgill.ca/info/McCAT/McCAT.html
64 :
65 : Basically, we walk down gimplifying the nodes that we encounter. As we
66 : walk back up, we check that they fit our constraints, and copy them
67 : into temporaries if not. */
68 :
69 :
70 : /* Check whether TP is an address computation whose base is a call to
71 : .ACCESS_WITH_SIZE. */
72 :
73 : static bool
74 1166128 : is_address_with_access_with_size (tree tp)
75 : {
76 1166128 : if (TREE_CODE (tp) == POINTER_PLUS_EXPR
77 1166128 : && is_access_with_size_p (TREE_OPERAND (tp, 0)))
78 : return true;
79 : return false;
80 : }
81 :
82 : /* Callback for c_genericize. */
83 :
84 : static tree
85 1293147 : ubsan_walk_array_refs_r (tree *tp, int *walk_subtrees, void *data)
86 : {
87 1293147 : hash_set<tree> *pset = (hash_set<tree> *) data;
88 :
89 1293147 : if (TREE_CODE (*tp) == BIND_EXPR)
90 : {
91 : /* Since walk_tree doesn't call the callback function on the decls
92 : in BIND_EXPR_VARS, we have to walk them manually, so we can avoid
93 : instrumenting DECL_INITIAL of TREE_STATIC vars. */
94 65754 : *walk_subtrees = 0;
95 81789 : for (tree decl = BIND_EXPR_VARS (*tp); decl; decl = DECL_CHAIN (decl))
96 : {
97 16035 : if (TREE_STATIC (decl))
98 155 : continue;
99 15880 : walk_tree (&DECL_INITIAL (decl), ubsan_walk_array_refs_r, pset,
100 : pset);
101 15880 : walk_tree (&DECL_SIZE (decl), ubsan_walk_array_refs_r, pset, pset);
102 15880 : walk_tree (&DECL_SIZE_UNIT (decl), ubsan_walk_array_refs_r, pset,
103 : pset);
104 : }
105 65754 : walk_tree (&BIND_EXPR_BODY (*tp), ubsan_walk_array_refs_r, pset, pset);
106 : }
107 1227393 : else if (TREE_CODE (*tp) == ADDR_EXPR
108 1227393 : && TREE_CODE (TREE_OPERAND (*tp, 0)) == ARRAY_REF)
109 : {
110 259 : ubsan_maybe_instrument_array_ref (&TREE_OPERAND (*tp, 0), true);
111 : /* Make sure ubsan_maybe_instrument_array_ref is not called again
112 : on the ARRAY_REF, the above call might not instrument anything
113 : as the index might be constant or masked, so ensure it is not
114 : walked again and walk its subtrees manually. */
115 259 : tree aref = TREE_OPERAND (*tp, 0);
116 259 : pset->add (aref);
117 259 : *walk_subtrees = 0;
118 259 : walk_tree (&TREE_OPERAND (aref, 0), ubsan_walk_array_refs_r, pset, pset);
119 259 : walk_tree (&TREE_OPERAND (aref, 1), ubsan_walk_array_refs_r, pset, pset);
120 259 : walk_tree (&TREE_OPERAND (aref, 2), ubsan_walk_array_refs_r, pset, pset);
121 259 : walk_tree (&TREE_OPERAND (aref, 3), ubsan_walk_array_refs_r, pset, pset);
122 : }
123 1227134 : else if (TREE_CODE (*tp) == ARRAY_REF)
124 4062 : ubsan_maybe_instrument_array_ref (tp, false);
125 1223072 : else if (TREE_CODE (*tp) == MODIFY_EXPR)
126 : {
127 : /* Since r7-1900, we gimplify RHS before LHS. Consider
128 : a[b] |= c;
129 : wherein we can have a single shared tree a[b] in both LHS and RHS.
130 : If we only instrument the LHS and the access is invalid, the program
131 : could crash before emitting a UBSan error. So instrument the RHS
132 : first. */
133 67815 : *walk_subtrees = 0;
134 67815 : walk_tree (&TREE_OPERAND (*tp, 1), ubsan_walk_array_refs_r, pset, pset);
135 67815 : walk_tree (&TREE_OPERAND (*tp, 0), ubsan_walk_array_refs_r, pset, pset);
136 : }
137 1155257 : else if (TREE_CODE (*tp) == INDIRECT_REF
138 1155257 : && is_address_with_access_with_size (TREE_OPERAND (*tp, 0)))
139 : {
140 157 : ubsan_maybe_instrument_array_ref (&TREE_OPERAND (*tp, 0), false);
141 : /* Make sure ubsan_maybe_instrument_array_ref is not called again on
142 : the POINTER_PLUS_EXPR, so ensure it is not walked again and walk
143 : its subtrees manually. */
144 157 : tree aref = TREE_OPERAND (*tp, 0);
145 157 : pset->add (aref);
146 157 : *walk_subtrees = 0;
147 157 : walk_tree (&TREE_OPERAND (aref, 0), ubsan_walk_array_refs_r, pset, pset);
148 : }
149 1155100 : else if (is_address_with_access_with_size (*tp))
150 0 : ubsan_maybe_instrument_array_ref (tp, true);
151 1293147 : return NULL_TREE;
152 : }
153 :
154 : /* Gimplification of statement trees. */
155 :
156 : /* Local declarations. */
157 :
158 : enum bc_t { bc_break = 0, bc_continue = 1 };
159 :
160 : /* Stack of labels which are targets for "break" or "continue",
161 : linked through TREE_CHAIN. */
162 : static tree bc_label[2];
163 :
164 : /* Hash map from loop/switch names (identified by LABEL_DECL) to
165 : corresponding break and (if any) continue labels. */
166 : static bc_hash_map_t *bc_hash_map;
167 :
168 : /* Begin a scope which can be exited by a break or continue statement. BC
169 : indicates which.
170 :
171 : Just creates a label with location LOCATION and pushes it into the current
172 : context. */
173 :
174 : static tree
175 9946546 : begin_bc_block (enum bc_t bc, location_t location)
176 : {
177 9946546 : tree label = create_artificial_label (location);
178 9946546 : DECL_CHAIN (label) = bc_label[bc];
179 9946546 : bc_label[bc] = label;
180 9946546 : if (bc == bc_break)
181 5285166 : LABEL_DECL_BREAK (label) = true;
182 : else
183 4661380 : LABEL_DECL_CONTINUE (label) = true;
184 9946546 : return label;
185 : }
186 :
187 : /* Finish a scope which can be exited by a break or continue statement.
188 : LABEL was returned from the most recent call to begin_bc_block. BLOCK is
189 : an expression for the contents of the scope.
190 :
191 : If we saw a break (or continue) in the scope, append a LABEL_EXPR to
192 : BLOCK. Otherwise, just forget the label. */
193 :
194 : static void
195 9946546 : finish_bc_block (tree *block, enum bc_t bc, tree label)
196 : {
197 9946546 : gcc_assert (label == bc_label[bc]);
198 :
199 9946546 : if (TREE_USED (label))
200 4325661 : append_to_statement_list (build1 (LABEL_EXPR, void_type_node, label),
201 : block);
202 :
203 9946546 : bc_label[bc] = DECL_CHAIN (label);
204 9946546 : DECL_CHAIN (label) = NULL_TREE;
205 9946546 : }
206 :
207 : /* For named loop or switch with NAME, remember corresponding break
208 : label BLAB and continue label CLAB. */
209 :
210 : static void
211 51 : note_named_bc (tree name, tree blab, tree clab)
212 : {
213 51 : if (bc_hash_map == NULL)
214 15 : bc_hash_map = new bc_hash_map_t (32);
215 51 : bc_hash_map->put (name, std::make_pair (blab, clab));
216 51 : }
217 :
218 : /* Remove NAME from the map after processing body of the loop or
219 : switch. */
220 :
221 : static void
222 51 : release_named_bc (tree name)
223 : {
224 0 : bc_hash_map->remove (name);
225 0 : }
226 :
227 : /* Allow saving and restoring break/continue state. */
228 :
229 : void
230 90988831 : save_bc_state (bc_state_t *state)
231 : {
232 90988831 : state->bc_label[bc_break] = bc_label[bc_break];
233 90988831 : state->bc_label[bc_continue] = bc_label[bc_continue];
234 90988831 : state->bc_hash_map = bc_hash_map;
235 90988831 : bc_label[bc_break] = NULL_TREE;
236 90988831 : bc_label[bc_continue] = NULL_TREE;
237 90988831 : bc_hash_map = NULL;
238 90988831 : }
239 :
240 : void
241 90988831 : restore_bc_state (bc_state_t *state)
242 : {
243 90988831 : gcc_assert (bc_label[bc_break] == NULL);
244 90988831 : gcc_assert (bc_label[bc_continue] == NULL);
245 90988831 : gcc_assert (bc_hash_map == NULL);
246 90988831 : bc_label[bc_break] = state->bc_label[bc_break];
247 90988831 : bc_label[bc_continue] = state->bc_label[bc_continue];
248 90988831 : bc_hash_map = state->bc_hash_map;
249 90988831 : }
250 :
251 : /* Get the LABEL_EXPR to represent a break or continue statement
252 : in the current block scope. BC indicates which. */
253 :
254 : static tree
255 6207785 : get_bc_label (enum bc_t bc)
256 : {
257 6207785 : tree label = bc_label[bc];
258 6207785 : gcc_assert (label);
259 :
260 : /* Mark the label used for finish_bc_block. */
261 6207785 : TREE_USED (label) = 1;
262 6207785 : return label;
263 : }
264 :
265 : /* Return the location from EXPR, or OR_LOC if the former is unknown. */
266 :
267 : location_t
268 11003329 : expr_loc_or_loc (const_tree expr, location_t or_loc)
269 : {
270 11003329 : tree t = const_cast<tree> (expr);
271 11003329 : location_t loc = UNKNOWN_LOCATION;
272 11003329 : if (t)
273 8268654 : loc = EXPR_LOCATION (t);
274 6802676 : if (loc == UNKNOWN_LOCATION)
275 5907076 : loc = or_loc;
276 11003329 : return loc;
277 : }
278 :
279 : /* Build a generic representation of one of the C loop forms. COND is the
280 : loop condition or NULL_TREE. BODY is the (possibly compound) statement
281 : controlled by the loop. INCR is the increment expression of a for-loop,
282 : or NULL_TREE. COND_IS_FIRST indicates whether the condition is
283 : evaluated before the loop body as in while and for loops, or after the
284 : loop body as in do-while loops. COND_PREP and COND_CLEANUP are used
285 : for C++ for/while loops with variable declaration as condition. COND_PREP
286 : is a BIND_EXPR with the declaration and initialization of the condition
287 : variable, into which COND, BODY, continue label if needed and INCR if
288 : non-NULL should be appended, and COND_CLEANUP is number of nested
289 : CLEANUP_STMT -> TRY_FINALLY_EXPR statements at the end. If non-NULL,
290 : COND, BODY, continue label if needed and INCR if non-NULL should be
291 : appended to the body of the COND_CLEANUP's nested TRY_FINALLY_EXPR. */
292 :
293 : static void
294 4619060 : genericize_c_loop (tree *stmt_p, location_t start_locus, tree cond, tree body,
295 : tree incr, tree name, tree cond_prep, tree cond_cleanup,
296 : bool cond_is_first, int *walk_subtrees, void *data,
297 : walk_tree_fn func, walk_tree_lh lh)
298 : {
299 4619060 : tree blab, clab;
300 4619060 : tree entry = NULL, exit = NULL, t;
301 4619060 : tree stmt_list = NULL, outer_stmt_list = NULL_TREE, *stmt_list_p = NULL;
302 4619060 : location_t cond_locus = expr_loc_or_loc (cond, start_locus);
303 4619060 : location_t incr_locus = expr_loc_or_loc (incr, start_locus);
304 :
305 4619060 : protected_set_expr_location_if_unset (incr, start_locus);
306 :
307 4619060 : walk_tree_1 (&cond_prep, func, data, NULL, lh);
308 4619060 : walk_tree_1 (&cond, func, data, NULL, lh);
309 4619060 : walk_tree_1 (&incr, func, data, NULL, lh);
310 :
311 4619060 : blab = begin_bc_block (bc_break, start_locus);
312 4619060 : clab = begin_bc_block (bc_continue, start_locus);
313 4619060 : if (name)
314 39 : note_named_bc (name, blab, clab);
315 :
316 4619060 : walk_tree_1 (&body, func, data, NULL, lh);
317 4619060 : *walk_subtrees = 0;
318 :
319 4619060 : if (name)
320 39 : release_named_bc (name);
321 :
322 4619060 : if (cond_prep)
323 : {
324 : /* The C++ cases of
325 : while (A x = 42) body;
326 : for (; A x = 42; expr) body;
327 : This should be expanded into:
328 :
329 : top:
330 : COND_PREP
331 :
332 : with either
333 :
334 : if (COND); else break;
335 : BODY;
336 : cont:
337 : EXPR;
338 : goto top;
339 :
340 : appended into COND_PREP body or body of some TRY_FINALLY_EXPRs
341 : at the end of COND_PREP. */
342 9340 : gcc_assert (cond_is_first && TREE_CODE (cond_prep) == BIND_EXPR);
343 9340 : tree top = build1 (LABEL_EXPR, void_type_node,
344 : create_artificial_label (start_locus));
345 9340 : exit = build1 (GOTO_EXPR, void_type_node, LABEL_EXPR_LABEL (top));
346 9340 : append_to_statement_list (top, &outer_stmt_list);
347 9340 : append_to_statement_list (cond_prep, &outer_stmt_list);
348 9340 : stmt_list_p = &BIND_EXPR_BODY (cond_prep);
349 9340 : if (cond_cleanup)
350 206 : for (unsigned depth = tree_to_uhwi (cond_cleanup); depth; --depth)
351 : {
352 109 : t = tsi_stmt (tsi_last (*stmt_list_p));
353 109 : gcc_assert (TREE_CODE (t) == TRY_FINALLY_EXPR);
354 109 : stmt_list_p = &TREE_OPERAND (t, 0);
355 : }
356 9340 : stmt_list = *stmt_list_p;
357 9340 : *stmt_list_p = NULL_TREE;
358 9340 : tree after_cond = create_artificial_label (cond_locus);
359 9340 : tree goto_after_cond = build1 (GOTO_EXPR, void_type_node, after_cond);
360 9340 : t = build1 (GOTO_EXPR, void_type_node, get_bc_label (bc_break));
361 9340 : t = fold_build3_loc (cond_locus, COND_EXPR, void_type_node, cond,
362 : goto_after_cond, t);
363 9340 : append_to_statement_list (t, &stmt_list);
364 9340 : t = build1 (LABEL_EXPR, void_type_node, after_cond);
365 9340 : append_to_statement_list (t, &stmt_list);
366 : }
367 4609720 : else if (cond && integer_zerop (cond))
368 : {
369 : /* If condition is zero don't generate a loop construct. */
370 1411541 : if (cond_is_first)
371 : {
372 405 : t = build1_loc (start_locus, GOTO_EXPR, void_type_node,
373 : get_bc_label (bc_break));
374 405 : append_to_statement_list (t, &stmt_list);
375 : }
376 : }
377 : else
378 : {
379 : /* Expand to gotos. */
380 3198179 : tree top = build1 (LABEL_EXPR, void_type_node,
381 : create_artificial_label (start_locus));
382 :
383 : /* If we have an exit condition, then we build an IF with gotos either
384 : out of the loop, or to the top of it. If there's no exit condition,
385 : then we just build a jump back to the top. */
386 3198179 : exit = build1 (GOTO_EXPR, void_type_node, LABEL_EXPR_LABEL (top));
387 :
388 3198179 : if (cond && !integer_nonzerop (cond))
389 : {
390 : /* Canonicalize the loop condition to the end. This means
391 : generating a branch to the loop condition. Reuse the
392 : continue label, if there is no incr expression. */
393 3066553 : if (cond_is_first)
394 : {
395 2771318 : if (incr)
396 : {
397 1942152 : entry = build1 (LABEL_EXPR, void_type_node,
398 : create_artificial_label (start_locus));
399 3884304 : t = build1_loc (start_locus, GOTO_EXPR, void_type_node,
400 1942152 : LABEL_EXPR_LABEL (entry));
401 : }
402 : else
403 829166 : t = build1_loc (start_locus, GOTO_EXPR, void_type_node,
404 : get_bc_label (bc_continue));
405 2771318 : append_to_statement_list (t, &stmt_list);
406 : }
407 :
408 3066553 : t = build1 (GOTO_EXPR, void_type_node, get_bc_label (bc_break));
409 3066553 : exit = fold_build3_loc (cond_locus,
410 : COND_EXPR, void_type_node, cond, exit, t);
411 : }
412 : else
413 : {
414 : /* For the backward-goto's location of an unconditional loop
415 : use the beginning of the body, or, if there is none, the
416 : top of the loop. */
417 131626 : location_t loc = expr_loc_or_loc (expr_first (body),
418 : start_locus);
419 131626 : SET_EXPR_LOCATION (exit, loc);
420 : }
421 3198179 : append_to_statement_list (top, &stmt_list);
422 : }
423 :
424 4619060 : append_to_statement_list (body, &stmt_list);
425 4619060 : if (c_dialect_cxx ()
426 4144774 : && stmt_list
427 4142877 : && TREE_CODE (stmt_list) == STATEMENT_LIST)
428 : {
429 4142877 : tree_stmt_iterator tsi = tsi_last (stmt_list);
430 4142877 : if (!tsi_end_p (tsi))
431 : {
432 4142877 : tree t = *tsi;
433 4142877 : while (TREE_CODE (t) == CLEANUP_POINT_EXPR
434 : || TREE_CODE (t) == EXPR_STMT
435 8162783 : || CONVERT_EXPR_CODE_P (TREE_CODE (t)))
436 4019906 : t = TREE_OPERAND (t, 0);
437 : /* For C++, if iteration statement body ends with fallthrough
438 : statement, mark it such that we diagnose it even if next
439 : statement would be labeled statement with case/default label. */
440 4142877 : if (TREE_CODE (t) == CALL_EXPR
441 284435 : && !CALL_EXPR_FN (t)
442 4142889 : && CALL_EXPR_IFN (t) == IFN_FALLTHROUGH)
443 12 : TREE_NOTHROW (t) = 1;
444 : }
445 : }
446 4619060 : finish_bc_block (&stmt_list, bc_continue, clab);
447 4619060 : if (incr)
448 : {
449 1962971 : if (MAY_HAVE_DEBUG_MARKER_STMTS && incr_locus != UNKNOWN_LOCATION)
450 : {
451 1633583 : tree d = build0 (DEBUG_BEGIN_STMT, void_type_node);
452 1633583 : SET_EXPR_LOCATION (d, expr_loc_or_loc (incr, start_locus));
453 1633583 : append_to_statement_list (d, &stmt_list);
454 : }
455 1962971 : append_to_statement_list (incr, &stmt_list);
456 : }
457 4619060 : append_to_statement_list (entry, &stmt_list);
458 :
459 4619060 : if (MAY_HAVE_DEBUG_MARKER_STMTS && cond_locus != UNKNOWN_LOCATION)
460 : {
461 4034998 : tree d = build0 (DEBUG_BEGIN_STMT, void_type_node);
462 4034998 : SET_EXPR_LOCATION (d, cond_locus);
463 4034998 : append_to_statement_list (d, &stmt_list);
464 : }
465 4619060 : append_to_statement_list (exit, &stmt_list);
466 4619060 : if (stmt_list_p)
467 : {
468 9340 : *stmt_list_p = stmt_list;
469 9340 : stmt_list = outer_stmt_list;
470 : }
471 4619060 : finish_bc_block (&stmt_list, bc_break, blab);
472 4619060 : if (!stmt_list)
473 3709 : stmt_list = build_empty_stmt (start_locus);
474 :
475 4619060 : *stmt_p = stmt_list;
476 4619060 : }
477 :
478 : /* Genericize a FOR_STMT node *STMT_P. */
479 :
480 : static void
481 2035235 : genericize_for_stmt (tree *stmt_p, int *walk_subtrees, void *data,
482 : walk_tree_fn func, walk_tree_lh lh)
483 : {
484 2035235 : tree stmt = *stmt_p;
485 2035235 : tree expr = NULL;
486 2035235 : tree loop;
487 2035235 : tree init = FOR_INIT_STMT (stmt);
488 :
489 2035235 : if (init)
490 : {
491 0 : walk_tree_1 (&init, func, data, NULL, lh);
492 0 : append_to_statement_list (init, &expr);
493 : }
494 :
495 4070470 : genericize_c_loop (&loop, EXPR_LOCATION (stmt), FOR_COND (stmt),
496 2035235 : FOR_BODY (stmt), FOR_EXPR (stmt), FOR_NAME (stmt),
497 2035235 : FOR_COND_PREP (stmt), FOR_COND_CLEANUP (stmt), 1,
498 : walk_subtrees, data, func, lh);
499 2035235 : append_to_statement_list (loop, &expr);
500 2035235 : if (expr == NULL_TREE)
501 0 : expr = loop;
502 2035235 : *stmt_p = expr;
503 2035235 : }
504 :
505 : /* Genericize a WHILE_STMT node *STMT_P. */
506 :
507 : static void
508 877038 : genericize_while_stmt (tree *stmt_p, int *walk_subtrees, void *data,
509 : walk_tree_fn func, walk_tree_lh lh)
510 : {
511 877038 : tree stmt = *stmt_p;
512 1754076 : genericize_c_loop (stmt_p, EXPR_LOCATION (stmt), WHILE_COND (stmt),
513 877038 : WHILE_BODY (stmt), NULL_TREE, WHILE_NAME (stmt),
514 877038 : WHILE_COND_PREP (stmt), WHILE_COND_CLEANUP (stmt), 1,
515 : walk_subtrees, data, func, lh);
516 877038 : }
517 :
518 : /* Genericize a DO_STMT node *STMT_P. */
519 :
520 : static void
521 1706787 : genericize_do_stmt (tree *stmt_p, int *walk_subtrees, void *data,
522 : walk_tree_fn func, walk_tree_lh lh)
523 : {
524 1706787 : tree stmt = *stmt_p;
525 3413574 : genericize_c_loop (stmt_p, EXPR_LOCATION (stmt), DO_COND (stmt),
526 1706787 : DO_BODY (stmt), NULL_TREE, DO_NAME (stmt),
527 : NULL_TREE, NULL_TREE, 0, walk_subtrees, data, func, lh);
528 1706787 : }
529 :
530 : /* Genericize a SWITCH_STMT node *STMT_P by turning it into a SWITCH_EXPR. */
531 :
532 : static void
533 666106 : genericize_switch_stmt (tree *stmt_p, int *walk_subtrees, void *data,
534 : walk_tree_fn func, walk_tree_lh lh)
535 : {
536 666106 : tree stmt = *stmt_p;
537 666106 : tree blab, body, cond, type;
538 666106 : location_t stmt_locus = EXPR_LOCATION (stmt);
539 :
540 666106 : body = SWITCH_STMT_BODY (stmt);
541 666106 : if (!body)
542 0 : body = build_empty_stmt (stmt_locus);
543 666106 : cond = SWITCH_STMT_COND (stmt);
544 666106 : type = SWITCH_STMT_TYPE (stmt);
545 :
546 666106 : walk_tree_1 (&cond, func, data, NULL, lh);
547 :
548 666106 : blab = begin_bc_block (bc_break, stmt_locus);
549 666106 : if (SWITCH_STMT_NAME (stmt))
550 12 : note_named_bc (SWITCH_STMT_NAME (stmt), blab, NULL_TREE);
551 :
552 666106 : walk_tree_1 (&body, func, data, NULL, lh);
553 :
554 666106 : if (SWITCH_STMT_NAME (stmt))
555 12 : release_named_bc (SWITCH_STMT_NAME (stmt));
556 :
557 666106 : walk_tree_1 (&type, func, data, NULL, lh);
558 666106 : *walk_subtrees = 0;
559 :
560 666106 : if (TREE_USED (blab))
561 354642 : SWITCH_BREAK_LABEL_P (blab) = 1;
562 666106 : finish_bc_block (&body, bc_break, blab);
563 666106 : *stmt_p = build2_loc (stmt_locus, SWITCH_EXPR, type, cond, body);
564 666106 : SWITCH_ALL_CASES_P (*stmt_p) = SWITCH_STMT_ALL_CASES_P (stmt);
565 666106 : gcc_checking_assert (!SWITCH_STMT_NO_BREAK_P (stmt)
566 : || !TREE_USED (blab));
567 666106 : }
568 :
569 : /* Genericize a CONTINUE_STMT node *STMT_P. */
570 :
571 : static void
572 17351 : genericize_continue_stmt (tree *stmt_p)
573 : {
574 17351 : tree stmt_list = NULL;
575 17351 : tree pred = build_predict_expr (PRED_CONTINUE, NOT_TAKEN);
576 17351 : tree label;
577 17351 : if (CONTINUE_NAME (*stmt_p))
578 : {
579 42 : tree_pair *slot = bc_hash_map->get (CONTINUE_NAME (*stmt_p));
580 42 : gcc_checking_assert (slot);
581 42 : label = slot->second;
582 42 : TREE_USED (label) = 1;
583 : }
584 : else
585 17309 : label = get_bc_label (bc_continue);
586 17351 : location_t location = EXPR_LOCATION (*stmt_p);
587 17351 : tree jump = build1_loc (location, GOTO_EXPR, void_type_node, label);
588 17351 : append_to_statement_list_force (pred, &stmt_list);
589 17351 : append_to_statement_list (jump, &stmt_list);
590 17351 : *stmt_p = stmt_list;
591 17351 : }
592 :
593 : /* Genericize a BREAK_STMT node *STMT_P. */
594 :
595 : static void
596 2285065 : genericize_break_stmt (tree *stmt_p)
597 : {
598 2285065 : tree label;
599 2285065 : if (BREAK_NAME (*stmt_p))
600 : {
601 53 : tree_pair *slot = bc_hash_map->get (BREAK_NAME (*stmt_p));
602 53 : gcc_checking_assert (slot);
603 53 : label = slot->first;
604 53 : TREE_USED (label) = 1;
605 : }
606 : else
607 2285012 : label = get_bc_label (bc_break);
608 2285065 : location_t location = EXPR_LOCATION (*stmt_p);
609 2285065 : *stmt_p = build1_loc (location, GOTO_EXPR, void_type_node, label);
610 2285065 : }
611 :
612 : /* Genericize a OMP_FOR node *STMT_P. */
613 :
614 : static void
615 42320 : genericize_omp_for_stmt (tree *stmt_p, int *walk_subtrees, void *data,
616 : walk_tree_fn func, walk_tree_lh lh)
617 : {
618 42320 : tree stmt = *stmt_p;
619 42320 : location_t locus = EXPR_LOCATION (stmt);
620 42320 : tree clab = begin_bc_block (bc_continue, locus);
621 :
622 42320 : walk_tree_1 (&OMP_FOR_BODY (stmt), func, data, NULL, lh);
623 42320 : if (TREE_CODE (stmt) != OMP_TASKLOOP)
624 40907 : walk_tree_1 (&OMP_FOR_CLAUSES (stmt), func, data, NULL, lh);
625 42320 : walk_tree_1 (&OMP_FOR_INIT (stmt), func, data, NULL, lh);
626 42320 : walk_tree_1 (&OMP_FOR_COND (stmt), func, data, NULL, lh);
627 42320 : walk_tree_1 (&OMP_FOR_INCR (stmt), func, data, NULL, lh);
628 42320 : walk_tree_1 (&OMP_FOR_PRE_BODY (stmt), func, data, NULL, lh);
629 42320 : *walk_subtrees = 0;
630 :
631 42320 : finish_bc_block (&OMP_FOR_BODY (stmt), bc_continue, clab);
632 42320 : }
633 :
634 : /* Genericize a OMP_METADIRECTIVE node *STMT_P. */
635 :
636 : static void
637 24 : genericize_omp_metadirective_stmt (tree *stmt_p, int *walk_subtrees,
638 : void *data, walk_tree_fn func,
639 : walk_tree_lh lh)
640 : {
641 24 : tree stmt = *stmt_p;
642 :
643 24 : for (tree variant = OMP_METADIRECTIVE_VARIANTS (stmt);
644 94 : variant != NULL_TREE;
645 70 : variant = TREE_CHAIN (variant))
646 : {
647 70 : walk_tree_1 (&OMP_METADIRECTIVE_VARIANT_DIRECTIVE (variant),
648 : func, data, NULL, lh);
649 70 : walk_tree_1 (&OMP_METADIRECTIVE_VARIANT_BODY (variant),
650 : func, data, NULL, lh);
651 : }
652 :
653 24 : *walk_subtrees = 0;
654 24 : }
655 :
656 : /* Lower structured control flow tree nodes, such as loops. The
657 : STMT_P, WALK_SUBTREES, and DATA arguments are as for the walk_tree_fn
658 : type. FUNC and LH are language-specific functions passed to walk_tree_1
659 : for node visiting and traversal, respectively; they are used to do
660 : subtree processing in a language-dependent way. */
661 :
662 : tree
663 747101100 : c_genericize_control_stmt (tree *stmt_p, int *walk_subtrees, void *data,
664 : walk_tree_fn func, walk_tree_lh lh)
665 : {
666 747101100 : tree stmt = *stmt_p;
667 :
668 747101100 : switch (TREE_CODE (stmt))
669 : {
670 2035235 : case FOR_STMT:
671 2035235 : genericize_for_stmt (stmt_p, walk_subtrees, data, func, lh);
672 2035235 : break;
673 :
674 877038 : case WHILE_STMT:
675 877038 : genericize_while_stmt (stmt_p, walk_subtrees, data, func, lh);
676 877038 : break;
677 :
678 1706787 : case DO_STMT:
679 1706787 : genericize_do_stmt (stmt_p, walk_subtrees, data, func, lh);
680 1706787 : break;
681 :
682 666106 : case SWITCH_STMT:
683 666106 : genericize_switch_stmt (stmt_p, walk_subtrees, data, func, lh);
684 666106 : break;
685 :
686 17351 : case CONTINUE_STMT:
687 17351 : genericize_continue_stmt (stmt_p);
688 17351 : break;
689 :
690 2285065 : case BREAK_STMT:
691 2285065 : genericize_break_stmt (stmt_p);
692 2285065 : break;
693 :
694 42320 : case OMP_FOR:
695 42320 : case OMP_SIMD:
696 42320 : case OMP_DISTRIBUTE:
697 42320 : case OMP_LOOP:
698 42320 : case OMP_TASKLOOP:
699 42320 : case OMP_TILE:
700 42320 : case OMP_UNROLL:
701 42320 : case OACC_LOOP:
702 42320 : genericize_omp_for_stmt (stmt_p, walk_subtrees, data, func, lh);
703 42320 : break;
704 :
705 24 : case OMP_METADIRECTIVE:
706 24 : genericize_omp_metadirective_stmt (stmt_p, walk_subtrees, data, func,
707 : lh);
708 24 : break;
709 :
710 82334918 : case STATEMENT_LIST:
711 82334918 : if (TREE_SIDE_EFFECTS (stmt))
712 : {
713 79539673 : tree_stmt_iterator i;
714 79539673 : int nondebug_stmts = 0;
715 79539673 : bool clear_side_effects = true;
716 : /* Genericization can clear TREE_SIDE_EFFECTS, e.g. when
717 : transforming an IF_STMT into COND_EXPR. If such stmt
718 : appears in a STATEMENT_LIST that contains only that
719 : stmt and some DEBUG_BEGIN_STMTs, without -g where the
720 : STATEMENT_LIST wouldn't be present at all the resulting
721 : expression wouldn't have TREE_SIDE_EFFECTS set, so make sure
722 : to clear it even on the STATEMENT_LIST in such cases. */
723 75893492 : hash_set<tree> *pset = (c_dialect_cxx ()
724 79539673 : ? nullptr
725 : : static_cast<hash_set<tree> *>(data));
726 390903251 : for (i = tsi_start (stmt); !tsi_end_p (i); tsi_next (&i))
727 : {
728 311363578 : tree t = tsi_stmt (i);
729 311363578 : if (TREE_CODE (t) != DEBUG_BEGIN_STMT && nondebug_stmts < 2)
730 133645757 : nondebug_stmts++;
731 311363578 : walk_tree_1 (tsi_stmt_ptr (i), func, data, pset, lh);
732 311363578 : if (TREE_CODE (t) != DEBUG_BEGIN_STMT
733 311363578 : && (nondebug_stmts > 1 || TREE_SIDE_EFFECTS (tsi_stmt (i))))
734 : clear_side_effects = false;
735 : }
736 79539673 : if (clear_side_effects)
737 370 : TREE_SIDE_EFFECTS (stmt) = 0;
738 79539673 : *walk_subtrees = 0;
739 : }
740 : break;
741 :
742 : default:
743 : break;
744 : }
745 :
746 747101100 : return NULL;
747 : }
748 :
749 :
750 : /* Wrapper for c_genericize_control_stmt to allow it to be used as a walk_tree
751 : callback. This is appropriate for C; C++ calls c_genericize_control_stmt
752 : directly. */
753 :
754 : static tree
755 661527714 : c_genericize_control_r (tree *stmt_p, int *walk_subtrees, void *data)
756 : {
757 661527714 : tree stmt = *stmt_p;
758 : /* Mark stores to parts of complex automatic non-addressable
759 : variables as DECL_NOT_GIMPLE_REG_P for -O0. This can't be
760 : done during gimplification. See PR119120. */
761 661527714 : if (TREE_CODE (stmt) == MODIFY_EXPR
762 37554064 : && (TREE_CODE (TREE_OPERAND (stmt, 0)) == REALPART_EXPR
763 37552992 : || TREE_CODE (TREE_OPERAND (stmt, 0)) == IMAGPART_EXPR)
764 2156 : && !optimize
765 138 : && DECL_P (TREE_OPERAND (TREE_OPERAND (stmt, 0), 0))
766 661527838 : && is_gimple_reg (TREE_OPERAND (TREE_OPERAND (stmt, 0), 0)))
767 63 : DECL_NOT_GIMPLE_REG_P (TREE_OPERAND (TREE_OPERAND (stmt, 0), 0)) = 1;
768 :
769 661527714 : c_genericize_control_stmt (stmt_p, walk_subtrees, data,
770 : c_genericize_control_r, NULL);
771 661527714 : return NULL;
772 : }
773 :
774 : /* Convert the tree representation of FNDECL from C frontend trees to
775 : GENERIC. */
776 :
777 : void
778 90988831 : c_genericize (tree fndecl)
779 : {
780 90988831 : dump_file_info *dfi;
781 90988831 : FILE *dump_orig;
782 90988831 : dump_flags_t local_dump_flags;
783 90988831 : struct cgraph_node *cgn;
784 :
785 90988831 : if (flag_sanitize & SANITIZE_BOUNDS)
786 : {
787 68004 : hash_set<tree> pset;
788 68004 : walk_tree (&DECL_SAVED_TREE (fndecl), ubsan_walk_array_refs_r, &pset,
789 : &pset);
790 68004 : }
791 :
792 : /* Genericize loops and other structured control constructs. The C++
793 : front end has already done this in lang-specific code. */
794 90988831 : if (!c_dialect_cxx ())
795 : {
796 36301419 : bc_state_t save_state;
797 36301419 : push_cfun (DECL_STRUCT_FUNCTION (fndecl));
798 36301419 : save_bc_state (&save_state);
799 36301419 : hash_set<tree> pset;
800 36301419 : walk_tree (&DECL_SAVED_TREE (fndecl), c_genericize_control_r, &pset,
801 : &pset);
802 36301434 : delete bc_hash_map;
803 36301419 : bc_hash_map = NULL;
804 36301419 : restore_bc_state (&save_state);
805 36301419 : pop_cfun ();
806 36301419 : }
807 :
808 90988831 : if (warn_duplicated_branches)
809 133 : walk_tree_without_duplicates (&DECL_SAVED_TREE (fndecl),
810 : do_warn_duplicated_branches_r, NULL);
811 :
812 : /* Dump the C-specific tree IR. */
813 90988831 : dfi = g->get_dumps ()->get_dump_file_info (TDI_original);
814 90988831 : dump_orig = dfi->pstream;
815 90988831 : local_dump_flags = dfi->pflags;
816 90988831 : if (dump_orig)
817 : {
818 7419 : fprintf (dump_orig, "\n;; Function %s",
819 7419 : lang_hooks.decl_printable_name (fndecl, 2));
820 7419 : fprintf (dump_orig, " (%s)\n",
821 7419 : (!DECL_ASSEMBLER_NAME_SET_P (fndecl) ? "null"
822 90 : : IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl))));
823 7419 : fprintf (dump_orig, ";; enabled by -%s\n", dump_flag_name (TDI_original));
824 7419 : fprintf (dump_orig, "\n");
825 :
826 7419 : if (local_dump_flags & TDF_RAW)
827 1 : dump_node (DECL_SAVED_TREE (fndecl),
828 : TDF_SLIM | local_dump_flags, dump_orig);
829 : else
830 7418 : print_c_tree (dump_orig, DECL_SAVED_TREE (fndecl), local_dump_flags);
831 7419 : fprintf (dump_orig, "\n");
832 : }
833 :
834 : /* Dump all nested functions now. */
835 90988831 : cgn = cgraph_node::get_create (fndecl);
836 90990415 : for (cgn = first_nested_function (cgn);
837 90990415 : cgn; cgn = next_nested_function (cgn))
838 1584 : c_genericize (cgn->decl);
839 90988831 : }
840 :
841 : static void
842 0 : add_block_to_enclosing (tree block)
843 : {
844 0 : unsigned i;
845 0 : tree enclosing;
846 0 : gbind *bind;
847 0 : vec<gbind *> stack = gimple_bind_expr_stack ();
848 :
849 0 : FOR_EACH_VEC_ELT (stack, i, bind)
850 0 : if (gimple_bind_block (bind))
851 : break;
852 :
853 0 : enclosing = gimple_bind_block (bind);
854 0 : BLOCK_SUBBLOCKS (enclosing) = chainon (BLOCK_SUBBLOCKS (enclosing), block);
855 0 : }
856 :
857 : /* Genericize a scope by creating a new BIND_EXPR.
858 : BLOCK is either a BLOCK representing the scope or a chain of _DECLs.
859 : In the latter case, we need to create a new BLOCK and add it to the
860 : BLOCK_SUBBLOCKS of the enclosing block.
861 : BODY is a chain of C _STMT nodes for the contents of the scope, to be
862 : genericized. */
863 :
864 : tree
865 185439040 : c_build_bind_expr (location_t loc, tree block, tree body)
866 : {
867 185439040 : tree decls, bind;
868 :
869 185439040 : if (block == NULL_TREE)
870 : decls = NULL_TREE;
871 70422540 : else if (TREE_CODE (block) == BLOCK)
872 70422540 : decls = BLOCK_VARS (block);
873 : else
874 : {
875 0 : decls = block;
876 0 : if (DECL_ARTIFICIAL (decls))
877 : block = NULL_TREE;
878 : else
879 : {
880 0 : block = make_node (BLOCK);
881 0 : BLOCK_VARS (block) = decls;
882 0 : add_block_to_enclosing (block);
883 : }
884 : }
885 :
886 185439040 : if (!body)
887 0 : body = build_empty_stmt (loc);
888 185439040 : if (decls || block)
889 : {
890 70422540 : bind = build3 (BIND_EXPR, void_type_node, decls, body, block);
891 70422540 : TREE_SIDE_EFFECTS (bind) = 1;
892 70422540 : SET_EXPR_LOCATION (bind, loc);
893 : }
894 : else
895 : bind = body;
896 :
897 185439040 : return bind;
898 : }
899 :
900 : /* Helper for c_gimplify_expr: test if target supports fma-like FN. */
901 :
902 : static bool
903 24 : fma_supported_p (enum internal_fn fn, tree type)
904 : {
905 22 : return direct_internal_fn_supported_p (fn, type, OPTIMIZE_FOR_BOTH);
906 : }
907 :
908 : /* Gimplification of expression trees. */
909 :
910 : /* Do C-specific gimplification on *EXPR_P. PRE_P and POST_P are as in
911 : gimplify_expr. */
912 :
913 : int
914 261979307 : c_gimplify_expr (tree *expr_p, gimple_seq *pre_p ATTRIBUTE_UNUSED,
915 : gimple_seq *post_p ATTRIBUTE_UNUSED)
916 : {
917 261979307 : enum tree_code code = TREE_CODE (*expr_p);
918 :
919 261979307 : switch (code)
920 : {
921 339417 : case LSHIFT_EXPR:
922 339417 : case RSHIFT_EXPR:
923 339417 : case LROTATE_EXPR:
924 339417 : case RROTATE_EXPR:
925 339417 : {
926 : /* We used to convert the right operand of a shift-expression
927 : to an integer_type_node in the FEs. But it is unnecessary
928 : and not desirable for diagnostics and sanitizers. We keep
929 : this here to not pessimize the code, but we convert to an
930 : unsigned type, because negative shift counts are undefined
931 : anyway.
932 : We should get rid of this conversion when we have a proper
933 : type demotion/promotion pass. */
934 339417 : tree *op1_p = &TREE_OPERAND (*expr_p, 1);
935 339417 : if (!error_operand_p (*op1_p)
936 339416 : && !VECTOR_TYPE_P (TREE_TYPE (*op1_p))
937 337643 : && !types_compatible_p (TYPE_MAIN_VARIANT (TREE_TYPE (*op1_p)),
938 : unsigned_type_node)
939 638099 : && !types_compatible_p (TYPE_MAIN_VARIANT (TREE_TYPE (*op1_p)),
940 : integer_type_node))
941 : /* Make sure to unshare the result, tree sharing is invalid
942 : during gimplification. */
943 13172 : *op1_p = unshare_expr (convert (unsigned_type_node, *op1_p));
944 : break;
945 : }
946 :
947 1141622 : case PREINCREMENT_EXPR:
948 1141622 : case PREDECREMENT_EXPR:
949 1141622 : case POSTINCREMENT_EXPR:
950 1141622 : case POSTDECREMENT_EXPR:
951 1141622 : {
952 1141622 : tree type = TREE_TYPE (TREE_OPERAND (*expr_p, 0));
953 1141622 : if (INTEGRAL_TYPE_P (type) && c_promoting_integer_type_p (type))
954 : {
955 5703 : if (!TYPE_OVERFLOW_WRAPS (type))
956 3312 : type = unsigned_type_for (type);
957 5703 : return gimplify_self_mod_expr (expr_p, pre_p, post_p, 1, type);
958 : }
959 : break;
960 : }
961 :
962 7705942 : case PLUS_EXPR:
963 7705942 : case MINUS_EXPR:
964 7705942 : {
965 7705942 : tree type = TREE_TYPE (*expr_p);
966 : /* For -ffp-contract=on we need to attempt FMA contraction only
967 : during initial gimplification. Late contraction across statement
968 : boundaries would violate language semantics. */
969 7705942 : if (SCALAR_FLOAT_TYPE_P (type)
970 957185 : && flag_fp_contract_mode == FP_CONTRACT_ON
971 22 : && cfun && !(cfun->curr_properties & PROP_gimple_any)
972 7705964 : && fma_supported_p (IFN_FMA, type))
973 : {
974 22 : bool neg_mul = false, neg_add = code == MINUS_EXPR;
975 :
976 22 : tree *op0_p = &TREE_OPERAND (*expr_p, 0);
977 22 : tree *op1_p = &TREE_OPERAND (*expr_p, 1);
978 :
979 : /* Look for ±(x * y) ± z, swapping operands if necessary. */
980 22 : if (TREE_CODE (*op0_p) == NEGATE_EXPR
981 22 : && TREE_CODE (TREE_OPERAND (*op0_p, 0)) == MULT_EXPR)
982 : /* '*EXPR_P' is '-(x * y) ± z'. This is fine. */;
983 22 : else if (TREE_CODE (*op0_p) != MULT_EXPR)
984 : {
985 : std::swap (op0_p, op1_p);
986 : std::swap (neg_mul, neg_add);
987 : }
988 22 : if (TREE_CODE (*op0_p) == NEGATE_EXPR)
989 : {
990 0 : op0_p = &TREE_OPERAND (*op0_p, 0);
991 0 : neg_mul = !neg_mul;
992 : }
993 22 : if (TREE_CODE (*op0_p) != MULT_EXPR)
994 : break;
995 12 : auto_vec<tree, 3> ops (3);
996 12 : ops.quick_push (TREE_OPERAND (*op0_p, 0));
997 12 : ops.quick_push (TREE_OPERAND (*op0_p, 1));
998 12 : ops.quick_push (*op1_p);
999 :
1000 12 : enum internal_fn ifn = IFN_FMA;
1001 12 : if (neg_mul)
1002 : {
1003 0 : if (fma_supported_p (IFN_FNMA, type))
1004 : ifn = IFN_FNMA;
1005 : else
1006 0 : ops[0] = build1 (NEGATE_EXPR, type, ops[0]);
1007 : }
1008 12 : if (neg_add)
1009 : {
1010 2 : enum internal_fn ifn2 = ifn == IFN_FMA ? IFN_FMS : IFN_FNMS;
1011 2 : if (fma_supported_p (ifn2, type))
1012 : ifn = ifn2;
1013 : else
1014 0 : ops[2] = build1 (NEGATE_EXPR, type, ops[2]);
1015 : }
1016 : /* Avoid gimplify_arg: it emits all side effects into *PRE_P. */
1017 72 : for (auto &&op : ops)
1018 36 : if (gimplify_expr (&op, pre_p, post_p, is_gimple_val, fb_rvalue)
1019 : == GS_ERROR)
1020 : return GS_ERROR;
1021 :
1022 12 : gcall *call = gimple_build_call_internal_vec (ifn, ops);
1023 12 : gimple_seq_add_stmt_without_update (pre_p, call);
1024 12 : *expr_p = create_tmp_var (type);
1025 12 : gimple_call_set_lhs (call, *expr_p);
1026 12 : return GS_ALL_DONE;
1027 12 : }
1028 : break;
1029 : }
1030 :
1031 3760289 : case CALL_EXPR:
1032 3760289 : {
1033 3760289 : tree fndecl = get_callee_fndecl (*expr_p);
1034 3760289 : if (fndecl
1035 3508638 : && fndecl_built_in_p (fndecl, BUILT_IN_CLZG, BUILT_IN_CTZG)
1036 74 : && call_expr_nargs (*expr_p) == 2
1037 3760363 : && TREE_CODE (CALL_EXPR_ARG (*expr_p, 1)) != INTEGER_CST)
1038 : {
1039 74 : tree a = CALL_EXPR_ARG (*expr_p, 0);
1040 74 : if (gimplify_expr (&a, pre_p, post_p, is_gimple_val, fb_rvalue)
1041 : == GS_ERROR)
1042 : return GS_ERROR;
1043 74 : tree b = CALL_EXPR_ARG (*expr_p, 1);
1044 74 : if (gimplify_expr (&b, pre_p, post_p, is_gimple_val, fb_rvalue)
1045 : == GS_ERROR)
1046 : return GS_ERROR;
1047 74 : tree c = build_call_expr_loc (EXPR_LOCATION (*expr_p),
1048 : fndecl, 1, a);
1049 148 : *expr_p = build3_loc (EXPR_LOCATION (*expr_p), COND_EXPR,
1050 : integer_type_node,
1051 74 : build2_loc (EXPR_LOCATION (*expr_p),
1052 : NE_EXPR, boolean_type_node, a,
1053 74 : build_zero_cst (TREE_TYPE (a))),
1054 : c, b);
1055 74 : return GS_OK;
1056 : }
1057 : break;
1058 : }
1059 :
1060 : default:;
1061 : }
1062 :
1063 : return GS_UNHANDLED;
1064 : }
|