OSDN Git Service

DR 176 permissiveness
[pf3gnuchains/gcc-fork.git] / gcc / tree-nested.c
index b3301a7..0b5e732 100644 (file)
@@ -1,5 +1,6 @@
 /* Nested function decomposition for GIMPLE.
-   Copyright (C) 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+   Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009
+   Free Software Foundation, Inc.
 
    This file is part of GCC.
 
@@ -102,6 +103,27 @@ struct nesting_info
 };
 
 
+/* Iterate over the nesting tree, starting with ROOT, depth first.  */
+
+static inline struct nesting_info *
+iter_nestinfo_start (struct nesting_info *root)
+{
+  while (root->inner)
+    root = root->inner;
+  return root;
+}
+
+static inline struct nesting_info *
+iter_nestinfo_next (struct nesting_info *node)
+{
+  if (node->next)
+    return iter_nestinfo_start (node->next);
+  return node->outer;
+}
+
+#define FOR_EACH_NEST_INFO(I, ROOT) \
+  for ((I) = iter_nestinfo_start (ROOT); (I); (I) = iter_nestinfo_next (I))
+
 /* Obstack used for the bitmaps in the struct above.  */
 static struct bitmap_obstack nesting_info_bitmap_obstack;
 
@@ -301,6 +323,7 @@ static tree
 get_chain_decl (struct nesting_info *info)
 {
   tree decl = info->chain_decl;
+
   if (!decl)
     {
       tree type;
@@ -314,7 +337,8 @@ get_chain_decl (struct nesting_info *info)
         Note also that it's represented as a parameter.  This is more
         close to the truth, since the initial value does come from 
         the caller.  */
-      decl = build_decl (PARM_DECL, create_tmp_var_name ("CHAIN"), type);
+      decl = build_decl (DECL_SOURCE_LOCATION (info->context),
+                        PARM_DECL, create_tmp_var_name ("CHAIN"), type);
       DECL_ARTIFICIAL (decl) = 1;
       DECL_IGNORED_P (decl) = 1;
       TREE_USED (decl) = 1;
@@ -326,6 +350,14 @@ get_chain_decl (struct nesting_info *info)
       TREE_READONLY (decl) = 1;
 
       info->chain_decl = decl;
+
+      if (dump_file
+          && (dump_flags & TDF_DETAILS)
+         && !DECL_STATIC_CHAIN (info->context))
+       fprintf (dump_file, "Setting static-chain for %s\n",
+                lang_hooks.decl_printable_name (info->context, 2));
+
+      DECL_STATIC_CHAIN (info->context) = 1;
     }
   return decl;
 }
@@ -338,6 +370,7 @@ static tree
 get_chain_field (struct nesting_info *info)
 {
   tree field = info->chain_field;
+
   if (!field)
     {
       tree type = build_pointer_type (get_frame_type (info->outer));
@@ -351,6 +384,14 @@ get_chain_field (struct nesting_info *info)
       insert_field_into_struct (get_frame_type (info), field);
 
       info->chain_field = field;
+
+      if (dump_file
+          && (dump_flags & TDF_DETAILS)
+         && !DECL_STATIC_CHAIN (info->context))
+       fprintf (dump_file, "Setting static-chain for %s\n",
+                lang_hooks.decl_printable_name (info->context, 2));
+
+      DECL_STATIC_CHAIN (info->context) = 1;
     }
   return field;
 }
@@ -427,7 +468,7 @@ save_tmp_var (struct nesting_info *info, tree exp, gimple_stmt_iterator *gsi)
 static GTY(()) tree trampoline_type;
 
 static tree
