1 /* Iterator routines for manipulating GENERIC and GIMPLE tree statements.
2 Copyright (C) 2003, 2004 Free Software Foundation, Inc.
3 Contributed by Andrew MacLeod <amacleod@redhat.com>
5 This file is part of GCC.
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 2, or (at your option)
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.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING. If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
24 #include "coretypes.h"
26 #include "tree-gimple.h"
27 #include "tree-iterator.h"
31 /* This is a cache of STATEMENT_LIST nodes. We create and destroy them
32 fairly often during gimplification. */
34 static GTY ((deletable (""))) tree stmt_list_cache
;
37 alloc_stmt_list (void)
39 tree list
= stmt_list_cache
;
42 stmt_list_cache
= TREE_CHAIN (list
);
43 TREE_CHAIN (list
) = NULL
;
44 TREE_SIDE_EFFECTS (list
) = 0;
48 list
= make_node (STATEMENT_LIST
);
49 TREE_TYPE (list
) = void_type_node
;
55 free_stmt_list (tree t
)
57 #ifdef ENABLE_CHECKING
58 if (STATEMENT_LIST_HEAD (t
) || STATEMENT_LIST_TAIL (t
))
61 TREE_CHAIN (t
) = stmt_list_cache
;
65 /* Links a statement, or a chain of statements, before the current stmt. */
68 tsi_link_before (tree_stmt_iterator
*i
, tree t
, enum tsi_iterator_update mode
)
70 struct tree_statement_list_node
*head
, *tail
, *cur
;
73 if (t
== i
->container
)
76 TREE_SIDE_EFFECTS (i
->container
) = 1;
78 if (TREE_CODE (t
) == STATEMENT_LIST
)
80 head
= STATEMENT_LIST_HEAD (t
);
81 tail
= STATEMENT_LIST_TAIL (t
);
82 STATEMENT_LIST_HEAD (t
) = NULL
;
83 STATEMENT_LIST_TAIL (t
) = NULL
;
87 /* Empty statement lists need no work. */
97 head
= ggc_alloc (sizeof (*head
));
106 /* Link it into the list. */
109 head
->prev
= cur
->prev
;
111 head
->prev
->next
= head
;
113 STATEMENT_LIST_HEAD (i
->container
) = head
;
119 if (STATEMENT_LIST_TAIL (i
->container
))
121 STATEMENT_LIST_HEAD (i
->container
) = head
;
122 STATEMENT_LIST_TAIL (i
->container
) = tail
;
125 /* Update the iterator, if requested. */
129 case TSI_CONTINUE_LINKING
:
130 case TSI_CHAIN_START
:
143 /* Links a statement, or a chain of statements, after the current stmt. */
146 tsi_link_after (tree_stmt_iterator
*i
, tree t
, enum tsi_iterator_update mode
)
148 struct tree_statement_list_node
*head
, *tail
, *cur
;
150 /* Die on looping. */
151 if (t
== i
->container
)
154 TREE_SIDE_EFFECTS (i
->container
) = 1;
156 if (TREE_CODE (t
) == STATEMENT_LIST
)
158 head
= STATEMENT_LIST_HEAD (t
);
159 tail
= STATEMENT_LIST_TAIL (t
);
160 STATEMENT_LIST_HEAD (t
) = NULL
;
161 STATEMENT_LIST_TAIL (t
) = NULL
;
165 /* Empty statement lists need no work. */
175 head
= ggc_alloc (sizeof (*head
));
184 /* Link it into the list. */
187 tail
->next
= cur
->next
;
189 tail
->next
->prev
= tail
;
191 STATEMENT_LIST_TAIL (i
->container
) = tail
;
197 if (STATEMENT_LIST_TAIL (i
->container
))
199 STATEMENT_LIST_HEAD (i
->container
) = head
;
200 STATEMENT_LIST_TAIL (i
->container
) = tail
;
203 /* Update the iterator, if requested. */
207 case TSI_CHAIN_START
:
210 case TSI_CONTINUE_LINKING
:
221 /* Remove a stmt from the tree list. The iterator is updated to point to
225 tsi_delink (tree_stmt_iterator
*i
)
227 struct tree_statement_list_node
*cur
, *next
, *prev
;
236 STATEMENT_LIST_HEAD (i
->container
) = next
;
240 STATEMENT_LIST_TAIL (i
->container
) = prev
;
243 TREE_SIDE_EFFECTS (i
->container
) = 0;
248 /* Move all statements in the statement list after I to a new
249 statement list. I itself is unchanged. */
252 tsi_split_statement_list_after (const tree_stmt_iterator
*i
)
254 struct tree_statement_list_node
*cur
, *next
;
258 /* How can we possibly split after the end, or before the beginning? */
263 old_sl
= i
->container
;
264 new_sl
= alloc_stmt_list ();
265 TREE_SIDE_EFFECTS (new_sl
) = 1;
267 STATEMENT_LIST_HEAD (new_sl
) = next
;
268 STATEMENT_LIST_TAIL (new_sl
) = STATEMENT_LIST_TAIL (old_sl
);
269 STATEMENT_LIST_TAIL (old_sl
) = cur
;
276 /* Move all statements in the statement list before I to a new
277 statement list. I is set to the head of the new list. */
280 tsi_split_statement_list_before (tree_stmt_iterator
*i
)
282 struct tree_statement_list_node
*cur
, *prev
;
286 /* How can we possibly split after the end, or before the beginning? */
291 old_sl
= i
->container
;
292 new_sl
= alloc_stmt_list ();
293 TREE_SIDE_EFFECTS (new_sl
) = 1;
294 i
->container
= new_sl
;
296 STATEMENT_LIST_HEAD (new_sl
) = cur
;
297 STATEMENT_LIST_TAIL (new_sl
) = STATEMENT_LIST_TAIL (old_sl
);
298 STATEMENT_LIST_TAIL (old_sl
) = prev
;
305 /* Return the first expression in a sequence of COMPOUND_EXPRs,
306 or in a STATEMENT_LIST. */
309 expr_first (tree expr
)
311 if (expr
== NULL_TREE
)
314 if (TREE_CODE (expr
) == STATEMENT_LIST
)
316 struct tree_statement_list_node
*n
= STATEMENT_LIST_HEAD (expr
);
317 return n
? n
->stmt
: NULL_TREE
;
320 while (TREE_CODE (expr
) == COMPOUND_EXPR
)
321 expr
= TREE_OPERAND (expr
, 0);
325 /* Return the last expression in a sequence of COMPOUND_EXPRs,
326 or in a STATEMENT_LIST. */
329 expr_last (tree expr
)
331 if (expr
== NULL_TREE
)
334 if (TREE_CODE (expr
) == STATEMENT_LIST
)
336 struct tree_statement_list_node
*n
= STATEMENT_LIST_TAIL (expr
);
337 return n
? n
->stmt
: NULL_TREE
;
340 while (TREE_CODE (expr
) == COMPOUND_EXPR
)
341 expr
= TREE_OPERAND (expr
, 1);
345 /* If EXPR is a single statement, naked or in a STATEMENT_LIST, then
346 return it. Otherwise return NULL. */
349 expr_only (tree expr
)
351 if (expr
== NULL_TREE
)
354 if (TREE_CODE (expr
) == STATEMENT_LIST
)
356 struct tree_statement_list_node
*n
= STATEMENT_LIST_TAIL (expr
);
357 if (n
&& STATEMENT_LIST_HEAD (expr
) == n
)
363 if (TREE_CODE (expr
) == COMPOUND_EXPR
)
369 #include "gt-tree-iterator.h"