Mercurial > hg > CbC > CbC_gcc
annotate gcc/tree-iterator.c @ 63:b7f97abdc517 gcc-4.6-20100522
update gcc from gcc-4.5.0 to gcc-4.6
author | ryoma <e075725@ie.u-ryukyu.ac.jp> |
---|---|
date | Mon, 24 May 2010 12:47:05 +0900 |
parents | 77e2b8dfacca |
children | f6334be47118 |
rev | line source |
---|---|
0 | 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 | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
64 /* A subroutine of append_to_statement_list{,_force}. T is not NULL. */ |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
65 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
66 static void |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
67 append_to_statement_list_1 (tree t, tree *list_p) |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
68 { |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
69 tree list = *list_p; |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
70 tree_stmt_iterator i; |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
71 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
72 if (!list) |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
73 { |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
74 if (t && TREE_CODE (t) == STATEMENT_LIST) |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
75 { |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
76 *list_p = t; |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
77 return; |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
78 } |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
79 *list_p = list = alloc_stmt_list (); |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
80 } |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
81 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
82 i = tsi_last (list); |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
83 tsi_link_after (&i, t, TSI_CONTINUE_LINKING); |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
84 } |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
85 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
86 /* Add T to the end of the list container pointed to by LIST_P. |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
87 If T is an expression with no effects, it is ignored. */ |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
88 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
89 void |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
90 append_to_statement_list (tree t, tree *list_p) |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
91 { |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
92 if (t && TREE_SIDE_EFFECTS (t)) |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
93 append_to_statement_list_1 (t, list_p); |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
94 } |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
95 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
96 /* Similar, but the statement is always added, regardless of side effects. */ |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
97 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
98 void |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
99 append_to_statement_list_force (tree t, tree *list_p) |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
100 { |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
101 if (t != NULL_TREE) |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
102 append_to_statement_list_1 (t, list_p); |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
103 } |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
104 |
0 | 105 /* Links a statement, or a chain of statements, before the current stmt. */ |
106 | |
107 void | |
108 tsi_link_before (tree_stmt_iterator *i, tree t, enum tsi_iterator_update mode) | |
109 { | |
110 struct tree_statement_list_node *head, *tail, *cur; | |
111 | |
112 /* Die on looping. */ | |
113 gcc_assert (t != i->container); | |
114 | |
115 if (TREE_CODE (t) == STATEMENT_LIST) | |
116 { | |
117 head = STATEMENT_LIST_HEAD (t); | |
118 tail = STATEMENT_LIST_TAIL (t); | |
119 STATEMENT_LIST_HEAD (t) = NULL; | |
120 STATEMENT_LIST_TAIL (t) = NULL; | |
121 | |
122 free_stmt_list (t); | |
123 | |
124 /* Empty statement lists need no work. */ | |
125 if (!head || !tail) | |
126 { | |
127 gcc_assert (head == tail); | |
128 return; | |
129 } | |
130 } | |
131 else | |
132 { | |
133 head = GGC_NEW (struct tree_statement_list_node); | |
134 head->prev = NULL; | |
135 head->next = NULL; | |
136 head->stmt = t; | |
137 tail = head; | |
138 } | |
139 | |
140 TREE_SIDE_EFFECTS (i->container) = 1; | |
141 | |
142 cur = i->ptr; | |
143 | |
144 /* Link it into the list. */ | |
145 if (cur) | |
146 { | |
147 head->prev = cur->prev; | |
148 if (head->prev) | |
149 head->prev->next = head; | |
150 else | |
151 STATEMENT_LIST_HEAD (i->container) = head; | |
152 tail->next = cur; | |
153 cur->prev = tail; | |
154 } | |
155 else | |
156 { | |
157 head->prev = STATEMENT_LIST_TAIL (i->container); | |
158 if (head->prev) | |
159 head->prev->next = head; | |
160 else | |
161 STATEMENT_LIST_HEAD (i->container) = head; | |
162 STATEMENT_LIST_TAIL (i->container) = tail; | |
163 } | |
164 | |
165 /* Update the iterator, if requested. */ | |
166 switch (mode) | |
167 { | |
168 case TSI_NEW_STMT: | |
169 case TSI_CONTINUE_LINKING: | |
170 case TSI_CHAIN_START: | |
171 i->ptr = head; | |
172 break; | |
173 case TSI_CHAIN_END: | |
174 i->ptr = tail; | |
175 break; | |
176 case TSI_SAME_STMT: | |
177 break; | |
178 } | |
179 } | |
180 | |
181 /* Links a statement, or a chain of statements, after the current stmt. */ | |
182 | |
183 void | |
184 tsi_link_after (tree_stmt_iterator *i, tree t, enum tsi_iterator_update mode) | |
185 { | |
186 struct tree_statement_list_node *head, *tail, *cur; | |
187 | |
188 /* Die on looping. */ | |
189 gcc_assert (t != i->container); | |
190 | |
191 if (TREE_CODE (t) == STATEMENT_LIST) | |
192 { | |
193 head = STATEMENT_LIST_HEAD (t); | |
194 tail = STATEMENT_LIST_TAIL (t); | |
195 STATEMENT_LIST_HEAD (t) = NULL; | |
196 STATEMENT_LIST_TAIL (t) = NULL; | |
197 | |
198 free_stmt_list (t); | |
199 | |
200 /* Empty statement lists need no work. */ | |
201 if (!head || !tail) | |
202 { | |
203 gcc_assert (head == tail); | |
204 return; | |
205 } | |
206 } | |
207 else | |
208 { | |
209 head = GGC_NEW (struct tree_statement_list_node); | |
210 head->prev = NULL; | |
211 head->next = NULL; | |
212 head->stmt = t; | |
213 tail = head; | |
214 } | |
215 | |
216 TREE_SIDE_EFFECTS (i->container) = 1; | |
217 | |
218 cur = i->ptr; | |
219 | |
220 /* Link it into the list. */ | |
221 if (cur) | |
222 { | |
223 tail->next = cur->next; | |
224 if (tail->next) | |
225 tail->next->prev = tail; | |
226 else | |
227 STATEMENT_LIST_TAIL (i->container) = tail; | |
228 head->prev = cur; | |
229 cur->next = head; | |
230 } | |
231 else | |
232 { | |
233 gcc_assert (!STATEMENT_LIST_TAIL (i->container)); | |
234 STATEMENT_LIST_HEAD (i->container) = head; | |
235 STATEMENT_LIST_TAIL (i->container) = tail; | |
236 } | |
237 | |
238 /* Update the iterator, if requested. */ | |
239 switch (mode) | |
240 { | |
241 case TSI_NEW_STMT: | |
242 case TSI_CHAIN_START: | |
243 i->ptr = head; | |
244 break; | |
245 case TSI_CONTINUE_LINKING: | |
246 case TSI_CHAIN_END: | |
247 i->ptr = tail; | |
248 break; | |
249 case TSI_SAME_STMT: | |
250 gcc_assert (cur); | |
251 break; | |
252 } | |
253 } | |
254 | |
255 /* Remove a stmt from the tree list. The iterator is updated to point to | |
256 the next stmt. */ | |
257 | |
258 void | |
259 tsi_delink (tree_stmt_iterator *i) | |
260 { | |
261 struct tree_statement_list_node *cur, *next, *prev; | |
262 | |
263 cur = i->ptr; | |
264 next = cur->next; | |
265 prev = cur->prev; | |
266 | |
267 if (prev) | |
268 prev->next = next; | |
269 else | |
270 STATEMENT_LIST_HEAD (i->container) = next; | |
271 if (next) | |
272 next->prev = prev; | |
273 else | |
274 STATEMENT_LIST_TAIL (i->container) = prev; | |
275 | |
276 if (!next && !prev) | |
277 TREE_SIDE_EFFECTS (i->container) = 0; | |
278 | |
279 i->ptr = next; | |
280 } | |
281 | |
282 /* Return the first expression in a sequence of COMPOUND_EXPRs, | |
283 or in a STATEMENT_LIST. */ | |
284 | |
285 tree | |
286 expr_first (tree expr) | |
287 { | |
288 if (expr == NULL_TREE) | |
289 return expr; | |
290 | |
291 if (TREE_CODE (expr) == STATEMENT_LIST) | |
292 { | |
293 struct tree_statement_list_node *n = STATEMENT_LIST_HEAD (expr); | |
294 return n ? n->stmt : NULL_TREE; | |
295 } | |
296 | |
297 while (TREE_CODE (expr) == COMPOUND_EXPR) | |
298 expr = TREE_OPERAND (expr, 0); | |
299 | |
300 return expr; | |
301 } | |
302 | |
303 /* Return the last expression in a sequence of COMPOUND_EXPRs, | |
304 or in a STATEMENT_LIST. */ | |
305 | |
306 tree | |
307 expr_last (tree expr) | |
308 { | |
309 if (expr == NULL_TREE) | |
310 return expr; | |
311 | |
312 if (TREE_CODE (expr) == STATEMENT_LIST) | |
313 { | |
314 struct tree_statement_list_node *n = STATEMENT_LIST_TAIL (expr); | |
315 return n ? n->stmt : NULL_TREE; | |
316 } | |
317 | |
318 while (TREE_CODE (expr) == COMPOUND_EXPR) | |
319 expr = TREE_OPERAND (expr, 1); | |
320 | |
321 return expr; | |
322 } | |
323 | |
324 #include "gt-tree-iterator.h" |