OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / gcc / c-gimplify.c
index f20ddfe..e50050c 100644 (file)
@@ -2,7 +2,8 @@
    by the C-based front ends.  The structure of gimplified, or
    language-independent, trees is dictated by the grammar described in this
    file.
    by the C-based front ends.  The structure of gimplified, or
    language-independent, trees is dictated by the grammar described in this
    file.
-   Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+   Copyright (C) 2002, 2003, 2004, 2005, 2007, 2008
+   Free Software Foundation, Inc.
    Lowering of expressions contributed by Sebastian Pop <s.pop@laposte.net>
    Re-written to support lowering of whole function trees, documentation
    and miscellaneous cleanups by Diego Novillo <dnovillo@redhat.com>
    Lowering of expressions contributed by Sebastian Pop <s.pop@laposte.net>
    Re-written to support lowering of whole function trees, documentation
    and miscellaneous cleanups by Diego Novillo <dnovillo@redhat.com>
@@ -11,7 +12,7 @@ This file is part of GCC.
 
 GCC is free software; you can redistribute it and/or modify it under
 the terms of the GNU General Public License as published by the Free
 
 GCC is free software; you can redistribute it and/or modify it under
 the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
+Software Foundation; either version 3, or (at your option) any later
 version.
 
 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
 version.
 
 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
@@ -20,20 +21,18 @@ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 for more details.
 
 You should have received a copy of the GNU General Public License
 for more details.
 
 You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA.  */
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
 #include "tm.h"
 #include "tree.h"
 
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
 #include "tm.h"
 #include "tree.h"
-#include "errors.h"
 #include "varray.h"
 #include "c-tree.h"
 #include "c-common.h"
 #include "varray.h"
 #include "c-tree.h"
 #include "c-common.h"
-#include "tree-gimple.h"
+#include "gimple.h"
 #include "hard-reg-set.h"
 #include "basic-block.h"
 #include "tree-flow.h"
 #include "hard-reg-set.h"
 #include "basic-block.h"
 #include "tree-flow.h"
@@ -70,61 +69,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
     walk back up, we check that they fit our constraints, and copy them
     into temporaries if not.  */
 
     walk back up, we check that they fit our constraints, and copy them
     into temporaries if not.  */
 
-/* Local declarations.  */
-
-static enum gimplify_status gimplify_expr_stmt (tree *);
-static enum gimplify_status gimplify_decl_stmt (tree *);
-static enum gimplify_status gimplify_for_stmt (tree *, tree *);
-static enum gimplify_status gimplify_while_stmt (tree *);
-static enum gimplify_status gimplify_do_stmt (tree *);
-static enum gimplify_status gimplify_if_stmt (tree *);
-static enum gimplify_status gimplify_switch_stmt (tree *);
-static enum gimplify_status gimplify_return_stmt (tree *);
-static enum gimplify_status gimplify_stmt_expr (tree *);
-static enum gimplify_status gimplify_compound_literal_expr (tree *);
-#if defined ENABLE_CHECKING
-static int is_last_stmt_of_scope (tree);
-#endif
-static enum gimplify_status gimplify_block (tree *, tree *);
-static enum gimplify_status gimplify_cleanup (tree *, tree *);
-static tree gimplify_c_loop (tree, tree, tree, bool);
-static void push_context (void);
-static void pop_context (void);
-static tree c_build_bind_expr (tree, tree);
-static void add_block_to_enclosing (tree);
-static void gimplify_condition (tree *);
-
-enum bc_t { bc_break = 0, bc_continue = 1 };
-static tree begin_bc_block (enum bc_t);
-static tree finish_bc_block (tree, tree);
-static tree build_bc_goto (enum bc_t);
-
-static struct c_gimplify_ctx
-{
-  /* For handling break and continue.  */
-  tree current_bc_label;
-  tree bc_id[2];
-} *ctxp;
-
-static void
-push_context (void)
-{
-  if (ctxp)
-    abort ();
-  ctxp = (struct c_gimplify_ctx *) xcalloc (1, sizeof (struct c_gimplify_ctx));
-  ctxp->bc_id[bc_continue] = get_identifier ("continue");
-  ctxp->bc_id[bc_break] = get_identifier ("break");
-}
-
-static void
-pop_context (void)
-{
-  if (!ctxp || ctxp->current_bc_label)
-    abort ();
-  free (ctxp);
-  ctxp = NULL;
-}
-
 /* Gimplification of statement trees.  */
 
 /* Convert the tree representation of FNDECL from C frontend trees to
 /* Gimplification of statement trees.  */
 
 /* Convert the tree representation of FNDECL from C frontend trees to
@@ -133,229 +77,51 @@ pop_context (void)
 void
 c_genericize (tree fndecl)
 {
 void
 c_genericize (tree fndecl)
 {
-  FILE *dump_file;
+  FILE *dump_orig;
   int local_dump_flags;
   struct cgraph_node *cgn;
 
   /* Dump the C-specific tree IR.  */
   int local_dump_flags;
   struct cgraph_node *cgn;
 
   /* Dump the C-specific tree IR.  */
