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