xref: /netbsd-src/external/gpl3/gcc/dist/gcc/c-family/c-gimplify.cc (revision b1e838363e3c6fc78a55519254d99869742dd33c)
1 /* Tree lowering pass.  This pass gimplifies the tree representation built
2    by the C-based front ends.  The structure of gimplified, or
3    language-independent, trees is dictated by the grammar described in this
4    file.
5    Copyright (C) 2002-2022 Free Software Foundation, Inc.
6    Lowering of expressions contributed by Sebastian Pop <s.pop@laposte.net>
7    Re-written to support lowering of whole function trees, documentation
8    and miscellaneous cleanups by Diego Novillo <dnovillo@redhat.com>
9 
10 This file is part of GCC.
11 
12 GCC is free software; you can redistribute it and/or modify it under
13 the terms of the GNU General Public License as published by the Free
14 Software Foundation; either version 3, or (at your option) any later
15 version.
16 
17 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
18 WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20 for more details.
21 
22 You should have received a copy of the GNU General Public License
23 along with GCC; see the file COPYING3.  If not see
24 <http://www.gnu.org/licenses/>.  */
25 
26 #include "config.h"
27 #include "system.h"
28 #include "coretypes.h"
29 #include "tm.h"
30 #include "function.h"
31 #include "basic-block.h"
32 #include "tree.h"
33 #include "tree-iterator.h"
34 #include "predict.h"
35 #include "gimple.h"
36 #include "cgraph.h"
37 #include "c-pretty-print.h"
38 #include "gimplify.h"
39 #include "langhooks.h"
40 #include "dumpfile.h"
41 #include "c-ubsan.h"
42 #include "tree-nested.h"
43 
44 /*  The gimplification pass converts the language-dependent trees
45     (ld-trees) emitted by the parser into language-independent trees
46     (li-trees) that are the target of SSA analysis and transformations.
47 
48     Language-independent trees are based on the SIMPLE intermediate
49     representation used in the McCAT compiler framework:
50 
51     "Designing the McCAT Compiler Based on a Family of Structured
52     Intermediate Representations,"
53     L. Hendren, C. Donawa, M. Emami, G. Gao, Justiani, and B. Sridharan,
54     Proceedings of the 5th International Workshop on Languages and
55     Compilers for Parallel Computing, no. 757 in Lecture Notes in
56     Computer Science, New Haven, Connecticut, pp. 406-420,
57     Springer-Verlag, August 3-5, 1992.
58 
59     http://www-acaps.cs.mcgill.ca/info/McCAT/McCAT.html
60 
61     Basically, we walk down gimplifying the nodes that we encounter.  As we
62     walk back up, we check that they fit our constraints, and copy them
63     into temporaries if not.  */
64 
65 /* Callback for c_genericize.  */
66 
67 static tree
ubsan_walk_array_refs_r(tree * tp,int * walk_subtrees,void * data)68 ubsan_walk_array_refs_r (tree *tp, int *walk_subtrees, void *data)
69 {
70   hash_set<tree> *pset = (hash_set<tree> *) data;
71 
72   if (TREE_CODE (*tp) == BIND_EXPR)
73     {
74       /* Since walk_tree doesn't call the callback function on the decls
75 	 in BIND_EXPR_VARS, we have to walk them manually, so we can avoid
76 	 instrumenting DECL_INITIAL of TREE_STATIC vars.  */
77       *walk_subtrees = 0;
78       for (tree decl = BIND_EXPR_VARS (*tp); decl; decl = DECL_CHAIN (decl))
79 	{
80 	  if (TREE_STATIC (decl))
81 	    continue;
82 	  walk_tree (&DECL_INITIAL (decl), ubsan_walk_array_refs_r, pset,
83 		     pset);
84 	  walk_tree (&DECL_SIZE (decl), ubsan_walk_array_refs_r, pset, pset);
85 	  walk_tree (&DECL_SIZE_UNIT (decl), ubsan_walk_array_refs_r, pset,
86 		     pset);
87 	}
88       walk_tree (&BIND_EXPR_BODY (*tp), ubsan_walk_array_refs_r, pset, pset);
89     }
90   else if (TREE_CODE (*tp) == ADDR_EXPR
91 	   && TREE_CODE (TREE_OPERAND (*tp, 0)) == ARRAY_REF)
92     {
93       ubsan_maybe_instrument_array_ref (&TREE_OPERAND (*tp, 0), true);
94       /* Make sure ubsan_maybe_instrument_array_ref is not called again
95 	 on the ARRAY_REF, the above call might not instrument anything
96 	 as the index might be constant or masked, so ensure it is not
97 	 walked again and walk its subtrees manually.  */
98       tree aref = TREE_OPERAND (*tp, 0);
99       pset->add (aref);
100       *walk_subtrees = 0;
101       walk_tree (&TREE_OPERAND (aref, 0), ubsan_walk_array_refs_r, pset, pset);
102       walk_tree (&TREE_OPERAND (aref, 1), ubsan_walk_array_refs_r, pset, pset);
103       walk_tree (&TREE_OPERAND (aref, 2), ubsan_walk_array_refs_r, pset, pset);
104       walk_tree (&TREE_OPERAND (aref, 3), ubsan_walk_array_refs_r, pset, pset);
105     }
106   else if (TREE_CODE (*tp) == ARRAY_REF)
107     ubsan_maybe_instrument_array_ref (tp, false);
108   else if (TREE_CODE (*tp) == MODIFY_EXPR)
109     {
110       /* Since r7-1900, we gimplify RHS before LHS.  Consider
111 	   a[b] |= c;
112 	 wherein we can have a single shared tree a[b] in both LHS and RHS.
113 	 If we only instrument the LHS and the access is invalid, the program
114 	 could crash before emitting a UBSan error.  So instrument the RHS
115 	 first.  */
116       *walk_subtrees = 0;
117       walk_tree (&TREE_OPERAND (*tp, 1), ubsan_walk_array_refs_r, pset, pset);
118       walk_tree (&TREE_OPERAND (*tp, 0), ubsan_walk_array_refs_r, pset, pset);
119     }
120   return NULL_TREE;
121 }
122 
123 /* Gimplification of statement trees.  */
124 
125 /* Local declarations.  */
126 
127 enum bc_t { bc_break = 0, bc_continue = 1 };
128 
129 /* Stack of labels which are targets for "break" or "continue",
130    linked through TREE_CHAIN.  */
131 static tree bc_label[2];
132 
133 /* Begin a scope which can be exited by a break or continue statement.  BC
134    indicates which.
135 
136    Just creates a label with location LOCATION and pushes it into the current
137    context.  */
138 
139 static tree
begin_bc_block(enum bc_t bc,location_t location)140 begin_bc_block (enum bc_t bc, location_t location)
141 {
142   tree label = create_artificial_label (location);
143   DECL_CHAIN (label) = bc_label[bc];
144   bc_label[bc] = label;
145   if (bc == bc_break)
146     LABEL_DECL_BREAK (label) = true;
147   else
148     LABEL_DECL_CONTINUE (label) = true;
149   return label;
150 }
151 
152 /* Finish a scope which can be exited by a break or continue statement.
153    LABEL was returned from the most recent call to begin_bc_block.  BLOCK is
154    an expression for the contents of the scope.
155 
156    If we saw a break (or continue) in the scope, append a LABEL_EXPR to
157    BLOCK.  Otherwise, just forget the label.  */
158 
159 static void
finish_bc_block(tree * block,enum bc_t bc,tree label)160 finish_bc_block (tree *block, enum bc_t bc, tree label)
161 {
162   gcc_assert (label == bc_label[bc]);
163 
164   if (TREE_USED (label))
165     append_to_statement_list (build1 (LABEL_EXPR, void_type_node, label),
166 			      block);
167 
168   bc_label[bc] = DECL_CHAIN (label);
169   DECL_CHAIN (label) = NULL_TREE;
170 }
171 
172 /* Allow saving and restoring break/continue state.  */
173 
174 void
save_bc_state(bc_state_t * state)175 save_bc_state (bc_state_t *state)
176 {
177   state->bc_label[bc_break] = bc_label[bc_break];
178   state->bc_label[bc_continue] = bc_label[bc_continue];
179   bc_label[bc_break] = NULL_TREE;
180   bc_label[bc_continue] = NULL_TREE;
181 }
182 
183 void
restore_bc_state(bc_state_t * state)184 restore_bc_state (bc_state_t *state)
185 {
186   gcc_assert (bc_label[bc_break] == NULL);
187   gcc_assert (bc_label[bc_continue] == NULL);
188   bc_label[bc_break] = state->bc_label[bc_break];
189   bc_label[bc_continue] = state->bc_label[bc_continue];
190 }
191 
192 /* Get the LABEL_EXPR to represent a break or continue statement
193    in the current block scope.  BC indicates which.  */
194 
195 static tree
get_bc_label(enum bc_t bc)196 get_bc_label (enum bc_t bc)
197 {
198   tree label = bc_label[bc];
199   gcc_assert (label);
200 
201   /* Mark the label used for finish_bc_block.  */
202   TREE_USED (label) = 1;
203   return label;
204 }
205 
206 /* Return the location from EXPR, or OR_LOC if the former is unknown.  */
207 
208 location_t
expr_loc_or_loc(const_tree expr,location_t or_loc)209 expr_loc_or_loc (const_tree expr, location_t or_loc)
210 {
211   tree t = CONST_CAST_TREE (expr);
212   location_t loc = UNKNOWN_LOCATION;
213   if (t)
214     loc = EXPR_LOCATION (t);
215   if (loc == UNKNOWN_LOCATION)
216     loc = or_loc;
217   return loc;
218 }
219 
220 /* Build a generic representation of one of the C loop forms.  COND is the
221    loop condition or NULL_TREE.  BODY is the (possibly compound) statement
222    controlled by the loop.  INCR is the increment expression of a for-loop,
223    or NULL_TREE.  COND_IS_FIRST indicates whether the condition is
224    evaluated before the loop body as in while and for loops, or after the
225    loop body as in do-while loops.  */
226 
227 static void
genericize_c_loop(tree * stmt_p,location_t start_locus,tree cond,tree body,tree incr,bool cond_is_first,int * walk_subtrees,void * data,walk_tree_fn func,walk_tree_lh lh)228 genericize_c_loop (tree *stmt_p, location_t start_locus, tree cond, tree body,
229 		   tree incr, bool cond_is_first, int *walk_subtrees,
230 		   void *data, walk_tree_fn func, walk_tree_lh lh)
231 {
232   tree blab, clab;
233   tree entry = NULL, exit = NULL, t;
234   tree stmt_list = NULL;
235   location_t cond_locus = expr_loc_or_loc (cond, start_locus);
236   location_t incr_locus = expr_loc_or_loc (incr, start_locus);
237 
238   protected_set_expr_location_if_unset (incr, start_locus);
239 
240   walk_tree_1 (&cond, func, data, NULL, lh);
241   walk_tree_1 (&incr, func, data, NULL, lh);
242 
243   blab = begin_bc_block (bc_break, start_locus);
244   clab = begin_bc_block (bc_continue, start_locus);
245 
246   walk_tree_1 (&body, func, data, NULL, lh);
247   *walk_subtrees = 0;
248 
249   /* If condition is zero don't generate a loop construct.  */
250   if (cond && integer_zerop (cond))
251     {
252       if (cond_is_first)
253 	{
254 	  t = build1_loc (start_locus, GOTO_EXPR, void_type_node,
255 			  get_bc_label (bc_break));
256 	  append_to_statement_list (t, &stmt_list);
257 	}
258     }
259   else
260     {
261       /* Expand to gotos.  */
262       tree top = build1 (LABEL_EXPR, void_type_node,
263 			 create_artificial_label (start_locus));
264 
265       /* If we have an exit condition, then we build an IF with gotos either
266 	 out of the loop, or to the top of it.  If there's no exit condition,
267 	 then we just build a jump back to the top.  */
268       exit = build1 (GOTO_EXPR, void_type_node, LABEL_EXPR_LABEL (top));
269 
270       if (cond && !integer_nonzerop (cond))
271 	{
272 	  /* Canonicalize the loop condition to the end.  This means
273 	     generating a branch to the loop condition.  Reuse the
274 	     continue label, if there is no incr expression.  */
275 	  if (cond_is_first)
276 	    {
277 	      if (incr)
278 		{
279 		  entry = build1 (LABEL_EXPR, void_type_node,
280 				  create_artificial_label (start_locus));
281 		  t = build1_loc (start_locus, GOTO_EXPR, void_type_node,
282 				  LABEL_EXPR_LABEL (entry));
283 		}
284 	      else
285 		t = build1_loc (start_locus, GOTO_EXPR, void_type_node,
286 				get_bc_label (bc_continue));
287 	      append_to_statement_list (t, &stmt_list);
288 	    }
289 
290 	  t = build1 (GOTO_EXPR, void_type_node, get_bc_label (bc_break));
291 	  exit = fold_build3_loc (cond_locus,
292 				  COND_EXPR, void_type_node, cond, exit, t);
293 	}
294       else
295 	{
296 	  /* For the backward-goto's location of an unconditional loop
297 	     use the beginning of the body, or, if there is none, the
298 	     top of the loop.  */
299 	  location_t loc = expr_loc_or_loc (expr_first (body),
300 					    start_locus);
301 	  SET_EXPR_LOCATION (exit, loc);
302 	}
303       append_to_statement_list (top, &stmt_list);
304     }
305 
306   append_to_statement_list (body, &stmt_list);
307   finish_bc_block (&stmt_list, bc_continue, clab);
308   if (incr)
309     {
310       if (MAY_HAVE_DEBUG_MARKER_STMTS && incr_locus != UNKNOWN_LOCATION)
311 	{
312 	  tree d = build0 (DEBUG_BEGIN_STMT, void_type_node);
313 	  SET_EXPR_LOCATION (d, expr_loc_or_loc (incr, start_locus));
314 	  append_to_statement_list (d, &stmt_list);
315 	}
316       append_to_statement_list (incr, &stmt_list);
317     }
318   append_to_statement_list (entry, &stmt_list);
319 
320   if (MAY_HAVE_DEBUG_MARKER_STMTS && cond_locus != UNKNOWN_LOCATION)
321     {
322       tree d = build0 (DEBUG_BEGIN_STMT, void_type_node);
323       SET_EXPR_LOCATION (d, cond_locus);
324       append_to_statement_list (d, &stmt_list);
325     }
326   append_to_statement_list (exit, &stmt_list);
327   finish_bc_block (&stmt_list, bc_break, blab);
328   if (!stmt_list)
329     stmt_list = build_empty_stmt (start_locus);
330 
331   *stmt_p = stmt_list;
332 }
333 
334 /* Genericize a FOR_STMT node *STMT_P.  */
335 
336 static void
genericize_for_stmt(tree * stmt_p,int * walk_subtrees,void * data,walk_tree_fn func,walk_tree_lh lh)337 genericize_for_stmt (tree *stmt_p, int *walk_subtrees, void *data,
338 		     walk_tree_fn func, walk_tree_lh lh)
339 {
340   tree stmt = *stmt_p;
341   tree expr = NULL;
342   tree loop;
343   tree init = FOR_INIT_STMT (stmt);
344 
345   if (init)
346     {
347       walk_tree_1 (&init, func, data, NULL, lh);
348       append_to_statement_list (init, &expr);
349     }
350 
351   genericize_c_loop (&loop, EXPR_LOCATION (stmt), FOR_COND (stmt),
352 		     FOR_BODY (stmt), FOR_EXPR (stmt), 1, walk_subtrees,
353 		     data, func, lh);
354   append_to_statement_list (loop, &expr);
355   if (expr == NULL_TREE)
356     expr = loop;
357   *stmt_p = expr;
358 }
359 
360 /* Genericize a WHILE_STMT node *STMT_P.  */
361 
362 static void
genericize_while_stmt(tree * stmt_p,int * walk_subtrees,void * data,walk_tree_fn func,walk_tree_lh lh)363 genericize_while_stmt (tree *stmt_p, int *walk_subtrees, void *data,
364 		       walk_tree_fn func, walk_tree_lh lh)
365 {
366   tree stmt = *stmt_p;
367   genericize_c_loop (stmt_p, EXPR_LOCATION (stmt), WHILE_COND (stmt),
368 		     WHILE_BODY (stmt), NULL_TREE, 1, walk_subtrees,
369 		     data, func, lh);
370 }
371 
372 /* Genericize a DO_STMT node *STMT_P.  */
373 
374 static void
genericize_do_stmt(tree * stmt_p,int * walk_subtrees,void * data,walk_tree_fn func,walk_tree_lh lh)375 genericize_do_stmt (tree *stmt_p, int *walk_subtrees, void *data,
376 		    walk_tree_fn func, walk_tree_lh lh)
377 {
378   tree stmt = *stmt_p;
379   genericize_c_loop (stmt_p, EXPR_LOCATION (stmt), DO_COND (stmt),
380 		     DO_BODY (stmt), NULL_TREE, 0, walk_subtrees,
381 		     data, func, lh);
382 }
383 
384 /* Genericize a SWITCH_STMT node *STMT_P by turning it into a SWITCH_EXPR.  */
385 
386 static void
genericize_switch_stmt(tree * stmt_p,int * walk_subtrees,void * data,walk_tree_fn func,walk_tree_lh lh)387 genericize_switch_stmt (tree *stmt_p, int *walk_subtrees, void *data,
388 			walk_tree_fn func, walk_tree_lh lh)
389 {
390   tree stmt = *stmt_p;
391   tree break_block, body, cond, type;
392   location_t stmt_locus = EXPR_LOCATION (stmt);
393 
394   body = SWITCH_STMT_BODY (stmt);
395   if (!body)
396     body = build_empty_stmt (stmt_locus);
397   cond = SWITCH_STMT_COND (stmt);
398   type = SWITCH_STMT_TYPE (stmt);
399 
400   walk_tree_1 (&cond, func, data, NULL, lh);
401 
402   break_block = begin_bc_block (bc_break, stmt_locus);
403 
404   walk_tree_1 (&body, func, data, NULL, lh);
405   walk_tree_1 (&type, func, data, NULL, lh);
406   *walk_subtrees = 0;
407 
408   if (TREE_USED (break_block))
409     SWITCH_BREAK_LABEL_P (break_block) = 1;
410   finish_bc_block (&body, bc_break, break_block);
411   *stmt_p = build2_loc (stmt_locus, SWITCH_EXPR, type, cond, body);
412   SWITCH_ALL_CASES_P (*stmt_p) = SWITCH_STMT_ALL_CASES_P (stmt);
413   gcc_checking_assert (!SWITCH_STMT_NO_BREAK_P (stmt)
414 		       || !TREE_USED (break_block));
415 }
416 
417 /* Genericize a CONTINUE_STMT node *STMT_P.  */
418 
419 static void
genericize_continue_stmt(tree * stmt_p)420 genericize_continue_stmt (tree *stmt_p)
421 {
422   tree stmt_list = NULL;
423   tree pred = build_predict_expr (PRED_CONTINUE, NOT_TAKEN);
424   tree label = get_bc_label (bc_continue);
425   location_t location = EXPR_LOCATION (*stmt_p);
426   tree jump = build1_loc (location, GOTO_EXPR, void_type_node, label);
427   append_to_statement_list_force (pred, &stmt_list);
428   append_to_statement_list (jump, &stmt_list);
429   *stmt_p = stmt_list;
430 }
431 
432 /* Genericize a BREAK_STMT node *STMT_P.  */
433 
434 static void
genericize_break_stmt(tree * stmt_p)435 genericize_break_stmt (tree *stmt_p)
436 {
437   tree label = get_bc_label (bc_break);
438   location_t location = EXPR_LOCATION (*stmt_p);
439   *stmt_p = build1_loc (location, GOTO_EXPR, void_type_node, label);
440 }
441 
442 /* Genericize a OMP_FOR node *STMT_P.  */
443 
444 static void
genericize_omp_for_stmt(tree * stmt_p,int * walk_subtrees,void * data,walk_tree_fn func,walk_tree_lh lh)445 genericize_omp_for_stmt (tree *stmt_p, int *walk_subtrees, void *data,
446 			 walk_tree_fn func, walk_tree_lh lh)
447 {
448   tree stmt = *stmt_p;
449   location_t locus = EXPR_LOCATION (stmt);
450   tree clab = begin_bc_block (bc_continue, locus);
451 
452   walk_tree_1 (&OMP_FOR_BODY (stmt), func, data, NULL, lh);
453   if (TREE_CODE (stmt) != OMP_TASKLOOP)
454     walk_tree_1 (&OMP_FOR_CLAUSES (stmt), func, data, NULL, lh);
455   walk_tree_1 (&OMP_FOR_INIT (stmt), func, data, NULL, lh);
456   walk_tree_1 (&OMP_FOR_COND (stmt), func, data, NULL, lh);
457   walk_tree_1 (&OMP_FOR_INCR (stmt), func, data, NULL, lh);
458   walk_tree_1 (&OMP_FOR_PRE_BODY (stmt), func, data, NULL, lh);
459   *walk_subtrees = 0;
460 
461   finish_bc_block (&OMP_FOR_BODY (stmt), bc_continue, clab);
462 }
463 
464 
465 /* Lower structured control flow tree nodes, such as loops.  The
466    STMT_P, WALK_SUBTREES, and DATA arguments are as for the walk_tree_fn
467    type.  FUNC and LH are language-specific functions passed to walk_tree_1
468    for node visiting and traversal, respectively; they are used to do
469    subtree processing in a language-dependent way.  */
470 
471 tree
c_genericize_control_stmt(tree * stmt_p,int * walk_subtrees,void * data,walk_tree_fn func,walk_tree_lh lh)472 c_genericize_control_stmt (tree *stmt_p, int *walk_subtrees, void *data,
473 			   walk_tree_fn func, walk_tree_lh lh)
474 {
475   tree stmt = *stmt_p;
476 
477   switch (TREE_CODE (stmt))
478     {
479     case FOR_STMT:
480       genericize_for_stmt (stmt_p, walk_subtrees, data, func, lh);
481       break;
482 
483     case WHILE_STMT:
484       genericize_while_stmt (stmt_p, walk_subtrees, data, func, lh);
485       break;
486 
487     case DO_STMT:
488       genericize_do_stmt (stmt_p, walk_subtrees, data, func, lh);
489       break;
490 
491     case SWITCH_STMT:
492       genericize_switch_stmt (stmt_p, walk_subtrees, data, func, lh);
493       break;
494 
495     case CONTINUE_STMT:
496       genericize_continue_stmt (stmt_p);
497       break;
498 
499     case BREAK_STMT:
500       genericize_break_stmt (stmt_p);
501       break;
502 
503     case OMP_FOR:
504     case OMP_SIMD:
505     case OMP_DISTRIBUTE:
506     case OMP_LOOP:
507     case OMP_TASKLOOP:
508     case OACC_LOOP:
509       genericize_omp_for_stmt (stmt_p, walk_subtrees, data, func, lh);
510       break;
511 
512     case STATEMENT_LIST:
513       if (TREE_SIDE_EFFECTS (stmt))
514 	{
515 	  tree_stmt_iterator i;
516 	  int nondebug_stmts = 0;
517 	  bool clear_side_effects = true;
518 	  /* Genericization can clear TREE_SIDE_EFFECTS, e.g. when
519 	     transforming an IF_STMT into COND_EXPR.  If such stmt
520 	     appears in a STATEMENT_LIST that contains only that
521 	     stmt and some DEBUG_BEGIN_STMTs, without -g where the
522 	     STATEMENT_LIST wouldn't be present at all the resulting
523 	     expression wouldn't have TREE_SIDE_EFFECTS set, so make sure
524 	     to clear it even on the STATEMENT_LIST in such cases.  */
525 	  hash_set<tree> *pset = (c_dialect_cxx ()
526 				  ? nullptr
527 				  : static_cast<hash_set<tree> *>(data));
528 	  for (i = tsi_start (stmt); !tsi_end_p (i); tsi_next (&i))
529 	    {
530 	      tree t = tsi_stmt (i);
531 	      if (TREE_CODE (t) != DEBUG_BEGIN_STMT && nondebug_stmts < 2)
532 		nondebug_stmts++;
533 	      walk_tree_1 (tsi_stmt_ptr (i), func, data, pset, lh);
534 	      if (TREE_CODE (t) != DEBUG_BEGIN_STMT
535 		  && (nondebug_stmts > 1 || TREE_SIDE_EFFECTS (tsi_stmt (i))))
536 		clear_side_effects = false;
537 	    }
538 	  if (clear_side_effects)
539 	    TREE_SIDE_EFFECTS (stmt) = 0;
540 	  *walk_subtrees = 0;
541 	}
542       break;
543 
544     default:
545       break;
546     }
547 
548   return NULL;
549 }
550 
551 
552 /* Wrapper for c_genericize_control_stmt to allow it to be used as a walk_tree
553    callback.  This is appropriate for C; C++ calls c_genericize_control_stmt
554    directly.  */
555 
556 static tree
c_genericize_control_r(tree * stmt_p,int * walk_subtrees,void * data)557 c_genericize_control_r (tree *stmt_p, int *walk_subtrees, void *data)
558 {
559   c_genericize_control_stmt (stmt_p, walk_subtrees, data,
560 			     c_genericize_control_r, NULL);
561   return NULL;
562 }
563 
564 /* Convert the tree representation of FNDECL from C frontend trees to
565    GENERIC.  */
566 
567 void
c_genericize(tree fndecl)568 c_genericize (tree fndecl)
569 {
570   FILE *dump_orig;
571   dump_flags_t local_dump_flags;
572   struct cgraph_node *cgn;
573 
574   if (flag_sanitize & SANITIZE_BOUNDS)
575     {
576       hash_set<tree> pset;
577       walk_tree (&DECL_SAVED_TREE (fndecl), ubsan_walk_array_refs_r, &pset,
578 		 &pset);
579     }
580 
581   /* Genericize loops and other structured control constructs.  The C++
582      front end has already done this in lang-specific code.  */
583   if (!c_dialect_cxx ())
584     {
585       bc_state_t save_state;
586       push_cfun (DECL_STRUCT_FUNCTION (fndecl));
587       save_bc_state (&save_state);
588       hash_set<tree> pset;
589       walk_tree (&DECL_SAVED_TREE (fndecl), c_genericize_control_r, &pset,
590 		 &pset);
591       restore_bc_state (&save_state);
592       pop_cfun ();
593     }
594 
595   if (warn_duplicated_branches)
596     walk_tree_without_duplicates (&DECL_SAVED_TREE (fndecl),
597 				  do_warn_duplicated_branches_r, NULL);
598 
599   /* Dump the C-specific tree IR.  */
600   dump_orig = get_dump_info (TDI_original, &local_dump_flags);
601   if (dump_orig)
602     {
603       fprintf (dump_orig, "\n;; Function %s",
604 	       lang_hooks.decl_printable_name (fndecl, 2));
605       fprintf (dump_orig, " (%s)\n",
606 	       (!DECL_ASSEMBLER_NAME_SET_P (fndecl) ? "null"
607 		: IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl))));
608       fprintf (dump_orig, ";; enabled by -%s\n", dump_flag_name (TDI_original));
609       fprintf (dump_orig, "\n");
610 
611       if (local_dump_flags & TDF_RAW)
612 	dump_node (DECL_SAVED_TREE (fndecl),
613 		   TDF_SLIM | local_dump_flags, dump_orig);
614       else
615 	print_c_tree (dump_orig, DECL_SAVED_TREE (fndecl));
616       fprintf (dump_orig, "\n");
617     }
618 
619   /* Dump all nested functions now.  */
620   cgn = cgraph_node::get_create (fndecl);
621   for (cgn = first_nested_function (cgn);
622        cgn; cgn = next_nested_function (cgn))
623     c_genericize (cgn->decl);
624 }
625 
626 static void
add_block_to_enclosing(tree block)627 add_block_to_enclosing (tree block)
628 {
629   unsigned i;
630   tree enclosing;
631   gbind *bind;
632   vec<gbind *> stack = gimple_bind_expr_stack ();
633 
634   FOR_EACH_VEC_ELT (stack, i, bind)
635     if (gimple_bind_block (bind))
636       break;
637 
638   enclosing = gimple_bind_block (bind);
639   BLOCK_SUBBLOCKS (enclosing) = chainon (BLOCK_SUBBLOCKS (enclosing), block);
640 }
641 
642 /* Genericize a scope by creating a new BIND_EXPR.
643    BLOCK is either a BLOCK representing the scope or a chain of _DECLs.
644      In the latter case, we need to create a new BLOCK and add it to the
645      BLOCK_SUBBLOCKS of the enclosing block.
646    BODY is a chain of C _STMT nodes for the contents of the scope, to be
647      genericized.  */
648 
649 tree
c_build_bind_expr(location_t loc,tree block,tree body)650 c_build_bind_expr (location_t loc, tree block, tree body)
651 {
652   tree decls, bind;
653 
654   if (block == NULL_TREE)
655     decls = NULL_TREE;
656   else if (TREE_CODE (block) == BLOCK)
657     decls = BLOCK_VARS (block);
658   else
659     {
660       decls = block;
661       if (DECL_ARTIFICIAL (decls))
662 	block = NULL_TREE;
663       else
664 	{
665 	  block = make_node (BLOCK);
666 	  BLOCK_VARS (block) = decls;
667 	  add_block_to_enclosing (block);
668 	}
669     }
670 
671   if (!body)
672     body = build_empty_stmt (loc);
673   if (decls || block)
674     {
675       bind = build3 (BIND_EXPR, void_type_node, decls, body, block);
676       TREE_SIDE_EFFECTS (bind) = 1;
677       SET_EXPR_LOCATION (bind, loc);
678     }
679   else
680     bind = body;
681 
682   return bind;
683 }
684 
685 /* Gimplification of expression trees.  */
686 
687 /* Do C-specific gimplification on *EXPR_P.  PRE_P and POST_P are as in
688    gimplify_expr.  */
689 
690 int
c_gimplify_expr(tree * expr_p,gimple_seq * pre_p ATTRIBUTE_UNUSED,gimple_seq * post_p ATTRIBUTE_UNUSED)691 c_gimplify_expr (tree *expr_p, gimple_seq *pre_p ATTRIBUTE_UNUSED,
692 		 gimple_seq *post_p ATTRIBUTE_UNUSED)
693 {
694   enum tree_code code = TREE_CODE (*expr_p);
695 
696   switch (code)
697     {
698     case LSHIFT_EXPR:
699     case RSHIFT_EXPR:
700     case LROTATE_EXPR:
701     case RROTATE_EXPR:
702       {
703 	/* We used to convert the right operand of a shift-expression
704 	   to an integer_type_node in the FEs.  But it is unnecessary
705 	   and not desirable for diagnostics and sanitizers.  We keep
706 	   this here to not pessimize the code, but we convert to an
707 	   unsigned type, because negative shift counts are undefined
708 	   anyway.
709 	   We should get rid of this conversion when we have a proper
710 	   type demotion/promotion pass.  */
711 	tree *op1_p = &TREE_OPERAND (*expr_p, 1);
712 	if (!VECTOR_TYPE_P (TREE_TYPE (*op1_p))
713 	    && !types_compatible_p (TYPE_MAIN_VARIANT (TREE_TYPE (*op1_p)),
714 				    unsigned_type_node)
715 	    && !types_compatible_p (TYPE_MAIN_VARIANT (TREE_TYPE (*op1_p)),
716 				    integer_type_node))
717 	  /* Make sure to unshare the result, tree sharing is invalid
718 	     during gimplification.  */
719 	  *op1_p = unshare_expr (convert (unsigned_type_node, *op1_p));
720 	break;
721       }
722 
723     case PREINCREMENT_EXPR:
724     case PREDECREMENT_EXPR:
725     case POSTINCREMENT_EXPR:
726     case POSTDECREMENT_EXPR:
727       {
728 	tree type = TREE_TYPE (TREE_OPERAND (*expr_p, 0));
729 	if (INTEGRAL_TYPE_P (type) && c_promoting_integer_type_p (type))
730 	  {
731 	    if (!TYPE_OVERFLOW_WRAPS (type))
732 	      type = unsigned_type_for (type);
733 	    return gimplify_self_mod_expr (expr_p, pre_p, post_p, 1, type);
734 	  }
735 	break;
736       }
737 
738     default:;
739     }
740 
741   return GS_UNHANDLED;
742 }
743