-  dump_file = dump_begin (TDI_original, &local_dump_flags);
-  if (dump_file)
+  dump_orig = dump_begin (TDI_original, &local_dump_flags);
+  if (dump_orig)
     {
     {
-      fprintf (dump_file, "\n;; Function %s",
+      fprintf (dump_orig, "\n;; Function %s",
               lang_hooks.decl_printable_name (fndecl, 2));
               lang_hooks.decl_printable_name (fndecl, 2));
-      fprintf (dump_file, " (%s)\n",
-              IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl)));
-      fprintf (dump_file, ";; enabled by -%s\n", dump_flag_name (TDI_original));
-      fprintf (dump_file, "\n");
+      fprintf (dump_orig, " (%s)\n",
+              (!DECL_ASSEMBLER_NAME_SET_P (fndecl) ? "null"
+               : IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl))));
+      fprintf (dump_orig, ";; enabled by -%s\n", dump_flag_name (TDI_original));
+      fprintf (dump_orig, "\n");
 
       if (local_dump_flags & TDF_RAW)
        dump_node (DECL_SAVED_TREE (fndecl),
 
       if (local_dump_flags & TDF_RAW)
        dump_node (DECL_SAVED_TREE (fndecl),
-                  TDF_SLIM | local_dump_flags, dump_file);
+                  TDF_SLIM | local_dump_flags, dump_orig);
       else
       else
-       print_c_tree (dump_file, DECL_SAVED_TREE (fndecl));
-      fprintf (dump_file, "\n");
+       print_c_tree (dump_orig, DECL_SAVED_TREE (fndecl));
+      fprintf (dump_orig, "\n");
 
 
-      dump_end (TDI_original, dump_file);
+      dump_end (TDI_original, dump_orig);
     }
 
     }
 
-  /* Go ahead and gimplify for now.  */
-  push_context ();
-  gimplify_function_tree (fndecl);
-  pop_context ();
-
-  /* Dump the genericized tree IR.  */
-  dump_function (TDI_generic, fndecl);
-
-  /* Genericize all nested functions now.  We do things in this order so
-     that items like VLA sizes are expanded properly in the context of
-     the correct function.  */
+  /* Dump all nested functions now.  */
   cgn = cgraph_node (fndecl);
   for (cgn = cgn->nested; cgn ; cgn = cgn->next_nested)
     c_genericize (cgn->decl);
 }
 
   cgn = cgraph_node (fndecl);
   for (cgn = cgn->nested; cgn ; cgn = cgn->next_nested)
     c_genericize (cgn->decl);
 }
 
