source: trunk/third/gcc/c-iterate.c @ 8834

Revision 8834, 15.7 KB checked in by ghudson, 28 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r8833, which included commits to RCS files with non-trunk default branches.
Line 
1/* Build expressions with type checking for C compiler.
2   Copyright (C) 1987, 1988, 1989, 1992, 1993 Free Software Foundation, Inc.
3
4This file is part of GNU CC.
5
6GNU CC is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11GNU CC is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU CC; see the file COPYING.  If not, write to
18the Free Software Foundation, 59 Temple Place - Suite 330,
19Boston, 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
34static void expand_stmt_with_iterators_1 ();
35static tree collect_iterators ();
36static void iterator_loop_prologue ();
37static void iterator_loop_epilogue ();
38static void add_ixpansion ();
39static void delete_ixpansion();
40static int top_level_ixpansion_p ();
41static 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).  */
45static struct obstack ixp_obstack;
46static 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
80struct  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
91struct 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
98struct iter_stack_node *iter_stack;
99
100struct iter_stack_node sublevel_ixpansions;
101
102/* During collect_iterators, a list of SAVE_EXPRs already scanned.  */
103static tree save_exprs;
104
105/* Initialize our obstack once per compilation.  */
106
107void
108init_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
116void
117iterator_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
127void
128iterator_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
147void
148iterator_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
159static void
160expand_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
188static tree
189collect_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
277static void
278iterator_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
325static void
326iterator_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
354static int
355top_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
363static void
364isn_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
390static void
391istack_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
408void
409push_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
424void
425pop_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
440static void
441add_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
470static void
471delete_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
521void
522prdecl (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
542tree
543pil (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
559struct ixpansion *
560pixl (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
582void
583pis ()
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 */
Note: See TracBrowser for help on using the repository browser.