Mercurial > hg > CbC > CbC_gcc
annotate gcc/tree-iterator.c @ 158:494b0b89df80 default tip
...
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Mon, 25 May 2020 18:13:55 +0900 |
parents | 1830386684a0 |
children |
rev | line source |
---|---|
0 | 1 /* Iterator routines for manipulating GENERIC and GIMPLE tree statements. |
145 | 2 Copyright (C) 2003-2020 Free Software Foundation, Inc. |
0 | 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 "tree-iterator.h" | |
26 | |
27 | |
28 /* This is a cache of STATEMENT_LIST nodes. We create and destroy them | |
29 fairly often during gimplification. */ | |
30 | |
111 | 31 static GTY ((deletable (""))) vec<tree, va_gc> *stmt_list_cache; |
0 | 32 |
33 tree | |
34 alloc_stmt_list (void) | |
35 { | |
111 | 36 tree list; |
37 if (!vec_safe_is_empty (stmt_list_cache)) | |
0 | 38 { |
111 | 39 list = stmt_list_cache->pop (); |
40 memset (list, 0, sizeof (struct tree_base)); | |
0 | 41 TREE_SET_CODE (list, STATEMENT_LIST); |
42 } | |
43 else | |
131 | 44 { |
45 list = make_node (STATEMENT_LIST); | |
46 TREE_SIDE_EFFECTS (list) = 0; | |
47 } | |
0 | 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)); | |
111 | 57 vec_safe_push (stmt_list_cache, t); |
0 | 58 } |
59 | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
60 /* 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
|
61 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
62 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
|
63 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
|
64 { |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
65 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
|
66 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
|
67 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
68 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
|
69 { |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
70 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
|
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 *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
|
73 return; |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
74 } |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
75 *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
|
76 } |
111 | 77 else if (TREE_CODE (list) != STATEMENT_LIST) |
78 { | |
79 tree first = list; | |
80 *list_p = list = alloc_stmt_list (); | |
81 i = tsi_last (list); | |
82 tsi_link_after (&i, first, TSI_CONTINUE_LINKING); | |
83 } | |
63
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 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
|
86 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
|
87 } |
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 /* 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
|
90 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
|
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 void |
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 (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
|
94 { |
131 | 95 if (t && (TREE_SIDE_EFFECTS (t) || TREE_CODE (t) == DEBUG_BEGIN_STMT)) |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
96 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
|
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 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
99 /* 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
|
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 void |
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_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
|
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 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
|
105 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
|
106 } |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
107 |
0 | 108 /* Links a statement, or a chain of statements, before the current stmt. */ |
109 | |
110 void | |
111 tsi_link_before (tree_stmt_iterator *i, tree t, enum tsi_iterator_update mode) | |
112 { | |
113 struct tree_statement_list_node *head, *tail, *cur; | |
114 | |
115 /* Die on looping. */ | |
116 gcc_assert (t != i->container); | |
117 | |
118 if (TREE_CODE (t) == STATEMENT_LIST) | |
119 { | |
120 head = STATEMENT_LIST_HEAD (t); | |
121 tail = STATEMENT_LIST_TAIL (t); | |
122 STATEMENT_LIST_HEAD (t) = NULL; | |
123 STATEMENT_LIST_TAIL (t) = NULL; | |
124 | |
125 free_stmt_list (t); | |
126 | |
127 /* Empty statement lists need no work. */ | |
128 if (!head || !tail) | |
129 { | |
130 gcc_assert (head == tail); | |
131 return; | |
132 } | |
133 } | |
134 else | |
135 { | |
111 | 136 head = ggc_alloc<tree_statement_list_node> (); |
0 | 137 head->prev = NULL; |
138 head->next = NULL; | |
139 head->stmt = t; | |
140 tail = head; | |
141 } | |
142 | |
131 | 143 if (TREE_CODE (t) != DEBUG_BEGIN_STMT) |
144 TREE_SIDE_EFFECTS (i->container) = 1; | |
0 | 145 |
146 cur = i->ptr; | |
147 | |
148 /* Link it into the list. */ | |
149 if (cur) | |
150 { | |
151 head->prev = cur->prev; | |
152 if (head->prev) | |
153 head->prev->next = head; | |
154 else | |
155 STATEMENT_LIST_HEAD (i->container) = head; | |
156 tail->next = cur; | |
157 cur->prev = tail; | |
158 } | |
159 else | |
160 { | |
161 head->prev = STATEMENT_LIST_TAIL (i->container); | |
162 if (head->prev) | |
163 head->prev->next = head; | |
164 else | |
165 STATEMENT_LIST_HEAD (i->container) = head; | |
166 STATEMENT_LIST_TAIL (i->container) = tail; | |
167 } | |
168 | |
169 /* Update the iterator, if requested. */ | |
170 switch (mode) | |
171 { | |
172 case TSI_NEW_STMT: | |
173 case TSI_CONTINUE_LINKING: | |
174 case TSI_CHAIN_START: | |
175 i->ptr = head; | |
176 break; | |
177 case TSI_CHAIN_END: | |
178 i->ptr = tail; | |
179 break; | |
180 case TSI_SAME_STMT: | |
181 break; | |
182 } | |
183 } | |
184 | |
185 /* Links a statement, or a chain of statements, after the current stmt. */ | |
186 | |
187 void | |
188 tsi_link_after (tree_stmt_iterator *i, tree t, enum tsi_iterator_update mode) | |
189 { | |
190 struct tree_statement_list_node *head, *tail, *cur; | |
191 | |
192 /* Die on looping. */ | |
193 gcc_assert (t != i->container); | |
194 | |
195 if (TREE_CODE (t) == STATEMENT_LIST) | |
196 { | |
197 head = STATEMENT_LIST_HEAD (t); | |
198 tail = STATEMENT_LIST_TAIL (t); | |
199 STATEMENT_LIST_HEAD (t) = NULL; | |
200 STATEMENT_LIST_TAIL (t) = NULL; | |
201 | |
202 free_stmt_list (t); | |
203 | |
204 /* Empty statement lists need no work. */ | |
205 if (!head || !tail) | |
206 { | |
207 gcc_assert (head == tail); | |
208 return; | |
209 } | |
210 } | |
211 else | |
212 { | |
111 | 213 head = ggc_alloc<tree_statement_list_node> (); |
0 | 214 head->prev = NULL; |
215 head->next = NULL; | |
216 head->stmt = t; | |
217 tail = head; | |
218 } | |
219 | |
131 | 220 if (TREE_CODE (t) != DEBUG_BEGIN_STMT) |
221 TREE_SIDE_EFFECTS (i->container) = 1; | |
0 | 222 |
223 cur = i->ptr; | |
224 | |
225 /* Link it into the list. */ | |
226 if (cur) | |
227 { | |
228 tail->next = cur->next; | |
229 if (tail->next) | |
230 tail->next->prev = tail; | |
231 else | |
232 STATEMENT_LIST_TAIL (i->container) = tail; | |
233 head->prev = cur; | |
234 cur->next = head; | |
235 } | |
236 else | |
237 { | |
238 gcc_assert (!STATEMENT_LIST_TAIL (i->container)); | |
239 STATEMENT_LIST_HEAD (i->container) = head; | |
240 STATEMENT_LIST_TAIL (i->container) = tail; | |
241 } | |
242 | |
243 /* Update the iterator, if requested. */ | |
244 switch (mode) | |
245 { | |
246 case TSI_NEW_STMT: | |
247 case TSI_CHAIN_START: | |
248 i->ptr = head; | |
249 break; | |
250 case TSI_CONTINUE_LINKING: | |
251 case TSI_CHAIN_END: | |
252 i->ptr = tail; | |
253 break; | |
254 case TSI_SAME_STMT: | |
255 gcc_assert (cur); | |
256 break; | |
257 } | |
258 } | |
259 | |
260 /* Remove a stmt from the tree list. The iterator is updated to point to | |
261 the next stmt. */ | |
262 | |
263 void | |
264 tsi_delink (tree_stmt_iterator *i) | |
265 { | |
266 struct tree_statement_list_node *cur, *next, *prev; | |
267 | |
268 cur = i->ptr; | |
269 next = cur->next; | |
270 prev = cur->prev; | |
271 | |
272 if (prev) | |
273 prev->next = next; | |
274 else | |
275 STATEMENT_LIST_HEAD (i->container) = next; | |
276 if (next) | |
277 next->prev = prev; | |
278 else | |
279 STATEMENT_LIST_TAIL (i->container) = prev; | |
280 | |
281 if (!next && !prev) | |
282 TREE_SIDE_EFFECTS (i->container) = 0; | |
283 | |
284 i->ptr = next; | |
285 } | |
286 | |
131 | 287 /* Return the first expression in a sequence of COMPOUND_EXPRs, or in |
288 a STATEMENT_LIST, disregarding DEBUG_BEGIN_STMTs, recursing into a | |
289 STATEMENT_LIST if that's the first non-DEBUG_BEGIN_STMT. */ | |
0 | 290 |
291 tree | |
292 expr_first (tree expr) | |
293 { | |
294 if (expr == NULL_TREE) | |
295 return expr; | |
296 | |
297 if (TREE_CODE (expr) == STATEMENT_LIST) | |
298 { | |
299 struct tree_statement_list_node *n = STATEMENT_LIST_HEAD (expr); | |
131 | 300 if (!n) |
301 return NULL_TREE; | |
302 while (TREE_CODE (n->stmt) == DEBUG_BEGIN_STMT) | |
303 { | |
304 n = n->next; | |
305 if (!n) | |
306 return NULL_TREE; | |
307 } | |
308 /* If the first non-debug stmt is not a statement list, we | |
309 already know it's what we're looking for. */ | |
310 if (TREE_CODE (n->stmt) != STATEMENT_LIST) | |
311 return n->stmt; | |
312 | |
313 return expr_first (n->stmt); | |
0 | 314 } |
315 | |
316 while (TREE_CODE (expr) == COMPOUND_EXPR) | |
317 expr = TREE_OPERAND (expr, 0); | |
318 | |
319 return expr; | |
320 } | |
321 | |
131 | 322 /* Return the last expression in a sequence of COMPOUND_EXPRs, or in a |
323 STATEMENT_LIST, disregarding DEBUG_BEGIN_STMTs, recursing into a | |
324 STATEMENT_LIST if that's the last non-DEBUG_BEGIN_STMT. */ | |
0 | 325 |
326 tree | |
327 expr_last (tree expr) | |
328 { | |
329 if (expr == NULL_TREE) | |
330 return expr; | |
331 | |
332 if (TREE_CODE (expr) == STATEMENT_LIST) | |
333 { | |
334 struct tree_statement_list_node *n = STATEMENT_LIST_TAIL (expr); | |
131 | 335 if (!n) |
336 return NULL_TREE; | |
337 while (TREE_CODE (n->stmt) == DEBUG_BEGIN_STMT) | |
338 { | |
339 n = n->prev; | |
340 if (!n) | |
341 return NULL_TREE; | |
342 } | |
343 /* If the last non-debug stmt is not a statement list, we | |
344 already know it's what we're looking for. */ | |
345 if (TREE_CODE (n->stmt) != STATEMENT_LIST) | |
346 return n->stmt; | |
347 | |
348 return expr_last (n->stmt); | |
0 | 349 } |
350 | |
351 while (TREE_CODE (expr) == COMPOUND_EXPR) | |
352 expr = TREE_OPERAND (expr, 1); | |
353 | |
354 return expr; | |
355 } | |
356 | |
357 #include "gt-tree-iterator.h" |