aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-nested.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/tree-nested.c')
-rw-r--r--gcc/tree-nested.c466
1 files changed, 422 insertions, 44 deletions
diff --git a/gcc/tree-nested.c b/gcc/tree-nested.c
index d5309ec..4c65a1d 100644
--- a/gcc/tree-nested.c
+++ b/gcc/tree-nested.c
@@ -89,9 +89,13 @@ struct nesting_info GTY ((chain_next ("%h.next")))
struct nesting_info *inner;
struct nesting_info *next;
+ htab_t GTY ((param_is (struct var_map_elt))) field_map;
htab_t GTY ((param_is (struct var_map_elt))) var_map;
+ bitmap suppress_expansion;
+
tree context;
tree new_local_var_chain;
+ tree debug_var_chain;
tree frame_type;
tree frame_decl;
tree chain_field;
@@ -180,7 +184,7 @@ build_addr (tree exp, tree context)
/* Insert FIELD into TYPE, sorted by alignment requirements. */
-static void
+void
insert_field_into_struct (tree type, tree field)
{
tree *p;
@@ -264,7 +268,7 @@ lookup_field_for_decl (struct nesting_info *info, tree decl,
tree field;
dummy.old = decl;
- slot = htab_find_slot (info->var_map, &dummy, insert);
+ slot = htab_find_slot (info->field_map, &dummy, insert);
if (!slot)
{
gcc_assert (insert != INSERT);
@@ -538,37 +542,21 @@ get_nl_goto_field (struct nesting_info *info)
return field;
}
-/* Convenience routines to walk all statements of a gimple function.
-
- For each statement, we invoke CALLBACK via walk_tree. The passed
- data is a walk_stmt_info structure. Of note here is a TSI that
- points to the current statement being walked. The VAL_ONLY flag
- that indicates whether the *TP being examined may be replaced
- with something that matches is_gimple_val (if true) or something
- slightly more complicated (if false). "Something" technically
- means the common subset of is_gimple_lvalue and is_gimple_rhs,
- but we never try to form anything more complicated than that, so
- we don't bother checking. */
-
-struct walk_stmt_info
-{
- walk_tree_fn callback;
- tree_stmt_iterator tsi;
- struct nesting_info *info;
- bool val_only;
- bool is_lhs;
- bool changed;
-};
+/* Iterate over all sub-statements of *TP calling walk_tree with
+ WI->CALLBACK for every sub-expression in each statement found. */
-/* A subroutine of walk_function. Iterate over all sub-statements of *TP. */
-
-static void
+void
walk_stmts (struct walk_stmt_info *wi, tree *tp)
{
tree t = *tp;
+ int walk_subtrees;
+
if (!t)
return;
+ if (wi->want_locations && EXPR_HAS_LOCATION (t))
+ input_location = EXPR_LOCATION (t);
+
switch (TREE_CODE (t))
{
case STATEMENT_LIST:
@@ -598,11 +586,26 @@ walk_stmts (struct walk_stmt_info *wi, tree *tp)
walk_stmts (wi, &TREE_OPERAND (t, 0));
walk_stmts (wi, &TREE_OPERAND (t, 1));
break;
+
case BIND_EXPR:
+ if (wi->want_bind_expr)
+ {
+ walk_subtrees = 1;
+ wi->callback (tp, &walk_subtrees, wi);
+ if (!walk_subtrees)
+ break;
+ }
walk_stmts (wi, &BIND_EXPR_BODY (t));
break;
case RETURN_EXPR:
+ if (wi->want_return_expr)
+ {
+ walk_subtrees = 1;
+ wi->callback (tp, &walk_subtrees, wi);
+ if (!walk_subtrees)
+ break;
+ }
walk_stmts (wi, &TREE_OPERAND (t, 0));
break;
@@ -628,10 +631,10 @@ walk_stmts (struct walk_stmt_info *wi, tree *tp)
}
}
-/* Invoke CALLBACK on all statements of INFO->CONTEXT. */
+/* Invoke CALLBACK on all statements of *STMT_P. */
static void
-walk_function (walk_tree_fn callback, struct nesting_info *info)
+walk_body (walk_tree_fn callback, struct nesting_info *info, tree *stmt_p)
{
struct walk_stmt_info wi;
@@ -640,7 +643,15 @@ walk_function (walk_tree_fn callback, struct nesting_info *info)
wi.info = info;
wi.val_only = true;
- walk_stmts (&wi, &DECL_SAVED_TREE (info->context));
+ walk_stmts (&wi, stmt_p);
+}
+
+/* Invoke CALLBACK on all statements of INFO->CONTEXT. */
+
+static inline void
+walk_function (walk_tree_fn callback, struct nesting_info *info)
+{
+ walk_body (callback, info, &DECL_SAVED_TREE (info->context));
}
/* Similarly for ROOT and all functions nested underneath, depth first. */
@@ -707,7 +718,9 @@ static struct nesting_info *
create_nesting_tree (struct cgraph_node *cgn)
{
struct nesting_info *info = GGC_CNEW (struct nesting_info);
+ info->field_map = htab_create_ggc (7, var_map_hash, var_map_eq, ggc_free);
info->var_map = htab_create_ggc (7, var_map_hash, var_map_eq, ggc_free);
+ info->suppress_expansion = BITMAP_GGC_ALLOC ();
info->context = cgn->decl;
for (cgn = cgn->nested; cgn ; cgn = cgn->next_nested)
@@ -794,6 +807,80 @@ get_frame_field (struct nesting_info *info, tree target_context,
return x;
}
+/* A subroutine of convert_nonlocal_reference. Create a local variable
+ in the nested function with DECL_VALUE_EXPR set to reference the true
+ variable in the parent function. This is used both for debug info
+ and in OpenMP lowering. */
+
+static tree
+get_nonlocal_debug_decl (struct nesting_info *info, tree decl)
+{
+ struct var_map_elt *elt, dummy;
+ tree target_context;
+ struct nesting_info *i;
+ tree x, field, new_decl;
+ void **slot;
+
+ dummy.old = decl;
+ slot = htab_find_slot (info->var_map, &dummy, INSERT);
+ elt = *slot;
+
+ if (elt)
+ return elt->new;
+
+ target_context = decl_function_context (decl);
+
+ /* A copy of the code in get_frame_field, but without the temporaries. */
+ if (info->context == target_context)
+ {
+ /* Make sure frame_decl gets created. */
+ (void) get_frame_type (info);
+ x = info->frame_decl;
+ i = info;
+ }
+ else
+ {
+ x = get_chain_decl (info);
+ for (i = info->outer; i->context != target_context; i = i->outer)
+ {
+ field = get_chain_field (i);
+ x = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (x)), x);
+ x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL_TREE);
+ }
+ x = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (x)), x);
+ }
+
+ field = lookup_field_for_decl (i, decl, INSERT);
+ x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL_TREE);
+ if (use_pointer_in_frame (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));
+ 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);
+ TREE_SIDE_EFFECTS (new_decl) = TREE_SIDE_EFFECTS (decl);
+ TREE_READONLY (new_decl) = TREE_READONLY (decl);
+ TREE_ADDRESSABLE (new_decl) = TREE_ADDRESSABLE (decl);
+ DECL_SEEN_IN_BIND_EXPR_P (new_decl) = 1;
+
+ SET_DECL_VALUE_EXPR (new_decl, x);
+ DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
+
+ elt = ggc_alloc (sizeof (*elt));
+ elt->old = decl;
+ elt->new = new_decl;
+ *slot = elt;
+
+ TREE_CHAIN (new_decl) = info->debug_var_chain;
+ info->debug_var_chain = new_decl;
+
+ return new_decl;
+}
+
/* Called via walk_function+walk_tree, rewrite all references to VAR
and PARM_DECLs that belong to outer functions.
@@ -802,12 +889,16 @@ get_frame_field (struct nesting_info *info, tree target_context,
be CHAIN->FOO. For two levels it'll be CHAIN->__chain->FOO. Further
indirections apply to decls for which use_pointer_in_frame is true. */
+static bool convert_nonlocal_omp_clauses (tree *, struct walk_stmt_info *);
+
static tree
convert_nonlocal_reference (tree *tp, int *walk_subtrees, void *data)
{
struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
struct nesting_info *info = wi->info;
tree t = *tp;
+ tree save_local_var_chain;
+ bitmap save_suppress;
*walk_subtrees = 0;
switch (TREE_CODE (t))
@@ -821,19 +912,23 @@ convert_nonlocal_reference (tree *tp, int *walk_subtrees, void *data)
case PARM_DECL:
if (decl_function_context (t) != info->context)
{
- tree target_context = decl_function_context (t);
- struct nesting_info *i;
tree x;
wi->changed = true;
- for (i = info->outer; i->context != target_context; i = i->outer)
- continue;
- x = lookup_field_for_decl (i, t, INSERT);
- x = get_frame_field (info, target_context, x, &wi->tsi);
- if (use_pointer_in_frame (t))
+ x = get_nonlocal_debug_decl (info, t);
+ if (!bitmap_bit_p (info->suppress_expansion, DECL_UID (t)))
{
- x = init_tmp_var (info, x, &wi->tsi);
- x = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (x)), x);
+ tree target_context = decl_function_context (t);
+ struct nesting_info *i;
+ for (i = info->outer; i->context != target_context; i = i->outer)
+ continue;
+ x = lookup_field_for_decl (i, t, INSERT);
+ x = get_frame_field (info, target_context, x, &wi->tsi);
+ if (use_pointer_in_frame (t))
+ {
+ x = init_tmp_var (info, x, &wi->tsi);
+ x = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (x)), x);
+ }
}
if (wi->val_only)
@@ -935,6 +1030,43 @@ convert_nonlocal_reference (tree *tp, int *walk_subtrees, void *data)
walk_tree (tp, convert_nonlocal_reference, wi, NULL);
break;
+ case OMP_PARALLEL:
+ save_suppress = info->suppress_expansion;
+ if (convert_nonlocal_omp_clauses (&OMP_PARALLEL_CLAUSES (t), wi))
+ {
+ tree c;
+ c = get_chain_decl (info);
+ c = build1 (OMP_CLAUSE_FIRSTPRIVATE, void_type_node, c);
+ OMP_CLAUSE_CHAIN (c) = OMP_PARALLEL_CLAUSES (t);
+ OMP_PARALLEL_CLAUSES (t) = c;
+ }
+
+ save_local_var_chain = info->new_local_var_chain;
+ info->new_local_var_chain = NULL;
+
+ walk_body (convert_nonlocal_reference, info, &OMP_PARALLEL_BODY (t));
+
+ if (info->new_local_var_chain)
+ declare_tmp_vars (info->new_local_var_chain, OMP_PARALLEL_BODY (t));
+ info->new_local_var_chain = save_local_var_chain;
+ info->suppress_expansion = save_suppress;
+ break;
+
+ case OMP_FOR:
+ case OMP_SECTIONS:
+ case OMP_SINGLE:
+ save_suppress = info->suppress_expansion;
+ convert_nonlocal_omp_clauses (&OMP_CLAUSES (t), wi);
+ walk_body (convert_nonlocal_reference, info, &OMP_BODY (t));
+ info->suppress_expansion = save_suppress;
+ break;
+
+ case OMP_SECTION:
+ case OMP_MASTER:
+ case OMP_ORDERED:
+ walk_body (convert_nonlocal_reference, info, &OMP_BODY (t));
+ break;
+
default:
if (!IS_TYPE_OR_DECL_P (t))
{
@@ -948,10 +1080,119 @@ convert_nonlocal_reference (tree *tp, int *walk_subtrees, void *data)
return NULL_TREE;
}
+static bool
+convert_nonlocal_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
+{
+ struct nesting_info *info = wi->info;
+ bool need_chain = false;
+ tree clause, decl;
+ int dummy;
+ bitmap new_suppress;
+
+ new_suppress = BITMAP_GGC_ALLOC ();
+ bitmap_copy (new_suppress, info->suppress_expansion);
+
+ for (clause = *pclauses; clause ; clause = OMP_CLAUSE_CHAIN (clause))
+ {
+ switch (TREE_CODE (clause))
+ {
+ case OMP_CLAUSE_PRIVATE:
+ case OMP_CLAUSE_FIRSTPRIVATE:
+ case OMP_CLAUSE_LASTPRIVATE:
+ case OMP_CLAUSE_REDUCTION:
+ case OMP_CLAUSE_COPYPRIVATE:
+ case OMP_CLAUSE_SHARED:
+ decl = OMP_CLAUSE_DECL (clause);
+ if (decl_function_context (decl) != info->context)
+ {
+ bitmap_set_bit (new_suppress, DECL_UID (decl));
+ OMP_CLAUSE_DECL (clause) = get_nonlocal_debug_decl (info, decl);
+ need_chain = true;
+ }
+ break;
+
+ case OMP_CLAUSE_SCHEDULE:
+ if (OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (clause) == NULL)
+ break;
+ /* FALLTHRU */
+ case OMP_CLAUSE_IF:
+ case OMP_CLAUSE_NUM_THREADS:
+ wi->val_only = true;
+ wi->is_lhs = false;
+ convert_nonlocal_reference (&TREE_OPERAND (clause, 0), &dummy, wi);
+ break;
+
+ case OMP_CLAUSE_NOWAIT:
+ case OMP_CLAUSE_ORDERED:
+ case OMP_CLAUSE_DEFAULT:
+ case OMP_CLAUSE_COPYIN:
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+ }
+
+ info->suppress_expansion = new_suppress;
+
+ return need_chain;
+}
+
+/* A subroutine of convert_local_reference. Create a local variable
+ in the parent function with DECL_VALUE_EXPR set to reference the
+ field in FRAME. This is used both for debug info and in OpenMP
+ lowering. */
+
+static tree
+get_local_debug_decl (struct nesting_info *info, tree decl, tree field)
+{
+ struct var_map_elt *elt, dummy;
+ tree x, new_decl;
+ void **slot;
+
+ dummy.old = decl;
+ slot = htab_find_slot (info->var_map, &dummy, INSERT);
+ elt = *slot;
+
+ if (elt)
+ return elt->new;
+
+ /* Make sure frame_decl gets created. */
+ (void) get_frame_type (info);
+ 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));
+ 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);
+ TREE_SIDE_EFFECTS (new_decl) = TREE_SIDE_EFFECTS (decl);
+ TREE_READONLY (new_decl) = TREE_READONLY (decl);
+ TREE_ADDRESSABLE (new_decl) = TREE_ADDRESSABLE (decl);
+ DECL_SEEN_IN_BIND_EXPR_P (new_decl) = 1;
+
+ SET_DECL_VALUE_EXPR (new_decl, x);
+ DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
+
+ elt = ggc_alloc (sizeof (*elt));
+ elt->old = decl;
+ elt->new = new_decl;
+ *slot = elt;
+
+ TREE_CHAIN (new_decl) = info->debug_var_chain;
+ info->debug_var_chain = new_decl;
+
+ return new_decl;
+}
+
/* Called via walk_function+walk_tree, rewrite all references to VAR
and PARM_DECLs that were referenced by inner nested functions.
The rewrite will be a structure reference to the local frame variable. */
+static bool convert_local_omp_clauses (tree *, struct walk_stmt_info *);
+
static tree
convert_local_reference (tree *tp, int *walk_subtrees, void *data)
{
@@ -959,6 +1200,8 @@ convert_local_reference (tree *tp, int *walk_subtrees, void *data)
struct nesting_info *info = wi->info;
tree t = *tp, field, x;
bool save_val_only;
+ tree save_local_var_chain;
+ bitmap save_suppress;
*walk_subtrees = 0;
switch (TREE_CODE (t))
@@ -984,7 +1227,9 @@ convert_local_reference (tree *tp, int *walk_subtrees, void *data)
break;
wi->changed = true;
- x = get_frame_field (info, info->context, field, &wi->tsi);
+ x = get_local_debug_decl (info, t, field);
+ if (!bitmap_bit_p (info->suppress_expansion, DECL_UID (t)))
+ x = get_frame_field (info, info->context, field, &wi->tsi);
if (wi->val_only)
{
@@ -1066,6 +1311,43 @@ convert_local_reference (tree *tp, int *walk_subtrees, void *data)
wi->val_only = save_val_only;
break;
+ case OMP_PARALLEL:
+ save_suppress = info->suppress_expansion;
+ if (convert_local_omp_clauses (&OMP_PARALLEL_CLAUSES (t), wi))
+ {
+ tree c;
+ (void) get_frame_type (info);
+ c = build1 (OMP_CLAUSE_SHARED, void_type_node, info->frame_decl);
+ OMP_CLAUSE_CHAIN (c) = OMP_PARALLEL_CLAUSES (t);
+ OMP_PARALLEL_CLAUSES (t) = c;
+ }
+
+ save_local_var_chain = info->new_local_var_chain;
+ info->new_local_var_chain = NULL;
+
+ walk_body (convert_local_reference, info, &OMP_PARALLEL_BODY (t));
+
+ if (info->new_local_var_chain)
+ declare_tmp_vars (info->new_local_var_chain, OMP_PARALLEL_BODY (t));
+ info->new_local_var_chain = save_local_var_chain;
+ info->suppress_expansion = save_suppress;
+ break;
+
+ case OMP_FOR:
+ case OMP_SECTIONS:
+ case OMP_SINGLE:
+ save_suppress = info->suppress_expansion;
+ convert_local_omp_clauses (&OMP_CLAUSES (t), wi);
+ walk_body (convert_local_reference, info, &OMP_BODY (t));
+ info->suppress_expansion = save_suppress;
+ break;
+
+ case OMP_SECTION:
+ case OMP_MASTER:
+ case OMP_ORDERED:
+ walk_body (convert_local_reference, info, &OMP_BODY (t));
+ break;
+
default:
if (!IS_TYPE_OR_DECL_P (t))
{
@@ -1079,6 +1361,70 @@ convert_local_reference (tree *tp, int *walk_subtrees, void *data)
return NULL_TREE;
}
+static bool
+convert_local_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
+{
+ struct nesting_info *info = wi->info;
+ bool need_frame = false;
+ tree clause, decl;
+ int dummy;
+ bitmap new_suppress;
+
+ new_suppress = BITMAP_GGC_ALLOC ();
+ bitmap_copy (new_suppress, info->suppress_expansion);
+
+ for (clause = *pclauses; clause ; clause = OMP_CLAUSE_CHAIN (clause))
+ {
+ switch (TREE_CODE (clause))
+ {
+ case OMP_CLAUSE_PRIVATE:
+ case OMP_CLAUSE_FIRSTPRIVATE:
+ case OMP_CLAUSE_LASTPRIVATE:
+ case OMP_CLAUSE_REDUCTION:
+ case OMP_CLAUSE_COPYPRIVATE:
+ case OMP_CLAUSE_SHARED:
+ decl = OMP_CLAUSE_DECL (clause);
+ if (decl_function_context (decl) == info->context
+ && !use_pointer_in_frame (decl))
+ {
+ tree field = lookup_field_for_decl (info, decl, NO_INSERT);
+ if (field)
+ {
+ bitmap_set_bit (new_suppress, DECL_UID (decl));
+ OMP_CLAUSE_DECL (clause)
+ = get_local_debug_decl (info, decl, field);
+ need_frame = true;
+ }
+ }
+ break;
+
+ case OMP_CLAUSE_SCHEDULE:
+ if (OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (clause) == NULL)
+ break;
+ /* FALLTHRU */
+ case OMP_CLAUSE_IF:
+ case OMP_CLAUSE_NUM_THREADS:
+ wi->val_only = true;
+ wi->is_lhs = false;
+ convert_local_reference (&TREE_OPERAND (clause, 0), &dummy, wi);
+ break;
+
+ case OMP_CLAUSE_NOWAIT:
+ case OMP_CLAUSE_ORDERED:
+ case OMP_CLAUSE_DEFAULT:
+ case OMP_CLAUSE_COPYIN:
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+ }
+
+ info->suppress_expansion = new_suppress;
+
+ return need_frame;
+}
+
/* Called via walk_function+walk_tree, rewrite all GOTO_EXPRs that
reference labels from outer functions. The rewrite will be a
call to __builtin_nonlocal_goto. */
@@ -1292,6 +1638,15 @@ convert_call_expr (tree *tp, int *walk_subtrees, void *data)
*walk_subtrees = 1;
break;
+ case OMP_FOR:
+ case OMP_SECTIONS:
+ case OMP_SINGLE:
+ case OMP_MASTER:
+ case OMP_ORDERED:
+ case OMP_CRITICAL:
+ walk_body (convert_call_expr, info, &OMP_BODY (t));
+ break;
+
default:
break;
}
@@ -1336,7 +1691,6 @@ finalize_nesting_tree_1 (struct nesting_info *root)
tree stmt_list = NULL;
tree context = root->context;
struct function *sf;
- struct cgraph_node *node;
/* If we created a non-local frame type or decl, we need to lay them
out at this time. */
@@ -1449,10 +1803,33 @@ finalize_nesting_tree_1 (struct nesting_info *root)
if (root->new_local_var_chain)
declare_tmp_vars (root->new_local_var_chain,
DECL_SAVED_TREE (root->context));
+ if (root->debug_var_chain)
+ declare_tmp_vars (root->debug_var_chain,
+ DECL_SAVED_TREE (root->context));
/* Dump the translated tree function. */
dump_function (TDI_nested, root->context);
- node = cgraph_node (root->context);
+}
+
+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);
+}
+
+/* Unnest the nodes and pass them to cgraph. */
+
+static void
+unnest_nesting_tree_1 (struct nesting_info *root)
+{
+ struct cgraph_node *node = cgraph_node (root->context);
/* For nested functions update the cgraph to reflect unnesting.
We also delay finalizing of these functions up to this point. */
@@ -1464,13 +1841,13 @@ finalize_nesting_tree_1 (struct nesting_info *root)
}
static void
-finalize_nesting_tree (struct nesting_info *root)
+unnest_nesting_tree (struct nesting_info *root)
{
do
{
if (root->inner)
- finalize_nesting_tree (root->inner);
- finalize_nesting_tree_1 (root);
+ unnest_nesting_tree (root->inner);
+ unnest_nesting_tree_1 (root);
root = root->next;
}
while (root);
@@ -1516,6 +1893,7 @@ lower_nested_functions (tree fndecl)
walk_all_functions (convert_nl_goto_receiver, root);
convert_all_function_calls (root);
finalize_nesting_tree (root);
+ unnest_nesting_tree (root);
free_nesting_tree (root);
root = NULL;
}