-get_trampoline_type (void)
+get_trampoline_type (struct nesting_info *info)
 {
   unsigned align, size;
   tree t;
@@ -448,7 +489,8 @@ get_trampoline_type (void)
 
   t = build_index_type (build_int_cst (NULL_TREE, size - 1));
   t = build_array_type (char_type_node, t);
-  t = build_decl (FIELD_DECL, get_identifier ("__data"), t);
+  t = build_decl (DECL_SOURCE_LOCATION (info->context),
+                 FIELD_DECL, get_identifier ("__data"), t);
   DECL_ALIGN (t) = align;
   DECL_USER_ALIGN (t) = 1;
 
@@ -481,7 +523,7 @@ lookup_tramp_for_decl (struct nesting_info *info, tree decl,
     {
       tree field = make_node (FIELD_DECL);
       DECL_NAME (field) = DECL_NAME (decl);
-      TREE_TYPE (field) = get_trampoline_type ();
+      TREE_TYPE (field) = get_trampoline_type (info);
       TREE_ADDRESSABLE (field) = 1;
 
       insert_field_into_struct (get_frame_type (info), field);
@@ -620,14 +662,9 @@ static void
 walk_all_functions (walk_stmt_fn callback_stmt, walk_tree_fn callback_op,
                    struct nesting_info *root)
 {
-  do
-    {
-      if (root->inner)
-       walk_all_functions (callback_stmt, callback_op, root->inner);
-      walk_function (callback_stmt, callback_op, root);
-      root = root->next;
-    }
-  while (root);
+  struct nesting_info *n;
+  FOR_EACH_NEST_INFO (n, root)
+    walk_function (callback_stmt, callback_op, n);
 }
 
 
@@ -770,6 +807,7 @@ get_frame_field (struct nesting_info *info, tree target_context,
   return x;
 }
 
+static void note_nonlocal_vla_type (struct nesting_info *info, tree type);
 
 /* A subroutine of convert_nonlocal_reference_op.  Create a local variable
    in the nested function with DECL_VALUE_EXPR set to reference the true
@@ -817,9 +855,9 @@ get_nonlocal_debug_decl (struct nesting_info *info, tree decl)
     x = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (x)), x);
 
   /* ??? We should be remapping types as well, surely.  */
-  new_decl = build_decl (VAR_DECL, DECL_NAME (decl), TREE_TYPE (decl));
+  new_decl = build_decl (DECL_SOURCE_LOCATION (decl),
+                        VAR_DECL, DECL_NAME (decl), TREE_TYPE (decl));
   DECL_CONTEXT (new_decl) = info->context;
-  DECL_SOURCE_LOCATION (new_decl) = DECL_SOURCE_LOCATION (decl);
   DECL_ARTIFICIAL (new_decl) = DECL_ARTIFICIAL (decl);
   DECL_IGNORED_P (new_decl) = DECL_IGNORED_P (decl);
   TREE_THIS_VOLATILE (new_decl) = TREE_THIS_VOLATILE (decl);
@@ -840,6 +878,11 @@ get_nonlocal_debug_decl (struct nesting_info *info, tree decl)
   TREE_CHAIN (new_decl) = info->debug_var_chain;
   info->debug_var_chain = new_decl;
 
+  if (!optimize
+      && info->context != target_context
+      && variably_modified_type_p (TREE_TYPE (decl), NULL))
+    note_nonlocal_vla_type (info, TREE_TYPE (decl));
+
   return new_decl;
 }
 
@@ -1111,6 +1154,60 @@ convert_nonlocal_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
   return need_chain;
 }
 
+/* Create nonlocal debug decls for nonlocal VLA array bounds.  */
+
+static void
+note_nonlocal_vla_type (struct nesting_info *info, tree type)
+{
+  while (POINTER_TYPE_P (type) && !TYPE_NAME (type))
+    type = TREE_TYPE (type);
+
+  if (TYPE_NAME (type)
+      && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
+      && DECL_ORIGINAL_TYPE (TYPE_NAME (type)))
+    type = DECL_ORIGINAL_TYPE (TYPE_NAME (type));
+
+  while (POINTER_TYPE_P (type)
+        || TREE_CODE (type) == VECTOR_TYPE
+        || TREE_CODE (type) == FUNCTION_TYPE
+        || TREE_CODE (type) == METHOD_TYPE)
+    type = TREE_TYPE (type);
+
+  if (TREE_CODE (type) == ARRAY_TYPE)
+    {
+      tree domain, t;
+
+      note_nonlocal_vla_type (info, TREE_TYPE (type));
+      domain = TYPE_DOMAIN (type);
+      if (domain)
+       {
+         t = TYPE_MIN_VALUE (domain);
+         if (t && (TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == PARM_DECL)
+             && decl_function_context (t) != info->context)
+           get_nonlocal_debug_decl (info, t);
+         t = TYPE_MAX_VALUE (domain);
+         if (t && (TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == PARM_DECL)
+             && decl_function_context (t) != info->context)
+           get_nonlocal_debug_decl (info, t);
+       }
+    }
+}
+
+/* Create nonlocal debug decls for nonlocal VLA array bounds for VLAs
+   in BLOCK.  */
+
+static void
+note_nonlocal_block_vlas (struct nesting_info *info, tree block)
+{
+  tree var;
+
+  for (var = BLOCK_VARS (block); var; var = TREE_CHAIN (var))
+    if (TREE_CODE (var) == VAR_DECL
+       && variably_modified_type_p (TREE_TYPE (var), NULL)
+       && DECL_HAS_VALUE_EXPR_P (var)
+       && decl_function_context (var) != info->context)
+      note_nonlocal_vla_type (info, TREE_TYPE (var));
+}
 
 /* Callback for walk_gimple_stmt.  Rewrite all references to VAR and
    PARM_DECLs that belong to outer functions.  This handles statements
@@ -1149,7 +1246,8 @@ convert_nonlocal_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
        {
          tree c, decl;
          decl = get_chain_decl (info);
-         c = build_omp_clause (OMP_CLAUSE_FIRSTPRIVATE);
+         c = build_omp_clause (gimple_location (stmt),
+                               OMP_CLAUSE_FIRSTPRIVATE);
          OMP_CLAUSE_DECL (c) = decl;
          OMP_CLAUSE_CHAIN (c) = gimple_omp_taskreg_clauses (stmt);
          gimple_omp_taskreg_set_clauses (stmt, c);
@@ -1202,6 +1300,19 @@ convert_nonlocal_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
                 info, gimple_omp_body (stmt));
       break;
 
+    case GIMPLE_BIND:
+      if (!optimize && gimple_bind_block (stmt))
+       note_nonlocal_block_vlas (info, gimple_bind_block (stmt));
+
+      *handled_ops_p = false;
+      return NULL_TREE;
+
+    case GIMPLE_COND:
+      wi->val_only = true;
+      wi->is_lhs = false;
+      *handled_ops_p = false;
+      return NULL_TREE;
+
     default:
       /* For every other statement that we are not interested in
         handling here, let the walker traverse the operands.  */
@@ -1235,9 +1346,9 @@ get_local_debug_decl (struct nesting_info *info, tree decl, tree field)
   x = info->frame_decl;
   x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL_TREE);
 
