Annotation of gcc/rtl.c, revision 1.1.1.4

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

unix.superglobalmegacorp.com

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