-/*  Entry point for the tree lowering pass.  Recursively scan
-    *STMT_P and convert it to a GIMPLE tree.  */
-
-int
-c_gimplify_stmt (tree *stmt_p)
-{
-  tree stmt, next;
-  tree outer_pre = NULL_TREE;
-
-  /* PRE and POST are tree chains that contain the side-effects of the
-     gimplified tree.  For instance, given the expression tree:
-
-               c = ++a * 3 + b++;
-
-     After gimplification, the tree will be re-written as:
-
-               a = a + 1;
-               t1 = a * 3;     <-- PRE
-               c = t1 + b;
-               b = b + 1;      <-- POST  */
-
-  for (stmt = *stmt_p; stmt && stmt != error_mark_node; stmt = next)
-    {
-      tree pre, post;
-      int saved_stmts_are_full_exprs_p;
-      location_t stmt_locus;
-      enum gimplify_status ret;
-
-      /* Set up context appropriately for handling this statement.  */
-      saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
-      prep_stmt (stmt);
-      stmt_locus = input_location;
-
-      pre = NULL_TREE;
-      post = NULL_TREE;
-
-      next = TREE_CHAIN (stmt);
-
-      switch (TREE_CODE (stmt))
-       {
-       case COMPOUND_STMT:
-         stmt = COMPOUND_BODY (stmt);
-         ret = GS_OK;
-         break;
-
-       case SCOPE_STMT:
-         ret = gimplify_block (&stmt, &next);
-         break;
-
-       case FOR_STMT:
-         ret = gimplify_for_stmt (&stmt, &next);
-         break;
-
-       case WHILE_STMT:
-         ret = gimplify_while_stmt (&stmt);
-         break;
-
-       case DO_STMT:
-         ret = gimplify_do_stmt (&stmt);
-         break;
-
-       case IF_STMT:
-         ret = gimplify_if_stmt (&stmt);
-         break;
-
-       case SWITCH_STMT:
-         ret = gimplify_switch_stmt (&stmt);
-         break;
-
-       case EXPR_STMT:
-         ret = gimplify_expr_stmt (&stmt);
-         break;
-
-       case RETURN_STMT:
-         ret = gimplify_return_stmt (&stmt);
-         break;
-
-       case DECL_STMT:
-         ret = gimplify_decl_stmt (&stmt);
-         break;
-
-       case LABEL_STMT:
-         stmt = build1 (LABEL_EXPR, void_type_node, LABEL_STMT_LABEL (stmt));
-         ret = GS_OK;
-         break;
-
-       case GOTO_STMT:
-         stmt = build1 (GOTO_EXPR, void_type_node, GOTO_DESTINATION (stmt));
-         ret = GS_OK;
-         break;
-
-       case CASE_LABEL:
-         {
-           tree label = create_artificial_label ();
-           stmt = build (CASE_LABEL_EXPR, void_type_node,
-                         CASE_LOW (stmt), CASE_HIGH (stmt), label);
-           ret = GS_OK;
-         }
-         break;
-
-       case CONTINUE_STMT:
-         stmt = build_bc_goto (bc_continue);
-         ret = GS_OK;
-         break;
-
-       case BREAK_STMT:
-         stmt = build_bc_goto (bc_break);
-         ret = GS_OK;
-         break;
-
-       case CLEANUP_STMT:
-         ret = gimplify_cleanup (&stmt, &next);
-         break;
-
-       case ASM_STMT:
-         {
-           tree new_stmt = build (ASM_EXPR, void_type_node, ASM_STRING (stmt),
-                                  ASM_OUTPUTS (stmt), ASM_INPUTS (stmt),
-                                  ASM_CLOBBERS (stmt));
-           ASM_INPUT_P (new_stmt) = ASM_INPUT_P (stmt);
-           ASM_VOLATILE_P (new_stmt) = ASM_VOLATILE_P (stmt);
-           stmt = new_stmt;
-           ret = GS_OK;
-         }
-         break;
-
-       default:
-         if (lang_gimplify_stmt && (*lang_gimplify_stmt) (&stmt, &next))
-           {
-             ret = GS_OK;
-             break;
-           }
-
-         fprintf (stderr, "unhandled statement node in c_gimplify_stmt:\n");
-         debug_tree (stmt);
-         abort ();
-         break;
-       }
-
-      switch (ret)
-       {
-       case GS_ERROR:
-         goto cont;
-       case GS_OK:
-          gimplify_stmt (&stmt);
-         break;
-       case GS_ALL_DONE:
-         break;
-       default:
-         abort ();
-       }
-
-      /* PRE and POST now contain a list of statements for all the
-        side-effects in STMT.  */
-
-      append_to_statement_list (stmt, &pre);
-      append_to_statement_list (post, &pre);
-      annotate_all_with_locus (&pre, stmt_locus);
-
-      append_to_statement_list (pre, &outer_pre);
-    cont:
-      /* Restore saved state.  */
-      current_stmt_tree ()->stmts_are_full_exprs_p
-       = saved_stmts_are_full_exprs_p;
-    }
-  append_to_statement_list (stmt, &outer_pre);
-  *stmt_p = outer_pre;
-
-  return GS_ALL_DONE;
-}
-
 static void
 add_block_to_enclosing (tree block)
 {
 static void
 add_block_to_enclosing (tree block)
 {
+  unsigned i;
   tree enclosing;
   tree enclosing;
+  gimple bind;
+  VEC(gimple, heap) *stack = gimple_bind_expr_stack ();
 
 
-  for (enclosing = gimple_current_bind_expr ();
-       enclosing; enclosing = TREE_CHAIN (enclosing))
-    if (BIND_EXPR_BLOCK (enclosing))
+  for (i = 0; VEC_iterate (gimple, stack, i, bind); i++)
+    if (gimple_bind_block (bind))
       break;
 
       break;
 
-  enclosing = BIND_EXPR_BLOCK (enclosing);
+  enclosing = gimple_bind_block (bind);
   BLOCK_SUBBLOCKS (enclosing) = chainon (BLOCK_SUBBLOCKS (enclosing), block);
 }
 
   BLOCK_SUBBLOCKS (enclosing) = chainon (BLOCK_SUBBLOCKS (enclosing), block);
 }
 
@@ -366,8 +132,8 @@ add_block_to_enclosing (tree block)
    BODY is a chain of C _STMT nodes for the contents of the scope, to be
      genericized.  */
 
    BODY is a chain of C _STMT nodes for the contents of the scope, to be
      genericized.  */
 
-static tree
-c_build_bind_expr (tree block, tree body)
+tree
+c_build_bind_expr (location_t loc, tree block, tree body)
 {
   tree decls, bind;
 
 {
   tree decls, bind;
 
@@ -389,714 +155,40 @@ c_build_bind_expr (tree block, tree body)
     }
 
   if (!body)
     }
 
   if (!body)