-  new_decl = build_decl (VAR_DECL, DECL_NAME (decl), TREE_TYPE (decl));
+  new_decl = build_decl (DECL_SOURCE_LOCATION (decl),
+                        VAR_DECL, DECL_NAME (decl), TREE_TYPE (decl));
   DECL_CONTEXT (new_decl) = info->context;
-  DECL_SOURCE_LOCATION (new_decl) = DECL_SOURCE_LOCATION (decl);
   DECL_ARTIFICIAL (new_decl) = DECL_ARTIFICIAL (decl);
   DECL_IGNORED_P (new_decl) = DECL_IGNORED_P (decl);
   TREE_THIS_VOLATILE (new_decl) = TREE_THIS_VOLATILE (decl);
@@ -1549,7 +1660,8 @@ convert_local_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
        {
          tree c;
          (void) get_frame_type (info);
-         c = build_omp_clause (OMP_CLAUSE_SHARED);
+         c = build_omp_clause (gimple_location (stmt),
+                               OMP_CLAUSE_SHARED);
          OMP_CLAUSE_DECL (c) = info->frame_decl;
          OMP_CLAUSE_CHAIN (c) = gimple_omp_taskreg_clauses (stmt);
          gimple_omp_taskreg_set_clauses (stmt, c);
@@ -1601,6 +1713,12 @@ convert_local_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
                 info, gimple_omp_body (stmt));
       break;
 
+    case GIMPLE_COND:
+      wi->val_only = true;
+      wi->is_lhs = false;
+      *handled_ops_p = false;
+      return NULL_TREE;
+
     default:
       /* For every other statement that we are not interested in
         handling here, let the walker traverse the operands.  */
