/* Iterator routines for manipulating GENERIC and GIMPLE tree statements.
- Copyright (C) 2003, 2004, 2007, 2008 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2004, 2007, 2008, 2009, 2010
+ Free Software Foundation, Inc.
Contributed by Andrew MacLeod <amacleod@redhat.com>
This file is part of GCC.
/* This is a cache of STATEMENT_LIST nodes. We create and destroy them
fairly often during gimplification. */
-static GTY ((deletable (""))) tree stmt_list_cache;
+static GTY ((deletable (""))) VEC(tree,gc) *stmt_list_cache;
tree
alloc_stmt_list (void)
{
- tree list = stmt_list_cache;
- if (list)
+ tree list;
+ if (!VEC_empty (tree, stmt_list_cache))
{
- stmt_list_cache = TREE_CHAIN (list);
- gcc_assert (stmt_list_cache != list);
- memset (list, 0, sizeof(struct tree_common));
+ list = VEC_pop (tree, stmt_list_cache);
+ memset (list, 0, sizeof(struct tree_base));
TREE_SET_CODE (list, STATEMENT_LIST);
}
else
{
gcc_assert (!STATEMENT_LIST_HEAD (t));
gcc_assert (!STATEMENT_LIST_TAIL (t));
- /* If this triggers, it's a sign that the same list is being freed
- twice. */
- gcc_assert (t != stmt_list_cache || stmt_list_cache == NULL);
- TREE_CHAIN (t) = stmt_list_cache;
- stmt_list_cache = t;
+ VEC_safe_push (tree, gc, stmt_list_cache, t);
+}
+
+/* A subroutine of append_to_statement_list{,_force}. T is not NULL. */
+
+static void
+append_to_statement_list_1 (tree t, tree *list_p)
+{
+ tree list = *list_p;
+ tree_stmt_iterator i;
+
+ if (!list)
+ {
+ if (t && TREE_CODE (t) == STATEMENT_LIST)
+ {
+ *list_p = t;
+ return;
+ }
+ *list_p = list = alloc_stmt_list ();
+ }
+
+ i = tsi_last (list);
+ tsi_link_after (&i, t, TSI_CONTINUE_LINKING);
+}
+
+/* Add T to the end of the list container pointed to by LIST_P.
+ If T is an expression with no effects, it is ignored. */
+
+void
+append_to_statement_list (tree t, tree *list_p)
+{
+ if (t && TREE_SIDE_EFFECTS (t))
+ append_to_statement_list_1 (t, list_p);
+}
+
+/* Similar, but the statement is always added, regardless of side effects. */
+
+void
+append_to_statement_list_force (tree t, tree *list_p)
+{
+ if (t != NULL_TREE)
+ append_to_statement_list_1 (t, list_p);
}
/* Links a statement, or a chain of statements, before the current stmt. */
}
else
{
- head = GGC_NEW (struct tree_statement_list_node);
+ head = ggc_alloc_tree_statement_list_node ();
head->prev = NULL;
head->next = NULL;
head->stmt = t;
}
else
{
- head = GGC_NEW (struct tree_statement_list_node);
+ head = ggc_alloc_tree_statement_list_node ();
head->prev = NULL;
head->next = NULL;
head->stmt = t;