[PATCH] Fix tree body copying
Richard Guenther
rguenther@suse.de
Tue Jul 7 11:12:00 GMT 2009
This is a split-out from the gimplify-unit-at-a-time patch which relies
on copy_tree_body_r properly copying GENERIC bodies.
There are several issues with the current implementation, the most
prominent being that statement-list copying is completely hosed
because of the 'optimization' tsi_link_after performs. Fixed by
providing a non-optimizing variant for tsi_link_after.
Other issues are that the FE requires the type on the statement-list
properly copied and TARGET_EXPR handled the same as SAVE_EXPR.
Separate bootstrap and regtest is running, I will apply this after
it succeeded.
Thanks,
Richard.
2009-07-07 Richard Guenther <rguenther@suse.de>
* tree-inline.c (copy_statement_list): Properly copy STATEMENT_LIST.
(copy_tree_body_r): Properly copy STATEMENT_LIST.
Properly handle TARGET_EXPR like SAVE_EXPR.
(unsave_r): Likewise.
* tree-iterator.h (tsi_link_stmt_after): Declare.
* tree-iterator.c (tsi_link_after_1): New helper split out from ...
(tsi_link_after): ... here.
(tsi_link_stmt_after): New function.
Index: gcc/tree-inline.c
===================================================================
*** gcc/tree-inline.c.orig 2009-07-07 12:51:02.000000000 +0200
--- gcc/tree-inline.c 2009-07-07 12:52:11.000000000 +0200
*************** copy_statement_list (tree *tp)
*** 603,609 ****
*tp = new_tree;
for (; !tsi_end_p (oi); tsi_next (&oi))
! tsi_link_after (&ni, tsi_stmt (oi), TSI_NEW_STMT);
}
static void
--- 603,609 ----
*tp = new_tree;
for (; !tsi_end_p (oi); tsi_next (&oi))
! tsi_link_stmt_after (&ni, tsi_stmt (oi), TSI_NEW_STMT);
}
static void
*************** copy_tree_body_r (tree *tp, int *walk_su
*** 919,926 ****
*walk_subtrees = 0;
}
else if (TREE_CODE (*tp) == STATEMENT_LIST)
! copy_statement_list (tp);
! else if (TREE_CODE (*tp) == SAVE_EXPR)
remap_save_expr (tp, id->decl_map, walk_subtrees);
else if (TREE_CODE (*tp) == LABEL_DECL
&& (! DECL_CONTEXT (*tp)
--- 919,931 ----
*walk_subtrees = 0;
}
else if (TREE_CODE (*tp) == STATEMENT_LIST)
! {
! tree new_type = remap_type (TREE_TYPE (*tp), id);
! copy_statement_list (tp);
! TREE_TYPE (*tp) = new_type;
! }
! else if (TREE_CODE (*tp) == SAVE_EXPR
! || TREE_CODE (*tp) == TARGET_EXPR)
remap_save_expr (tp, id->decl_map, walk_subtrees);
else if (TREE_CODE (*tp) == LABEL_DECL
&& (! DECL_CONTEXT (*tp)
*************** unsave_r (tree *tp, int *walk_subtrees,
*** 3917,3923 ****
gcc_unreachable ();
else if (TREE_CODE (*tp) == BIND_EXPR)
copy_bind_expr (tp, walk_subtrees, id);
! else if (TREE_CODE (*tp) == SAVE_EXPR)
remap_save_expr (tp, st, walk_subtrees);
else
{
--- 3922,3929 ----
gcc_unreachable ();
else if (TREE_CODE (*tp) == BIND_EXPR)
copy_bind_expr (tp, walk_subtrees, id);
! else if (TREE_CODE (*tp) == SAVE_EXPR
! || TREE_CODE (*tp) == TARGET_EXPR)
remap_save_expr (tp, st, walk_subtrees);
else
{
Index: gcc/tree-iterator.c
===================================================================
*** gcc/tree-iterator.c.orig 2009-07-07 12:51:02.000000000 +0200
--- gcc/tree-iterator.c 2009-07-07 12:52:01.000000000 +0200
*************** tsi_link_before (tree_stmt_iterator *i,
*** 137,176 ****
}
}
! /* Links a statement, or a chain of statements, after the current stmt. */
! void
! tsi_link_after (tree_stmt_iterator *i, tree t, enum tsi_iterator_update mode)
{
! struct tree_statement_list_node *head, *tail, *cur;
!
! /* Die on looping. */
! gcc_assert (t != i->container);
!
! if (TREE_CODE (t) == STATEMENT_LIST)
! {
! head = STATEMENT_LIST_HEAD (t);
! tail = STATEMENT_LIST_TAIL (t);
! STATEMENT_LIST_HEAD (t) = NULL;
! STATEMENT_LIST_TAIL (t) = NULL;
!
! free_stmt_list (t);
!
! /* Empty statement lists need no work. */
! if (!head || !tail)
! {
! gcc_assert (head == tail);
! return;
! }
! }
! else
! {
! head = GGC_NEW (struct tree_statement_list_node);
! head->prev = NULL;
! head->next = NULL;
! head->stmt = t;
! tail = head;
! }
TREE_SIDE_EFFECTS (i->container) = 1;
--- 137,152 ----
}
}
! /* Links a statement, or a chain of statements, specified by HEAD and TAIL
! after the current stmt. */
! static void
! tsi_link_after_1 (tree_stmt_iterator *i,
! struct tree_statement_list_node *head,
! struct tree_statement_list_node *tail,
! enum tsi_iterator_update mode)
{
! struct tree_statement_list_node *cur;
TREE_SIDE_EFFECTS (i->container) = 1;
*************** tsi_link_after (tree_stmt_iterator *i, t
*** 211,216 ****
--- 187,250 ----
}
}
+ /* Links a statement after the current stmt. */
+
+ void
+ tsi_link_stmt_after (tree_stmt_iterator *i, tree t,
+ enum tsi_iterator_update mode)
+ {
+ struct tree_statement_list_node *head, *tail;
+
+ /* Die on looping. */
+ gcc_assert (t != i->container);
+
+ head = GGC_NEW (struct tree_statement_list_node);
+ head->prev = NULL;
+ head->next = NULL;
+ head->stmt = t;
+ tail = head;
+
+ tsi_link_after_1 (i, head, tail, mode);
+ }
+
+ /* Links a statement, or a chain of statements, after the current stmt. */
+
+ void
+ tsi_link_after (tree_stmt_iterator *i, tree t, enum tsi_iterator_update mode)
+ {
+ struct tree_statement_list_node *head, *tail;
+
+ /* Die on looping. */
+ gcc_assert (t != i->container);
+
+ if (TREE_CODE (t) == STATEMENT_LIST)
+ {
+ head = STATEMENT_LIST_HEAD (t);
+ tail = STATEMENT_LIST_TAIL (t);
+ STATEMENT_LIST_HEAD (t) = NULL;
+ STATEMENT_LIST_TAIL (t) = NULL;
+
+ free_stmt_list (t);
+
+ /* Empty statement lists need no work. */
+ if (!head || !tail)
+ {
+ gcc_assert (head == tail);
+ return;
+ }
+ }
+ else
+ {
+ head = GGC_NEW (struct tree_statement_list_node);
+ head->prev = NULL;
+ head->next = NULL;
+ head->stmt = t;
+ tail = head;
+ }
+
+ tsi_link_after_1 (i, head, tail, mode);
+ }
+
/* Remove a stmt from the tree list. The iterator is updated to point to
the next stmt. */
Index: gcc/tree-iterator.h
===================================================================
*** gcc/tree-iterator.h.orig 2009-07-07 12:51:02.000000000 +0200
--- gcc/tree-iterator.h 2009-07-07 12:52:01.000000000 +0200
*************** extern void tsi_link_before (tree_stmt_i
*** 110,115 ****
--- 110,117 ----
enum tsi_iterator_update);
extern void tsi_link_after (tree_stmt_iterator *, tree,
enum tsi_iterator_update);
+ extern void tsi_link_stmt_after (tree_stmt_iterator *, tree,
+ enum tsi_iterator_update);
void tsi_delink (tree_stmt_iterator *);
More information about the Gcc-patches
mailing list