Annotation of gcc/rtl.c, revision 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.