@@ -1661,7 +1779,7 @@ convert_nl_goto_reference (gimple_stmt_iterator *gsi, bool *handled_ops_p,
   slot = pointer_map_insert (i->var_map, label);
   if (*slot == NULL)
     {
-      new_label = create_artificial_label ();
+      new_label = create_artificial_label (UNKNOWN_LOCATION);
       DECL_NONLOCAL (new_label) = 1;
       *slot = new_label;
     }
@@ -1766,7 +1884,7 @@ convert_tramp_reference_op (tree *tp, int *walk_subtrees, void *data)
 
       /* If the nested function doesn't use a static chain, then
         it doesn't need a trampoline.  */
-      if (DECL_NO_STATIC_CHAIN (decl))
+      if (!DECL_STATIC_CHAIN (decl))
        break;
 
       /* If we don't want a trampoline, then don't build one.  */
@@ -1860,11 +1978,13 @@ convert_gimple_call (gimple_stmt_iterator *gsi, bool *handled_ops_p,
   switch (gimple_code (stmt))
     {
     case GIMPLE_CALL:
+      if (gimple_call_chain (stmt))
+       break;
       decl = gimple_call_fndecl (stmt);
       if (!decl)
        break;
       target_context = decl_function_context (decl);
-      if (target_context && !DECL_NO_STATIC_CHAIN (decl))
+      if (target_context && DECL_STATIC_CHAIN (decl))
        {
          gimple_call_set_chain (stmt, get_static_chain (info, target_context,
                                                         &wi->gsi));
@@ -1893,8 +2013,9 @@ convert_gimple_call (gimple_stmt_iterator *gsi, bool *handled_ops_p,
              break;
          if (c == NULL)
            {
-             c = build_omp_clause (i ? OMP_CLAUSE_FIRSTPRIVATE
-                                     : OMP_CLAUSE_SHARED);
+             c = build_omp_clause (gimple_location (stmt),
+                                   i ? OMP_CLAUSE_FIRSTPRIVATE
+                                   : OMP_CLAUSE_SHARED);
              OMP_CLAUSE_DECL (c) = decl;
              OMP_CLAUSE_CHAIN (c) = gimple_omp_taskreg_clauses (stmt);
              gimple_omp_taskreg_set_clauses (stmt, c);
@@ -1926,32 +2047,69 @@ convert_gimple_call (gimple_stmt_iterator *gsi, bool *handled_ops_p,
   return NULL_TREE;
 }
 
-
-/* Walk the nesting tree starting with ROOT, depth first.  Convert all
-   trampolines and call expressions.  On the way back up, determine if
-   a nested function actually uses its static chain; if not, remember that.  */
+/* Walk the nesting tree starting with ROOT.  Convert all trampolines and
+   call expressions.  At the same time, determine if a nested function
+   actually uses its static chain; if not, remember that.  */
 
 static void
 convert_all_function_calls (struct nesting_info *root)
 {
+  struct nesting_info *n;
+  int iter_count;
+  bool any_changed;
+
+  /* First, optimistically clear static_chain for all decls that haven't
+     used the static chain already for variable access.  */
+  FOR_EACH_NEST_INFO (n, root)
+    {
+      tree decl = n->context;
+      if (!n->outer || (!n->chain_decl && !n->chain_field))
+       {
+         DECL_STATIC_CHAIN (decl) = 0;
+         if (dump_file && (dump_flags & TDF_DETAILS))
+           fprintf (dump_file, "Guessing no static-chain for %s\n",
+                    lang_hooks.decl_printable_name (decl, 2));
+       }
+      else
+       DECL_STATIC_CHAIN (decl) = 1;
+    }
+
+  /* Walk the functions and perform transformations.  Note that these
+     transformations can induce new uses of the static chain, which in turn
+     require re-examining all users of the decl.  */
+  /* ??? It would make sense to try to use the call graph to speed this up,
+     but the call graph hasn't really been built yet.  Even if it did, we 
+     would still need to iterate in this loop since address-of references
+     wouldn't show up in the callgraph anyway.  */
+  iter_count = 0;
   do
     {
-      if (root->inner)
-       convert_all_function_calls (root->inner);
+      any_changed = false;
+      iter_count++;
 
-      walk_function (convert_tramp_reference_stmt, convert_tramp_reference_op,
-                    root);
-      walk_function (convert_gimple_call, NULL, root);
+      if (dump_file && (dump_flags & TDF_DETAILS))
+       fputc ('\n', dump_file);
 
-      /* If the function does not use a static chain, then remember that.  */
-      if (root->outer && !root->chain_decl && !root->chain_field)
-       DECL_NO_STATIC_CHAIN (root->context) = 1;
-      else
-       gcc_assert (!DECL_NO_STATIC_CHAIN (root->context));
+      FOR_EACH_NEST_INFO (n, root)
+       {
+         tree decl = n->context;
+         bool old_static_chain = DECL_STATIC_CHAIN (decl);
 
-      root = root->next;
+         walk_function (convert_tramp_reference_stmt,
+                        convert_tramp_reference_op, n);
+         walk_function (convert_gimple_call, NULL, n);
+
+         /* If a call to another function created the use of a chain
+            within this function, we'll have to continue iteration.  */
+         if (!old_static_chain && DECL_STATIC_CHAIN (decl))
+           any_changed = true;
+       }
     }
-  while (root);
+  while (any_changed);
+
+  if (dump_file && (dump_flags & TDF_DETAILS))
+    fprintf (dump_file, "convert_all_function_calls iterations: %d\n\n",
+            iter_count);
 }
 
 struct nesting_copy_body_data
@@ -1979,9 +2137,117 @@ nesting_copy_decl (tree decl, copy_body_data *id)
       return new_decl;
     }
 
+  if (TREE_CODE (decl) == VAR_DECL
+      || TREE_CODE (decl) == PARM_DECL
+      || TREE_CODE (decl) == RESULT_DECL)
+    return decl;
+
   return copy_decl_no_change (decl, id);
 }
 
+/* A helper function for remap_vla_decls.  See if *TP contains
+   some remapped variables.  */
+
+static tree
+contains_remapped_vars (tree *tp, int *walk_subtrees, void *data)
+{
+  struct nesting_info *root = (struct nesting_info *) data;
+  tree t = *tp;
+  void **slot;
+
+  if (DECL_P (t))
+    {
+      *walk_subtrees = 0;
+      slot = pointer_map_contains (root->var_map, t);
+
+      if (slot)
+       return (tree) *slot;
+    }
+  return NULL;
+}
+
+/* Remap VLA decls in BLOCK and subblocks if remapped variables are
+   involved.  */
+
+static void
+remap_vla_decls (tree block, struct nesting_info *root)
+{
+  tree var, subblock, val, type;
+  struct nesting_copy_body_data id;
+
+  for (subblock = BLOCK_SUBBLOCKS (block);
+       subblock;
+       subblock = BLOCK_CHAIN (subblock))
+    remap_vla_decls (subblock, root);
+
+  for (var = BLOCK_VARS (block); var; var = TREE_CHAIN (var))
+    {
+      if (TREE_CODE (var) == VAR_DECL
+         && variably_modified_type_p (TREE_TYPE (var), NULL)
+         && DECL_HAS_VALUE_EXPR_P (var))
+       {
+         type = TREE_TYPE (var);
+         val = DECL_VALUE_EXPR (var);
+         if (walk_tree (&type, contains_remapped_vars, root, NULL) != NULL
+             ||  walk_tree (&val, contains_remapped_vars, root, NULL) != NULL)
+           break;
+       }
+    }
+  if (var == NULL_TREE)
+    return;
+
+  memset (&id, 0, sizeof (id));
+  id.cb.copy_decl = nesting_copy_decl;
+  id.cb.decl_map = pointer_map_create ();
+  id.root = root;
+
+  for (; var; var = TREE_CHAIN (var))
+    if (TREE_CODE (var) == VAR_DECL
+       && variably_modified_type_p (TREE_TYPE (var), NULL)
+       && DECL_HAS_VALUE_EXPR_P (var))
+      {
+       struct nesting_info *i;
+       tree newt, t, context;
+
+       t = type = TREE_TYPE (var);
+       val = DECL_VALUE_EXPR (var);
+       if (walk_tree (&type, contains_remapped_vars, root, NULL) == NULL
+           && walk_tree (&val, contains_remapped_vars, root, NULL) == NULL)
+         continue;
+
+       context = decl_function_context (var);
+       for (i = root; i; i = i->outer)
+         if (i->context == context)
+           break;
+
+       if (i == NULL)
+         continue;
+
+       id.cb.src_fn = i->context;
+       id.cb.dst_fn = i->context;
+       id.cb.src_cfun = DECL_STRUCT_FUNCTION (root->context);
+
+       TREE_TYPE (var) = newt = remap_type (type, &id.cb);
+       while (POINTER_TYPE_P (newt) && !TYPE_NAME (newt))
+         {
+           newt = TREE_TYPE (newt);
+           t = TREE_TYPE (t);
+         }
+       if (TYPE_NAME (newt)
+           && TREE_CODE (TYPE_NAME (newt)) == TYPE_DECL
+           && DECL_ORIGINAL_TYPE (TYPE_NAME (newt))
+           && newt != t
+           && TYPE_NAME (newt) == TYPE_NAME (t))
+         TYPE_NAME (newt) = remap_decl (TYPE_NAME (newt), &id.cb);
+
+       walk_tree (&val, copy_tree_body_r, &id.cb, NULL);
+       if (val != DECL_VALUE_EXPR (var))
+         SET_DECL_VALUE_EXPR (var, val);
+      }
+
+  pointer_map_destroy (id.cb.decl_map);
+}
+
 /* Do "everything else" to clean up or complete state collected by the
    various walking passes -- lay out the types and decls, generate code
    to initialize the frame decl, store critical expressions in the
@@ -2004,10 +2270,26 @@ finalize_nesting_tree_1 (struct nesting_info *root)
       /* In some cases the frame type will trigger the -Wpadded warning.
         This is not helpful; suppress it. */
       int save_warn_padded = warn_padded;
+      tree *adjust;
+
       warn_padded = 0;
       layout_type (root->frame_type);
       warn_padded = save_warn_padded;
       layout_decl (root->frame_decl, 0);
+
+      /* Remove root->frame_decl from root->new_local_var_chain, so
+        that we can declare it also in the lexical blocks, which
+        helps ensure virtual regs that end up appearing in its RTL
+        expression get substituted in instantiate_virtual_regs().  */
+      for (adjust = &root->new_local_var_chain;
+          *adjust != root->frame_decl;
+          adjust = &TREE_CHAIN (*adjust))
+       gcc_assert (TREE_CHAIN (*adjust));
+      *adjust = TREE_CHAIN (*adjust);
+
+      TREE_CHAIN (root->frame_decl) = NULL_TREE;
+      declare_vars (root->frame_decl,
+                   gimple_seq_first_stmt (gimple_body (context)), true);
     }
 
   /* If any parameters were referenced non-locally, then we need to 
@@ -2067,10 +2349,8 @@ finalize_nesting_tree_1 (struct nesting_info *root)
          if (!field)
            continue;
 
-         if (DECL_NO_STATIC_CHAIN (i->context))
-           arg3 = null_pointer_node;
-         else
-           arg3 = build_addr (root->frame_decl, context);
+         gcc_assert (DECL_STATIC_CHAIN (i->context));
+         arg3 = build_addr (root->frame_decl, context);
 
          arg2 = build_addr (i->context, context);
 
@@ -2118,6 +2398,9 @@ finalize_nesting_tree_1 (struct nesting_info *root)
   if (root->debug_var_chain)
     {
       tree debug_var;
+      gimple scope;
+
+      remap_vla_decls (DECL_INITIAL (root->context), root);
 
       for (debug_var = root->debug_var_chain; debug_var;
           debug_var = TREE_CHAIN (debug_var))
@@ -2170,26 +2453,29 @@ finalize_nesting_tree_1 (struct nesting_info *root)
          pointer_map_destroy (id.cb.decl_map);
        }
 
-      declare_vars (root->debug_var_chain,
-                   gimple_seq_first_stmt (gimple_body (root->context)),
-                   true);
+      scope = gimple_seq_first_stmt (gimple_body (root->context));
+      if (gimple_bind_block (scope))
+       declare_vars (root->debug_var_chain, scope, true);
+      else
+       BLOCK_VARS (DECL_INITIAL (root->context))
+         = chainon (BLOCK_VARS (DECL_INITIAL (root->context)),
+                    root->debug_var_chain);
     }
 
   /* Dump the translated tree function.  */
-  dump_function (TDI_nested, root->context);
+  if (dump_file)
+    {
+      fputs ("\n\n", dump_file);
+      dump_function_to_file (root->context, dump_file, dump_flags);
+    }
 }
 
 static void
 finalize_nesting_tree (struct nesting_info *root)
 {
-  do
-    {
-      if (root->inner)
-       finalize_nesting_tree (root->inner);
-      finalize_nesting_tree_1 (root);
-      root = root->next;
-    }
-  while (root);
+  struct nesting_info *n;
+  FOR_EACH_NEST_INFO (n, root)
+    finalize_nesting_tree_1 (n);
 }
 
 /* Unnest the nodes and pass them to cgraph.  */
@@ -2211,14 +2497,9 @@ unnest_nesting_tree_1 (struct nesting_info *root)
 static void
 unnest_nesting_tree (struct nesting_info *root)
 {
-  do
-    {
-      if (root->inner)
-       unnest_nesting_tree (root->inner);
-      unnest_nesting_tree_1 (root);
-      root = root->next;
-    }
-  while (root);
+  struct nesting_info *n;
+  FOR_EACH_NEST_INFO (n, root)
+    unnest_nesting_tree_1 (n);
 }
 
 /* Free the data structures allocated during this pass.  */
@@ -2226,18 +2507,29 @@ unnest_nesting_tree (struct nesting_info *root)
 static void
 free_nesting_tree (struct nesting_info *root)
 {
-  struct nesting_info *next;
+  struct nesting_info *node, *next;
+
+  node = iter_nestinfo_start (root);
   do
     {
-      if (root->inner)
-       free_nesting_tree (root->inner);
-      pointer_map_destroy (root->var_map);
-      pointer_map_destroy (root->field_map);
-      next = root->next;
-      free (root);
-      root = next;
+      next = iter_nestinfo_next (node);
+      pointer_map_destroy (node->var_map);
+      pointer_map_destroy (node->field_map);
+      free (node);
+      node = next;
     }
-  while (root);
+  while (node);
+}
+
+/* Gimplify a function and all its nested functions.  */
+static void
+gimplify_all_functions (struct cgraph_node *root)
+{
+  struct cgraph_node *iter;
+  if (!gimple_body (root->decl))
+    gimplify_function_tree (root->decl);
+  for (iter = root->nested; iter; iter = iter->next_nested)
+    gimplify_all_functions (iter);
 }
 
 /* Main entry point for this pass.  Process FNDECL and all of its nested
@@ -2254,8 +2546,16 @@ lower_nested_functions (tree fndecl)
   if (!cgn->nested)
     return;
 
+  gimplify_all_functions (cgn);
+
+  dump_file = dump_begin (TDI_nested, &dump_flags);
+  if (dump_file)
+    fprintf (dump_file, "\n;; Function %s\n\n",
+            lang_hooks.decl_printable_name (fndecl, 2));
+
   bitmap_obstack_initialize (&nesting_info_bitmap_obstack);
   root = create_nesting_tree (cgn);
+
   walk_all_functions (convert_nonlocal_reference_stmt,
                       convert_nonlocal_reference_op,
                      root);
@@ -2264,11 +2564,19 @@ lower_nested_functions (tree fndecl)
                      root);
   walk_all_functions (convert_nl_goto_reference, NULL, root);
   walk_all_functions (convert_nl_goto_receiver, NULL, root);
+
   convert_all_function_calls (root);
   finalize_nesting_tree (root);
   unnest_nesting_tree (root);
+
   free_nesting_tree (root);
   bitmap_obstack_release (&nesting_info_bitmap_obstack);
+
+  if (dump_file)
+    {
+      dump_end (TDI_nested, dump_file);
+      dump_file = NULL;
+    }
 }
 
 #include "gt-tree-nested.h"