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