1*e4b17023SJohn Marino /* Iterator routines for manipulating GENERIC and GIMPLE tree statements.
2*e4b17023SJohn Marino Copyright (C) 2003, 2004, 2007, 2008, 2009, 2010
3*e4b17023SJohn Marino Free Software Foundation, Inc.
4*e4b17023SJohn Marino Contributed by Andrew MacLeod <amacleod@redhat.com>
5*e4b17023SJohn Marino
6*e4b17023SJohn Marino This file is part of GCC.
7*e4b17023SJohn Marino
8*e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify
9*e4b17023SJohn Marino it under the terms of the GNU General Public License as published by
10*e4b17023SJohn Marino the Free Software Foundation; either version 3, or (at your option)
11*e4b17023SJohn Marino any later version.
12*e4b17023SJohn Marino
13*e4b17023SJohn Marino GCC is distributed in the hope that it will be useful,
14*e4b17023SJohn Marino but WITHOUT ANY WARRANTY; without even the implied warranty of
15*e4b17023SJohn Marino MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16*e4b17023SJohn Marino GNU General Public License for more details.
17*e4b17023SJohn Marino
18*e4b17023SJohn Marino You should have received a copy of the GNU General Public License
19*e4b17023SJohn Marino along with GCC; see the file COPYING3. If not see
20*e4b17023SJohn Marino <http://www.gnu.org/licenses/>. */
21*e4b17023SJohn Marino
22*e4b17023SJohn Marino #include "config.h"
23*e4b17023SJohn Marino #include "system.h"
24*e4b17023SJohn Marino #include "coretypes.h"
25*e4b17023SJohn Marino #include "tree.h"
26*e4b17023SJohn Marino #include "gimple.h"
27*e4b17023SJohn Marino #include "tree-iterator.h"
28*e4b17023SJohn Marino #include "ggc.h"
29*e4b17023SJohn Marino
30*e4b17023SJohn Marino
31*e4b17023SJohn Marino /* This is a cache of STATEMENT_LIST nodes. We create and destroy them
32*e4b17023SJohn Marino fairly often during gimplification. */
33*e4b17023SJohn Marino
34*e4b17023SJohn Marino static GTY ((deletable (""))) VEC(tree,gc) *stmt_list_cache;
35*e4b17023SJohn Marino
36*e4b17023SJohn Marino tree
alloc_stmt_list(void)37*e4b17023SJohn Marino alloc_stmt_list (void)
38*e4b17023SJohn Marino {
39*e4b17023SJohn Marino tree list;
40*e4b17023SJohn Marino if (!VEC_empty (tree, stmt_list_cache))
41*e4b17023SJohn Marino {
42*e4b17023SJohn Marino list = VEC_pop (tree, stmt_list_cache);
43*e4b17023SJohn Marino memset (list, 0, sizeof(struct tree_base));
44*e4b17023SJohn Marino TREE_SET_CODE (list, STATEMENT_LIST);
45*e4b17023SJohn Marino }
46*e4b17023SJohn Marino else
47*e4b17023SJohn Marino list = make_node (STATEMENT_LIST);
48*e4b17023SJohn Marino TREE_TYPE (list) = void_type_node;
49*e4b17023SJohn Marino return list;
50*e4b17023SJohn Marino }
51*e4b17023SJohn Marino
52*e4b17023SJohn Marino void
free_stmt_list(tree t)53*e4b17023SJohn Marino free_stmt_list (tree t)
54*e4b17023SJohn Marino {
55*e4b17023SJohn Marino gcc_assert (!STATEMENT_LIST_HEAD (t));
56*e4b17023SJohn Marino gcc_assert (!STATEMENT_LIST_TAIL (t));
57*e4b17023SJohn Marino VEC_safe_push (tree, gc, stmt_list_cache, t);
58*e4b17023SJohn Marino }
59*e4b17023SJohn Marino
60*e4b17023SJohn Marino /* A subroutine of append_to_statement_list{,_force}. T is not NULL. */
61*e4b17023SJohn Marino
62*e4b17023SJohn Marino static void
append_to_statement_list_1(tree t,tree * list_p)63*e4b17023SJohn Marino append_to_statement_list_1 (tree t, tree *list_p)
64*e4b17023SJohn Marino {
65*e4b17023SJohn Marino tree list = *list_p;
66*e4b17023SJohn Marino tree_stmt_iterator i;
67*e4b17023SJohn Marino
68*e4b17023SJohn Marino if (!list)
69*e4b17023SJohn Marino {
70*e4b17023SJohn Marino if (t && TREE_CODE (t) == STATEMENT_LIST)
71*e4b17023SJohn Marino {
72*e4b17023SJohn Marino *list_p = t;
73*e4b17023SJohn Marino return;
74*e4b17023SJohn Marino }
75*e4b17023SJohn Marino *list_p = list = alloc_stmt_list ();
76*e4b17023SJohn Marino }
77*e4b17023SJohn Marino
78*e4b17023SJohn Marino i = tsi_last (list);
79*e4b17023SJohn Marino tsi_link_after (&i, t, TSI_CONTINUE_LINKING);
80*e4b17023SJohn Marino }
81*e4b17023SJohn Marino
82*e4b17023SJohn Marino /* Add T to the end of the list container pointed to by LIST_P.
83*e4b17023SJohn Marino If T is an expression with no effects, it is ignored. */
84*e4b17023SJohn Marino
85*e4b17023SJohn Marino void
append_to_statement_list(tree t,tree * list_p)86*e4b17023SJohn Marino append_to_statement_list (tree t, tree *list_p)
87*e4b17023SJohn Marino {
88*e4b17023SJohn Marino if (t && TREE_SIDE_EFFECTS (t))
89*e4b17023SJohn Marino append_to_statement_list_1 (t, list_p);
90*e4b17023SJohn Marino }
91*e4b17023SJohn Marino
92*e4b17023SJohn Marino /* Similar, but the statement is always added, regardless of side effects. */
93*e4b17023SJohn Marino
94*e4b17023SJohn Marino void
append_to_statement_list_force(tree t,tree * list_p)95*e4b17023SJohn Marino append_to_statement_list_force (tree t, tree *list_p)
96*e4b17023SJohn Marino {
97*e4b17023SJohn Marino if (t != NULL_TREE)
98*e4b17023SJohn Marino append_to_statement_list_1 (t, list_p);
99*e4b17023SJohn Marino }
100*e4b17023SJohn Marino
101*e4b17023SJohn Marino /* Links a statement, or a chain of statements, before the current stmt. */
102*e4b17023SJohn Marino
103*e4b17023SJohn Marino void
tsi_link_before(tree_stmt_iterator * i,tree t,enum tsi_iterator_update mode)104*e4b17023SJohn Marino tsi_link_before (tree_stmt_iterator *i, tree t, enum tsi_iterator_update mode)
105*e4b17023SJohn Marino {
106*e4b17023SJohn Marino struct tree_statement_list_node *head, *tail, *cur;
107*e4b17023SJohn Marino
108*e4b17023SJohn Marino /* Die on looping. */
109*e4b17023SJohn Marino gcc_assert (t != i->container);
110*e4b17023SJohn Marino
111*e4b17023SJohn Marino if (TREE_CODE (t) == STATEMENT_LIST)
112*e4b17023SJohn Marino {
113*e4b17023SJohn Marino head = STATEMENT_LIST_HEAD (t);
114*e4b17023SJohn Marino tail = STATEMENT_LIST_TAIL (t);
115*e4b17023SJohn Marino STATEMENT_LIST_HEAD (t) = NULL;
116*e4b17023SJohn Marino STATEMENT_LIST_TAIL (t) = NULL;
117*e4b17023SJohn Marino
118*e4b17023SJohn Marino free_stmt_list (t);
119*e4b17023SJohn Marino
120*e4b17023SJohn Marino /* Empty statement lists need no work. */
121*e4b17023SJohn Marino if (!head || !tail)
122*e4b17023SJohn Marino {
123*e4b17023SJohn Marino gcc_assert (head == tail);
124*e4b17023SJohn Marino return;
125*e4b17023SJohn Marino }
126*e4b17023SJohn Marino }
127*e4b17023SJohn Marino else
128*e4b17023SJohn Marino {
129*e4b17023SJohn Marino head = ggc_alloc_tree_statement_list_node ();
130*e4b17023SJohn Marino head->prev = NULL;
131*e4b17023SJohn Marino head->next = NULL;
132*e4b17023SJohn Marino head->stmt = t;
133*e4b17023SJohn Marino tail = head;
134*e4b17023SJohn Marino }
135*e4b17023SJohn Marino
136*e4b17023SJohn Marino TREE_SIDE_EFFECTS (i->container) = 1;
137*e4b17023SJohn Marino
138*e4b17023SJohn Marino cur = i->ptr;
139*e4b17023SJohn Marino
140*e4b17023SJohn Marino /* Link it into the list. */
141*e4b17023SJohn Marino if (cur)
142*e4b17023SJohn Marino {
143*e4b17023SJohn Marino head->prev = cur->prev;
144*e4b17023SJohn Marino if (head->prev)
145*e4b17023SJohn Marino head->prev->next = head;
146*e4b17023SJohn Marino else
147*e4b17023SJohn Marino STATEMENT_LIST_HEAD (i->container) = head;
148*e4b17023SJohn Marino tail->next = cur;
149*e4b17023SJohn Marino cur->prev = tail;
150*e4b17023SJohn Marino }
151*e4b17023SJohn Marino else
152*e4b17023SJohn Marino {
153*e4b17023SJohn Marino head->prev = STATEMENT_LIST_TAIL (i->container);
154*e4b17023SJohn Marino if (head->prev)
155*e4b17023SJohn Marino head->prev->next = head;
156*e4b17023SJohn Marino else
157*e4b17023SJohn Marino STATEMENT_LIST_HEAD (i->container) = head;
158*e4b17023SJohn Marino STATEMENT_LIST_TAIL (i->container) = tail;
159*e4b17023SJohn Marino }
160*e4b17023SJohn Marino
161*e4b17023SJohn Marino /* Update the iterator, if requested. */
162*e4b17023SJohn Marino switch (mode)
163*e4b17023SJohn Marino {
164*e4b17023SJohn Marino case TSI_NEW_STMT:
165*e4b17023SJohn Marino case TSI_CONTINUE_LINKING:
166*e4b17023SJohn Marino case TSI_CHAIN_START:
167*e4b17023SJohn Marino i->ptr = head;
168*e4b17023SJohn Marino break;
169*e4b17023SJohn Marino case TSI_CHAIN_END:
170*e4b17023SJohn Marino i->ptr = tail;
171*e4b17023SJohn Marino break;
172*e4b17023SJohn Marino case TSI_SAME_STMT:
173*e4b17023SJohn Marino break;
174*e4b17023SJohn Marino }
175*e4b17023SJohn Marino }
176*e4b17023SJohn Marino
177*e4b17023SJohn Marino /* Links a statement, or a chain of statements, after the current stmt. */
178*e4b17023SJohn Marino
179*e4b17023SJohn Marino void
tsi_link_after(tree_stmt_iterator * i,tree t,enum tsi_iterator_update mode)180*e4b17023SJohn Marino tsi_link_after (tree_stmt_iterator *i, tree t, enum tsi_iterator_update mode)
181*e4b17023SJohn Marino {
182*e4b17023SJohn Marino struct tree_statement_list_node *head, *tail, *cur;
183*e4b17023SJohn Marino
184*e4b17023SJohn Marino /* Die on looping. */
185*e4b17023SJohn Marino gcc_assert (t != i->container);
186*e4b17023SJohn Marino
187*e4b17023SJohn Marino if (TREE_CODE (t) == STATEMENT_LIST)
188*e4b17023SJohn Marino {
189*e4b17023SJohn Marino head = STATEMENT_LIST_HEAD (t);
190*e4b17023SJohn Marino tail = STATEMENT_LIST_TAIL (t);
191*e4b17023SJohn Marino STATEMENT_LIST_HEAD (t) = NULL;
192*e4b17023SJohn Marino STATEMENT_LIST_TAIL (t) = NULL;
193*e4b17023SJohn Marino
194*e4b17023SJohn Marino free_stmt_list (t);
195*e4b17023SJohn Marino
196*e4b17023SJohn Marino /* Empty statement lists need no work. */
197*e4b17023SJohn Marino if (!head || !tail)
198*e4b17023SJohn Marino {
199*e4b17023SJohn Marino gcc_assert (head == tail);
200*e4b17023SJohn Marino return;
201*e4b17023SJohn Marino }
202*e4b17023SJohn Marino }
203*e4b17023SJohn Marino else
204*e4b17023SJohn Marino {
205*e4b17023SJohn Marino head = ggc_alloc_tree_statement_list_node ();
206*e4b17023SJohn Marino head->prev = NULL;
207*e4b17023SJohn Marino head->next = NULL;
208*e4b17023SJohn Marino head->stmt = t;
209*e4b17023SJohn Marino tail = head;
210*e4b17023SJohn Marino }
211*e4b17023SJohn Marino
212*e4b17023SJohn Marino TREE_SIDE_EFFECTS (i->container) = 1;
213*e4b17023SJohn Marino
214*e4b17023SJohn Marino cur = i->ptr;
215*e4b17023SJohn Marino
216*e4b17023SJohn Marino /* Link it into the list. */
217*e4b17023SJohn Marino if (cur)
218*e4b17023SJohn Marino {
219*e4b17023SJohn Marino tail->next = cur->next;
220*e4b17023SJohn Marino if (tail->next)
221*e4b17023SJohn Marino tail->next->prev = tail;
222*e4b17023SJohn Marino else
223*e4b17023SJohn Marino STATEMENT_LIST_TAIL (i->container) = tail;
224*e4b17023SJohn Marino head->prev = cur;
225*e4b17023SJohn Marino cur->next = head;
226*e4b17023SJohn Marino }
227*e4b17023SJohn Marino else
228*e4b17023SJohn Marino {
229*e4b17023SJohn Marino gcc_assert (!STATEMENT_LIST_TAIL (i->container));
230*e4b17023SJohn Marino STATEMENT_LIST_HEAD (i->container) = head;
231*e4b17023SJohn Marino STATEMENT_LIST_TAIL (i->container) = tail;
232*e4b17023SJohn Marino }
233*e4b17023SJohn Marino
234*e4b17023SJohn Marino /* Update the iterator, if requested. */
235*e4b17023SJohn Marino switch (mode)
236*e4b17023SJohn Marino {
237*e4b17023SJohn Marino case TSI_NEW_STMT:
238*e4b17023SJohn Marino case TSI_CHAIN_START:
239*e4b17023SJohn Marino i->ptr = head;
240*e4b17023SJohn Marino break;
241*e4b17023SJohn Marino case TSI_CONTINUE_LINKING:
242*e4b17023SJohn Marino case TSI_CHAIN_END:
243*e4b17023SJohn Marino i->ptr = tail;
244*e4b17023SJohn Marino break;
245*e4b17023SJohn Marino case TSI_SAME_STMT:
246*e4b17023SJohn Marino gcc_assert (cur);
247*e4b17023SJohn Marino break;
248*e4b17023SJohn Marino }
249*e4b17023SJohn Marino }
250*e4b17023SJohn Marino
251*e4b17023SJohn Marino /* Remove a stmt from the tree list. The iterator is updated to point to
252*e4b17023SJohn Marino the next stmt. */
253*e4b17023SJohn Marino
254*e4b17023SJohn Marino void
tsi_delink(tree_stmt_iterator * i)255*e4b17023SJohn Marino tsi_delink (tree_stmt_iterator *i)
256*e4b17023SJohn Marino {
257*e4b17023SJohn Marino struct tree_statement_list_node *cur, *next, *prev;
258*e4b17023SJohn Marino
259*e4b17023SJohn Marino cur = i->ptr;
260*e4b17023SJohn Marino next = cur->next;
261*e4b17023SJohn Marino prev = cur->prev;
262*e4b17023SJohn Marino
263*e4b17023SJohn Marino if (prev)
264*e4b17023SJohn Marino prev->next = next;
265*e4b17023SJohn Marino else
266*e4b17023SJohn Marino STATEMENT_LIST_HEAD (i->container) = next;
267*e4b17023SJohn Marino if (next)
268*e4b17023SJohn Marino next->prev = prev;
269*e4b17023SJohn Marino else
270*e4b17023SJohn Marino STATEMENT_LIST_TAIL (i->container) = prev;
271*e4b17023SJohn Marino
272*e4b17023SJohn Marino if (!next && !prev)
273*e4b17023SJohn Marino TREE_SIDE_EFFECTS (i->container) = 0;
274*e4b17023SJohn Marino
275*e4b17023SJohn Marino i->ptr = next;
276*e4b17023SJohn Marino }
277*e4b17023SJohn Marino
278*e4b17023SJohn Marino /* Return the first expression in a sequence of COMPOUND_EXPRs,
279*e4b17023SJohn Marino or in a STATEMENT_LIST. */
280*e4b17023SJohn Marino
281*e4b17023SJohn Marino tree
expr_first(tree expr)282*e4b17023SJohn Marino expr_first (tree expr)
283*e4b17023SJohn Marino {
284*e4b17023SJohn Marino if (expr == NULL_TREE)
285*e4b17023SJohn Marino return expr;
286*e4b17023SJohn Marino
287*e4b17023SJohn Marino if (TREE_CODE (expr) == STATEMENT_LIST)
288*e4b17023SJohn Marino {
289*e4b17023SJohn Marino struct tree_statement_list_node *n = STATEMENT_LIST_HEAD (expr);
290*e4b17023SJohn Marino return n ? n->stmt : NULL_TREE;
291*e4b17023SJohn Marino }
292*e4b17023SJohn Marino
293*e4b17023SJohn Marino while (TREE_CODE (expr) == COMPOUND_EXPR)
294*e4b17023SJohn Marino expr = TREE_OPERAND (expr, 0);
295*e4b17023SJohn Marino
296*e4b17023SJohn Marino return expr;
297*e4b17023SJohn Marino }
298*e4b17023SJohn Marino
299*e4b17023SJohn Marino /* Return the last expression in a sequence of COMPOUND_EXPRs,
300*e4b17023SJohn Marino or in a STATEMENT_LIST. */
301*e4b17023SJohn Marino
302*e4b17023SJohn Marino tree
expr_last(tree expr)303*e4b17023SJohn Marino expr_last (tree expr)
304*e4b17023SJohn Marino {
305*e4b17023SJohn Marino if (expr == NULL_TREE)
306*e4b17023SJohn Marino return expr;
307*e4b17023SJohn Marino
308*e4b17023SJohn Marino if (TREE_CODE (expr) == STATEMENT_LIST)
309*e4b17023SJohn Marino {
310*e4b17023SJohn Marino struct tree_statement_list_node *n = STATEMENT_LIST_TAIL (expr);
311*e4b17023SJohn Marino return n ? n->stmt : NULL_TREE;
312*e4b17023SJohn Marino }
313*e4b17023SJohn Marino
314*e4b17023SJohn Marino while (TREE_CODE (expr) == COMPOUND_EXPR)
315*e4b17023SJohn Marino expr = TREE_OPERAND (expr, 1);
316*e4b17023SJohn Marino
317*e4b17023SJohn Marino return expr;
318*e4b17023SJohn Marino }
319*e4b17023SJohn Marino
320*e4b17023SJohn Marino #include "gt-tree-iterator.h"
321