Home | History | Annotate | Line # | Download | only in c-family
c-gimplify.cc revision 1.1.1.1
      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 (at) laposte.net>
      7    Re-written to support lowering of whole function trees, documentation
      8    and miscellaneous cleanups by Diego Novillo <dnovillo (at) 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
     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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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