-    body = build_empty_stmt ();
-
-  bind = build (BIND_EXPR, void_type_node, decls, body, block);
-  TREE_SIDE_EFFECTS (bind) = 1;
-
-  return bind;
-}
-
-/* Genericize a syntactic block by removing the bracketing SCOPE_STMTs and
-   wrapping the intervening code in a BIND_EXPR.  This function assumes
-   that matching SCOPE_STMTs will always appear in the same statement
-   sequence.  */
-
-static enum gimplify_status
-gimplify_block (tree *stmt_p, tree *next_p)
-{
-  tree *p;
-  tree block;
-  tree bind;
-  int depth;
-  location_t stmt_locus;
-
-  if (!SCOPE_BEGIN_P (*stmt_p))
-    {
-      /* Can wind up mismatched with syntax errors.  */
-      if (!errorcount && !sorrycount)
-       abort ();
-      *stmt_p = NULL;
-      return GS_ERROR;
-    }
-
-  block = SCOPE_STMT_BLOCK (*stmt_p);
-
-  /* Find the matching ending SCOPE_STMT.  */
-  depth = 1;
-  for (p = &TREE_CHAIN (*stmt_p);; p = &TREE_CHAIN (*p))
-    {
-      if (*p == NULL)
-       break;
-      if (TREE_CODE (*p) == SCOPE_STMT)
-       {
-         if (SCOPE_BEGIN_P (*p))
-           ++depth;
-         else if (--depth == 0)
-           break;
-       }
-    }
-
-  stmt_locus = input_location;
-  if (*p)
-    {
-      if (SCOPE_STMT_BLOCK (*p) != block)
-       abort ();
-      if (EXPR_LOCUS (*p))
-       stmt_locus = *EXPR_LOCUS (*p);
-      *next_p = TREE_CHAIN (*p);
-      *p = NULL_TREE;
-    }
-  else
-    {
-      /* Can wind up mismatched with syntax errors.  */
-      if (!errorcount && !sorrycount)
-       abort ();
-    }
-
-  bind = c_build_bind_expr (block, TREE_CHAIN (*stmt_p));
-  *stmt_p = bind;
-  input_location = stmt_locus;
-
-  return GS_OK;
-}
-
-/* Genericize a CLEANUP_STMT.  Just wrap everything from here to the end of
-   the block in a TRY_FINALLY_EXPR.  Or a TRY_CATCH_EXPR, if it's an
-   EH-only cleanup.  */
-
-static enum gimplify_status
-gimplify_cleanup (tree *stmt_p, tree *next_p)
-{
-  tree stmt = *stmt_p;
-  tree body = TREE_CHAIN (stmt);
-  tree cleanup = CLEANUP_EXPR (stmt);
-  enum tree_code code
-    = (CLEANUP_EH_ONLY (stmt) ? TRY_CATCH_EXPR : TRY_FINALLY_EXPR);
-
-  if (!body)
-    body = build_empty_stmt ();
-  if (!cleanup)
-    cleanup = build_empty_stmt ();
-
-  *stmt_p = build (code, void_type_node, body, cleanup);
-  *next_p = NULL_TREE;
-
-  return GS_OK;
-}
-
-/*  Gimplify an EXPR_STMT node.
-
-    STMT is the statement node.
-
-    PRE_P points to the list where side effects that must happen before
-       STMT should be stored.
-
-    POST_P points to the list where side effects that must happen after
-       STMT should be stored.  */
-
-static enum gimplify_status
-gimplify_expr_stmt (tree *stmt_p)
-{
-  tree stmt = EXPR_STMT_EXPR (*stmt_p);
-
-  if (stmt == error_mark_node)
-    stmt = NULL;
-
-  /* Gimplification of a statement expression will nullify the
-     statement if all its side effects are moved to *PRE_P and *POST_P.
-
-     In this case we will not want to emit the gimplified statement.
-     However, we may still want to emit a warning, so we do that before
-     gimplification.  */
-  if (stmt && (extra_warnings || warn_unused_value))
-    {
-      if (!TREE_SIDE_EFFECTS (stmt))
-       {
-         if (!IS_EMPTY_STMT (stmt)
-             && !VOID_TYPE_P (TREE_TYPE (stmt))
-             && !TREE_NO_WARNING (stmt))
-           warning ("statement with no effect");
-       }
-      else if (warn_unused_value)
-       {
-         /* Kludge for 20020220-2.c.  warn_if_unused_value shouldn't use
-            the stmt file location info.  */
-         set_file_and_line_for_stmt (input_location);
-         warn_if_unused_value (stmt);
-       }
-    }
-
-  if (stmt == NULL_TREE)
-    stmt = build_empty_stmt ();
-  else if (stmts_are_full_exprs_p ())
-    stmt = build1 (CLEANUP_POINT_EXPR, void_type_node, stmt);
-
-  *stmt_p = stmt;
-
-  return GS_OK;
-}
-
-/* If the condition for a loop (or the like) is a decl, it will be a
-   TREE_LIST where the TREE_PURPOSE is a DECL_STMT and the TREE_VALUE is
-   a use of the decl.  Turn such a thing into a COMPOUND_EXPR.  */
-
-static void
-gimplify_condition (tree *cond_p)
-{
-  tree cond = *cond_p;
-  if (cond && TREE_CODE (cond) == TREE_LIST)
-    {
-      tree decl = TREE_PURPOSE (cond);
-      tree value = TREE_VALUE (cond);
-      c_gimplify_stmt (&decl);
-      *cond_p = build (COMPOUND_EXPR, TREE_TYPE (value), decl, value);
-    }
-}
-
-/* Begin a scope which can be exited by a break or continue statement.  BC
-   indicates which.
-
-   Just creates a label and pushes it into the current context.  */
-
-static tree
-begin_bc_block (enum bc_t bc)
-{
-  tree label = create_artificial_label ();
-  DECL_NAME (label) = ctxp->bc_id[bc];
-  TREE_CHAIN (label) = ctxp->current_bc_label;
-  ctxp->current_bc_label = label;
-  return label;
-}
-
-/* Finish a scope which can be exited by a break or continue statement.
-   LABEL was returned from the most recent call to begin_bc_block.  BODY is
-   an expression for the contents of the scope.
-
-   If we saw a break (or continue) in the scope, append a LABEL_EXPR to
-   body.  Otherwise, just forget the label.  */
-
-static tree
-finish_bc_block (tree label, tree body)
-{
-  if (label != ctxp->current_bc_label)
-    abort ();
-
-  if (TREE_USED (label))
-    {
-      tree t, sl = NULL;
-
-      /* Clear the name so flow can delete the label.  */
-      DECL_NAME (label) = NULL_TREE;
-      t = build1 (LABEL_EXPR, void_type_node, label);
-
-      append_to_statement_list (body, &sl);
-      append_to_statement_list (t, &sl);
-      body = sl;
-    }
-
-  ctxp->current_bc_label = TREE_CHAIN (label);
-  TREE_CHAIN (label) = NULL_TREE;
-  return body;
-}
-
-/* Build a GOTO_EXPR to represent a break or continue statement.  BC
-   indicates which.  */
-
-static tree
-build_bc_goto (enum bc_t bc)
-{
-  tree label;
-  tree target_name = ctxp->bc_id[bc];
-
-  /* Look for the appropriate type of label.  */
-  for (label = ctxp->current_bc_label;
-       label;
-       label = TREE_CHAIN (label))
-    if (DECL_NAME (label) == target_name)
-      break;
-
-  if (label == NULL_TREE)
-    {
-      if (bc == bc_break)
-       error ("break statement not within loop or switch");
-      else
-       error ("continue statement not within loop or switch");
-
-      return NULL_TREE;
-    }
-
-  /* Mark the label used for finish_bc_block.  */
-  TREE_USED (label) = 1;
-  return build1 (GOTO_EXPR, void_type_node, label);
-}
-
-/* Build a generic representation of one of the C loop forms.  COND is the
-   loop condition or NULL_TREE.  BODY is the (possibly compound) statement
-   controlled by the loop.  INCR is the increment expression of a for-loop,
-   or NULL_TREE.  COND_IS_FIRST indicates whether the condition is
-   evaluated before the loop body as in while and for loops, or after the
-   loop body as in do-while loops.  */
-
-static tree
-gimplify_c_loop (tree cond, tree body, tree incr, bool cond_is_first)
-{
-  tree top, entry, exit, cont_block, break_block, stmt_list, t;
-  location_t stmt_locus;
-
-  stmt_locus = input_location;
-
-  /* Detect do { ... } while (0) and don't generate loop construct.  */
-  if (!cond_is_first && cond && integer_zerop (cond))
-    top = cond = NULL;
-  else
-    {
-      /* If we use a LOOP_EXPR here, we have to feed the whole thing
-        back through the main gimplifier to lower it.  Given that we
-        have to gimplify the loop body NOW so that we can resolve
-        break/continue stmts, seems easier to just expand to gotos.  */
-      top = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
-    }
-
-  break_block = begin_bc_block (bc_break);
-
-  if (top)
-    {
-      /* If we have an exit condition, then we build an IF with gotos either
-        out of the loop, or to the top of it.  If there's no exit condition,
-        then we just build a jump back to the top.  */
-      exit = build_and_jump (&LABEL_EXPR_LABEL (top));
-      if (cond)
-       {
-         gimplify_condition (&cond);
-         t = build_bc_goto (bc_break);
-         exit = build (COND_EXPR, void_type_node, cond, exit, t);
-         exit = fold (exit);
-         gimplify_stmt (&exit);
-       }
-    }
-  else
-    exit = NULL_TREE;
-
-  cont_block = begin_bc_block (bc_continue);
-
-  gimplify_stmt (&body);
-  if (incr && stmts_are_full_exprs_p ())
-    incr = fold (build1 (CLEANUP_POINT_EXPR, void_type_node, incr));
-  gimplify_stmt (&incr);
-
-  body = finish_bc_block (cont_block, body);
-
-  stmt_list = NULL;
-
-  if (cond_is_first && cond)
-    {
-      entry = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
-      t = build_and_jump (&LABEL_EXPR_LABEL (entry));
-      append_to_statement_list (t, &stmt_list);
-    }
-  else
-    entry = NULL_TREE;
-
-  append_to_statement_list (top, &stmt_list);
-  append_to_statement_list (body, &stmt_list);
-  append_to_statement_list (incr, &stmt_list);
-  append_to_statement_list (entry, &stmt_list);
-  append_to_statement_list (exit, &stmt_list);
-
-  annotate_all_with_locus (&stmt_list, stmt_locus);
-
-  return finish_bc_block (break_block, stmt_list);
-}
-
-/* Gimplify a FOR_STMT node.  Move the stuff in the for-init-stmt into the
-   prequeue and hand off to gimplify_c_loop.  */
-
-static enum gimplify_status
-gimplify_for_stmt (tree *stmt_p, tree *next_p)
-{
-  tree stmt = *stmt_p;
-  tree init = FOR_INIT_STMT (stmt);
-
-  if (init)
+    body = build_empty_stmt (loc);
+  if (decls || block)
     {
     {
-      /* Reorganize the statements so that we do the right thing with a
-        CLEANUP_STMT.  We want the FOR_STMT and nothing else to be in the
-        scope of the cleanup, so play with pointers to accomplish that.  */
-      FOR_INIT_STMT (stmt) = NULL_TREE;
-      chainon (init, stmt);
-      *stmt_p = init;
-      *next_p = TREE_CHAIN (stmt);
-      TREE_CHAIN (stmt) = NULL_TREE;
-      c_gimplify_stmt (stmt_p);
+      bind = build3 (BIND_EXPR, void_type_node, decls, body, block);
+      TREE_SIDE_EFFECTS (bind) = 1;
+      SET_EXPR_LOCATION (bind, loc);
     }
   else
     }
   else
-    *stmt_p = gimplify_c_loop (FOR_COND (stmt), FOR_BODY (stmt),
-                              FOR_EXPR (stmt), 1);
-
-  return GS_ALL_DONE;
-}
-
-/* Gimplify a WHILE_STMT node.  */
-
-static enum gimplify_status
-gimplify_while_stmt (tree *stmt_p)
-{
-  tree stmt = *stmt_p;
-  *stmt_p = gimplify_c_loop (WHILE_COND (stmt), WHILE_BODY (stmt),
-                            NULL_TREE, 1);
-  return GS_ALL_DONE;
-}
-
-/* Gimplify a DO_STMT node.  */
-
-static enum gimplify_status
-gimplify_do_stmt (tree *stmt_p)
-{
-  tree stmt = *stmt_p;
-  *stmt_p = gimplify_c_loop (DO_COND (stmt), DO_BODY (stmt),
-                            NULL_TREE, 0);
-  return GS_ALL_DONE;
-}
-
-/* Genericize an IF_STMT by turning it into a COND_EXPR.  */
-
-static enum gimplify_status
-gimplify_if_stmt (tree *stmt_p)
-{
-  tree stmt, then_, else_;
-
-  stmt = *stmt_p;
- restart:
-  then_ = THEN_CLAUSE (stmt);
-  else_ = ELSE_CLAUSE (stmt);
-
-  if (!then_)
-    then_ = build_empty_stmt ();
-  if (!else_)
-    else_ = build_empty_stmt ();
-
-  stmt = build (COND_EXPR, void_type_node, IF_COND (stmt), then_, else_);
-  gimplify_condition (& TREE_OPERAND (stmt, 0));
-  *stmt_p = stmt;
-
-  /* Handle properly nested if-else chains via iteration instead of
-     mutual recursion between gimplify.c and c-simplify.c.  */
-  annotate_with_locus (stmt, input_location);
-  if (TREE_CODE (else_) == IF_STMT && !TREE_CHAIN (else_))
-    {
-      stmt_p = &COND_EXPR_ELSE (stmt);
-      stmt = else_;
-      prep_stmt (stmt);
-      goto restart;
-    }
-
-  return GS_OK;
-}
-
-/* Genericize a SWITCH_STMT by turning it into a SWITCH_EXPR.  */
-
-static enum gimplify_status
-gimplify_switch_stmt (tree *stmt_p)
-{
-  tree stmt = *stmt_p;
-  tree break_block, body;
-  location_t stmt_locus = input_location;
-
-  break_block = begin_bc_block (bc_break);
-
-  gimplify_condition (&SWITCH_COND (stmt));
-
-  body = SWITCH_BODY (stmt);
-  if (!body)
-    body = build_empty_stmt ();
-
-  *stmt_p = build (SWITCH_EXPR, SWITCH_TYPE (stmt), SWITCH_COND (stmt),
-                  body, NULL_TREE);
-  annotate_with_locus (*stmt_p, stmt_locus);
-  gimplify_stmt (stmt_p);
-
-  *stmt_p = finish_bc_block (break_block, *stmt_p);
-  return GS_ALL_DONE;
-}
-
-/* Genericize a RETURN_STMT by turning it into a RETURN_EXPR.  */
-
-static enum gimplify_status
-gimplify_return_stmt (tree *stmt_p)
-{
-  tree expr = RETURN_STMT_EXPR (*stmt_p);
-  expr = build1 (RETURN_EXPR, void_type_node, expr);
-  if (stmts_are_full_exprs_p ())
-    expr = build1 (CLEANUP_POINT_EXPR, void_type_node, expr);
-  *stmt_p = expr;
-  return GS_OK;
-}
-
-/* Gimplifies a DECL_STMT node T.
-
-   If a declaration V has an initial value I, create an expression 'V = I'
-   and insert it after the DECL_STMT.
-
-   PRE_P is a queue for effects that should happen before the DECL_STMT.
-
-   MID_P is a queue for effects that should happen after the DECL_STMT,
-   but before uses of the initialized decl.
+    bind = body;
 
 
-   POST_P is a queue for effects that should happen after uses of the
-   initialized decl.
-
-   Usually these last two will be the same, but they may need to be
-   different if the DECL_STMT is somehow embedded in an expression.  */
-
-static enum gimplify_status
-gimplify_decl_stmt (tree *stmt_p)
-{
-  tree stmt = *stmt_p;
-  tree decl = DECL_STMT_DECL (stmt);
-  tree pre = NULL_TREE;
-  tree post = NULL_TREE;
-
-  if (TREE_TYPE (decl) == error_mark_node)
-    {
-      *stmt_p = NULL;
-      return GS_ERROR;
-    }
-    
-  if (TREE_CODE (decl) == TYPE_DECL)
-    {
-      tree type = TREE_TYPE (decl);
-      if (TYPE_SIZE_UNIT (type)
-          && !TREE_CONSTANT (TYPE_SIZE_UNIT (type)))
-        {
-          /* This is a variable-sized array type.  Simplify its size.  */
-          tree temp = TYPE_SIZE_UNIT (type);
-          gimplify_expr (&temp, &pre, &post, is_gimple_val, fb_rvalue);
-        }
-    }
-
-  if (TREE_CODE (decl) == VAR_DECL && !DECL_EXTERNAL (decl))
-    {
-      tree init = DECL_INITIAL (decl);
-
-      if (!TREE_CONSTANT (DECL_SIZE (decl)))
-       {
-         tree pt_type = build_pointer_type (TREE_TYPE (decl));
-         tree alloc, size;
-
-         /* This is a variable-sized decl.  Simplify its size and mark it
-            for deferred expansion.  Note that mudflap depends on the format
-            of the emitted code: see mx_register_decls().  */
-
-         size = get_initialized_tmp_var (DECL_SIZE_UNIT (decl), &pre, &post);
-         DECL_DEFER_OUTPUT (decl) = 1;
-         alloc = build_function_call_expr
-           (implicit_built_in_decls[BUILT_IN_STACK_ALLOC],
-            tree_cons (NULL_TREE,
-                       build1 (ADDR_EXPR, pt_type, decl),
-                       tree_cons (NULL_TREE, size, NULL_TREE)));
-         append_to_compound_expr (alloc, &pre);
-       }
-
-      if (init && init != error_mark_node)
-       {
-         if (!TREE_STATIC (decl))
-           {
-              /* Do not warn about int x = x; as it is a GCC extension
-                 to turn off this warning but only if warn_init_self
-                is zero.  */
-              if (init == decl && !warn_init_self)
-                TREE_NO_WARNING (decl) = 1;
-              
-             DECL_INITIAL (decl) = NULL_TREE;
-             init = build (MODIFY_EXPR, void_type_node, decl, init);
-             if (stmts_are_full_exprs_p ())
-               init = build1 (CLEANUP_POINT_EXPR, void_type_node, init);
-             append_to_compound_expr (init, &pre);
-           }
-         else
-           {
-             /* We must still examine initializers for static variables
-                as they may contain a label address.  */
-             walk_tree (&init, force_labels_r, NULL, NULL);
-           }
-       }
-
-      /* This decl isn't mentioned in the enclosing block, so add it to the
-        list of temps.  FIXME it seems a bit of a kludge to say that
-        anonymous artificial vars aren't pushed, but everything else is.  */
-      if (DECL_ARTIFICIAL (decl) && DECL_NAME (decl) == NULL_TREE)
-       gimple_add_tmp_var (decl);
-    }
-
-  append_to_compound_expr (post, &pre);
-  *stmt_p = pre;
-  return GS_OK;
+  return bind;
 }
 
 /* Gimplification of expression trees.  */
 
 }
 
 /* Gimplification of expression trees.  */
 
