OSDN Git Service

ChangeLogs fixed, again.
[pf3gnuchains/gcc-fork.git] / gcc / tree-iterator.c
1 /* Iterator routines for manipulating GENERIC and GIMPLE tree statements.
2    Copyright (C) 2003, 2004, 2007, 2008 Free Software Foundation, Inc.
3    Contributed by Andrew MacLeod  <amacleod@redhat.com>
4
5 This file is part of GCC.
6
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)
10 any later version.
11
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.
16
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/>.  */
20
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "tree.h"
25 #include "gimple.h"
26 #include "tree-iterator.h"
27 #include "ggc.h"
28
29
30 /* This is a cache of STATEMENT_LIST nodes.  We create and destroy them
31    fairly often during gimplification.  */
32
33 static GTY ((deletable (""))) tree stmt_list_cache;
34
35 tree
36 alloc_stmt_list (void)
37 {
38   tree list = stmt_list_cache;
39   if (list)
40     {
41       stmt_list_cache = TREE_CHAIN (list);
42       gcc_assert (stmt_list_cache != list);
43       memset (list, 0, sizeof(struct tree_common));
44       TREE_SET_CODE (list, STATEMENT_LIST);
45     }
46   else
47     list = make_node (STATEMENT_LIST);
48   TREE_TYPE (list) = void_type_node;
49   return list;
50 }
51
52 void
53 free_stmt_list (tree t)
54 {
55   gcc_assert (!STATEMENT_LIST_HEAD (t));
56   gcc_assert (!STATEMENT_LIST_TAIL (t));
57   /* If this triggers, it's a sign that the same list is being freed
58      twice.  */
59   gcc_assert (t != stmt_list_cache || stmt_list_cache == NULL);
60   TREE_CHAIN (t) = stmt_list_cache;
61   stmt_list_cache = t;
62 }
63
64 /* Links a statement, or a chain of statements, before the current stmt.  */
65
66 void
67 tsi_link_before (tree_stmt_iterator *i, tree t, enum tsi_iterator_update mode)
68 {
69   struct tree_statement_list_node *head, *tail, *cur;
70
71   /* Die on looping.  */
72   gcc_assert (t != i->container);
73
74   if (TREE_CODE (t) == STATEMENT_LIST)
75     {
76       head = STATEMENT_LIST_HEAD (t);
77       tail = STATEMENT_LIST_TAIL (t);
78       STATEMENT_LIST_HEAD (t) = NULL;
79       STATEMENT_LIST_TAIL (t) = NULL;
80
81       free_stmt_list (t);
82
83       /* Empty statement lists need no work.  */
84       if (!head || !tail)
85         {
86           gcc_assert (head == tail);
87           return;
88         }
89     }
90   else
91     {
92       head = GGC_NEW (struct tree_statement_list_node);
93       head->prev = NULL;
94       head->next = NULL;
95       head->stmt = t;
96       tail = head;
97     }
98
99   TREE_SIDE_EFFECTS (i->container) = 1;
100
101   cur = i->ptr;
102
103   /* Link it into the list.  */
104   if (cur)
105     {
106       head->prev = cur->prev;
107       if (head->prev)
108         head->prev->next = head;
109       else
110         STATEMENT_LIST_HEAD (i->container) = head;
111       tail->next = cur;
112       cur->prev = tail;
113     }
114   else
115     {
116       head->prev = STATEMENT_LIST_TAIL (i->container);
117       if (head->prev)
118        head->prev->next = head;
119       else
120        STATEMENT_LIST_HEAD (i->container) = head;
121       STATEMENT_LIST_TAIL (i->container) = tail;
122     }
123
124   /* Update the iterator, if requested.  */
125   switch (mode)
126     {
127     case TSI_NEW_STMT:
128     case TSI_CONTINUE_LINKING:
129     case TSI_CHAIN_START:
130       i->ptr = head;
131       break;
132     case TSI_CHAIN_END:
133       i->ptr = tail;
134       break;
135     case TSI_SAME_STMT:
136       break;
137     }
138 }
139
140 /* Links a statement, or a chain of statements, after the current stmt.  */
141
142 void
143 tsi_link_after (tree_stmt_iterator *i, tree t, enum tsi_iterator_update mode)
144 {
145   struct tree_statement_list_node *head, *tail, *cur;
146
147   /* Die on looping.  */
148   gcc_assert (t != i->container);
149
150   if (TREE_CODE (t) == STATEMENT_LIST)
151     {
152       head = STATEMENT_LIST_HEAD (t);
153       tail = STATEMENT_LIST_TAIL (t);
154       STATEMENT_LIST_HEAD (t) = NULL;
155       STATEMENT_LIST_TAIL (t) = NULL;
156
157       free_stmt_list (t);
158
159       /* Empty statement lists need no work.  */
160       if (!head || !tail)
161         {
162           gcc_assert (head == tail);
163           return;
164         }
165     }
166   else
167     {
168       head = GGC_NEW (struct tree_statement_list_node);
169       head->prev = NULL;
170       head->next = NULL;
171       head->stmt = t;
172       tail = head;
173     }
174
175   TREE_SIDE_EFFECTS (i->container) = 1;
176
177   cur = i->ptr;
178
179   /* Link it into the list.  */
180   if (cur)
181     {
182       tail->next = cur->next;
183       if (tail->next)
184         tail->next->prev = tail;
185       else
186         STATEMENT_LIST_TAIL (i->container) = tail;
187       head->prev = cur;
188       cur->next = head;
189     }
190   else
191     {
192       gcc_assert (!STATEMENT_LIST_TAIL (i->container));
193       STATEMENT_LIST_HEAD (i->container) = head;
194       STATEMENT_LIST_TAIL (i->container) = tail;
195     }
196
197   /* Update the iterator, if requested.  */
198   switch (mode)
199     {
200     case TSI_NEW_STMT:
201     case TSI_CHAIN_START:
202       i->ptr = head;
203       break;
204     case TSI_CONTINUE_LINKING:
205     case TSI_CHAIN_END:
206       i->ptr = tail;
207       break;
208     case TSI_SAME_STMT:
209       gcc_assert (cur);
210       break;
211     }
212 }
213
214 /* Remove a stmt from the tree list.  The iterator is updated to point to
215    the next stmt.  */
216
217 void
218 tsi_delink (tree_stmt_iterator *i)
219 {
220   struct tree_statement_list_node *cur, *next, *prev;
221
222   cur = i->ptr;
223   next = cur->next;
224   prev = cur->prev;
225
226   if (prev)
227     prev->next = next;
228   else
229     STATEMENT_LIST_HEAD (i->container) = next;
230   if (next)
231     next->prev = prev;
232   else
233     STATEMENT_LIST_TAIL (i->container) = prev;
234
235   if (!next && !prev)
236     TREE_SIDE_EFFECTS (i->container) = 0;
237
238   i->ptr = next;
239 }
240
241 /* Return the first expression in a sequence of COMPOUND_EXPRs,
242    or in a STATEMENT_LIST.  */
243
244 tree
245 expr_first (tree expr)
246 {
247   if (expr == NULL_TREE)
248     return expr;
249
250   if (TREE_CODE (expr) == STATEMENT_LIST)
251     {
252       struct tree_statement_list_node *n = STATEMENT_LIST_HEAD (expr);
253       return n ? n->stmt : NULL_TREE;
254     }
255
256   while (TREE_CODE (expr) == COMPOUND_EXPR)
257     expr = TREE_OPERAND (expr, 0);
258
259   return expr;
260 }
261
262 /* Return the last expression in a sequence of COMPOUND_EXPRs,
263    or in a STATEMENT_LIST.  */
264
265 tree
266 expr_last (tree expr)
267 {
268   if (expr == NULL_TREE)
269     return expr;
270
271   if (TREE_CODE (expr) == STATEMENT_LIST)
272     {
273       struct tree_statement_list_node *n = STATEMENT_LIST_TAIL (expr);
274       return n ? n->stmt : NULL_TREE;
275     }
276
277   while (TREE_CODE (expr) == COMPOUND_EXPR)
278     expr = TREE_OPERAND (expr, 1);
279
280   return expr;
281 }
282
283 #include "gt-tree-iterator.h"