[8833] | 1 | /* Build expressions with type checking for C compiler. |
---|
| 2 | Copyright (C) 1987, 1988, 1989, 1992, 1993 Free Software Foundation, Inc. |
---|
| 3 | |
---|
| 4 | This file is part of GNU CC. |
---|
| 5 | |
---|
| 6 | GNU CC is free software; you can redistribute it and/or modify |
---|
| 7 | it under the terms of the GNU General Public License as published by |
---|
| 8 | the Free Software Foundation; either version 2, or (at your option) |
---|
| 9 | any later version. |
---|
| 10 | |
---|
| 11 | GNU CC is distributed in the hope that it will be useful, |
---|
| 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
| 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
| 14 | GNU General Public License for more details. |
---|
| 15 | |
---|
| 16 | You should have received a copy of the GNU General Public License |
---|
| 17 | along with GNU CC; see the file COPYING. If not, write to |
---|
| 18 | the Free Software Foundation, 59 Temple Place - Suite 330, |
---|
| 19 | Boston, MA 02111-1307, USA. */ |
---|
| 20 | |
---|
| 21 | |
---|
| 22 | /* This file is part of the C front end. |
---|
| 23 | It is responsible for implementing iterators, |
---|
| 24 | both their declarations and the expansion of statements using them. */ |
---|
| 25 | |
---|
| 26 | #include "config.h" |
---|
| 27 | #include <stdio.h> |
---|
| 28 | #include "tree.h" |
---|
| 29 | #include "c-tree.h" |
---|
| 30 | #include "flags.h" |
---|
| 31 | #include "obstack.h" |
---|
| 32 | #include "rtl.h" |
---|
| 33 | |
---|
| 34 | static void expand_stmt_with_iterators_1 (); |
---|
| 35 | static tree collect_iterators (); |
---|
| 36 | static void iterator_loop_prologue (); |
---|
| 37 | static void iterator_loop_epilogue (); |
---|
| 38 | static void add_ixpansion (); |
---|
| 39 | static void delete_ixpansion(); |
---|
| 40 | static int top_level_ixpansion_p (); |
---|
| 41 | static void istack_sublevel_to_current (); |
---|
| 42 | |
---|
| 43 | /* A special obstack, and a pointer to the start of |
---|
| 44 | all the data in it (so we can free everything easily). */ |
---|
| 45 | static struct obstack ixp_obstack; |
---|
| 46 | static char *ixp_firstobj; |
---|
| 47 | |
---|
| 48 | /* |
---|
| 49 | KEEPING TRACK OF EXPANSIONS |
---|
| 50 | |
---|
| 51 | In order to clean out expansions corresponding to statements inside |
---|
| 52 | "{(...)}" constructs we have to keep track of all expansions. The |
---|
| 53 | cleanup is needed when an automatic, or implicit, expansion on |
---|
| 54 | iterator, say X, happens to a statement which contains a {(...)} |
---|
| 55 | form with a statement already expanded on X. In this case we have |
---|
| 56 | to go back and cleanup the inner expansion. This can be further |
---|
| 57 | complicated by the fact that {(...)} can be nested. |
---|
| 58 | |
---|
| 59 | To make this cleanup possible, we keep lists of all expansions, and |
---|
| 60 | to make it work for nested constructs, we keep a stack. The list at |
---|
| 61 | the top of the stack (ITER_STACK.CURRENT_LEVEL) corresponds to the |
---|
| 62 | currently parsed level. All expansions of the levels below the |
---|
| 63 | current one are kept in one list whose head is pointed to by |
---|
| 64 | ITER_STACK.SUBLEVEL_FIRST (SUBLEVEL_LAST is there for making merges |
---|
| 65 | easy). The process works as follows: |
---|
| 66 | |
---|
| 67 | -- On "({" a new node is added to the stack by PUSH_ITERATOR_STACK. |
---|
| 68 | The sublevel list is not changed at this point. |
---|
| 69 | |
---|
| 70 | -- On "})" the list for the current level is appended to the sublevel |
---|
| 71 | list. |
---|
| 72 | |
---|
| 73 | -- On ";" sublevel lists are appended to the current level lists. |
---|
| 74 | The reason is this: if they have not been superseded by the |
---|
| 75 | expansion at the current level, they still might be |
---|
| 76 | superseded later by the expansion on the higher level. |
---|
| 77 | The levels do not have to distinguish levels below, so we |
---|
| 78 | can merge the lists together. */ |
---|
| 79 | |
---|
| 80 | struct ixpansion |
---|
| 81 | { |
---|
| 82 | tree ixdecl; /* Iterator decl */ |
---|
| 83 | rtx ixprologue_start; /* First insn of epilogue. NULL means */ |
---|
| 84 | /* explicit (FOR) expansion*/ |
---|
| 85 | rtx ixprologue_end; |
---|
| 86 | rtx ixepilogue_start; |
---|
| 87 | rtx ixepilogue_end; |
---|
| 88 | struct ixpansion *next; /* Next in the list */ |
---|
| 89 | }; |
---|
| 90 | |
---|
| 91 | struct iter_stack_node |
---|
| 92 | { |
---|
| 93 | struct ixpansion *first; /* Head of list of ixpansions */ |
---|
| 94 | struct ixpansion *last; /* Last node in list of ixpansions */ |
---|
| 95 | struct iter_stack_node *next; /* Next level iterator stack node */ |
---|
| 96 | }; |
---|
| 97 | |
---|
| 98 | struct iter_stack_node *iter_stack; |
---|
| 99 | |
---|
| 100 | struct iter_stack_node sublevel_ixpansions; |
---|
| 101 | |
---|
| 102 | /* During collect_iterators, a list of SAVE_EXPRs already scanned. */ |
---|
| 103 | static tree save_exprs; |
---|
| 104 | |
---|
| 105 | /* Initialize our obstack once per compilation. */ |
---|
| 106 | |
---|
| 107 | void |
---|
| 108 | init_iterators () |
---|
| 109 | { |
---|
| 110 | gcc_obstack_init (&ixp_obstack); |
---|
| 111 | ixp_firstobj = (char *) obstack_alloc (&ixp_obstack, 0); |
---|
| 112 | } |
---|
| 113 | |
---|
| 114 | /* Handle the start of an explicit `for' loop for iterator IDECL. */ |
---|
| 115 | |
---|
| 116 | void |
---|
| 117 | iterator_for_loop_start (idecl) |
---|
| 118 | tree idecl; |
---|
| 119 | { |
---|
| 120 | ITERATOR_BOUND_P (idecl) = 1; |
---|
| 121 | add_ixpansion (idecl, 0, 0, 0, 0); |
---|
| 122 | iterator_loop_prologue (idecl, 0, 0); |
---|
| 123 | } |
---|
| 124 | |
---|
| 125 | /* Handle the end of an explicit `for' loop for iterator IDECL. */ |
---|
| 126 | |
---|
| 127 | void |
---|
| 128 | iterator_for_loop_end (idecl) |
---|
| 129 | tree idecl; |
---|
| 130 | { |
---|
| 131 | iterator_loop_epilogue (idecl, 0, 0); |
---|
| 132 | ITERATOR_BOUND_P (idecl) = 0; |
---|
| 133 | } |
---|
| 134 | |
---|
| 135 | /* |
---|
| 136 | ITERATOR RTL EXPANSIONS |
---|
| 137 | |
---|
| 138 | Expanding simple statements with iterators is straightforward: |
---|
| 139 | collect the list of all free iterators in the statement, and |
---|
| 140 | generate a loop for each of them. |
---|
| 141 | |
---|
| 142 | An iterator is "free" if it has not been "bound" by a FOR |
---|
| 143 | operator. The DECL_RTL of the iterator is the loop counter. */ |
---|
| 144 | |
---|
| 145 | /* Expand a statement STMT, possibly containing iterator usage, into RTL. */ |
---|
| 146 | |
---|
| 147 | void |
---|
| 148 | iterator_expand (stmt) |
---|
| 149 | tree stmt; |
---|
| 150 | { |
---|
| 151 | tree iter_list; |
---|
| 152 | save_exprs = NULL_TREE; |
---|
| 153 | iter_list = collect_iterators (stmt, NULL_TREE); |
---|
| 154 | expand_stmt_with_iterators_1 (stmt, iter_list); |
---|
| 155 | istack_sublevel_to_current (); |
---|
| 156 | } |
---|
| 157 | |
---|
| 158 | |
---|
| 159 | static void |
---|
| 160 | expand_stmt_with_iterators_1 (stmt, iter_list) |
---|
| 161 | tree stmt, iter_list; |
---|
| 162 | { |
---|
| 163 | if (iter_list == 0) |
---|
| 164 | expand_expr_stmt (stmt); |
---|
| 165 | else |
---|
| 166 | { |
---|
| 167 | tree current_iterator = TREE_VALUE (iter_list); |
---|
| 168 | tree iter_list_tail = TREE_CHAIN (iter_list); |
---|
| 169 | rtx p_start, p_end, e_start, e_end; |
---|
| 170 | |
---|
| 171 | iterator_loop_prologue (current_iterator, &p_start, &p_end); |
---|
| 172 | expand_stmt_with_iterators_1 (stmt, iter_list_tail); |
---|
| 173 | iterator_loop_epilogue (current_iterator, &e_start, &e_end); |
---|
| 174 | |
---|
| 175 | /** Delete all inner expansions based on current_iterator **/ |
---|
| 176 | /** before adding the outer one. **/ |
---|
| 177 | |
---|
| 178 | delete_ixpansion (current_iterator); |
---|
| 179 | add_ixpansion (current_iterator, p_start, p_end, e_start, e_end); |
---|
| 180 | } |
---|
| 181 | } |
---|
| 182 | |
---|
| 183 | |
---|
| 184 | /* Return a list containing all the free (i.e. not bound by a |
---|
| 185 | containing `for' statement) iterators mentioned in EXP, plus those |
---|
| 186 | in LIST. Do not add duplicate entries to the list. */ |
---|
| 187 | |
---|
| 188 | static tree |
---|
| 189 | collect_iterators (exp, list) |
---|
| 190 | tree exp, list; |
---|
| 191 | { |
---|
| 192 | if (exp == 0) return list; |
---|
| 193 | |
---|
| 194 | switch (TREE_CODE (exp)) |
---|
| 195 | { |
---|
| 196 | case VAR_DECL: |
---|
| 197 | if (! ITERATOR_P (exp) || ITERATOR_BOUND_P (exp)) |
---|
| 198 | return list; |
---|
| 199 | if (value_member (exp, list)) |
---|
| 200 | return list; |
---|
| 201 | return tree_cons (NULL_TREE, exp, list); |
---|
| 202 | |
---|
| 203 | case TREE_LIST: |
---|
| 204 | { |
---|
| 205 | tree tail; |
---|
| 206 | for (tail = exp; tail; tail = TREE_CHAIN (tail)) |
---|
| 207 | list = collect_iterators (TREE_VALUE (tail), list); |
---|
| 208 | return list; |
---|
| 209 | } |
---|
| 210 | |
---|
| 211 | case SAVE_EXPR: |
---|
| 212 | /* In each scan, scan a given save_expr only once. */ |
---|
| 213 | if (value_member (exp, save_exprs)) |
---|
| 214 | return list; |
---|
| 215 | |
---|
| 216 | save_exprs = tree_cons (NULL_TREE, exp, save_exprs); |
---|
| 217 | return collect_iterators (TREE_OPERAND (exp, 0), list); |
---|
| 218 | |
---|
| 219 | /* we do not automatically iterate blocks -- one must */ |
---|
| 220 | /* use the FOR construct to do that */ |
---|
| 221 | |
---|
| 222 | case BLOCK: |
---|
| 223 | return list; |
---|
| 224 | |
---|
| 225 | default: |
---|
| 226 | switch (TREE_CODE_CLASS (TREE_CODE (exp))) |
---|
| 227 | { |
---|
| 228 | case '1': |
---|
| 229 | return collect_iterators (TREE_OPERAND (exp, 0), list); |
---|
| 230 | |
---|
| 231 | case '2': |
---|
| 232 | case '<': |
---|
| 233 | return collect_iterators (TREE_OPERAND (exp, 0), |
---|
| 234 | collect_iterators (TREE_OPERAND (exp, 1), |
---|
| 235 | list)); |
---|
| 236 | |
---|
| 237 | case 'e': |
---|
| 238 | case 'r': |
---|
| 239 | { |
---|
| 240 | int num_args = tree_code_length[(int) TREE_CODE (exp)]; |
---|
| 241 | int i; |
---|
| 242 | |
---|
| 243 | /* Some tree codes have RTL, not trees, as operands. */ |
---|
| 244 | switch (TREE_CODE (exp)) |
---|
| 245 | { |
---|
| 246 | case CALL_EXPR: |
---|
| 247 | num_args = 2; |
---|
| 248 | break; |
---|
| 249 | case METHOD_CALL_EXPR: |
---|
| 250 | num_args = 3; |
---|
| 251 | break; |
---|
| 252 | case WITH_CLEANUP_EXPR: |
---|
| 253 | num_args = 1; |
---|
| 254 | break; |
---|
| 255 | case RTL_EXPR: |
---|
| 256 | return list; |
---|
| 257 | } |
---|
| 258 | |
---|
| 259 | for (i = 0; i < num_args; i++) |
---|
| 260 | list = collect_iterators (TREE_OPERAND (exp, i), list); |
---|
| 261 | return list; |
---|
| 262 | } |
---|
| 263 | default: |
---|
| 264 | return list; |
---|
| 265 | } |
---|
| 266 | } |
---|
| 267 | } |
---|
| 268 | |
---|
| 269 | /* Emit rtl for the start of a loop for iterator IDECL. |
---|
| 270 | |
---|
| 271 | If necessary, create loop counter rtx and store it as DECL_RTL of IDECL. |
---|
| 272 | |
---|
| 273 | The prologue normally starts and ends with notes, which are returned |
---|
| 274 | by this function in *START_NOTE and *END_NODE. |
---|
| 275 | If START_NOTE and END_NODE are 0, we don't make those notes. */ |
---|
| 276 | |
---|
| 277 | static void |
---|
| 278 | iterator_loop_prologue (idecl, start_note, end_note) |
---|
| 279 | tree idecl; |
---|
| 280 | rtx *start_note, *end_note; |
---|
| 281 | { |
---|
| 282 | tree expr; |
---|
| 283 | |
---|
| 284 | /* Force the save_expr in DECL_INITIAL to be calculated |
---|
| 285 | if it hasn't been calculated yet. */ |
---|
| 286 | expand_expr (DECL_INITIAL (idecl), const0_rtx, VOIDmode, 0); |
---|
| 287 | |
---|
| 288 | if (DECL_RTL (idecl) == 0) |
---|
| 289 | expand_decl (idecl); |
---|
| 290 | |
---|
| 291 | if (start_note) |
---|
| 292 | *start_note = emit_note (0, NOTE_INSN_DELETED); |
---|
| 293 | |
---|
| 294 | /* Initialize counter. */ |
---|
| 295 | expr = build (MODIFY_EXPR, TREE_TYPE (idecl), idecl, integer_zero_node); |
---|
| 296 | TREE_SIDE_EFFECTS (expr) = 1; |
---|
| 297 | expand_expr (expr, const0_rtx, VOIDmode, 0); |
---|
| 298 | |
---|
| 299 | expand_start_loop_continue_elsewhere (1); |
---|
| 300 | |
---|
| 301 | ITERATOR_BOUND_P (idecl) = 1; |
---|
| 302 | |
---|
| 303 | if (end_note) |
---|
| 304 | *end_note = emit_note (0, NOTE_INSN_DELETED); |
---|
| 305 | } |
---|
| 306 | |
---|
| 307 | /* Similar to the previous function, but for the end of the loop. |
---|
| 308 | |
---|
| 309 | DECL_RTL is zeroed unless we are inside "({...})". The reason for that is |
---|
| 310 | described below. |
---|
| 311 | |
---|
| 312 | When we create two (or more) loops based on the same IDECL, and |
---|
| 313 | both inside the same "({...})" construct, we must be prepared to |
---|
| 314 | delete both of the loops and create a single one on the level |
---|
| 315 | above, i.e. enclosing the "({...})". The new loop has to use the |
---|
| 316 | same counter rtl because the references to the iterator decl |
---|
| 317 | (IDECL) have already been expanded as references to the counter |
---|
| 318 | rtl. |
---|
| 319 | |
---|
| 320 | It is incorrect to use the same counter reg in different functions, |
---|
| 321 | and it is desirable to use different counters in disjoint loops |
---|
| 322 | when we know there's no need to combine them (because then they can |
---|
| 323 | get allocated separately). */ |
---|
| 324 | |
---|
| 325 | static void |
---|
| 326 | iterator_loop_epilogue (idecl, start_note, end_note) |
---|
| 327 | tree idecl; |
---|
| 328 | rtx *start_note, *end_note; |
---|
| 329 | { |
---|
| 330 | tree test, incr; |
---|
| 331 | |
---|
| 332 | if (start_note) |
---|
| 333 | *start_note = emit_note (0, NOTE_INSN_DELETED); |
---|
| 334 | expand_loop_continue_here (); |
---|
| 335 | incr = build_binary_op (PLUS_EXPR, idecl, integer_one_node, 0); |
---|
| 336 | incr = build (MODIFY_EXPR, TREE_TYPE (idecl), idecl, incr); |
---|
| 337 | TREE_SIDE_EFFECTS (incr) = 1; |
---|
| 338 | expand_expr (incr, const0_rtx, VOIDmode, 0); |
---|
| 339 | test = build_binary_op (LT_EXPR, idecl, DECL_INITIAL (idecl), 0); |
---|
| 340 | expand_exit_loop_if_false (0, test); |
---|
| 341 | expand_end_loop (); |
---|
| 342 | |
---|
| 343 | ITERATOR_BOUND_P (idecl) = 0; |
---|
| 344 | /* we can reset rtl since there is not chance that this expansion */ |
---|
| 345 | /* would be superseded by a higher level one */ |
---|
| 346 | if (top_level_ixpansion_p ()) |
---|
| 347 | DECL_RTL (idecl) = 0; |
---|
| 348 | if (end_note) |
---|
| 349 | *end_note = emit_note (0, NOTE_INSN_DELETED); |
---|
| 350 | } |
---|
| 351 | |
---|
| 352 | /* Return true if we are not currently inside a "({...})" construct. */ |
---|
| 353 | |
---|
| 354 | static int |
---|
| 355 | top_level_ixpansion_p () |
---|
| 356 | { |
---|
| 357 | return iter_stack == 0; |
---|
| 358 | } |
---|
| 359 | |
---|
| 360 | /* Given two chains of iter_stack_nodes, |
---|
| 361 | append the nodes in X into Y. */ |
---|
| 362 | |
---|
| 363 | static void |
---|
| 364 | isn_append (x, y) |
---|
| 365 | struct iter_stack_node *x, *y; |
---|
| 366 | { |
---|
| 367 | if (x->first == 0) |
---|
| 368 | return; |
---|
| 369 | |
---|
| 370 | if (y->first == 0) |
---|
| 371 | { |
---|
| 372 | y->first = x->first; |
---|
| 373 | y->last = x->last; |
---|
| 374 | } |
---|
| 375 | else |
---|
| 376 | { |
---|
| 377 | y->last->next = x->first; |
---|
| 378 | y->last = x->last; |
---|
| 379 | } |
---|
| 380 | } |
---|
| 381 | |
---|
| 382 | /** Make X empty **/ |
---|
| 383 | |
---|
| 384 | #define ISN_ZERO(X) (X).first=(X).last=0 |
---|
| 385 | |
---|
| 386 | /* Move the ixpansions in sublevel_ixpansions into the current |
---|
| 387 | node on the iter_stack, or discard them if the iter_stack is empty. |
---|
| 388 | We do this at the end of a statement. */ |
---|
| 389 | |
---|
| 390 | static void |
---|
| 391 | istack_sublevel_to_current () |
---|
| 392 | { |
---|
| 393 | /* At the top level we can throw away sublevel's expansions **/ |
---|
| 394 | /* because there is nobody above us to ask for a cleanup **/ |
---|
| 395 | if (iter_stack != 0) |
---|
| 396 | /** Merging with empty sublevel list is a no-op **/ |
---|
| 397 | if (sublevel_ixpansions.last) |
---|
| 398 | isn_append (&sublevel_ixpansions, iter_stack); |
---|
| 399 | |
---|
| 400 | if (iter_stack == 0) |
---|
| 401 | obstack_free (&ixp_obstack, ixp_firstobj); |
---|
| 402 | |
---|
| 403 | ISN_ZERO (sublevel_ixpansions); |
---|
| 404 | } |
---|
| 405 | |
---|
| 406 | /* Push a new node on the iter_stack, when we enter a ({...}). */ |
---|
| 407 | |
---|
| 408 | void |
---|
| 409 | push_iterator_stack () |
---|
| 410 | { |
---|
| 411 | struct iter_stack_node *new_top |
---|
| 412 | = (struct iter_stack_node*) |
---|
| 413 | obstack_alloc (&ixp_obstack, sizeof (struct iter_stack_node)); |
---|
| 414 | |
---|
| 415 | new_top->first = 0; |
---|
| 416 | new_top->last = 0; |
---|
| 417 | new_top->next = iter_stack; |
---|
| 418 | iter_stack = new_top; |
---|
| 419 | } |
---|
| 420 | |
---|
| 421 | /* Pop iter_stack, moving the ixpansions in the node being popped |
---|
| 422 | into sublevel_ixpansions. */ |
---|
| 423 | |
---|
| 424 | void |
---|
| 425 | pop_iterator_stack () |
---|
| 426 | { |
---|
| 427 | if (iter_stack == 0) |
---|
| 428 | abort (); |
---|
| 429 | |
---|
| 430 | isn_append (iter_stack, &sublevel_ixpansions); |
---|
| 431 | /** Pop current level node: */ |
---|
| 432 | iter_stack = iter_stack->next; |
---|
| 433 | } |
---|
| 434 | |
---|
| 435 | |
---|
| 436 | /* Record an iterator expansion ("ixpansion") for IDECL. |
---|
| 437 | The remaining parameters are the notes in the loop entry |
---|
| 438 | and exit rtl. */ |
---|
| 439 | |
---|
| 440 | static void |
---|
| 441 | add_ixpansion (idecl, pro_start, pro_end, epi_start, epi_end) |
---|
| 442 | tree idecl; |
---|
| 443 | rtx pro_start, pro_end, epi_start, epi_end; |
---|
| 444 | { |
---|
| 445 | struct ixpansion* newix; |
---|
| 446 | |
---|
| 447 | /* Do nothing if we are not inside "({...})", |
---|
| 448 | as in that case this expansion can't need subsequent RTL modification. */ |
---|
| 449 | if (iter_stack == 0) |
---|
| 450 | return; |
---|
| 451 | |
---|
| 452 | newix = (struct ixpansion*) obstack_alloc (&ixp_obstack, |
---|
| 453 | sizeof (struct ixpansion)); |
---|
| 454 | newix->ixdecl = idecl; |
---|
| 455 | newix->ixprologue_start = pro_start; |
---|
| 456 | newix->ixprologue_end = pro_end; |
---|
| 457 | newix->ixepilogue_start = epi_start; |
---|
| 458 | newix->ixepilogue_end = epi_end; |
---|
| 459 | |
---|
| 460 | newix->next = iter_stack->first; |
---|
| 461 | iter_stack->first = newix; |
---|
| 462 | if (iter_stack->last == 0) |
---|
| 463 | iter_stack->last = newix; |
---|
| 464 | } |
---|
| 465 | |
---|
| 466 | /* Delete the RTL for all ixpansions for iterator IDECL |
---|
| 467 | in our sublevels. We do this when we make a larger |
---|
| 468 | containing expansion for IDECL. */ |
---|
| 469 | |
---|
| 470 | static void |
---|
| 471 | delete_ixpansion (idecl) |
---|
| 472 | tree idecl; |
---|
| 473 | { |
---|
| 474 | struct ixpansion* previx = 0, *ix; |
---|
| 475 | |
---|
| 476 | for (ix = sublevel_ixpansions.first; ix; ix = ix->next) |
---|
| 477 | if (ix->ixdecl == idecl) |
---|
| 478 | { |
---|
| 479 | /** zero means that this is a mark for FOR -- **/ |
---|
| 480 | /** we do not delete anything, just issue an error. **/ |
---|
| 481 | |
---|
| 482 | if (ix->ixprologue_start == 0) |
---|
| 483 | error_with_decl (idecl, |
---|
| 484 | "`for (%s)' appears within implicit iteration"); |
---|
| 485 | else |
---|
| 486 | { |
---|
| 487 | rtx insn; |
---|
| 488 | /* We delete all insns, including notes because leaving loop */ |
---|
| 489 | /* notes and barriers produced by iterator expansion would */ |
---|
| 490 | /* be misleading to other phases */ |
---|
| 491 | |
---|
| 492 | for (insn = NEXT_INSN (ix->ixprologue_start); |
---|
| 493 | insn != ix->ixprologue_end; |
---|
| 494 | insn = NEXT_INSN (insn)) |
---|
| 495 | delete_insn (insn); |
---|
| 496 | for (insn = NEXT_INSN (ix->ixepilogue_start); |
---|
| 497 | insn != ix->ixepilogue_end; |
---|
| 498 | insn = NEXT_INSN (insn)) |
---|
| 499 | delete_insn (insn); |
---|
| 500 | } |
---|
| 501 | |
---|
| 502 | /* Delete this ixpansion from sublevel_ixpansions. */ |
---|
| 503 | if (previx) |
---|
| 504 | previx->next = ix->next; |
---|
| 505 | else |
---|
| 506 | sublevel_ixpansions.first = ix->next; |
---|
| 507 | if (sublevel_ixpansions.last == ix) |
---|
| 508 | sublevel_ixpansions.last = previx; |
---|
| 509 | } |
---|
| 510 | else |
---|
| 511 | previx = ix; |
---|
| 512 | } |
---|
| 513 | |
---|
| 514 | #ifdef DEBUG_ITERATORS |
---|
| 515 | |
---|
| 516 | /* The functions below are for use from source level debugger. |
---|
| 517 | They print short forms of iterator lists and the iterator stack. */ |
---|
| 518 | |
---|
| 519 | /* Print the name of the iterator D. */ |
---|
| 520 | |
---|
| 521 | void |
---|
| 522 | prdecl (d) |
---|
| 523 | tree d; |
---|
| 524 | { |
---|
| 525 | if (d) |
---|
| 526 | { |
---|
| 527 | if (TREE_CODE (d) == VAR_DECL) |
---|
| 528 | { |
---|
| 529 | tree tname = DECL_NAME (d); |
---|
| 530 | char *dname = IDENTIFIER_POINTER (tname); |
---|
| 531 | fprintf (stderr, dname); |
---|
| 532 | } |
---|
| 533 | else |
---|
| 534 | fprintf (stderr, "<<Not a Decl!!!>>"); |
---|
| 535 | } |
---|
| 536 | else |
---|
| 537 | fprintf (stderr, "<<NULL!!>>"); |
---|
| 538 | } |
---|
| 539 | |
---|
| 540 | /* Print Iterator List -- names only */ |
---|
| 541 | |
---|
| 542 | tree |
---|
| 543 | pil (head) |
---|
| 544 | tree head; |
---|
| 545 | { |
---|
| 546 | tree current, next; |
---|
| 547 | for (current = head; current; current = next) |
---|
| 548 | { |
---|
| 549 | tree node = TREE_VALUE (current); |
---|
| 550 | prdecl (node); |
---|
| 551 | next = TREE_CHAIN (current); |
---|
| 552 | if (next) fprintf (stderr, ","); |
---|
| 553 | } |
---|
| 554 | fprintf (stderr, "\n"); |
---|
| 555 | } |
---|
| 556 | |
---|
| 557 | /* Print IXpansion List */ |
---|
| 558 | |
---|
| 559 | struct ixpansion * |
---|
| 560 | pixl (head) |
---|
| 561 | struct ixpansion *head; |
---|
| 562 | { |
---|
| 563 | struct ixpansion *current, *next; |
---|
| 564 | fprintf (stderr, "> "); |
---|
| 565 | if (head == 0) |
---|
| 566 | fprintf (stderr, "(empty)"); |
---|
| 567 | |
---|
| 568 | for (current=head; current; current = next) |
---|
| 569 | { |
---|
| 570 | tree node = current->ixdecl; |
---|
| 571 | prdecl (node); |
---|
| 572 | next = current->next; |
---|
| 573 | if (next) |
---|
| 574 | fprintf (stderr, ","); |
---|
| 575 | } |
---|
| 576 | fprintf (stderr, "\n"); |
---|
| 577 | return head; |
---|
| 578 | } |
---|
| 579 | |
---|
| 580 | /* Print Iterator Stack*/ |
---|
| 581 | |
---|
| 582 | void |
---|
| 583 | pis () |
---|
| 584 | { |
---|
| 585 | struct iter_stack_node *stack_node; |
---|
| 586 | |
---|
| 587 | fprintf (stderr, "--SubLevel: "); |
---|
| 588 | pixl (sublevel_ixpansions.first); |
---|
| 589 | fprintf (stderr, "--Stack:--\n"); |
---|
| 590 | for (stack_node = iter_stack; |
---|
| 591 | stack_node; |
---|
| 592 | stack_node = stack_node->next) |
---|
| 593 | pixl (stack_node->first); |
---|
| 594 | } |
---|
| 595 | |
---|
| 596 | #endif /* DEBUG_ITERATORS */ |
---|