xref: /dflybsd-src/contrib/gcc-4.7/gcc/tree-iterator.c (revision 04febcfb30580676d3e95f58a16c5137ee478b32)
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