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" 284