1 /* Iterator routines for manipulating GENERIC and GIMPLE tree statements.
2 Copyright (C) 2003-2015 Free Software Foundation, Inc.
3 Contributed by Andrew MacLeod <amacleod@redhat.com>
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
12 GCC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
23 #include "coretypes.h"
29 #include "tree-iterator.h"
32 /* This is a cache of STATEMENT_LIST nodes. We create and destroy them
33 fairly often during gimplification. */
35 static GTY ((deletable (""))) vec
<tree
, va_gc
> *stmt_list_cache
;
38 alloc_stmt_list (void)
41 if (!vec_safe_is_empty (stmt_list_cache
))
43 list
= stmt_list_cache
->pop ();
44 memset (list
, 0, sizeof (struct tree_base
));
45 TREE_SET_CODE (list
, STATEMENT_LIST
);
48 list
= make_node (STATEMENT_LIST
);
49 TREE_TYPE (list
) = void_type_node
;
54 free_stmt_list (tree t
)
56 gcc_assert (!STATEMENT_LIST_HEAD (t
));
57 gcc_assert (!STATEMENT_LIST_TAIL (t
));
58 vec_safe_push (stmt_list_cache
, t
);
61 /* A subroutine of append_to_statement_list{,_force}. T is not NULL. */
64 append_to_statement_list_1 (tree t
, tree
*list_p
)
71 if (t
&& TREE_CODE (t
) == STATEMENT_LIST
)
76 *list_p
= list
= alloc_stmt_list ();
78 else if (TREE_CODE (list
) != STATEMENT_LIST
)
81 *list_p
= list
= alloc_stmt_list ();
83 tsi_link_after (&i
, first
, TSI_CONTINUE_LINKING
);
87 tsi_link_after (&i
, t
, TSI_CONTINUE_LINKING
);
90 /* Add T to the end of the list container pointed to by LIST_P.
91 If T is an expression with no effects, it is ignored. */
94 append_to_statement_list (tree t
, tree
*list_p
)
96 if (t
&& TREE_SIDE_EFFECTS (t
))
97 append_to_statement_list_1 (t
, list_p
);
100 /* Similar, but the statement is always added, regardless of side effects. */
103 append_to_statement_list_force (tree t
, tree
*list_p
)
106 append_to_statement_list_1 (t
, list_p
);
109 /* Links a statement, or a chain of statements, before the current stmt. */
112 tsi_link_before (tree_stmt_iterator
*i
, tree t
, enum tsi_iterator_update mode
)
114 struct tree_statement_list_node
*head
, *tail
, *cur
;
116 /* Die on looping. */
117 gcc_assert (t
!= i
->container
);
119 if (TREE_CODE (t
) == STATEMENT_LIST
)
121 head
= STATEMENT_LIST_HEAD (t
);
122 tail
= STATEMENT_LIST_TAIL (t
);
123 STATEMENT_LIST_HEAD (t
) = NULL
;
124 STATEMENT_LIST_TAIL (t
) = NULL
;
128 /* Empty statement lists need no work. */
131 gcc_assert (head
== tail
);
137 head
= ggc_alloc
<tree_statement_list_node
> ();
144 TREE_SIDE_EFFECTS (i
->container
) = 1;
148 /* Link it into the list. */
151 head
->prev
= cur
->prev
;
153 head
->prev
->next
= head
;
155 STATEMENT_LIST_HEAD (i
->container
) = head
;
161 head
->prev
= STATEMENT_LIST_TAIL (i
->container
);
163 head
->prev
->next
= head
;
165 STATEMENT_LIST_HEAD (i
->container
) = head
;
166 STATEMENT_LIST_TAIL (i
->container
) = tail
;
169 /* Update the iterator, if requested. */
173 case TSI_CONTINUE_LINKING
:
174 case TSI_CHAIN_START
:
185 /* Links a statement, or a chain of statements, after the current stmt. */
188 tsi_link_after (tree_stmt_iterator
*i
, tree t
, enum tsi_iterator_update mode
)
190 struct tree_statement_list_node
*head
, *tail
, *cur
;
192 /* Die on looping. */
193 gcc_assert (t
!= i
->container
);
195 if (TREE_CODE (t
) == STATEMENT_LIST
)
197 head
= STATEMENT_LIST_HEAD (t
);
198 tail
= STATEMENT_LIST_TAIL (t
);
199 STATEMENT_LIST_HEAD (t
) = NULL
;
200 STATEMENT_LIST_TAIL (t
) = NULL
;
204 /* Empty statement lists need no work. */
207 gcc_assert (head
== tail
);
213 head
= ggc_alloc
<tree_statement_list_node
> ();
220 TREE_SIDE_EFFECTS (i
->container
) = 1;
224 /* Link it into the list. */
227 tail
->next
= cur
->next
;
229 tail
->next
->prev
= tail
;
231 STATEMENT_LIST_TAIL (i
->container
) = tail
;
237 gcc_assert (!STATEMENT_LIST_TAIL (i
->container
));
238 STATEMENT_LIST_HEAD (i
->container
) = head
;
239 STATEMENT_LIST_TAIL (i
->container
) = tail
;
242 /* Update the iterator, if requested. */
246 case TSI_CHAIN_START
:
249 case TSI_CONTINUE_LINKING
:
259 /* Remove a stmt from the tree list. The iterator is updated to point to
263 tsi_delink (tree_stmt_iterator
*i
)
265 struct tree_statement_list_node
*cur
, *next
, *prev
;
274 STATEMENT_LIST_HEAD (i
->container
) = next
;
278 STATEMENT_LIST_TAIL (i
->container
) = prev
;
281 TREE_SIDE_EFFECTS (i
->container
) = 0;
286 /* Return the first expression in a sequence of COMPOUND_EXPRs,
287 or in a STATEMENT_LIST. */
290 expr_first (tree expr
)
292 if (expr
== NULL_TREE
)
295 if (TREE_CODE (expr
) == STATEMENT_LIST
)
297 struct tree_statement_list_node
*n
= STATEMENT_LIST_HEAD (expr
);
298 return n
? n
->stmt
: NULL_TREE
;
301 while (TREE_CODE (expr
) == COMPOUND_EXPR
)
302 expr
= TREE_OPERAND (expr
, 0);
307 /* Return the last expression in a sequence of COMPOUND_EXPRs,
308 or in a STATEMENT_LIST. */
311 expr_last (tree expr
)
313 if (expr
== NULL_TREE
)
316 if (TREE_CODE (expr
) == STATEMENT_LIST
)
318 struct tree_statement_list_node
*n
= STATEMENT_LIST_TAIL (expr
);
319 return n
? n
->stmt
: NULL_TREE
;
322 while (TREE_CODE (expr
) == COMPOUND_EXPR
)
323 expr
= TREE_OPERAND (expr
, 1);
328 #include "gt-tree-iterator.h"