-/* Gimplify a C99 compound literal expression.  This just means adding the
-   DECL_STMT before the current EXPR_STMT and using its anonymous decl
-   instead.  */
-
-static enum gimplify_status
-gimplify_compound_literal_expr (tree *expr_p)
-{
-  tree decl_s = COMPOUND_LITERAL_EXPR_DECL_STMT (*expr_p);
-  tree decl = DECL_STMT_DECL (decl_s);
-
-  /* This decl isn't mentioned in the enclosing block, so add it to the
-     list of temps.  FIXME it seems a bit of a kludge to say that
-     anonymous artificial vars aren't pushed, but everything else is.  */
-  if (DECL_NAME (decl) == NULL_TREE)
-    gimple_add_tmp_var (decl);
-
-  gimplify_decl_stmt (&decl_s);
-  *expr_p = decl_s ? decl_s : decl;
-  return GS_OK;
-}
-
-/* Do C-specific gimplification.  Args are as for gimplify_expr.  */
+/* Do C-specific gimplification on *EXPR_P.  PRE_P and POST_P are as in
+   gimplify_expr.  */
 
 int
 
 int
-c_gimplify_expr (tree *expr_p, tree *pre_p ATTRIBUTE_UNUSED,
-                tree *post_p ATTRIBUTE_UNUSED)
+c_gimplify_expr (tree *expr_p, gimple_seq *pre_p ATTRIBUTE_UNUSED,
+                gimple_seq *post_p ATTRIBUTE_UNUSED)
 {
   enum tree_code code = TREE_CODE (*expr_p);
 
 {
   enum tree_code code = TREE_CODE (*expr_p);
 
-  if (STATEMENT_CODE_P (code))
-    return c_gimplify_stmt (expr_p);
-
-  switch (code)
-    {
-    case COMPOUND_LITERAL_EXPR:
-      return gimplify_compound_literal_expr (expr_p);
-
-    case STMT_EXPR:
-      return gimplify_stmt_expr (expr_p);
-
-    default:
-      return GS_UNHANDLED;
-    }
-}
-
-/* Returns the final EXPR_STMT which represents the return value of a
-   STMT_EXPR, or NULL_TREE if none.  */
-
-tree
-stmt_expr_last_stmt (tree stmt_expr)
-{
-  tree body = STMT_EXPR_STMT (stmt_expr);
-  tree last_stmt, substmt;
-
-  /* Splice the last expression out of the STMT chain.  */
-  last_stmt = NULL_TREE;
-  for (substmt = COMPOUND_BODY (body); substmt;
-       substmt = TREE_CHAIN (substmt))
-    if (TREE_CODE (substmt) != SCOPE_STMT)
-      last_stmt = substmt;
-
-  if (last_stmt == NULL_TREE
-      || TREE_CODE (last_stmt) != EXPR_STMT
-      || (TREE_TYPE (last_stmt)
-         && VOID_TYPE_P (TREE_TYPE (last_stmt))))
-    {
-      location_t loc;
-      if (last_stmt && EXPR_LOCUS (last_stmt))
-       loc = *EXPR_LOCUS (last_stmt);
-      else if (EXPR_LOCUS (stmt_expr))
-       loc = *EXPR_LOCUS (stmt_expr);
-      else
-       loc = input_location;
-      warning ("%Hstatement-expressions should end with a "
-              "non-void expression", &loc);
-      last_stmt = NULL_TREE;
-    }
-
-#if defined ENABLE_CHECKING
-  if (last_stmt && !is_last_stmt_of_scope (last_stmt))
-    abort ();
-#endif
-
-  return last_stmt;
-}
-
-/* Gimplify a STMT_EXPR.  EXPR_P points to the expression to gimplify.
-   After gimplification, if the STMT_EXPR returns a value, EXPR_P will
-   point to a new temporary that holds that value; otherwise it will be
-   null.
-
-   PRE_P points to the list where side effects that must happen before
-     *EXPR_P should be stored.  */
-
-static enum gimplify_status
-gimplify_stmt_expr (tree *expr_p)
-{
-  tree body = STMT_EXPR_STMT (*expr_p);
-
-  if (VOID_TYPE_P (TREE_TYPE (*expr_p)))
-    {
-      *expr_p = body;
-      return c_gimplify_stmt (expr_p);
-    }
-  else
-    {
-      tree last_stmt = stmt_expr_last_stmt (*expr_p);
-      tree last_expr = NULL_TREE;
-
-      if (last_stmt)
-       {
-         last_expr = EXPR_STMT_EXPR (last_stmt);
-
-         if (stmts_are_full_exprs_p ())
-           last_expr = build1 (CLEANUP_POINT_EXPR, TREE_TYPE (last_expr),
-                               last_expr);
-         EXPR_STMT_EXPR (last_stmt) = NULL_TREE;
-       }
-
-      /* Genericize the block.  */
-      c_gimplify_stmt (&body);
-
-      /* Now retrofit that last expression into the BIND_EXPR.  */
-      if (last_expr)
-       {
-         tree *sub_p;
-
-         if (!STMT_EXPR_NO_SCOPE (*expr_p))
-           {
-             /* Our BIND_EXPR will always be hidden within
-                a STATEMENT_LIST.  Discard that.  */
-             body = expr_first (body);
-             sub_p = &BIND_EXPR_BODY (body);
+  /* This is handled mostly by gimplify.c, but we have to deal with
+     not warning about int x = x; as it is a GCC extension to turn off
+     this warning but only if warn_init_self is zero.  */
+  if (code == DECL_EXPR
+      && TREE_CODE (DECL_EXPR_DECL (*expr_p)) == VAR_DECL
+      && !DECL_EXTERNAL (DECL_EXPR_DECL (*expr_p))
+      && !TREE_STATIC (DECL_EXPR_DECL (*expr_p))
+      && (DECL_INITIAL (DECL_EXPR_DECL (*expr_p)) == DECL_EXPR_DECL (*expr_p))
+      && !warn_init_self)
+    TREE_NO_WARNING (DECL_EXPR_DECL (*expr_p)) = 1;
 
 
-             /* Append the last expression to the end of the BIND_EXPR.
-                We'll now re-process this, and let voidify_wrapper_expr
-                do its job.  */
-             append_to_statement_list_force (last_expr, sub_p);
-             TREE_TYPE (body) = TREE_TYPE (last_expr);
-           }
-         else
-           append_to_compound_expr (last_expr, &body);
-       }
-
-      *expr_p = body;
-      return GS_OK;
-    }
-}
-
-/* Code generation.  */
-
-/* Miscellaneous helpers.  */
-
-#if defined ENABLE_CHECKING
-/*  Return nonzero if STMT is the last statement of its scope.  */
-
-static int
-is_last_stmt_of_scope (tree stmt)
-{
-  return (TREE_CHAIN (stmt) == NULL_TREE
-         || (TREE_CODE (TREE_CHAIN (stmt)) == SCOPE_STMT
-             && SCOPE_END_P (TREE_CHAIN (stmt))));
+  return GS_UNHANDLED;
 }
 }
-#endif