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 1157874 : is_address_with_access_with_size (tree tp)
75 : {
76 1157874 : if (TREE_CODE (tp) == POINTER_PLUS_EXPR
77 1157874 : && 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 1283763 : ubsan_walk_array_refs_r (tree *tp, int *walk_subtrees, void *data)
86 : {
87 1283763 : hash_set<tree> *pset = (hash_set<tree> *) data;
88 :
89 1283763 : 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 65326 : *walk_subtrees = 0;
95 81281 : for (tree decl = BIND_EXPR_VARS (*tp); decl; decl = DECL_CHAIN (decl))
96 : {
97 15955 : if (TREE_STATIC (decl))
98 155 : continue;
99 15800 : walk_tree (&DECL_INITIAL (decl), ubsan_walk_array_refs_r, pset,
100 : pset);
101 15800 : walk_tree (&DECL_SIZE (decl), ubsan_walk_array_refs_r, pset, pset);
102 15800 : walk_tree (&DECL_SIZE_UNIT (decl), ubsan_walk_array_refs_r, pset,
103 : pset);
104 : }
105 65326 : walk_tree (&BIND_EXPR_BODY (*tp), ubsan_walk_array_refs_r, pset, pset);
106 : }
107 1218437 : else if (TREE_CODE (*tp) == ADDR_EXPR
108 1218437 : && 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 1218178 : else if (TREE_CODE (*tp) == ARRAY_REF)
124 4068 : ubsan_maybe_instrument_array_ref (tp, false);
125 1214110 : 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 66882 : *walk_subtrees = 0;
134 66882 : walk_tree (&TREE_OPERAND (*tp, 1), ubsan_walk_array_refs_r, pset, pset);
135 66882 : walk_tree (&TREE_OPERAND (*tp, 0), ubsan_walk_array_refs_r, pset, pset);
136 : }
137 1147228 : else if (TREE_CODE (*tp) == INDIRECT_REF
138 1147228 : && is_address_with_access_with_size (TREE_OPERAND (*tp, 0)))
139 : {
140 77 : 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 77 : tree aref = TREE_OPERAND (*tp, 0);
145 77 : pset->add (aref);
146 77 : *walk_subtrees = 0;
147 77 : walk_tree (&TREE_OPERAND (aref, 0), ubsan_walk_array_refs_r, pset, pset);
148 : }
149 1147151 : else if (is_address_with_access_with_size (*tp))
150 0 : ubsan_maybe_instrument_array_ref (tp, true);
151 1283763 : 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 9989574 : begin_bc_block (enum bc_t bc, location_t location)
176 : {
177 9989574 : tree label = create_artificial_label (location);
178 9989574 : DECL_CHAIN (label) = bc_label[bc];
179 9989574 : bc_label[bc] = label;
180 9989574 : if (bc == bc_break)
181 5297873 : LABEL_DECL_BREAK (label) = true;
182 : else
183 4691701 : LABEL_DECL_CONTINUE (label) = true;
184 9989574 : 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 9989574 : finish_bc_block (tree *block, enum bc_t bc, tree label)
196 : {
197 9989574 : gcc_assert (label == bc_label[bc]);
198 :
199 9989574 : if (TREE_USED (label))
200 4339178 : append_to_statement_list (build1 (LABEL_EXPR, void_type_node, label),
201 : block);
202 :
203 9989574 : bc_label[bc] = DECL_CHAIN (label);
204 9989574 : DECL_CHAIN (label) = NULL_TREE;
205 9989574 : }
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 91273449 : save_bc_state (bc_state_t *state)
231 : {
232 91273449 : state->bc_label[bc_break] = bc_label[bc_break];
233 91273449 : state->bc_label[bc_continue] = bc_label[bc_continue];
234 91273449 : state->bc_hash_map = bc_hash_map;
235 91273449 : bc_label[bc_break] = NULL_TREE;
236 91273449 : bc_label[bc_continue] = NULL_TREE;
237 91273449 : bc_hash_map = NULL;
238 91273449 : }
239 :
240 : void
241 91273449 : restore_bc_state (bc_state_t *state)
242 : {
243 91273449 : gcc_assert (bc_label[bc_break] == NULL);
244 91273449 : gcc_assert (bc_label[bc_continue] == NULL);
245 91273449 : gcc_assert (bc_hash_map == NULL);
246 91273449 : bc_label[bc_break] = state->bc_label[bc_break];
247 91273449 : bc_label[bc_continue] = state->bc_label[bc_continue];
248 91273449 : bc_hash_map = state->bc_hash_map;
249 91273449 : }
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 6169750 : get_bc_label (enum bc_t bc)
256 : {
257 6169750 : tree label = bc_label[bc];
258 6169750 : gcc_assert (label);
259 :
260 : /* Mark the label used for finish_bc_block. */
261 6169750 : TREE_USED (label) = 1;
262 6169750 : return label;
263 : }
264 :
265 : /* Return the location from EXPR, or OR_LOC if the former is unknown. */
266 :
267 : location_t
268 11090033 : expr_loc_or_loc (const_tree expr, location_t or_loc)
269 : {
270 11090033 : tree t = const_cast<tree> (expr);
271 11090033 : location_t loc = UNKNOWN_LOCATION;
272 11090033 : if (t)
273 8349360 : loc = EXPR_LOCATION (t);
274 6881973 : if (loc == UNKNOWN_LOCATION)
275 5939385 : loc = or_loc;
276 11090033 : 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 4649381 : 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 4649381 : tree blab, clab;
300 4649381 : tree entry = NULL, exit = NULL, t;
301 4649381 : tree stmt_list = NULL, outer_stmt_list = NULL_TREE, *stmt_list_p = NULL;
302 4649381 : location_t cond_locus = expr_loc_or_loc (cond, start_locus);
303 4649381 : location_t incr_locus = expr_loc_or_loc (incr, start_locus);
304 :
305 4649381 : protected_set_expr_location_if_unset (incr, start_locus);
306 :
307 4649381 : walk_tree_1 (&cond_prep, func, data, NULL, lh);
308 4649381 : walk_tree_1 (&cond, func, data, NULL, lh);
309 4649381 : walk_tree_1 (&incr, func, data, NULL, lh);
310 :
311 4649381 : blab = begin_bc_block (bc_break, start_locus);
312 4649381 : clab = begin_bc_block (bc_continue, start_locus);
313 4649381 : if (name)
314 39 : note_named_bc (name, blab, clab);
315 :
316 4649381 : walk_tree_1 (&body, func, data, NULL, lh);
317 4649381 : *walk_subtrees = 0;
318 :
319 4649381 : if (name)
320 39 : release_named_bc (name);
321 :
322 4649381 : 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 9356 : gcc_assert (cond_is_first && TREE_CODE (cond_prep) == BIND_EXPR);
343 9356 : tree top = build1 (LABEL_EXPR, void_type_node,
344 : create_artificial_label (start_locus));
345 9356 : exit = build1 (GOTO_EXPR, void_type_node, LABEL_EXPR_LABEL (top));
346 9356 : append_to_statement_list (top, &outer_stmt_list);
347 9356 : append_to_statement_list (cond_prep, &outer_stmt_list);
348 9356 : stmt_list_p = &BIND_EXPR_BODY (cond_prep);
349 9356 : 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 9356 : stmt_list = *stmt_list_p;
357 9356 : *stmt_list_p = NULL_TREE;
358 9356 : tree after_cond = create_artificial_label (cond_locus);
359 9356 : tree goto_after_cond = build1 (GOTO_EXPR, void_type_node, after_cond);
360 9356 : t = build1 (GOTO_EXPR, void_type_node, get_bc_label (bc_break));
361 9356 : t = fold_build3_loc (cond_locus, COND_EXPR, void_type_node, cond,
362 : goto_after_cond, t);
363 9356 : append_to_statement_list (t, &stmt_list);
364 9356 : t = build1 (LABEL_EXPR, void_type_node, after_cond);
365 9356 : append_to_statement_list (t, &stmt_list);
366 : }
367 4640025 : else if (cond && integer_zerop (cond))
368 : {
369 : /* If condition is zero don't generate a loop construct. */
370 1412875 : if (cond_is_first)
371 : {
372 403 : t = build1_loc (start_locus, GOTO_EXPR, void_type_node,
373 : get_bc_label (bc_break));
374 403 : append_to_statement_list (t, &stmt_list);
375 : }
376 : }
377 : else
378 : {
379 : /* Expand to gotos. */
380 3227150 : 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 3227150 : exit = build1 (GOTO_EXPR, void_type_node, LABEL_EXPR_LABEL (top));
387 :
388 3227150 : 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 3094985 : if (cond_is_first)
394 : {
395 2798772 : if (incr)
396 : {
397 1966890 : entry = build1 (LABEL_EXPR, void_type_node,
398 : create_artificial_label (start_locus));
399 3933780 : t = build1_loc (start_locus, GOTO_EXPR, void_type_node,
400 1966890 : LABEL_EXPR_LABEL (entry));
401 : }
402 : else
403 831882 : t = build1_loc (start_locus, GOTO_EXPR, void_type_node,
404 : get_bc_label (bc_continue));
405 2798772 : append_to_statement_list (t, &stmt_list);
406 : }
407 :
408 3094985 : t = build1 (GOTO_EXPR, void_type_node, get_bc_label (bc_break));
409 3094985 : 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 132165 : location_t loc = expr_loc_or_loc (expr_first (body),
418 : start_locus);
419 132165 : SET_EXPR_LOCATION (exit, loc);
420 : }
421 3227150 : append_to_statement_list (top, &stmt_list);
422 : }
423 :
424 4649381 : append_to_statement_list (body, &stmt_list);
425 4649381 : if (c_dialect_cxx ()
426 4175301 : && stmt_list
427 4173404 : && TREE_CODE (stmt_list) == STATEMENT_LIST)
428 : {
429 4173404 : tree_stmt_iterator tsi = tsi_last (stmt_list);
430 4173404 : if (!tsi_end_p (tsi))
431 : {
432 4173404 : tree t = *tsi;
433 4173404 : while (TREE_CODE (t) == CLEANUP_POINT_EXPR
434 : || TREE_CODE (t) == EXPR_STMT
435 8267949 : || CONVERT_EXPR_CODE_P (TREE_CODE (t)))
436 4094545 : 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 4173404 : if (TREE_CODE (t) == CALL_EXPR
441 305439 : && !CALL_EXPR_FN (t)
442 4173416 : && CALL_EXPR_IFN (t) == IFN_FALLTHROUGH)
443 12 : TREE_NOTHROW (t) = 1;
444 : }
445 : }
446 4649381 : finish_bc_block (&stmt_list, bc_continue, clab);
447 4649381 : if (incr)
448 : {
449 1987759 : if (MAY_HAVE_DEBUG_MARKER_STMTS && incr_locus != UNKNOWN_LOCATION)
450 : {
451 1659106 : tree d = build0 (DEBUG_BEGIN_STMT, void_type_node);
452 1659106 : SET_EXPR_LOCATION (d, expr_loc_or_loc (incr, start_locus));
453 1659106 : append_to_statement_list (d, &stmt_list);
454 : }
455 1987759 : append_to_statement_list (incr, &stmt_list);
456 : }
457 4649381 : append_to_statement_list (entry, &stmt_list);
458 :
459 4649381 : if (MAY_HAVE_DEBUG_MARKER_STMTS && cond_locus != UNKNOWN_LOCATION)
460 : {
461 4067777 : tree d = build0 (DEBUG_BEGIN_STMT, void_type_node);
462 4067777 : SET_EXPR_LOCATION (d, cond_locus);
463 4067777 : append_to_statement_list (d, &stmt_list);
464 : }
465 4649381 : append_to_statement_list (exit, &stmt_list);
466 4649381 : if (stmt_list_p)
467 : {
468 9356 : *stmt_list_p = stmt_list;
469 9356 : stmt_list = outer_stmt_list;
470 : }
471 4649381 : finish_bc_block (&stmt_list, bc_break, blab);
472 4649381 : if (!stmt_list)
473 3709 : stmt_list = build_empty_stmt (start_locus);
474 :
475 4649381 : *stmt_p = stmt_list;
476 4649381 : }
477 :
478 : /* Genericize a FOR_STMT node *STMT_P. */
479 :
480 : static void
481 2060436 : genericize_for_stmt (tree *stmt_p, int *walk_subtrees, void *data,
482 : walk_tree_fn func, walk_tree_lh lh)
483 : {
484 2060436 : tree stmt = *stmt_p;
485 2060436 : tree expr = NULL;
486 2060436 : tree loop;
487 2060436 : tree init = FOR_INIT_STMT (stmt);
488 :
489 2060436 : if (init)
490 : {
491 0 : walk_tree_1 (&init, func, data, NULL, lh);
492 0 : append_to_statement_list (init, &expr);
493 : }
494 :
495 4120872 : genericize_c_loop (&loop, EXPR_LOCATION (stmt), FOR_COND (stmt),
496 2060436 : FOR_BODY (stmt), FOR_EXPR (stmt), FOR_NAME (stmt),
497 2060436 : FOR_COND_PREP (stmt), FOR_COND_CLEANUP (stmt), 1,
498 : walk_subtrees, data, func, lh);
499 2060436 : append_to_statement_list (loop, &expr);
500 2060436 : if (expr == NULL_TREE)
501 0 : expr = loop;
502 2060436 : *stmt_p = expr;
503 2060436 : }
504 :
505 : /* Genericize a WHILE_STMT node *STMT_P. */
506 :
507 : static void
508 879844 : genericize_while_stmt (tree *stmt_p, int *walk_subtrees, void *data,
509 : walk_tree_fn func, walk_tree_lh lh)
510 : {
511 879844 : tree stmt = *stmt_p;
512 1759688 : genericize_c_loop (stmt_p, EXPR_LOCATION (stmt), WHILE_COND (stmt),
513 879844 : WHILE_BODY (stmt), NULL_TREE, WHILE_NAME (stmt),
514 879844 : WHILE_COND_PREP (stmt), WHILE_COND_CLEANUP (stmt), 1,
515 : walk_subtrees, data, func, lh);
516 879844 : }
517 :
518 : /* Genericize a DO_STMT node *STMT_P. */
519 :
520 : static void
521 1709101 : genericize_do_stmt (tree *stmt_p, int *walk_subtrees, void *data,
522 : walk_tree_fn func, walk_tree_lh lh)
523 : {
524 1709101 : tree stmt = *stmt_p;
525 3418202 : genericize_c_loop (stmt_p, EXPR_LOCATION (stmt), DO_COND (stmt),
526 1709101 : DO_BODY (stmt), NULL_TREE, DO_NAME (stmt),
527 : NULL_TREE, NULL_TREE, 0, walk_subtrees, data, func, lh);
528 1709101 : }
529 :
530 : /* Genericize a SWITCH_STMT node *STMT_P by turning it into a SWITCH_EXPR. */
531 :
532 : static void
533 648492 : genericize_switch_stmt (tree *stmt_p, int *walk_subtrees, void *data,
534 : walk_tree_fn func, walk_tree_lh lh)
535 : {
536 648492 : tree stmt = *stmt_p;
537 648492 : tree blab, body, cond, type;
538 648492 : location_t stmt_locus = EXPR_LOCATION (stmt);
539 :
540 648492 : body = SWITCH_STMT_BODY (stmt);
541 648492 : if (!body)
542 0 : body = build_empty_stmt (stmt_locus);
543 648492 : cond = SWITCH_STMT_COND (stmt);
544 648492 : type = SWITCH_STMT_TYPE (stmt);
545 :
546 648492 : walk_tree_1 (&cond, func, data, NULL, lh);
547 :
548 648492 : blab = begin_bc_block (bc_break, stmt_locus);
549 648492 : if (SWITCH_STMT_NAME (stmt))
550 12 : note_named_bc (SWITCH_STMT_NAME (stmt), blab, NULL_TREE);
551 :
552 648492 : walk_tree_1 (&body, func, data, NULL, lh);
553 :
554 648492 : if (SWITCH_STMT_NAME (stmt))
555 12 : release_named_bc (SWITCH_STMT_NAME (stmt));
556 :
557 648492 : walk_tree_1 (&type, func, data, NULL, lh);
558 648492 : *walk_subtrees = 0;
559 :
560 648492 : if (TREE_USED (blab))
561 336895 : SWITCH_BREAK_LABEL_P (blab) = 1;
562 648492 : finish_bc_block (&body, bc_break, blab);
563 648492 : *stmt_p = build2_loc (stmt_locus, SWITCH_EXPR, type, cond, body);
564 648492 : SWITCH_ALL_CASES_P (*stmt_p) = SWITCH_STMT_ALL_CASES_P (stmt);
565 648492 : gcc_checking_assert (!SWITCH_STMT_NO_BREAK_P (stmt)
566 : || !TREE_USED (blab));
567 648492 : }
568 :
569 : /* Genericize a CONTINUE_STMT node *STMT_P. */
570 :
571 : static void
572 17401 : genericize_continue_stmt (tree *stmt_p)
573 : {
574 17401 : tree stmt_list = NULL;
575 17401 : tree pred = build_predict_expr (PRED_CONTINUE, NOT_TAKEN);
576 17401 : tree label;
577 17401 : 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 17359 : label = get_bc_label (bc_continue);
586 17401 : location_t location = EXPR_LOCATION (*stmt_p);
587 17401 : tree jump = build1_loc (location, GOTO_EXPR, void_type_node, label);
588 17401 : append_to_statement_list_force (pred, &stmt_list);
589 17401 : append_to_statement_list (jump, &stmt_list);
590 17401 : *stmt_p = stmt_list;
591 17401 : }
592 :
593 : /* Genericize a BREAK_STMT node *STMT_P. */
594 :
595 : static void
596 2215818 : genericize_break_stmt (tree *stmt_p)
597 : {
598 2215818 : tree label;
599 2215818 : 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 2215765 : label = get_bc_label (bc_break);
608 2215818 : location_t location = EXPR_LOCATION (*stmt_p);
609 2215818 : *stmt_p = build1_loc (location, GOTO_EXPR, void_type_node, label);
610 2215818 : }
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 747112325 : c_genericize_control_stmt (tree *stmt_p, int *walk_subtrees, void *data,
664 : walk_tree_fn func, walk_tree_lh lh)
665 : {
666 747112325 : tree stmt = *stmt_p;
667 :
668 747112325 : switch (TREE_CODE (stmt))
669 : {
670 2060436 : case FOR_STMT:
671 2060436 : genericize_for_stmt (stmt_p, walk_subtrees, data, func, lh);
672 2060436 : break;
673 :
674 879844 : case WHILE_STMT:
675 879844 : genericize_while_stmt (stmt_p, walk_subtrees, data, func, lh);
676 879844 : break;
677 :
678 1709101 : case DO_STMT:
679 1709101 : genericize_do_stmt (stmt_p, walk_subtrees, data, func, lh);
680 1709101 : break;
681 :
682 648492 : case SWITCH_STMT:
683 648492 : genericize_switch_stmt (stmt_p, walk_subtrees, data, func, lh);
684 648492 : break;
685 :
686 17401 : case CONTINUE_STMT:
687 17401 : genericize_continue_stmt (stmt_p);
688 17401 : break;
689 :
690 2215818 : case BREAK_STMT:
691 2215818 : genericize_break_stmt (stmt_p);
692 2215818 : 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 83292987 : case STATEMENT_LIST:
711 83292987 : if (TREE_SIDE_EFFECTS (stmt))
712 : {
713 80486498 : tree_stmt_iterator i;
714 80486498 : int nondebug_stmts = 0;
715 80486498 : 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 76842418 : hash_set<tree> *pset = (c_dialect_cxx ()
724 80486498 : ? nullptr
725 : : static_cast<hash_set<tree> *>(data));
726 395104818 : for (i = tsi_start (stmt); !tsi_end_p (i); tsi_next (&i))
727 : {
728 314618320 : tree t = tsi_stmt (i);
729 314618320 : if (TREE_CODE (t) != DEBUG_BEGIN_STMT && nondebug_stmts < 2)
730 135398430 : nondebug_stmts++;
731 314618320 : walk_tree_1 (tsi_stmt_ptr (i), func, data, pset, lh);
732 314618320 : if (TREE_CODE (t) != DEBUG_BEGIN_STMT
733 314618320 : && (nondebug_stmts > 1 || TREE_SIDE_EFFECTS (tsi_stmt (i))))
734 : clear_side_effects = false;
735 : }
736 80486498 : if (clear_side_effects)
737 370 : TREE_SIDE_EFFECTS (stmt) = 0;
738 80486498 : *walk_subtrees = 0;
739 : }
740 : break;
741 :
742 : default:
743 : break;
744 : }
745 :
746 747112325 : 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 660634824 : c_genericize_control_r (tree *stmt_p, int *walk_subtrees, void *data)
756 : {
757 660634824 : 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 660634824 : if (TREE_CODE (stmt) == MODIFY_EXPR
762 37502565 : && (TREE_CODE (TREE_OPERAND (stmt, 0)) == REALPART_EXPR
763 37501493 : || TREE_CODE (TREE_OPERAND (stmt, 0)) == IMAGPART_EXPR)
764 2156 : && !optimize
765 138 : && DECL_P (TREE_OPERAND (TREE_OPERAND (stmt, 0), 0))
766 660634948 : && 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 660634824 : c_genericize_control_stmt (stmt_p, walk_subtrees, data,
770 : c_genericize_control_r, NULL);
771 660634824 : return NULL;
772 : }
773 :
774 : /* Convert the tree representation of FNDECL from C frontend trees to
775 : GENERIC. */
776 :
777 : void
778 91273449 : c_genericize (tree fndecl)
779 : {
780 91273449 : dump_file_info *dfi;
781 91273449 : FILE *dump_orig;
782 91273449 : dump_flags_t local_dump_flags;
783 91273449 : struct cgraph_node *cgn;
784 :
785 91273449 : if (flag_sanitize & SANITIZE_BOUNDS)
786 : {
787 67497 : hash_set<tree> pset;
788 67497 : walk_tree (&DECL_SAVED_TREE (fndecl), ubsan_walk_array_refs_r, &pset,
789 : &pset);
790 67497 : }
791 :
792 : /* Genericize loops and other structured control constructs. The C++
793 : front end has already done this in lang-specific code. */
794 91273449 : if (!c_dialect_cxx ())
795 : {
796 36250308 : bc_state_t save_state;
797 36250308 : push_cfun (DECL_STRUCT_FUNCTION (fndecl));
798 36250308 : save_bc_state (&save_state);
799 36250308 : hash_set<tree> pset;
800 36250308 : walk_tree (&DECL_SAVED_TREE (fndecl), c_genericize_control_r, &pset,
801 : &pset);
802 36250323 : delete bc_hash_map;
803 36250308 : bc_hash_map = NULL;
804 36250308 : restore_bc_state (&save_state);
805 36250308 : pop_cfun ();
806 36250308 : }
807 :
808 91273449 : 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 91273449 : dfi = g->get_dumps ()->get_dump_file_info (TDI_original);
814 91273449 : dump_orig = dfi->pstream;
815 91273449 : local_dump_flags = dfi->pflags;
816 91273449 : 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 91273449 : cgn = cgraph_node::get_create (fndecl);
836 91275032 : for (cgn = first_nested_function (cgn);
837 91275032 : cgn; cgn = next_nested_function (cgn))
838 1583 : c_genericize (cgn->decl);
839 91273449 : }
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 185617572 : c_build_bind_expr (location_t loc, tree block, tree body)
866 : {
867 185617572 : tree decls, bind;
868 :
869 185617572 : if (block == NULL_TREE)
870 : decls = NULL_TREE;
871 71137315 : else if (TREE_CODE (block) == BLOCK)
872 71137315 : 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 185617572 : if (!body)
887 0 : body = build_empty_stmt (loc);
888 185617572 : if (decls || block)
889 : {
890 71137315 : bind = build3 (BIND_EXPR, void_type_node, decls, body, block);
891 71137315 : TREE_SIDE_EFFECTS (bind) = 1;
892 71137315 : SET_EXPR_LOCATION (bind, loc);
893 : }
894 : else
895 : bind = body;
896 :
897 185617572 : 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 262517496 : c_gimplify_expr (tree *expr_p, gimple_seq *pre_p ATTRIBUTE_UNUSED,
915 : gimple_seq *post_p ATTRIBUTE_UNUSED)
916 : {
917 262517496 : enum tree_code code = TREE_CODE (*expr_p);
918 :
919 262517496 : switch (code)
920 : {
921 338794 : case LSHIFT_EXPR:
922 338794 : case RSHIFT_EXPR:
923 338794 : case LROTATE_EXPR:
924 338794 : case RROTATE_EXPR:
925 338794 : {
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 338794 : tree *op1_p = &TREE_OPERAND (*expr_p, 1);
935 338794 : if (!error_operand_p (*op1_p)
936 338793 : && !VECTOR_TYPE_P (TREE_TYPE (*op1_p))
937 337076 : && !types_compatible_p (TYPE_MAIN_VARIANT (TREE_TYPE (*op1_p)),
938 : unsigned_type_node)
939 636909 : && !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 13168 : *op1_p = unshare_expr (convert (unsigned_type_node, *op1_p));
944 : break;
945 : }
946 :
947 1141914 : case PREINCREMENT_EXPR:
948 1141914 : case PREDECREMENT_EXPR:
949 1141914 : case POSTINCREMENT_EXPR:
950 1141914 : case POSTDECREMENT_EXPR:
951 1141914 : {
952 1141914 : tree type = TREE_TYPE (TREE_OPERAND (*expr_p, 0));
953 1141914 : if (INTEGRAL_TYPE_P (type) && c_promoting_integer_type_p (type))
954 : {
955 5702 : if (!TYPE_OVERFLOW_WRAPS (type))
956 3311 : type = unsigned_type_for (type);
957 5702 : return gimplify_self_mod_expr (expr_p, pre_p, post_p, 1, type);
958 : }
959 : break;
960 : }
961 :
962 7705491 : case PLUS_EXPR:
963 7705491 : case MINUS_EXPR:
964 7705491 : {
965 7705491 : 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 7705491 : if (SCALAR_FLOAT_TYPE_P (type)
970 957248 : && flag_fp_contract_mode == FP_CONTRACT_ON
971 22 : && cfun && !(cfun->curr_properties & PROP_gimple_any)
972 7705513 : && 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 3757363 : case CALL_EXPR:
1032 3757363 : {
1033 3757363 : tree fndecl = get_callee_fndecl (*expr_p);
1034 3757363 : if (fndecl
1035 3506340 : && fndecl_built_in_p (fndecl, BUILT_IN_CLZG, BUILT_IN_CTZG)
1036 74 : && call_expr_nargs (*expr_p) == 2
1037 3757437 : && 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 : }
|