Annotation of gcc/rtl.c, revision 1.1.1.1

1.1       root        1: /* Allocate and read RTL for GNU C Compiler.
                      2:    Copyright (C) 1987, 1988, 1991 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: #include "config.h"
                     22: #include <ctype.h>
                     23: #include <stdio.h>
                     24: #include "rtl.h"
                     25: 
                     26: #include "obstack.h"
                     27: #define        obstack_chunk_alloc     xmalloc
                     28: #define        obstack_chunk_free      free
                     29: extern int xmalloc ();
                     30: extern void free ();
                     31: 
                     32: /* Obstack used for allocating RTL objects.
                     33:    Between functions, this is the permanent_obstack.
                     34:    While parsing and expanding a function, this is maybepermanent_obstack
                     35:    so we can save it if it is an inline function.
                     36:    During optimization and output, this is function_obstack.  */
                     37: 
                     38: extern struct obstack *rtl_obstack;
                     39: 
                     40: extern long ftell();
                     41: 
                     42: /* Indexed by rtx code, gives number of operands for an rtx with that code.
                     43:    Does NOT include rtx header data (code and links).
                     44:    This array is initialized in init_rtl.  */
                     45: 
                     46: int rtx_length[NUM_RTX_CODE + 1];
                     47: 
                     48: /* Indexed by rtx code, gives the name of that kind of rtx, as a C string.  */
                     49: 
                     50: #define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS)   NAME ,
                     51: 
                     52: char *rtx_name[] = {
                     53: #include "rtl.def"             /* rtl expressions are documented here */
                     54: };
                     55: 
                     56: #undef DEF_RTL_EXPR
                     57: 
                     58: /* Indexed by machine mode, gives the name of that machine mode.
                     59:    This name does not include the letters "mode".  */
                     60: 
                     61: #define DEF_MACHMODE(SYM, NAME, CLASS, SIZE, UNIT, WIDER)  NAME,
                     62: 
                     63: char *mode_name[(int) MAX_MACHINE_MODE] = {
                     64: #include "machmode.def"
                     65: 
                     66: #ifdef EXTRA_CC_MODES
                     67:   EXTRA_CC_NAMES
                     68: #endif
                     69: 
                     70: };
                     71: 
                     72: #undef DEF_MACHMODE
                     73: 
                     74: /* Indexed by machine mode, gives the length of the mode, in bytes.
                     75:    GET_MODE_CLASS uses this.  */
                     76: 
                     77: #define DEF_MACHMODE(SYM, NAME, CLASS, SIZE, UNIT, WIDER)  CLASS,
                     78: 
                     79: enum mode_class mode_class[(int) MAX_MACHINE_MODE] = {
                     80: #include "machmode.def"
                     81: };
                     82: 
                     83: #undef DEF_MACHMODE
                     84: 
                     85: /* Indexed by machine mode, gives the length of the mode, in bytes.
                     86:    GET_MODE_SIZE uses this.  */
                     87: 
                     88: #define DEF_MACHMODE(SYM, NAME, CLASS, SIZE, UNIT, WIDER)  SIZE,
                     89: 
                     90: int mode_size[(int) MAX_MACHINE_MODE] = {
                     91: #include "machmode.def"
                     92: };
                     93: 
                     94: #undef DEF_MACHMODE
                     95: 
                     96: /* Indexed by machine mode, gives the length of the mode's subunit.
                     97:    GET_MODE_UNIT_SIZE uses this.  */
                     98: 
                     99: #define DEF_MACHMODE(SYM, NAME, CLASS, SIZE, UNIT, WIDER)  UNIT,
                    100: 
                    101: int mode_unit_size[(int) MAX_MACHINE_MODE] = {
                    102: #include "machmode.def"                /* machine modes are documented here */
                    103: };
                    104: 
                    105: #undef DEF_MACHMODE
                    106: 
                    107: /* Indexed by machine mode, gives next wider natural mode
                    108:    (QI -> HI -> SI -> DI, etc.)  Widening multiply instructions
                    109:    use this.  */
                    110: 
                    111: #define DEF_MACHMODE(SYM, NAME, CLASS, SIZE, UNIT, WIDER)  \
                    112:   (enum machine_mode) WIDER,
                    113: 
                    114: enum machine_mode mode_wider_mode[(int) MAX_MACHINE_MODE] = {
                    115: #include "machmode.def"                /* machine modes are documented here */
                    116: };
                    117: 
                    118: #undef DEF_MACHMODE
                    119: 
                    120: /* Indexed by mode class, gives the narrowest mode for each class.  */
                    121: 
                    122: enum machine_mode class_narrowest_mode[(int) MAX_MODE_CLASS];
                    123: 
                    124: /* Commonly used modes.  */
                    125: 
                    126: enum machine_mode byte_mode;   /* Mode whose width is BITS_PER_UNIT */
                    127: enum machine_mode word_mode;   /* Mode whose width is BITS_PER_WORD */
                    128: 
                    129: /* Indexed by rtx code, gives a sequence of operand-types for
                    130:    rtx's of that code.  The sequence is a C string in which
                    131:    each charcter describes one operand.  */
                    132: 
                    133: char *rtx_format[] = {
                    134:   /* "*" undefined.
                    135:          can cause a warning message
                    136:      "0" field is unused (or used in a phase-dependent manner)
                    137:          prints nothing
                    138:      "i" an integer
                    139:          prints the integer
                    140:      "n" like "i", but prints entries from `note_insn_name'
                    141:      "s" a pointer to a string
                    142:          prints the string
                    143:      "S" like "s", but optional:
                    144:         the containing rtx may end before this operand
                    145:      "e" a pointer to an rtl expression
                    146:          prints the expression
                    147:      "E" a pointer to a vector that points to a number of rtl expressions
                    148:          prints a list of the rtl expressions
                    149:      "V" like "E", but optional:
                    150:         the containing rtx may end before this operand
                    151:      "u" a pointer to another insn
                    152:          prints the uid of the insn.  */
                    153: 
                    154: #define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS)   FORMAT ,
                    155: #include "rtl.def"             /* rtl expressions are defined here */
                    156: #undef DEF_RTL_EXPR
                    157: };
                    158: 
                    159: /* Indexed by rtx code, gives a character representing the "class" of
                    160:    that rtx code.  See rtl.def for documentation on the defined classes.  */
                    161: 
                    162: char rtx_class[] = {
                    163: #define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS)   CLASS, 
                    164: #include "rtl.def"             /* rtl expressions are defined here */
                    165: #undef DEF_RTL_EXPR
                    166: };
                    167: 
                    168: /* Names for kinds of NOTEs and REG_NOTEs.  */
                    169: 
                    170: char *note_insn_name[] = { "NOTE_INSN_FUNCTION_BEG", "NOTE_INSN_DELETED",
                    171:                           "NOTE_INSN_BLOCK_BEG", "NOTE_INSN_BLOCK_END",
                    172:                           "NOTE_INSN_LOOP_BEG", "NOTE_INSN_LOOP_END",
                    173:                           "NOTE_INSN_FUNCTION_END", "NOTE_INSN_SETJMP",
                    174:                           "NOTE_INSN_LOOP_CONT", "NOTE_INSN_LOOP_VTOP" };
                    175: 
                    176: char *reg_note_name[] = { "", "REG_DEAD", "REG_INC", "REG_EQUIV", "REG_WAS_0",
                    177:                          "REG_EQUAL", "REG_RETVAL", "REG_LIBCALL",
                    178:                          "REG_NONNEG", "REG_NO_CONFLICT", "REG_UNUSED",
                    179:                          "REG_CC_SETTER", "REG_CC_USER", "REG_LABEL",
                    180:                          "REG_DEP_ANTI", "REG_DEP_OUTPUT" };
                    181: 
                    182: /* Allocate an rtx vector of N elements.
                    183:    Store the length, and initialize all elements to zero.  */
                    184: 
                    185: rtvec
                    186: rtvec_alloc (n)
                    187:      int n;
                    188: {
                    189:   rtvec rt;
                    190:   int i;
                    191: 
                    192:   rt = (rtvec) obstack_alloc (rtl_obstack,
                    193:                              sizeof (struct rtvec_def)
                    194:                              + (( n - 1) * sizeof (rtunion)));
                    195: 
                    196:   /* clear out the vector */
                    197:   PUT_NUM_ELEM(rt, n);
                    198:   for (i=0; i < n; i++)
                    199:     rt->elem[i].rtvec = NULL;  /* @@ not portable due to rtunion */
                    200: 
                    201:   return rt;
                    202: }
                    203: 
                    204: /* Allocate an rtx of code CODE.  The CODE is stored in the rtx;
                    205:    all the rest is initialized to zero.  */
                    206: 
                    207: rtx
                    208: rtx_alloc (code)
                    209:   RTX_CODE code;
                    210: {
                    211:   rtx rt;
                    212:   register struct obstack *ob = rtl_obstack;
                    213:   register int nelts = GET_RTX_LENGTH (code);
                    214:   register int length = sizeof (struct rtx_def)
                    215:     + (nelts - 1) * sizeof (rtunion);
                    216: 
                    217:   /* This function is called more than any other in GCC,
                    218:      so we manipulate the obstack directly.
                    219: 
                    220:      Even though rtx objects are word aligned, we may be sharing an obstack
                    221:      with tree nodes, which may have to be double-word aligned.  So align
                    222:      our length to the alignment mask in the obstack.  */
                    223: 
                    224:   length = (length + ob->alignment_mask) & ~ ob->alignment_mask;
                    225: 
                    226:   if (ob->chunk_limit - ob->next_free < length)
                    227:     _obstack_newchunk (ob, length);
                    228:   rt = (rtx)ob->object_base;
                    229:   ob->next_free += length;
                    230:   ob->object_base = ob->next_free;
                    231: 
                    232:   * (int *) rt = 0;
                    233:   PUT_CODE (rt, code);
                    234: 
                    235:   return rt;
                    236: }
                    237: 
                    238: /* Create a new copy of an rtx.
                    239:    Recursively copies the operands of the rtx,
                    240:    except for those few rtx codes that are sharable.  */
                    241: 
                    242: rtx
                    243: copy_rtx (orig)
                    244:      register rtx orig;
                    245: {
                    246:   register rtx copy;
                    247:   register int i, j;
                    248:   register RTX_CODE code;
                    249:   register char *format_ptr;
                    250: 
                    251:   code = GET_CODE (orig);
                    252: 
                    253:   switch (code)
                    254:     {
                    255:     case REG:
                    256:     case QUEUED:
                    257:     case CONST_INT:
                    258:     case CONST_DOUBLE:
                    259:     case SYMBOL_REF:
                    260:     case CODE_LABEL:
                    261:     case PC:
                    262:     case CC0:
                    263:       return orig;
                    264:     }
                    265: 
                    266:   copy = rtx_alloc (code);
                    267:   PUT_MODE (copy, GET_MODE (orig));
                    268:   copy->in_struct = orig->in_struct;
                    269:   copy->volatil = orig->volatil;
                    270:   copy->unchanging = orig->unchanging;
                    271:   copy->integrated = orig->integrated;
                    272:   
                    273:   format_ptr = GET_RTX_FORMAT (GET_CODE (copy));
                    274: 
                    275:   for (i = 0; i < GET_RTX_LENGTH (GET_CODE (copy)); i++)
                    276:     {
                    277:       switch (*format_ptr++)
                    278:        {
                    279:        case 'e':
                    280:          XEXP (copy, i) = XEXP (orig, i);
                    281:          if (XEXP (orig, i) != NULL)
                    282:            XEXP (copy, i) = copy_rtx (XEXP (orig, i));
                    283:          break;
                    284: 
                    285:        case 'E':
                    286:        case 'V':
                    287:          XVEC (copy, i) = XVEC (orig, i);
                    288:          if (XVEC (orig, i) != NULL)
                    289:            {
                    290:              XVEC (copy, i) = rtvec_alloc (XVECLEN (orig, i));
                    291:              for (j = 0; j < XVECLEN (copy, i); j++)
                    292:                XVECEXP (copy, i, j) = copy_rtx (XVECEXP (orig, i, j));
                    293:            }
                    294:          break;
                    295: 
                    296:        default:
                    297:          XINT (copy, i) = XINT (orig, i);
                    298:          break;
                    299:        }
                    300:     }
                    301:   return copy;
                    302: }
                    303: 
                    304: /* Similar to `copy_rtx' except that if MAY_SHARE is present, it is
                    305:    placed in the result directly, rather than being copied.  */
                    306: 
                    307: rtx
                    308: copy_most_rtx (orig, may_share)
                    309:      register rtx orig;
                    310:      register rtx may_share;
                    311: {
                    312:   register rtx copy;
                    313:   register int i, j;
                    314:   register RTX_CODE code;
                    315:   register char *format_ptr;
                    316: 
                    317:   if (orig == may_share)
                    318:     return orig;
                    319: 
                    320:   code = GET_CODE (orig);
                    321: 
                    322:   switch (code)
                    323:     {
                    324:     case REG:
                    325:     case QUEUED:
                    326:     case CONST_INT:
                    327:     case CONST_DOUBLE:
                    328:     case SYMBOL_REF:
                    329:     case CODE_LABEL:
                    330:     case PC:
                    331:     case CC0:
                    332:       return orig;
                    333:     }
                    334: 
                    335:   copy = rtx_alloc (code);
                    336:   PUT_MODE (copy, GET_MODE (orig));
                    337:   copy->in_struct = orig->in_struct;
                    338:   copy->volatil = orig->volatil;
                    339:   copy->unchanging = orig->unchanging;
                    340:   copy->integrated = orig->integrated;
                    341:   
                    342:   format_ptr = GET_RTX_FORMAT (GET_CODE (copy));
                    343: 
                    344:   for (i = 0; i < GET_RTX_LENGTH (GET_CODE (copy)); i++)
                    345:     {
                    346:       switch (*format_ptr++)
                    347:        {
                    348:        case 'e':
                    349:          XEXP (copy, i) = XEXP (orig, i);
                    350:          if (XEXP (orig, i) != NULL && XEXP (orig, i) != may_share)
                    351:            XEXP (copy, i) = copy_most_rtx (XEXP (orig, i), may_share);
                    352:          break;
                    353: 
                    354:        case 'E':
                    355:        case 'V':
                    356:          XVEC (copy, i) = XVEC (orig, i);
                    357:          if (XVEC (orig, i) != NULL)
                    358:            {
                    359:              XVEC (copy, i) = rtvec_alloc (XVECLEN (orig, i));
                    360:              for (j = 0; j < XVECLEN (copy, i); j++)
                    361:                XVECEXP (copy, i, j)
                    362:                  = copy_most_rtx (XVECEXP (orig, i, j), may_share);
                    363:            }
                    364:          break;
                    365: 
                    366:        default:
                    367:          XINT (copy, i) = XINT (orig, i);
                    368:          break;
                    369:        }
                    370:     }
                    371:   return copy;
                    372: }
                    373: 
                    374: /* Helper functions for instruction scheduling.  */
                    375: 
                    376: /* Add ELEM wrapped in an INSN_LIST with reg note kind DEP_TYPE to the
                    377:    LOG_LINKS of INSN, if not already there.  DEP_TYPE indicates the type
                    378:    of dependence that this link represents.  */
                    379: 
                    380: void
                    381: add_dependence (insn, elem, dep_type)
                    382:      rtx insn;
                    383:      rtx elem;
                    384:      enum reg_note dep_type;
                    385: {
                    386:   rtx link;
                    387: 
                    388:   /* Don't depend an insn on itself.  */
                    389:   if (insn == elem)
                    390:     return;
                    391: 
                    392:   /* If elem is part of a sequence that must be scheduled together, then
                    393:      make the dependence point to the last insn of the sequence.  */
                    394:   if (NEXT_INSN (elem) && SCHED_GROUP_P (NEXT_INSN (elem)))
                    395:     {
                    396:       while (NEXT_INSN (elem) && SCHED_GROUP_P (NEXT_INSN (elem)))
                    397:        elem = NEXT_INSN (elem);
                    398:       /* Again, don't depend an insn of itself.  */
                    399:       if (insn == elem)
                    400:        return;
                    401:     }
                    402: 
                    403:   /* Check that we don't already have this dependence.  */
                    404:   for (link = LOG_LINKS (insn); link; link = XEXP (link, 1))
                    405:     if (XEXP (link, 0) == elem)
                    406:       {
                    407:        /* If this is a more restrictive type of dependence than the existing
                    408:           one, then change the existing dependence to this type.  */
                    409:        if ((int) dep_type < (int) REG_NOTE_KIND (link))
                    410:          PUT_REG_NOTE_KIND (link, dep_type);
                    411:        return;
                    412:       }
                    413:   /* Might want to check one level of transitivity to save conses.  */
                    414: 
                    415:   link = rtx_alloc (INSN_LIST);
                    416:   /* Insn dependency, not data dependency.  */
                    417:   PUT_REG_NOTE_KIND (link, dep_type);
                    418:   XEXP (link, 0) = elem;
                    419:   XEXP (link, 1) = LOG_LINKS (insn);
                    420:   LOG_LINKS (insn) = link;
                    421: }
                    422: 
                    423: /* Remove ELEM wrapped in an INSN_LIST from the LOG_LINKS
                    424:    of INSN.  Abort if not found.  */
                    425: void
                    426: remove_dependence (insn, elem)
                    427:      rtx insn;
                    428:      rtx elem;
                    429: {
                    430:   rtx prev, link;
                    431:   int found = 0;
                    432: 
                    433:   for (prev = 0, link = LOG_LINKS (insn); link;
                    434:        prev = link, link = XEXP (link, 1))
                    435:     {
                    436:       if (XEXP (link, 0) == elem)
                    437:        {
                    438:          if (prev)
                    439:            XEXP (prev, 1) = XEXP (link, 1);
                    440:          else
                    441:            LOG_LINKS (insn) = XEXP (link, 1);
                    442:          found = 1;
                    443:        }
                    444:     }
                    445: 
                    446:   if (! found)
                    447:     abort ();
                    448:   return;
                    449: }
                    450: 
                    451: /* Subroutines of read_rtx.  */
                    452: 
                    453: /* Dump code after printing a message.  Used when read_rtx finds
                    454:    invalid data.  */
                    455: 
                    456: static void
                    457: dump_and_abort (expected_c, actual_c, infile)
                    458:      int expected_c, actual_c;
                    459:      FILE *infile;
                    460: {
                    461:   int c, i;
                    462: 
                    463:   if (expected_c >= 0)
                    464:     fprintf (stderr,
                    465:             "Expected character %c.  Found character %c.",
                    466:             expected_c, actual_c);
                    467:   fprintf (stderr, "  At file position: %ld\n", ftell (infile));
                    468:   fprintf (stderr, "Following characters are:\n\t");
                    469:   for (i = 0; i < 200; i++)
                    470:     {
                    471:       c = getc (infile);
                    472:       if (EOF == c) break;
                    473:       putc (c, stderr);
                    474:     }
                    475:   fprintf (stderr, "Aborting.\n");
                    476:   abort ();
                    477: }
                    478: 
                    479: /* Read chars from INFILE until a non-whitespace char
                    480:    and return that.  Comments, both Lisp style and C style,
                    481:    are treated as whitespace.
                    482:    Tools such as genflags use this function.  */
                    483: 
                    484: int
                    485: read_skip_spaces (infile)
                    486:      FILE *infile;
                    487: {
                    488:   register int c;
                    489:   while (c = getc (infile))
                    490:     {
                    491:       if (c == ' ' || c == '\n' || c == '\t' || c == '\f')
                    492:        ;
                    493:       else if (c == ';')
                    494:        {
                    495:          while ((c = getc (infile)) && c != '\n') ;
                    496:        }
                    497:       else if (c == '/')
                    498:        {
                    499:          register int prevc;
                    500:          c = getc (infile);
                    501:          if (c != '*')
                    502:            dump_and_abort ('*', c, infile);
                    503:          
                    504:          prevc = 0;
                    505:          while (c = getc (infile))
                    506:            {
                    507:              if (prevc == '*' && c == '/')
                    508:                break;
                    509:              prevc = c;
                    510:            }
                    511:        }
                    512:       else break;
                    513:     }
                    514:   return c;
                    515: }
                    516: 
                    517: /* Read an rtx code name into the buffer STR[].
                    518:    It is terminated by any of the punctuation chars of rtx printed syntax.  */
                    519: 
                    520: static void
                    521: read_name (str, infile)
                    522:      char *str;
                    523:      FILE *infile;
                    524: {
                    525:   register char *p;
                    526:   register int c;
                    527: 
                    528:   c = read_skip_spaces(infile);
                    529: 
                    530:   p = str;
                    531:   while (1)
                    532:     {
                    533:       if (c == ' ' || c == '\n' || c == '\t' || c == '\f')
                    534:        break;
                    535:       if (c == ':' || c == ')' || c == ']' || c == '"' || c == '/'
                    536:          || c == '(' || c == '[')
                    537:        {
                    538:          ungetc (c, infile);
                    539:          break;
                    540:        }
                    541:       *p++ = c;
                    542:       c = getc (infile);
                    543:     }
                    544:   if (p == str)
                    545:     {
                    546:       fprintf (stderr, "missing name or number");
                    547:       dump_and_abort (-1, -1, infile);
                    548:     }
                    549: 
                    550:   *p = 0;
                    551: }
                    552: 
                    553: /* Read an rtx in printed representation from INFILE
                    554:    and return an actual rtx in core constructed accordingly.
                    555:    read_rtx is not used in the compiler proper, but rather in
                    556:    the utilities gen*.c that construct C code from machine descriptions.  */
                    557: 
                    558: rtx
                    559: read_rtx (infile)
                    560:      FILE *infile;
                    561: {
                    562:   register int i, j, list_counter;
                    563:   RTX_CODE tmp_code;
                    564:   register char *format_ptr;
                    565:   /* tmp_char is a buffer used for reading decimal integers
                    566:      and names of rtx types and machine modes.
                    567:      Therefore, 256 must be enough.  */
                    568:   char tmp_char[256];
                    569:   rtx return_rtx;
                    570:   register int c;
                    571:   int tmp_int;
                    572: 
                    573:   /* Linked list structure for making RTXs: */
                    574:   struct rtx_list
                    575:     {
                    576:       struct rtx_list *next;
                    577:       rtx value;               /* Value of this node...                */
                    578:     };
                    579: 
                    580:   c = read_skip_spaces (infile); /* Should be open paren.  */
                    581:   if (c != '(')
                    582:     dump_and_abort ('(', c, infile);
                    583: 
                    584:   read_name (tmp_char, infile);
                    585: 
                    586:   tmp_code = UNKNOWN;
                    587: 
                    588:   for (i=0; i < NUM_RTX_CODE; i++) /* @@ might speed this search up */
                    589:     {
                    590:       if (!(strcmp (tmp_char, GET_RTX_NAME (i))))
                    591:        {
                    592:          tmp_code = (RTX_CODE) i;      /* get value for name */
                    593:          break;
                    594:        }
                    595:     }
                    596:   if (tmp_code == UNKNOWN)
                    597:     {
                    598:       fprintf (stderr,
                    599:               "Unknown rtx read in rtl.read_rtx(). Code name was %s .",
                    600:               tmp_char);
                    601:     }
                    602:   /* (NIL) stands for an expression that isn't there.  */
                    603:   if (tmp_code == NIL)
                    604:     {
                    605:       /* Discard the closeparen.  */
                    606:       while ((c = getc (infile)) && c != ')');
                    607:       return 0;
                    608:     }
                    609: 
                    610:   return_rtx = rtx_alloc (tmp_code); /* if we end up with an insn expression
                    611:                                       then we free this space below.  */
                    612:   format_ptr = GET_RTX_FORMAT (GET_CODE (return_rtx));
                    613: 
                    614:   /* If what follows is `: mode ', read it and
                    615:      store the mode in the rtx.  */
                    616: 
                    617:   i = read_skip_spaces (infile);
                    618:   if (i == ':')
                    619:     {
                    620:       register int k;
                    621:       read_name (tmp_char, infile);
                    622:       for (k = 0; k < NUM_MACHINE_MODES; k++)
                    623:        if (!strcmp (GET_MODE_NAME (k), tmp_char))
                    624:          break;
                    625: 
                    626:       PUT_MODE (return_rtx, (enum machine_mode) k );
                    627:     }
                    628:   else
                    629:     ungetc (i, infile);
                    630: 
                    631:   for (i = 0; i < GET_RTX_LENGTH (GET_CODE (return_rtx)); i++)
                    632:     switch (*format_ptr++)
                    633:       {
                    634:        /* 0 means a field for internal use only.
                    635:           Don't expect it to be present in the input.  */
                    636:       case '0':
                    637:        break;
                    638: 
                    639:       case 'e':
                    640:       case 'u':
                    641:        XEXP (return_rtx, i) = read_rtx (infile);
                    642:        break;
                    643: 
                    644:       case 'V':
                    645:        /* 'V' is an optional vector: if a closeparen follows,
                    646:           just store NULL for this element.  */
                    647:        c = read_skip_spaces (infile);
                    648:        ungetc (c, infile);
                    649:        if (c == ')')
                    650:          {
                    651:            XVEC (return_rtx, i) = 0;
                    652:            break;
                    653:          }
                    654:        /* Now process the vector.  */
                    655:   
                    656:       case 'E':
                    657:        {
                    658:          register struct rtx_list *next_rtx, *rtx_list_link;
                    659:          struct rtx_list *list_rtx;
                    660: 
                    661:          c = read_skip_spaces (infile);
                    662:          if (c != '[')
                    663:            dump_and_abort ('[', c, infile);
                    664: 
                    665:          /* add expressions to a list, while keeping a count */
                    666:          next_rtx = NULL;
                    667:          list_counter = 0;
                    668:          while ((c = read_skip_spaces (infile)) && c != ']')
                    669:            {
                    670:              ungetc (c, infile);
                    671:              list_counter++;
                    672:              rtx_list_link = (struct rtx_list *)
                    673:                alloca (sizeof (struct rtx_list));
                    674:              rtx_list_link->value = read_rtx (infile);
                    675:              if (next_rtx == 0)
                    676:                list_rtx = rtx_list_link;
                    677:              else
                    678:                next_rtx->next = rtx_list_link;
                    679:              next_rtx = rtx_list_link;
                    680:              rtx_list_link->next = 0;
                    681:            }
                    682:          /* get vector length and allocate it */
                    683:          XVEC (return_rtx, i) = (list_counter
                    684:                                  ? rtvec_alloc (list_counter)
                    685:                                  : (struct rtvec_def *) NULL);
                    686:          if (list_counter > 0)
                    687:            {
                    688:              next_rtx = list_rtx;
                    689:              for (j = 0; j < list_counter; j++,
                    690:                   next_rtx = next_rtx->next)
                    691:                XVECEXP (return_rtx, i, j) = next_rtx->value;
                    692:            }
                    693:          /* close bracket gotten */
                    694:        }
                    695:        break;
                    696: 
                    697:       case 'S':
                    698:        /* 'S' is an optional string: if a closeparen follows,
                    699:           just store NULL for this element.  */
                    700:        c = read_skip_spaces (infile);
                    701:        ungetc (c, infile);
                    702:        if (c == ')')
                    703:          {
                    704:            XSTR (return_rtx, i) = 0;
                    705:            break;
                    706:          }
                    707: 
                    708:       case 's':
                    709:        {
                    710:          int saw_paren = 0;
                    711:          register char *stringbuf;
                    712:          int stringbufsize;
                    713: 
                    714:          c = read_skip_spaces (infile);
                    715:          if (c == '(')
                    716:            {
                    717:              saw_paren = 1;
                    718:              c = read_skip_spaces (infile);
                    719:            }
                    720:          if (c != '"')
                    721:            dump_and_abort ('"', c, infile);
                    722:          j = 0;
                    723:          stringbufsize = 10;
                    724:          stringbuf = (char *) xmalloc (stringbufsize + 1);
                    725: 
                    726:          while (1)
                    727:            {
                    728:              if (j >= stringbufsize - 4)
                    729:                {
                    730:                  stringbufsize *= 2;
                    731:                  stringbuf = (char *) xrealloc (stringbuf, stringbufsize + 1);
                    732:                }
                    733:              stringbuf[j] = getc (infile); /* Read the string  */
                    734:              if (stringbuf[j] == '\\')
                    735:                {
                    736:                  stringbuf[j] = getc (infile); /* Read the string  */
                    737:                  /* \; makes stuff for a C string constant containing
                    738:                     newline and tab.  */
                    739:                  if (stringbuf[j] == ';')
                    740:                    {
                    741:                      strcpy (&stringbuf[j], "\\n\\t");
                    742:                      j += 3;
                    743:                    }
                    744:                }
                    745:              else if (stringbuf[j] == '"')
                    746:                break;
                    747:              j++;
                    748:            }
                    749: 
                    750:          stringbuf[j] = 0;     /* NUL terminate the string  */
                    751:          stringbuf = (char *) xrealloc (stringbuf, j + 1);
                    752: 
                    753:          if (saw_paren)
                    754:            {
                    755:              c = read_skip_spaces (infile);
                    756:              if (c != ')')
                    757:                dump_and_abort (')', c, infile);
                    758:            }
                    759:          XSTR (return_rtx, i) = stringbuf;
                    760:        }
                    761:        break;
                    762: 
                    763:       case 'i':
                    764:       case 'n':
                    765:        read_name (tmp_char, infile);
                    766:        tmp_int = atoi (tmp_char);
                    767:        XINT (return_rtx, i) = tmp_int;
                    768:        break;
                    769: 
                    770:       default:
                    771:        fprintf (stderr,
                    772:                 "switch format wrong in rtl.read_rtx(). format was: %c.\n",
                    773:                 format_ptr[-1]);
                    774:        fprintf (stderr, "\tfile position: %ld\n", ftell (infile));
                    775:        abort ();
                    776:       }
                    777: 
                    778:   c = read_skip_spaces (infile);
                    779:   if (c != ')')
                    780:     dump_and_abort (')', c, infile);
                    781: 
                    782:   return return_rtx;
                    783: }
                    784: 
                    785: /* This is called once per compilation, before any rtx's are constructed.
                    786:    It initializes the vector `rtx_length', the extra CC modes, if any,
                    787:    and computes certain commonly-used modes.  */
                    788: 
                    789: void
                    790: init_rtl ()
                    791: {
                    792:   int min_class_size[(int) MAX_MODE_CLASS];
                    793:   enum machine_mode mode;
                    794:   int i;
                    795: 
                    796:   for (i = 0; i < NUM_RTX_CODE; i++)
                    797:     rtx_length[i] = strlen (rtx_format[i]);
                    798: 
                    799:   /* Make CONST_DOUBLE bigger, if real values are bigger than
                    800:      it normally expects to have room for.
                    801:      Note that REAL_VALUE_TYPE is not defined by default,
                    802:      since tree.h is not included.  But the default dfn as `double'
                    803:      would do no harm.  */
                    804: #ifdef REAL_VALUE_TYPE
                    805:   i = sizeof (REAL_VALUE_TYPE) / sizeof (rtunion) + 2;
                    806:   if (rtx_length[(int) CONST_DOUBLE] < i)
                    807:     {
                    808:       char *s = (char *) xmalloc (i + 1);
                    809:       rtx_length[(int) CONST_DOUBLE] = i;
                    810:       rtx_format[(int) CONST_DOUBLE] = s;
                    811:       *s++ = 'e';
                    812:       *s++ = '0';
                    813:       /* Set the GET_RTX_FORMAT of CONST_DOUBLE to a string
                    814:         of as many `i's as we now have elements.  */
                    815:       for (i = 0; i < rtx_length[(int) CONST_DOUBLE]; i++)
                    816:        *s++ = 'i';
                    817:       *s++ = 0;
                    818:     }
                    819: #endif
                    820: 
                    821: #ifdef EXTRA_CC_MODES
                    822:   for (i = (int) CCmode + 1; i < (int) MAX_MACHINE_MODE; i++)
                    823:     {
                    824:       mode_class[i] = MODE_CC;
                    825:       mode_size[i] = mode_size[(int) CCmode];
                    826:       mode_unit_size[i] = mode_unit_size[(int) CCmode];
                    827:       mode_wider_mode[i - 1] = (enum machine_mode) i;
                    828:       mode_wider_mode[i] = VOIDmode;
                    829:     }
                    830: #endif
                    831: 
                    832:   /* Find the narrowest mode for each class and compute the word and byte
                    833:      modes.  */
                    834: 
                    835:   for (i = 0; i < (int) MAX_MODE_CLASS; i++)
                    836:     min_class_size[i] = 1000;
                    837: 
                    838:   for (mode = VOIDmode; (int) mode < (int) MAX_MACHINE_MODE;
                    839:        mode = (enum machine_mode) ((int) mode + 1))
                    840:     {
                    841:       if (GET_MODE_SIZE (mode) < min_class_size[(int) GET_MODE_CLASS (mode)])
                    842:        {
                    843:          class_narrowest_mode[(int) GET_MODE_CLASS (mode)] = mode;
                    844:          min_class_size[(int) GET_MODE_CLASS (mode)] = GET_MODE_SIZE (mode);
                    845:        }
                    846:       if (GET_MODE_CLASS (mode) == MODE_INT
                    847:          && GET_MODE_BITSIZE (mode) == BITS_PER_UNIT)
                    848:        byte_mode = mode;
                    849: 
                    850:       if (GET_MODE_CLASS (mode) == MODE_INT
                    851:          && GET_MODE_BITSIZE (mode) == BITS_PER_WORD)
                    852:        word_mode = mode;
                    853:     }
                    854: }

unix.superglobalmegacorp.com

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