1 /* Iterator routines for manipulating GENERIC and GIMPLE tree statements. 2 Copyright (C) 2003, 2004, 2007, 2008, 2009, 2010 3 Free Software Foundation, Inc. 4 Contributed by Andrew MacLeod <amacleod@redhat.com> 5 6 This file is part of GCC. 7 8 GCC is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 3, or (at your option) 11 any later version. 12 13 GCC is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with GCC; see the file COPYING3. If not see 20 <http://www.gnu.org/licenses/>. */ 21 22 #include "config.h" 23 #include "system.h" 24 #include "coretypes.h" 25 #include "tree.h" 26 #include "gimple.h" 27 #include "tree-iterator.h" 28 #include "ggc.h" 29 30 31 /* This is a cache of STATEMENT_LIST nodes. We create and destroy them 32 fairly often during gimplification. */ 33 34 static GTY ((deletable (""))) VEC(tree,gc) *stmt_list_cache; 35 36 tree 37 alloc_stmt_list (void) 38 { 39 tree list; 40 if (!VEC_empty (tree, stmt_list_cache)) 41 { 42 list = VEC_pop (tree, stmt_list_cache); 43 memset (list, 0, sizeof(struct tree_base)); 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 VEC_safe_push (tree, gc, stmt_list_cache, t); 58 } 59 60 /* A subroutine of append_to_statement_list{,_force}. T is not NULL. */ 61 62 static void 63 append_to_statement_list_1 (tree t, tree *list_p) 64 { 65 tree list = *list_p; 66 tree_stmt_iterator i; 67 68 if (!list) 69 { 70 if (t && TREE_CODE (t) == STATEMENT_LIST) 71 { 72 *list_p = t; 73 return; 74 } 75 *list_p = list = alloc_stmt_list (); 76 } 77 78 i = tsi_last (list); 79 tsi_link_after (&i, t, TSI_CONTINUE_LINKING); 80 } 81 82 /* Add T to the end of the list container pointed to by LIST_P. 83 If T is an expression with no effects, it is ignored. */ 84 85 void 86 append_to_statement_list (tree t, tree *list_p) 87 { 88 if (t && TREE_SIDE_EFFECTS (t)) 89 append_to_statement_list_1 (t, list_p); 90 } 91 92 /* Similar, but the statement is always added, regardless of side effects. */ 93 94 void 95 append_to_statement_list_force (tree t, tree *list_p) 96 { 97 if (t != NULL_TREE) 98 append_to_statement_list_1 (t, list_p); 99 } 100 101 /* Links a statement, or a chain of statements, before the current stmt. */ 102 103 void 104 tsi_link_before (tree_stmt_iterator *i, tree t, enum tsi_iterator_update mode) 105 { 106 struct tree_statement_list_node *head, *tail, *cur; 107 108 /* Die on looping. */ 109 gcc_assert (t != i->container); 110 111 if (TREE_CODE (t) == STATEMENT_LIST) 112 { 113 head = STATEMENT_LIST_HEAD (t); 114 tail = STATEMENT_LIST_TAIL (t); 115 STATEMENT_LIST_HEAD (t) = NULL; 116 STATEMENT_LIST_TAIL (t) = NULL; 117 118 free_stmt_list (t); 119 120 /* Empty statement lists need no work. */ 121 if (!head || !tail) 122 { 123 gcc_assert (head == tail); 124 return; 125 } 126 } 127 else 128 { 129 head = ggc_alloc_tree_statement_list_node (); 130 head->prev = NULL; 131 head->next = NULL; 132 head->stmt = t; 133 tail = head; 134 } 135 136 TREE_SIDE_EFFECTS (i->container) = 1; 137 138 cur = i->ptr; 139 140 /* Link it into the list. */ 141 if (cur) 142 { 143 head->prev = cur->prev; 144 if (head->prev) 145 head->prev->next = head; 146 else 147 STATEMENT_LIST_HEAD (i->container) = head; 148 tail->next = cur; 149 cur->prev = tail; 150 } 151 else 152 { 153 head->prev = STATEMENT_LIST_TAIL (i->container); 154 if (head->prev) 155 head->prev->next = head; 156 else 157 STATEMENT_LIST_HEAD (i->container) = head; 158 STATEMENT_LIST_TAIL (i->container) = tail; 159 } 160 161 /* Update the iterator, if requested. */ 162 switch (mode) 163 { 164 case TSI_NEW_STMT: 165 case TSI_CONTINUE_LINKING: 166 case TSI_CHAIN_START: 167 i->ptr = head; 168 break; 169 case TSI_CHAIN_END: 170 i->ptr = tail; 171 break; 172 case TSI_SAME_STMT: 173 break; 174 } 175 } 176 177 /* Links a statement, or a chain of statements, after the current stmt. */ 178 179 void 180 tsi_link_after (tree_stmt_iterator *i, tree t, enum tsi_iterator_update mode) 181 { 182 struct tree_statement_list_node *head, *tail, *cur; 183 184 /* Die on looping. */ 185 gcc_assert (t != i->container); 186 187 if (TREE_CODE (t) == STATEMENT_LIST) 188 { 189 head = STATEMENT_LIST_HEAD (t); 190 tail = STATEMENT_LIST_TAIL (t); 191 STATEMENT_LIST_HEAD (t) = NULL; 192 STATEMENT_LIST_TAIL (t) = NULL; 193 194 free_stmt_list (t); 195 196 /* Empty statement lists need no work. */ 197 if (!head || !tail) 198 { 199 gcc_assert (head == tail); 200 return; 201 } 202 } 203 else 204 { 205 head = ggc_alloc_tree_statement_list_node (); 206 head->prev = NULL; 207 head->next = NULL; 208 head->stmt = t; 209 tail = head; 210 } 211 212 TREE_SIDE_EFFECTS (i->container) = 1; 213 214 cur = i->ptr; 215 216 /* Link it into the list. */ 217 if (cur) 218 { 219 tail->next = cur->next; 220 if (tail->next) 221 tail->next->prev = tail; 222 else 223 STATEMENT_LIST_TAIL (i->container) = tail; 224 head->prev = cur; 225 cur->next = head; 226 } 227 else 228 { 229 gcc_assert (!STATEMENT_LIST_TAIL (i->container)); 230 STATEMENT_LIST_HEAD (i->container) = head; 231 STATEMENT_LIST_TAIL (i->container) = tail; 232 } 233 234 /* Update the iterator, if requested. */ 235 switch (mode) 236 { 237 case TSI_NEW_STMT: 238 case TSI_CHAIN_START: 239 i->ptr = head; 240 break; 241 case TSI_CONTINUE_LINKING: 242 case TSI_CHAIN_END: 243 i->ptr = tail; 244 break; 245 case TSI_SAME_STMT: 246 gcc_assert (cur); 247 break; 248 } 249 } 250 251 /* Remove a stmt from the tree list. The iterator is updated to point to 252 the next stmt. */ 253 254 void 255 tsi_delink (tree_stmt_iterator *i) 256 { 257 struct tree_statement_list_node *cur, *next, *prev; 258 259 cur = i->ptr; 260 next = cur->next; 261 prev = cur->prev; 262 263 if (prev) 264 prev->next = next; 265 else 266 STATEMENT_LIST_HEAD (i->container) = next; 267 if (next) 268 next->prev = prev; 269 else 270 STATEMENT_LIST_TAIL (i->container) = prev; 271 272 if (!next && !prev) 273 TREE_SIDE_EFFECTS (i->container) = 0; 274 275 i->ptr = next; 276 } 277 278 /* Return the first expression in a sequence of COMPOUND_EXPRs, 279 or in a STATEMENT_LIST. */ 280 281 tree 282 expr_first (tree expr) 283 { 284 if (expr == NULL_TREE) 285 return expr; 286 287 if (TREE_CODE (expr) == STATEMENT_LIST) 288 { 289 struct tree_statement_list_node *n = STATEMENT_LIST_HEAD (expr); 290 return n ? n->stmt : NULL_TREE; 291 } 292 293 while (TREE_CODE (expr) == COMPOUND_EXPR) 294 expr = TREE_OPERAND (expr, 0); 295 296 return expr; 297 } 298 299 /* Return the last expression in a sequence of COMPOUND_EXPRs, 300 or in a STATEMENT_LIST. */ 301 302 tree 303 expr_last (tree expr) 304 { 305 if (expr == NULL_TREE) 306 return expr; 307 308 if (TREE_CODE (expr) == STATEMENT_LIST) 309 { 310 struct tree_statement_list_node *n = STATEMENT_LIST_TAIL (expr); 311 return n ? n->stmt : NULL_TREE; 312 } 313 314 while (TREE_CODE (expr) == COMPOUND_EXPR) 315 expr = TREE_OPERAND (expr, 1); 316 317 return expr; 318 } 319 320 #include "gt-tree-iterator.h" 321