Annotation of GNUtools/cc/c-iterate.c, revision 1.1.1.1

1.1       root        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, 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: 
                     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: 
                    101: /* During collect_iterators, a list of SAVE_EXPRs already scanned.  */
                    102: static tree save_exprs;
                    103: 
                    104: /* Initialize our obstack once per compilation.  */
                    105: 
                    106: void
                    107: init_iterators ()
                    108: {
                    109:   gcc_obstack_init (&ixp_obstack);
                    110:   ixp_firstobj = (char *) obstack_alloc (&ixp_obstack, 0);
                    111: }
                    112: 
                    113: /* Handle the start of an explicit `for' loop for iterator IDECL.  */
                    114: 
                    115: void
                    116: iterator_for_loop_start (idecl)
                    117:      tree idecl;
                    118: {
                    119:   ITERATOR_BOUND_P (idecl) = 1;
                    120:   add_ixpansion (idecl, 0, 0, 0, 0);
                    121:   iterator_loop_prologue (idecl, 0, 0);
                    122: }
                    123: 
                    124: /* Handle the end of an explicit `for' loop for iterator IDECL.  */
                    125: 
                    126: void
                    127: iterator_for_loop_end (idecl)
                    128:      tree idecl;
                    129: {
                    130:   iterator_loop_epilogue (idecl, 0, 0);
                    131:   ITERATOR_BOUND_P (idecl) = 0;
                    132: }
                    133: 
                    134: /*
                    135:                ITERATOR RTL EXPANSIONS
                    136: 
                    137:    Expanding simple statements with iterators is straightforward:
                    138:    collect the list of all free iterators in the statement, and
                    139:    generate a loop for each of them.
                    140: 
                    141:    An iterator is "free" if it has not been "bound" by a FOR
                    142:    operator.  The DECL_RTL of the iterator is the loop counter.  */
                    143: 
                    144: /* Expand a statement STMT, possibly containing iterator usage, into RTL.  */
                    145: 
                    146: void
                    147: iterator_expand (stmt)
                    148:     tree stmt;
                    149: {
                    150:   tree iter_list;
                    151:   save_exprs = NULL_TREE;
                    152:   iter_list = collect_iterators (stmt, NULL_TREE);
                    153:   expand_stmt_with_iterators_1 (stmt, iter_list);
                    154:   istack_sublevel_to_current ();
                    155: }
                    156: 
                    157: 
                    158: static void 
                    159: expand_stmt_with_iterators_1 (stmt, iter_list)
                    160:      tree stmt, iter_list;
                    161: {
                    162:   if (iter_list == 0)
                    163:     expand_expr_stmt (stmt);
                    164:   else
                    165:     {
                    166:       tree current_iterator = TREE_VALUE (iter_list);
                    167:       tree iter_list_tail   = TREE_CHAIN (iter_list);
                    168:       rtx p_start, p_end, e_start, e_end;
                    169: 
                    170:       iterator_loop_prologue (current_iterator, &p_start, &p_end);
                    171:       expand_stmt_with_iterators_1 (stmt, iter_list_tail);
                    172:       iterator_loop_epilogue (current_iterator, &e_start, &e_end);
                    173: 
                    174:       /** Delete all inner expansions based on current_iterator **/
                    175:       /** before adding the outer one. **/
                    176: 
                    177:       delete_ixpansion (current_iterator);
                    178:       add_ixpansion (current_iterator, p_start, p_end, e_start, e_end);
                    179:     }
                    180: }
                    181: 
                    182: 
                    183: /* Return a list containing all the free (i.e. not bound by a
                    184:    containing `for' statement) iterators mentioned in EXP, plus those
                    185:    in LIST.  Do not add duplicate entries to the list.  */
                    186: 
                    187: static tree
                    188: collect_iterators (exp, list)
                    189:      tree exp, list;
                    190: {
                    191:   if (exp == 0) return list;
                    192: 
                    193:   switch (TREE_CODE (exp))
                    194:     {
                    195:     case VAR_DECL:
                    196:       if (! ITERATOR_P (exp) || ITERATOR_BOUND_P (exp))
                    197:        return list;
                    198:       if (value_member (exp, list))
                    199:        return list;
                    200:       return tree_cons (NULL_TREE, exp, list);
                    201: 
                    202:     case TREE_LIST:
                    203:       {
                    204:        tree tail;
                    205:        for (tail = exp; tail; tail = TREE_CHAIN (tail))
                    206:          list = collect_iterators (TREE_VALUE (tail), list);
                    207:        return list;
                    208:       }
                    209: 
                    210:     case SAVE_EXPR:
                    211:       /* In each scan, scan a given save_expr only once.  */
                    212:       if (value_member (exp, save_exprs))
                    213:        return list;
                    214: 
                    215:       save_exprs = tree_cons (NULL_TREE, exp, save_exprs);
                    216:       return collect_iterators (TREE_OPERAND (exp, 0), list);
                    217: 
                    218:       /* we do not automatically iterate blocks -- one must */
                    219:       /* use the FOR construct to do that */
                    220: 
                    221:     case BLOCK:
                    222:       return list;
                    223: 
                    224:     default:
                    225:       switch (TREE_CODE_CLASS (TREE_CODE (exp)))
                    226:        {
                    227:        case '1':
                    228:          return collect_iterators (TREE_OPERAND (exp, 0), list);
                    229: 
                    230:        case '2':
                    231:        case '<':
                    232:          return collect_iterators (TREE_OPERAND (exp, 0),
                    233:                                    collect_iterators (TREE_OPERAND (exp, 1),
                    234:                                                       list));
                    235: 
                    236:        case 'e':
                    237:        case 'r':
                    238:          {
                    239:            int num_args = tree_code_length[(int) TREE_CODE (exp)];
                    240:            int i;
                    241: 
                    242:            /* Some tree codes have RTL, not trees, as operands.  */
                    243:            switch (TREE_CODE (exp))
                    244:              {
                    245:              case CALL_EXPR:
                    246:                num_args = 2;
                    247:                break;
                    248:              case METHOD_CALL_EXPR:
                    249:                num_args = 3;
                    250:                break;
                    251:              case WITH_CLEANUP_EXPR:
                    252:                num_args = 1;
                    253:                break;
                    254:              case RTL_EXPR:
                    255:                return list;
                    256:              }
                    257:                
                    258:            for (i = 0; i < num_args; i++)
                    259:              list = collect_iterators (TREE_OPERAND (exp, i), list);
                    260:            return list;
                    261:          }
                    262:        default:
                    263:          return list;
                    264:        }
                    265:     }
                    266: }
                    267: 
                    268: /* Emit rtl for the start of a loop for iterator IDECL.
                    269: 
                    270:    If necessary, create loop counter rtx and store it as DECL_RTL of IDECL.
                    271: 
                    272:    The prologue normally starts and ends with notes, which are returned
                    273:    by this function in *START_NOTE and *END_NODE.
                    274:    If START_NOTE and END_NODE are 0, we don't make those notes.  */
                    275: 
                    276: static void
                    277: iterator_loop_prologue (idecl, start_note, end_note)
                    278:      tree idecl;
                    279:      rtx *start_note, *end_note;
                    280: {
                    281:   tree expr;
                    282: 
                    283:   /* Force the save_expr in DECL_INITIAL to be calculated
                    284:      if it hasn't been calculated yet.  */
                    285:   expand_expr (DECL_INITIAL (idecl), const0_rtx, VOIDmode, 0);
                    286: 
                    287:   if (DECL_RTL (idecl) == 0)
                    288:     expand_decl (idecl);
                    289: 
                    290:   if (start_note)
                    291:     *start_note = emit_note (0, NOTE_INSN_DELETED);
                    292: 
                    293:   /* Initialize counter.  */
                    294:   expr = build (MODIFY_EXPR, TREE_TYPE (idecl), idecl, integer_zero_node);
                    295:   TREE_SIDE_EFFECTS (expr) = 1;
                    296:   expand_expr (expr, const0_rtx, VOIDmode, 0);
                    297: 
                    298:   expand_start_loop_continue_elsewhere (1);
                    299: 
                    300:   ITERATOR_BOUND_P (idecl) = 1;
                    301: 
                    302:   if (end_note)
                    303:     *end_note = emit_note (0, NOTE_INSN_DELETED);
                    304: }
                    305: 
                    306: /* Similar to the previous function, but for the end of the loop.
                    307: 
                    308:    DECL_RTL is zeroed unless we are inside "({...})". The reason for that is
                    309:    described below.
                    310: 
                    311:    When we create two (or more) loops based on the same IDECL, and
                    312:    both inside the same "({...})"  construct, we must be prepared to
                    313:    delete both of the loops and create a single one on the level
                    314:    above, i.e.  enclosing the "({...})". The new loop has to use the
                    315:    same counter rtl because the references to the iterator decl
                    316:    (IDECL) have already been expanded as references to the counter
                    317:    rtl.
                    318: 
                    319:    It is incorrect to use the same counter reg in different functions,
                    320:    and it is desirable to use different counters in disjoint loops
                    321:    when we know there's no need to combine them (because then they can
                    322:    get allocated separately).  */
                    323: 
                    324: static void
                    325: iterator_loop_epilogue (idecl, start_note, end_note)
                    326:      tree idecl;
                    327:      rtx *start_note, *end_note;
                    328: {
                    329:   tree test, incr;
                    330: 
                    331:   if (start_note)
                    332:     *start_note = emit_note (0, NOTE_INSN_DELETED);
                    333:   expand_loop_continue_here ();
                    334:   incr = build_binary_op (PLUS_EXPR, idecl, integer_one_node, 0);
                    335:   incr = build (MODIFY_EXPR, TREE_TYPE (idecl), idecl, incr);
                    336:   TREE_SIDE_EFFECTS (incr) = 1;
                    337:   expand_expr (incr, const0_rtx, VOIDmode, 0);
                    338:   test = build_binary_op (LT_EXPR, idecl, DECL_INITIAL (idecl), 0);
                    339:   expand_exit_loop_if_false (0, test);
                    340:   expand_end_loop ();
                    341: 
                    342:   ITERATOR_BOUND_P (idecl) = 0;
                    343:   /* we can reset rtl since there is not chance that this expansion */
                    344:   /* would be superceded by a higher level one */
                    345:   if (top_level_ixpansion_p ())
                    346:     DECL_RTL (idecl) = 0;
                    347:   if (end_note)
                    348:     *end_note = emit_note (0, NOTE_INSN_DELETED);
                    349: }
                    350: 
                    351: /* Return true if we are not currently inside a "({...})" construct.  */
                    352: 
                    353: static int
                    354: top_level_ixpansion_p ()
                    355: {
                    356:   return iter_stack == 0;
                    357: }
                    358: 
                    359: /* Given two chains of iter_stack_nodes,
                    360:    append the nodes in X into Y.  */
                    361: 
                    362: static void
                    363: isn_append (x, y)
                    364:      struct iter_stack_node *x, *y;
                    365: {
                    366:   if (x->first == 0) 
                    367:     return;
                    368: 
                    369:   if (y->first == 0)
                    370:     {
                    371:       y->first = x->first;
                    372:       y->last  = x->last;
                    373:     }
                    374:   else
                    375:     {
                    376:       y->last->next = x->first;
                    377:       y->last = x->last;
                    378:     }
                    379: }
                    380: 
                    381: /** Make X empty **/
                    382: 
                    383: #define ISN_ZERO(X) (X).first=(X).last=0
                    384: 
                    385: /* Move the ixpansions in sublevel_ixpansions into the current
                    386:    node on the iter_stack, or discard them if the iter_stack is empty.
                    387:    We do this at the end of a statement.  */
                    388: 
                    389: static void
                    390: istack_sublevel_to_current ()
                    391: {
                    392:   /* At the top level we can throw away sublevel's expansions  **/
                    393:   /* because there is nobody above us to ask for a cleanup **/
                    394:   if (iter_stack != 0)
                    395:     /** Merging with empty sublevel list is a no-op **/
                    396:     if (sublevel_ixpansions.last)
                    397:       isn_append (&sublevel_ixpansions, iter_stack);
                    398: 
                    399:   if (iter_stack == 0)
                    400:     obstack_free (&ixp_obstack, ixp_firstobj);
                    401: 
                    402:   ISN_ZERO (sublevel_ixpansions);
                    403: }
                    404: 
                    405: /* Push a new node on the iter_stack, when we enter a ({...}).  */
                    406: 
                    407: void
                    408: push_iterator_stack ()
                    409: {
                    410:   struct iter_stack_node *new_top
                    411:     = (struct iter_stack_node*) 
                    412:       obstack_alloc (&ixp_obstack, sizeof (struct iter_stack_node));
                    413: 
                    414:   new_top->first = 0;
                    415:   new_top->last = 0;
                    416:   new_top->next = iter_stack;
                    417:   iter_stack = new_top;
                    418: }
                    419: 
                    420: /* Pop iter_stack, moving the ixpansions in the node being popped
                    421:    into sublevel_ixpansions.  */
                    422: 
                    423: void
                    424: pop_iterator_stack ()
                    425: {
                    426:   if (iter_stack == 0)
                    427:     abort ();
                    428: 
                    429:   isn_append (iter_stack, &sublevel_ixpansions);
                    430:   /** Pop current level node: */
                    431:   iter_stack = iter_stack->next;
                    432: }
                    433: 
                    434: 
                    435: /* Record an iterator expansion ("ixpansion") for IDECL.
                    436:    The remaining paramters are the notes in the loop entry
                    437:    and exit rtl.  */
                    438: 
                    439: static void
                    440: add_ixpansion (idecl, pro_start, pro_end, epi_start, epi_end)
                    441:      tree idecl;
                    442:      rtx pro_start, pro_end, epi_start, epi_end;
                    443: {
                    444:   struct ixpansion* newix;
                    445:     
                    446:   /* Do nothing if we are not inside "({...})",
                    447:      as in that case this expansion can't need subsequent RTL modification.  */
                    448:   if (iter_stack == 0)
                    449:     return;
                    450: 
                    451:   newix = (struct ixpansion*) obstack_alloc (&ixp_obstack,
                    452:                                             sizeof (struct ixpansion));
                    453:   newix->ixdecl = idecl;
                    454:   newix->ixprologue_start = pro_start;
                    455:   newix->ixprologue_end   = pro_end;
                    456:   newix->ixepilogue_start = epi_start;
                    457:   newix->ixepilogue_end   = epi_end;
                    458: 
                    459:   newix->next = iter_stack->first;
                    460:   iter_stack->first = newix;
                    461:   if (iter_stack->last == 0)
                    462:     iter_stack->last = newix;
                    463: }
                    464: 
                    465: /* Delete the RTL for all ixpansions for iterator IDECL
                    466:    in our sublevels.  We do this when we make a larger
                    467:    containing expansion for IDECL.  */
                    468: 
                    469: static void
                    470: delete_ixpansion (idecl)
                    471:      tree idecl;
                    472: {
                    473:   struct ixpansion* previx = 0, *ix;
                    474: 
                    475:   for (ix = sublevel_ixpansions.first; ix; ix = ix->next)
                    476:     if (ix->ixdecl == idecl)
                    477:       {
                    478:        /** zero means that this is a mark for FOR -- **/
                    479:        /** we do not delete anything, just issue an error. **/
                    480: 
                    481:        if (ix->ixprologue_start == 0)
                    482:          error_with_decl (idecl,
                    483:                           "`for (%s)' appears within implicit iteration");
                    484:        else
                    485:          {
                    486:            rtx insn;
                    487:            /* We delete all insns, including notes because leaving loop */
                    488:            /* notes and barriers produced by iterator expansion would */
                    489:            /* be misleading to other phases */
                    490: 
                    491:            for (insn = NEXT_INSN (ix->ixprologue_start);
                    492:                 insn != ix->ixprologue_end;
                    493:                 insn = NEXT_INSN (insn)) 
                    494:              delete_insn (insn);
                    495:            for (insn = NEXT_INSN (ix->ixepilogue_start);
                    496:                 insn != ix->ixepilogue_end;
                    497:                 insn = NEXT_INSN (insn)) 
                    498:              delete_insn (insn);
                    499:          }
                    500: 
                    501:        /* Delete this ixpansion from sublevel_ixpansions.  */
                    502:        if (previx)
                    503:          previx->next = ix->next;
                    504:        else 
                    505:          sublevel_ixpansions.first = ix->next;
                    506:        if (sublevel_ixpansions.last == ix)
                    507:          sublevel_ixpansions.last = previx;
                    508:       }
                    509:     else
                    510:       previx = ix;
                    511: }
                    512: 
                    513: #ifdef DEBUG_ITERATORS
                    514: 
                    515: /* The functions below are for use from source level debugger.
                    516:    They print short forms of iterator lists and the iterator stack.  */
                    517: 
                    518: /* Print the name of the iterator D.  */
                    519: 
                    520: void
                    521: prdecl (d)
                    522:      tree d;
                    523: {
                    524:   if (d)
                    525:     {
                    526:       if (TREE_CODE (d) == VAR_DECL)
                    527:        {
                    528:          tree tname = DECL_NAME (d);
                    529:          char *dname = IDENTIFIER_POINTER (tname);
                    530:          fprintf (stderr, dname);
                    531:        }
                    532:       else
                    533:        fprintf (stderr, "<<Not a Decl!!!>>");
                    534:     }
                    535:   else
                    536:     fprintf (stderr, "<<NULL!!>>");
                    537: }
                    538: 
                    539: /* Print Iterator List -- names only */
                    540: 
                    541: tree
                    542: pil (head)
                    543:      tree head;
                    544: {
                    545:   tree current, next;
                    546:   for (current = head; current; current = next)
                    547:     {
                    548:       tree node = TREE_VALUE (current);
                    549:       prdecl (node);
                    550:       next = TREE_CHAIN (current);
                    551:       if (next) fprintf (stderr, ",");
                    552:     }
                    553:   fprintf (stderr, "\n");
                    554: }
                    555: 
                    556: /* Print IXpansion List */
                    557: 
                    558: struct ixpansion *
                    559: pixl (head)
                    560:      struct ixpansion *head;
                    561: {
                    562:   struct ixpansion *current, *next;
                    563:   fprintf (stderr, "> ");
                    564:   if (head == 0)
                    565:     fprintf (stderr, "(empty)");
                    566:        
                    567:   for (current=head; current; current = next)
                    568:     {
                    569:       tree node = current->ixdecl;
                    570:       prdecl (node);
                    571:       next = current->next;
                    572:       if (next)
                    573:        fprintf (stderr, ",");
                    574:     }
                    575:   fprintf (stderr, "\n");
                    576:   return head;
                    577: }
                    578: 
                    579: /* Print Iterator Stack*/
                    580: 
                    581: void
                    582: pis ()
                    583: {
                    584:   struct iter_stack_node *stack_node;
                    585: 
                    586:   fprintf (stderr, "--SubLevel: ");
                    587:   pixl (sublevel_ixpansions.first);
                    588:   fprintf (stderr, "--Stack:--\n");
                    589:   for (stack_node = iter_stack;
                    590:        stack_node;
                    591:        stack_node = stack_node->next)
                    592:     pixl (stack_node->first);
                    593: }
                    594: 
                    595: #endif /* DEBUG_ITERATORS */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.