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 5This file is part of GCC. 6 7GCC is free software; you can redistribute it and/or modify 8it under the terms of the GNU General Public License as published by 9the Free Software Foundation; either version 3, or (at your option) 10any later version. 11 12GCC is distributed in the hope that it will be useful, 13but WITHOUT ANY WARRANTY; without even the implied warranty of 14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15GNU General Public License for more details. 16 17You should have received a copy of the GNU General Public License 18along 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 33static GTY ((deletable (""))) tree stmt_list_cache; 34 35tree 36alloc_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 52void 53free_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 66void 67tsi_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 142void 143tsi_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 217void 218tsi_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 244tree 245expr_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 265tree 266expr_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