Annotation of researchv10dc/cmd/gcc/rtl.c, revision 1.1.1.1

1.1       root        1: /* Manage RTL for C-Compiler
                      2:    Copyright (C) 1987, 1988 Free Software Foundation, Inc.
                      3: 
                      4: This file is part of GNU CC.
                      5: 
                      6: GNU CC is distributed in the hope that it will be useful,
                      7: but WITHOUT ANY WARRANTY.  No author or distributor
                      8: accepts responsibility to anyone for the consequences of using it
                      9: or for whether it serves any particular purpose or works at all,
                     10: unless he says so in writing.  Refer to the GNU CC General Public
                     11: License for full details.
                     12: 
                     13: Everyone is granted permission to copy, modify and redistribute
                     14: GNU CC, but only under the conditions described in the
                     15: GNU CC General Public License.   A copy of this license is
                     16: supposed to have been given to you along with GNU CC so you
                     17: can know your rights and responsibilities.  It should be in a
                     18: file named COPYING.  Among other things, the copyright notice
                     19: and this notice must be preserved on all copies.  */
                     20: 
                     21: 
                     22: /* This file contains the low level primitives for allocating,
                     23:    printing and reading rtl expressions and vectors.
                     24:    It also contains some functions for semantic analysis
                     25:    on rtl expressions.  */
                     26: 
                     27: #include "config.h"
                     28: #include <ctype.h>
                     29: #include <stdio.h>
                     30: #include "rtl.h"
                     31: 
                     32: #include "obstack.h"
                     33: #define        obstack_chunk_alloc     xmalloc
                     34: #define        obstack_chunk_free      free
                     35: extern int xmalloc ();
                     36: extern void free ();
                     37: 
                     38: /* Obstack used for allocating RTL objects.
                     39:    Between functions, this is the permanent_obstack.
                     40:    While parsing and expanding a function, this is maybepermanent_obstack
                     41:    so we can save it if it is an inline function.
                     42:    During optimization and output, this is temporary_obstack.  */
                     43: 
                     44: extern struct obstack *rtl_obstack;
                     45: 
                     46: #define MIN(x,y) ((x < y) ? x : y)
                     47: 
                     48: extern long ftell();
                     49: 
                     50: /* Indexed by rtx code, gives number of operands for an rtx with that code.
                     51:    Does NOT include rtx header data (code and links).
                     52:    This array is initialized in init_rtx.  */
                     53: 
                     54: int rtx_length[NUM_RTX_CODE + 1];
                     55: 
                     56: /* Indexed by rtx code, gives the name of that kind of rtx, as a C string.  */
                     57: 
                     58: #define DEF_RTL_EXPR(ENUM, NAME, FORMAT)   NAME ,
                     59: 
                     60: char *rtx_name[] = {
                     61: #include "rtl.def"             /* rtl expressions are documented here */
                     62: };
                     63: 
                     64: #undef DEF_RTL_EXPR
                     65: 
                     66: /* Indexed by machine mode, gives the name of that machine mode.
                     67:    This name does not include the letters "mode".  */
                     68: 
                     69: #define DEF_MACHMODE(SYM, NAME, CLASS, SIZE, UNIT)  NAME,
                     70: 
                     71: char *mode_name[] = {
                     72: #include "machmode.def"
                     73: };
                     74: 
                     75: #undef DEF_MACHMODE
                     76: 
                     77: /* Indexed by machine mode, gives the length of the mode, in bytes.
                     78:    GET_MODE_CLASS uses this.  */
                     79: 
                     80: #define DEF_MACHMODE(SYM, NAME, CLASS, SIZE, UNIT)  CLASS,
                     81: 
                     82: enum mode_class mode_class[] = {
                     83: #include "machmode.def"
                     84: };
                     85: 
                     86: #undef DEF_MACHMODE
                     87: 
                     88: /* Indexed by machine mode, gives the length of the mode, in bytes.
                     89:    GET_MODE_SIZE uses this.  */
                     90: 
                     91: #define DEF_MACHMODE(SYM, NAME, CLASS, SIZE, UNIT)  SIZE,
                     92: 
                     93: int mode_size[] = {
                     94: #include "machmode.def"
                     95: };
                     96: 
                     97: #undef DEF_MACHMODE
                     98: 
                     99: /* Indexed by machine mode, gives the length of the mode's subunit.
                    100:    GET_MODE_UNIT_SIZE uses this.  */
                    101: 
                    102: #define DEF_MACHMODE(SYM, NAME, CLASS, SIZE, UNIT)  UNIT,
                    103: 
                    104: int mode_unit_size[] = {
                    105: #include "machmode.def"                /* machine modes are documented here */
                    106: };
                    107: 
                    108: #undef DEF_MACHMODE
                    109: 
                    110: /* Indexed by rtx code, gives a sequence of operand-types for
                    111:    rtx's of that code.  The sequence is a C string in which
                    112:    each charcter describes one operand.  */
                    113: 
                    114: char *rtx_format[] = {
                    115:   /* "*" undefined.
                    116:          can cause a warning message
                    117:      "0" field is unused (or used in a phase-dependent manner)
                    118:          prints nothing
                    119:      "i" an integer
                    120:          prints the integer
                    121:      "s" a pointer to a string
                    122:          prints the string
                    123:      "e" a pointer to an rtl expression
                    124:          prints the expression
                    125:      "E" a pointer to a vector that points to a number of rtl expressions
                    126:          prints a list of the rtl expressions
                    127:      "u" a pointer to another insn
                    128:          prints the uid of the insn.  */
                    129: 
                    130: #define DEF_RTL_EXPR(ENUM, NAME, FORMAT)   FORMAT ,
                    131: #include "rtl.def"             /* rtl expressions are defined here */
                    132: #undef DEF_RTL_EXPR
                    133: };
                    134: 
                    135: /* Allocate an rtx vector of N elements.
                    136:    Store the length, and initialize all elements to zero.  */
                    137: 
                    138: rtvec
                    139: rtvec_alloc (n)
                    140:      int n;
                    141: {
                    142:   rtvec rt;
                    143:   int i;
                    144: 
                    145:   rt = (rtvec) obstack_alloc (rtl_obstack,
                    146:                              sizeof (struct rtvec_def)
                    147:                              + (( n - 1) * sizeof (rtunion)));
                    148: 
                    149:   /* clear out the vector */
                    150:   PUT_NUM_ELEM(rt, n);
                    151:   for (i=0; i < n; i++)
                    152:     rt->elem[i].rtvec = NULL;  /* @@ not portable due to rtunion */
                    153: 
                    154:   return rt;
                    155: }
                    156: 
                    157: /* Allocate an rtx of code CODE.  The CODE is stored in the rtx;
                    158:    all the rest is initialized to zero.  */
                    159: 
                    160: rtx
                    161: rtx_alloc (code)
                    162:   RTX_CODE code;
                    163: {
                    164:   rtx rt;
                    165:   register int nelts = GET_RTX_LENGTH (code);
                    166:   register int length = sizeof (struct rtx_def)
                    167:     + (nelts - 1) * sizeof (rtunion);
                    168: 
                    169:   rt = (rtx) obstack_alloc (rtl_obstack, length);
                    170: 
                    171:   * (int *) rt = 0;
                    172:   PUT_CODE (rt, code);
                    173: 
                    174:   return rt;
                    175: }
                    176: 
                    177: /* Create a new copy of an rtx.
                    178:    Recursively copies the operands of the rtx,
                    179:    except for those few rtx codes that are sharable.  */
                    180: 
                    181: rtx
                    182: copy_rtx (orig)
                    183:      register rtx orig;
                    184: {
                    185:   register rtx copy;
                    186:   register int i, j;
                    187:   register RTX_CODE code;
                    188:   register char *format_ptr;
                    189: 
                    190:   code = GET_CODE (orig);
                    191: 
                    192:   switch (code)
                    193:     {
                    194:     case REG:
                    195:     case QUEUED:
                    196:     case CONST_INT:
                    197:     case CONST_DOUBLE:
                    198:     case SYMBOL_REF:
                    199:     case CODE_LABEL:
                    200:     case PC:
                    201:     case CC0:
                    202:       return orig;
                    203:     }
                    204: 
                    205:   copy = rtx_alloc (code);
                    206:   PUT_MODE (copy, GET_MODE (orig));
                    207:   copy->in_struct = orig->in_struct;
                    208:   copy->volatil = orig->volatil;
                    209:   copy->unchanging = orig->unchanging;
                    210:   copy->integrated = orig->integrated;
                    211:   
                    212:   format_ptr = GET_RTX_FORMAT (GET_CODE (copy));
                    213: 
                    214:   for (i = 0; i < GET_RTX_LENGTH (GET_CODE (copy)); i++)
                    215:     {
                    216:       switch (*format_ptr++)
                    217:        {
                    218:        case 'e':
                    219:          XEXP (copy, i) = copy_rtx (XEXP (orig, i));
                    220:          break;
                    221: 
                    222:        case 'E':
                    223:          XVEC (copy, i) = XVEC (orig, i);
                    224:          if (XVEC (orig, i) != NULL)
                    225:            {
                    226:              XVEC (copy, i) = rtvec_alloc (XVECLEN (orig, i));
                    227:              for (j = 0; j < XVECLEN (copy, i); j++)
                    228:                XVECEXP (copy, i, j) = copy_rtx (XVECEXP (orig, i, j));
                    229:            }
                    230:          break;
                    231: 
                    232:        default:
                    233:          XINT (copy, i) = XINT (orig, i);
                    234:          break;
                    235:        }
                    236:     }
                    237:   return copy;
                    238: }
                    239: 
                    240: /* Return 1 if the value of X is unstable
                    241:    (would be different at a different point in the program).
                    242:    The frame pointer, arg pointer, etc. are considered stable
                    243:    (within one function) and so is anything marked `unchanging'.  */
                    244: 
                    245: int
                    246: rtx_unstable_p (x)
                    247:      rtx x;
                    248: {
                    249:   register RTX_CODE code = GET_CODE (x);
                    250:   register int i;
                    251:   register char *fmt;
                    252: 
                    253:   if (code == MEM)
                    254:     return ! x->unchanging;
                    255: 
                    256:   if (code == QUEUED)
                    257:     return 1;
                    258: 
                    259:   if (code == CONST || code == CONST_INT)
                    260:     return 0;
                    261: 
                    262:   if (code == REG)
                    263:     return ! (REGNO (x) == FRAME_POINTER_REGNUM
                    264:              || REGNO (x) == ARG_POINTER_REGNUM
                    265:              || x->unchanging);
                    266: 
                    267:   fmt = GET_RTX_FORMAT (code);
                    268:   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
                    269:     if (fmt[i] == 'e')
                    270:       if (rtx_unstable_p (XEXP (x, i)))
                    271:        return 1;
                    272:   return 0;
                    273: }
                    274: 
                    275: /* Return 1 if X has a value that can vary even between two
                    276:    executions of the program.  0 means X can be compared reliably
                    277:    against certain constants or near-constants.
                    278:    The frame pointer and the arg pointer are considered constant.  */
                    279: 
                    280: int
                    281: rtx_varies_p (x)
                    282:      rtx x;
                    283: {
                    284:   register RTX_CODE code = GET_CODE (x);
                    285:   register int i;
                    286:   register char *fmt;
                    287: 
                    288:   if (code == MEM)
                    289:     return 1;
                    290: 
                    291:   if (code == QUEUED)
                    292:     return 1;
                    293: 
                    294:   if (code == CONST || code == CONST_INT)
                    295:     return 0;
                    296: 
                    297:   if (code == REG)
                    298:     return ! (REGNO (x) == FRAME_POINTER_REGNUM
                    299:              || REGNO (x) == ARG_POINTER_REGNUM);
                    300: 
                    301:   fmt = GET_RTX_FORMAT (code);
                    302:   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
                    303:     if (fmt[i] == 'e')
                    304:       if (rtx_varies_p (XEXP (x, i)))
                    305:        return 1;
                    306:   return 0;
                    307: }
                    308: 
                    309: /* Return 1 if X refers to a memory location whose address 
                    310:    cannot be compared reliably with constant addresses,
                    311:    or if X refers to a BLKmode memory object.  */
                    312: 
                    313: int
                    314: rtx_addr_varies_p (x)
                    315:      rtx x;
                    316: {
                    317:   register RTX_CODE code = GET_CODE (x);
                    318:   register int i;
                    319:   register char *fmt;
                    320: 
                    321:   if (code == MEM)
                    322:     return GET_MODE (x) == BLKmode || rtx_varies_p (XEXP (x, 0));
                    323: 
                    324:   fmt = GET_RTX_FORMAT (code);
                    325:   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
                    326:     if (fmt[i] == 'e')
                    327:       if (rtx_addr_varies_p (XEXP (x, i)))
                    328:        return 1;
                    329:   return 0;
                    330: }
                    331: 
                    332: /* Nonzero if register REG appears somewhere within IN.
                    333:    Also works if REG is not a register; in this case it checks
                    334:    for a subexpression of IN that is Lisp "equal" to REG.  */
                    335: 
                    336: int
                    337: reg_mentioned_p (reg, in)
                    338:      register rtx reg, in;
                    339: {
                    340:   register char *fmt;
                    341:   register int i;
                    342:   register enum rtx_code code;
                    343: 
                    344:   if (in == 0)
                    345:     return 0;
                    346: 
                    347:   if (reg == in)
                    348:     return 1;
                    349: 
                    350:   code = GET_CODE (in);
                    351: 
                    352:   switch (code)
                    353:     {
                    354:       /* Compare registers by number.  */
                    355:     case REG:
                    356:       return GET_CODE (reg) == REG && REGNO (in) == REGNO (reg);
                    357: 
                    358:       /* These codes have no constituent expressions
                    359:         and are unique.  */
                    360:     case CC0:
                    361:     case PC:
                    362:     case CONST_INT:
                    363:     case CONST:
                    364:     case CONST_DOUBLE:
                    365:     case LABEL_REF:
                    366:     case SYMBOL_REF:
                    367:       return 0;
                    368:     }
                    369: 
                    370:   if (GET_CODE (reg) == code && rtx_equal_p (reg, in))
                    371:     return 1;
                    372: 
                    373:   fmt = GET_RTX_FORMAT (code);
                    374: 
                    375:   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
                    376:     {
                    377:       if (fmt[i] == 'E')
                    378:        {
                    379:          register int j;
                    380:          for (j = XVECLEN (in, i) - 1; j >= 0; j--)
                    381:            if (reg_mentioned_p (reg, XVECEXP (in, i, j)))
                    382:              return 1;
                    383:        }
                    384:       else if (fmt[i] == 'e'
                    385:               && reg_mentioned_p (reg, XEXP (in, i)))
                    386:        return 1;
                    387:     }
                    388:   return 0;
                    389: }
                    390: 
                    391: /* Nonzero if register REG is used in an insn between
                    392:    FROM_INSN and TO_INSN (exclusive of those two).  */
                    393: 
                    394: int
                    395: reg_used_between_p (reg, from_insn, to_insn)
                    396:      rtx reg, from_insn, to_insn;
                    397: {
                    398:   register rtx insn;
                    399:   register RTX_CODE code;
                    400:   for (insn = NEXT_INSN (from_insn); insn != to_insn; insn = NEXT_INSN (insn))
                    401:     if (((code = GET_CODE (insn)) == INSN
                    402:         || code == JUMP_INSN || code == CALL_INSN)
                    403:        && reg_mentioned_p (reg, PATTERN (insn)))
                    404:       return 1;
                    405:   return 0;
                    406: }
                    407: 
                    408: /* Return 1 if X and Y are identical-looking rtx's.
                    409:    This is the Lisp function EQUAL for rtx arguments.  */
                    410: 
                    411: int
                    412: rtx_equal_p (x, y)
                    413:      rtx x, y;
                    414: {
                    415:   register int i;
                    416:   register int hash = 0;
                    417:   register RTX_CODE code = GET_CODE (x);
                    418:   register char *fmt;
                    419: 
                    420:   if (x == y)
                    421:     return 1;
                    422: 
                    423:   /* Rtx's of different codes cannot be equal.  */
                    424:   if (code != GET_CODE (y))
                    425:     return 0;
                    426: 
                    427:   /* (MULT:SI x y) and (MULT:HI x y) are NOT equivalent.
                    428:      (REG:SI x) and (REG:HI x) are NOT equivalent.  */
                    429: 
                    430:   if (GET_MODE (x) != GET_MODE (y))
                    431:     return 0;
                    432: 
                    433:   /* These three types of rtx's can be compared nonrecursively.  */
                    434:   if (code == REG)
                    435:     return (REGNO (x) == REGNO (y));
                    436:   if (code == LABEL_REF)
                    437:     return XEXP (x, 0) == XEXP (y, 0);
                    438:   if (code == SYMBOL_REF)
                    439:     return XSTR (x, 0) == XSTR (y, 0);
                    440: 
                    441:   /* Compare the elements.  If any pair of corresponding elements
                    442:      fail to match, return 0 for the whole things.  */
                    443: 
                    444:   fmt = GET_RTX_FORMAT (code);
                    445:   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
                    446:     {
                    447:       switch (fmt[i])
                    448:        {
                    449:        case 'i':
                    450:          if (XINT (x, i) != XINT (y, i))
                    451:            return 0;
                    452:          break;
                    453: 
                    454:        case 'e':
                    455:          if (rtx_equal_p (XEXP (x, i), XEXP (y, i)) == 0)
                    456:            return 0;
                    457:          break;
                    458: 
                    459:        case 's':
                    460:          if (strcmp (XSTR (x, i), XSTR (y, i)))
                    461:            return 0;
                    462:          break;
                    463: 
                    464:        case '0':
                    465:          break;
                    466: 
                    467:          /* It is believed that rtx's at this level will never
                    468:             contain anything but integers and other rtx's,
                    469:             except for within LABEL_REFs and SYMBOL_REFs.  */
                    470:        default:
                    471:          abort ();
                    472:        }
                    473:     }
                    474:   return 1;
                    475: }
                    476: 
                    477: /* Call FUN on each register or MEM that is stored into or clobbered by X.
                    478:    (X would be the pattern of an insn).
                    479:    FUN receives two arguments:
                    480:      the REG, MEM, CC0 or PC being stored in or clobbered,
                    481:      the SET or CLOBBER rtx that does the store.  */
                    482:      
                    483: void
                    484: note_stores (x, fun)
                    485:      register rtx x;
                    486:      void (*fun) ();
                    487: {
                    488:   if ((GET_CODE (x) == SET || GET_CODE (x) == CLOBBER))
                    489:     {
                    490:       register rtx dest = SET_DEST (x);
                    491:       while (GET_CODE (dest) == SUBREG
                    492:             || GET_CODE (dest) == ZERO_EXTRACT
                    493:             || GET_CODE (dest) == SIGN_EXTRACT
                    494:             || GET_CODE (dest) == STRICT_LOW_PART)
                    495:        dest = XEXP (dest, 0);
                    496:       (*fun) (dest, GET_CODE (x) == CLOBBER);
                    497:     }
                    498:   else if (GET_CODE (x) == PARALLEL)
                    499:     {
                    500:       register int i;
                    501:       for (i = XVECLEN (x, 0) - 1; i >= 0; i--)
                    502:        {
                    503:          register rtx y = XVECEXP (x, 0, i);
                    504:          if (GET_CODE (y) == SET || GET_CODE (y) == CLOBBER)
                    505:            {
                    506:              register rtx dest = SET_DEST (y);
                    507:              while (GET_CODE (dest) == SUBREG
                    508:                     || GET_CODE (dest) == ZERO_EXTRACT
                    509:                     || GET_CODE (dest) == SIGN_EXTRACT
                    510:                     || GET_CODE (dest) == STRICT_LOW_PART)
                    511:                dest = XEXP (dest, 0);
                    512:              (*fun) (dest, GET_CODE (y) == CLOBBER);
                    513:            }
                    514:        }
                    515:     }
                    516: }
                    517: 
                    518: /* Return nonzero if register REG's old contents don't survive after INSN.
                    519:    This can be because REG dies in INSN or because INSN entirely sets REG.
                    520: 
                    521:    "Entirely set" means set directly and not through a SUBREG,
                    522:    ZERO_EXTRACT or SIGN_EXTRACT, so no trace of the old contents remains.
                    523: 
                    524:    REG may be a hard or pseudo reg.  Renumbering is not taken into account,
                    525:    but for this use that makes no difference, since regs don't overlap
                    526:    during their lifetimes.  Therefore, this function may be used
                    527:    at any time after deaths have been computed (in flow.c).  */
                    528: 
                    529: int
                    530: dead_or_set_p (insn, reg)
                    531:      rtx insn;
                    532:      rtx reg;
                    533: {
                    534:   register rtx link;
                    535:   register int regno = REGNO (reg);
                    536: 
                    537:   for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
                    538:     if ((REG_NOTE_KIND (link) == REG_DEAD
                    539:         || REG_NOTE_KIND (link) == REG_INC)
                    540:        && REGNO (XEXP (link, 0)) == regno)
                    541:       return 1;
                    542: 
                    543:   if (GET_CODE (PATTERN (insn)) == SET)
                    544:     return SET_DEST (PATTERN (insn)) == reg;
                    545:   else if (GET_CODE (PATTERN (insn)) == PARALLEL)
                    546:     {
                    547:       register int i;
                    548:       for (i = XVECLEN (PATTERN (insn), 0) - 1; i >= 0; i--)
                    549:        {
                    550:          if (GET_CODE (XVECEXP (PATTERN (insn), 0, i)) == SET
                    551:              && SET_DEST (XVECEXP (PATTERN (insn), 0, i)) == reg)
                    552:            return 1;
                    553:        }
                    554:     }
                    555:   return 0;
                    556: }
                    557: 
                    558: /* Return the reg-note of kind KIND in insn INSN, if there is one.
                    559:    If DATUM is nonzero, look for one whose datum is DATUM.  */
                    560: 
                    561: rtx
                    562: find_reg_note (insn, kind, datum)
                    563:      rtx insn;
                    564:      enum reg_note kind;
                    565:      rtx datum;
                    566: {
                    567:   register rtx link;
                    568: 
                    569:   for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
                    570:     if (REG_NOTE_KIND (link) == kind
                    571:        && (datum == 0 || datum == XEXP (link, 0)))
                    572:       return link;
                    573:   return 0;
                    574: }
                    575: 
                    576: /* Return the reg-note of kind KIND in insn INSN which applies to register
                    577:    number REGNO, if any.  Return 0 if there is no such reg-note.  */
                    578: 
                    579: rtx
                    580: find_regno_note (insn, kind, regno)
                    581:      rtx insn;
                    582:      enum reg_note kind;
                    583:      int regno;
                    584: {
                    585:   register rtx link;
                    586: 
                    587:   for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
                    588:     if (REG_NOTE_KIND (link) == kind
                    589:        && REGNO (XEXP (link, 0)) == regno)
                    590:       return link;
                    591:   return 0;
                    592: }
                    593: 
                    594: /* Printing rtl for debugging dumps.  */
                    595: 
                    596: static FILE *outfile;
                    597: 
                    598: char spaces[] = "                                                                                                                                                                ";
                    599: 
                    600: static int sawclose = 0;
                    601: 
                    602: /* Print IN_RTX onto OUTFILE.  This is the recursive part of printing.  */
                    603: 
                    604: static void
                    605: print_rtx (in_rtx)
                    606:      register rtx in_rtx;
                    607: {
                    608:   static int indent;
                    609:   register int i, j;
                    610:   register char *format_ptr;
                    611: 
                    612:   if (sawclose)
                    613:     {
                    614:       fprintf (outfile, "\n%s",
                    615:               (spaces + (sizeof spaces - indent * 2)));
                    616:       sawclose = 0;
                    617:     }
                    618: 
                    619:   if (in_rtx == 0)
                    620:     {
                    621:       fprintf (outfile, "(nil)");
                    622:       sawclose = 1;
                    623:       return;
                    624:     }
                    625: 
                    626:   /* print name of expression code */
                    627:   fprintf (outfile, "(%s", GET_RTX_NAME (GET_CODE (in_rtx)));
                    628: 
                    629:   if (in_rtx->in_struct)
                    630:     fprintf (outfile, "/s");
                    631: 
                    632:   if (in_rtx->volatil)
                    633:     fprintf (outfile, "/v");
                    634: 
                    635:   if (in_rtx->unchanging)
                    636:     fprintf (outfile, "/u");
                    637: 
                    638:   if (in_rtx->integrated)
                    639:     fprintf (outfile, "/i");
                    640: 
                    641:   if (GET_MODE (in_rtx) != VOIDmode)
                    642:     fprintf (outfile, ":%s", GET_MODE_NAME (GET_MODE (in_rtx)));
                    643: 
                    644:   format_ptr = GET_RTX_FORMAT (GET_CODE (in_rtx));
                    645: 
                    646:   for (i = 0; i < GET_RTX_LENGTH (GET_CODE (in_rtx)); i++)
                    647:     switch (*format_ptr++)
                    648:       {
                    649:       case 's':
                    650:        if (XSTR (in_rtx, i) == 0)
                    651:          fprintf (outfile, " \"\"");
                    652:        else
                    653:          fprintf (outfile, " (\"%s\")", XSTR (in_rtx, i));
                    654:        sawclose = 1;
                    655:        break;
                    656: 
                    657:        /* 0 indicates a field for internal use that should not be printed.  */
                    658:       case '0':
                    659:        break;
                    660: 
                    661:       case 'e':
                    662:        indent += 2;
                    663:        if (!sawclose)
                    664:          fprintf (outfile, " ");
                    665:        print_rtx (XEXP (in_rtx, i));
                    666:        indent -= 2;
                    667:        break;
                    668: 
                    669:       case 'E':
                    670:        indent += 2;
                    671:        if (sawclose)
                    672:          {
                    673:            fprintf (outfile, "\n%s",
                    674:                     (spaces + (sizeof spaces - indent * 2)));
                    675:            sawclose = 0;
                    676:          }
                    677:        fprintf (outfile, "[ ");
                    678:        if (NULL != XVEC (in_rtx, i))
                    679:          {
                    680:            indent += 2;
                    681:            if (XVECLEN (in_rtx, i))
                    682:              sawclose = 1;
                    683: 
                    684:            for (j = 0; j < XVECLEN (in_rtx, i); j++)
                    685:              print_rtx (XVECEXP (in_rtx, i, j));
                    686: 
                    687:            indent -= 2;
                    688:          }
                    689:        if (sawclose)
                    690:          fprintf (outfile, "\n%s",
                    691:                   (spaces + (sizeof spaces - indent * 2)));
                    692: 
                    693:        fprintf (outfile, "] ");
                    694:        sawclose = 1;
                    695:        indent -= 2;
                    696:        break;
                    697: 
                    698:       case 'i':
                    699:        fprintf (outfile, " %d", XINT (in_rtx, i));
                    700:        sawclose = 0;
                    701:        break;
                    702: 
                    703:       case 'u':
                    704:        if (XEXP (in_rtx, i) != NULL)
                    705:          fprintf(outfile, " %d", INSN_UID (XEXP (in_rtx, i)));
                    706:        else
                    707:          fprintf(outfile, " 0");
                    708:        sawclose = 0;
                    709:        break;
                    710: 
                    711:       default:
                    712:        fprintf (stderr,
                    713:                 "switch format wrong in rtl.print_rtx(). format was: %c.\n",
                    714:                 format_ptr[-1]);
                    715:        abort ();
                    716:       }
                    717: 
                    718:   fprintf (outfile, ")");
                    719:   sawclose = 1;
                    720: }
                    721: 
                    722: /* Call this function from the debugger to see what X looks like.  */
                    723: 
                    724: void
                    725: debug_rtx (x)
                    726:      rtx x;
                    727: {
                    728:   outfile = stderr;
                    729:   print_rtx (x);
                    730:   fprintf (stderr, "\n");
                    731: }
                    732: 
                    733: /* External entry point for printing a chain of INSNs
                    734:    starting with RTX_FIRST onto file OUTF.  */
                    735: 
                    736: void
                    737: print_rtl (outf, rtx_first)
                    738:      FILE *outf;
                    739:      rtx rtx_first;
                    740: {
                    741:   register rtx tmp_rtx;
                    742: 
                    743:   outfile = outf;
                    744:   sawclose = 0;
                    745: 
                    746:   for (tmp_rtx = rtx_first; NULL != tmp_rtx; tmp_rtx = NEXT_INSN (tmp_rtx))
                    747:     {
                    748:       print_rtx (tmp_rtx);
                    749:       fprintf (outfile, "\n");
                    750:     }
                    751: }
                    752: 
                    753: /* Subroutines of read_rtx.  */
                    754: 
                    755: /* Dump code after printing a message.  Used when read_rtx finds
                    756:    invalid data.  */
                    757: 
                    758: static void
                    759: dump_and_abort (expected_c, actual_c, infile)
                    760:      int expected_c, actual_c;
                    761:      FILE *infile;
                    762: {
                    763:   int c, i;
                    764: 
                    765:   fprintf (stderr,
                    766:           "Expected character %c. Read character %c. At file position: %ld\n",
                    767:           expected_c, actual_c, ftell (infile));
                    768:   fprintf (stderr, "Following characters are:\n\t");
                    769:   for (i = 0; i < 200; i++)
                    770:     {
                    771:       c = getc (infile);
                    772:       if (EOF == c) break;
                    773:       putc (c, stderr);
                    774:     }
                    775:   fprintf (stderr, "Aborting.\n");
                    776:   abort ();
                    777: }
                    778: 
                    779: /* Read chars from INFILE until a non-whitespace char
                    780:    and return that.  Comments, both Lisp style and C style,
                    781:    are treated as whitespace.
                    782:    Tools such as genflags use this function.  */
                    783: 
                    784: int
                    785: read_skip_spaces (infile)
                    786:      FILE *infile;
                    787: {
                    788:   register int c;
                    789:   while (c = getc (infile))
                    790:     {
                    791:       if (c == ' ' || c == '\n' || c == '\t' || c == '\f')
                    792:        ;
                    793:       else if (c == ';')
                    794:        {
                    795:          while ((c = getc (infile)) && c != '\n') ;
                    796:        }
                    797:       else if (c == '/')
                    798:        {
                    799:          register int prevc;
                    800:          c = getc (infile);
                    801:          if (c != '*')
                    802:            dump_and_abort ('*', c, infile);
                    803:          
                    804:          prevc = 0;
                    805:          while (c = getc (infile))
                    806:            {
                    807:              if (prevc == '*' && c == '/')
                    808:                break;
                    809:              prevc = c;
                    810:            }
                    811:        }
                    812:       else break;
                    813:     }
                    814:   return c;
                    815: }
                    816: 
                    817: /* Read an rtx code name into the buffer STR[].
                    818:    It is terminated by any of the punctuation chars of rtx printed syntax.  */
                    819: 
                    820: static void
                    821: read_name (str, infile)
                    822:      char *str;
                    823:      FILE *infile;
                    824: {
                    825:   register char *p;
                    826:   register int c;
                    827: 
                    828:   c = read_skip_spaces(infile);
                    829: 
                    830:   p = str;
                    831:   while (1)
                    832:     {
                    833:       if (c == ' ' || c == '\n' || c == '\t' || c == '\f')
                    834:        break;
                    835:       if (c == ':' || c == ')' || c == ']' || c == '"' || c == '/'
                    836:          || c == '(' || c == '[')
                    837:        {
                    838:          ungetc (c, infile);
                    839:          break;
                    840:        }
                    841:       *p++ = c;
                    842:       c = getc (infile);
                    843:     }
                    844:   *p = NULL;
                    845: }
                    846: 
                    847: /* Read an rtx in printed representation from INFILE
                    848:    and return an actual rtx in core constructed accordingly.
                    849:    read_rtx is not used in the compiler proper, but rather in
                    850:    the utilities gen*.c that construct C code from machine descriptions.  */
                    851: 
                    852: rtx
                    853: read_rtx (infile)
                    854:      FILE *infile;
                    855: {
                    856:   register int i, j, list_counter;
                    857:   RTX_CODE tmp_code;
                    858:   register char *format_ptr;
                    859:   /* tmp_char is a buffer used for reading decimal integers
                    860:      and names of rtx types and machine modes.
                    861:      Therefore, 256 must be enough.  */
                    862:   char tmp_char[256];
                    863:   rtx return_rtx;
                    864:   register int c;
                    865:   int tmp_int;
                    866: 
                    867:   /* Linked list structure for making RTXs: */
                    868:   struct rtx_list
                    869:     {
                    870:       struct rtx_list *next;
                    871:       rtx value;               /* Value of this node...                */
                    872:     };
                    873: 
                    874:   c = read_skip_spaces (infile); /* Should be open paren.  */
                    875:   if (c != '(')
                    876:     dump_and_abort ('(', c, infile);
                    877: 
                    878:   read_name (tmp_char, infile);
                    879: 
                    880:   tmp_code = UNKNOWN;
                    881: 
                    882:   for (i=0; i < NUM_RTX_CODE; i++) /* @@ might speed this search up */
                    883:     {
                    884:       if (!(strcmp (tmp_char, GET_RTX_NAME (i))))
                    885:        {
                    886:          tmp_code = (RTX_CODE) i;      /* get value for name */
                    887:          break;
                    888:        }
                    889:     }
                    890:   if (tmp_code == UNKNOWN)
                    891:     {
                    892:       fprintf (stderr,
                    893:               "Unknown rtx read in rtl.read_rtx(). Code name was %s .",
                    894:               tmp_char);
                    895:     }
                    896:   /* (NIL) stands for an expression that isn't there.  */
                    897:   if (tmp_code == NIL)
                    898:     {
                    899:       /* Discard the closeparen.  */
                    900:       while ((c = getc (infile)) && c != ')');
                    901:       return 0;
                    902:     }
                    903: 
                    904:   return_rtx = rtx_alloc (tmp_code); /* if we end up with an insn expression
                    905:                                       then we free this space below.  */
                    906:   format_ptr = GET_RTX_FORMAT (GET_CODE (return_rtx));
                    907: 
                    908:   /* If what follows is `: mode ', read it and
                    909:      store the mode in the rtx.  */
                    910: 
                    911:   i = read_skip_spaces (infile);
                    912:   if (i == ':')
                    913:     {
                    914:       register int k;
                    915:       read_name (tmp_char, infile);
                    916:       for (k = 0; k < NUM_MACHINE_MODES; k++)
                    917:        if (!strcmp (GET_MODE_NAME (k), tmp_char))
                    918:          break;
                    919: 
                    920:       PUT_MODE (return_rtx, (enum machine_mode) k );
                    921:     }
                    922:   else
                    923:     ungetc (i, infile);
                    924: 
                    925:   for (i = 0; i < GET_RTX_LENGTH (GET_CODE (return_rtx)); i++)
                    926:     switch (*format_ptr++)
                    927:       {
                    928:        /* 0 means a field for internal use only.
                    929:           Don't expect it to be present in the input.  */
                    930:       case '0':
                    931:        break;
                    932: 
                    933:       case 'e':
                    934:       case 'u':
                    935:        XEXP (return_rtx, i) = read_rtx (infile);
                    936:        break;
                    937: 
                    938:       case 'E':
                    939:        {
                    940:          register struct rtx_list *next_rtx, *rtx_list_link;
                    941:          struct rtx_list *list_rtx;
                    942: 
                    943:          c = read_skip_spaces (infile);
                    944:          if (c != '[')
                    945:            dump_and_abort ('[', c, infile);
                    946: 
                    947:          /* add expressions to a list, while keeping a count */
                    948:          next_rtx = NULL;
                    949:          list_counter = 0;
                    950:          while ((c = read_skip_spaces (infile)) && c != ']')
                    951:            {
                    952:              ungetc (c, infile);
                    953:              list_counter++;
                    954:              rtx_list_link = (struct rtx_list *)
                    955:                alloca (sizeof (struct rtx_list));
                    956:              rtx_list_link->value = read_rtx (infile);
                    957:              if (next_rtx == 0)
                    958:                list_rtx = rtx_list_link;
                    959:              else
                    960:                next_rtx->next = rtx_list_link;
                    961:              next_rtx = rtx_list_link;
                    962:              rtx_list_link->next = 0;
                    963:            }
                    964:          /* get vector length and allocate it */
                    965:          XVEC (return_rtx, i) = (list_counter
                    966:                                  ? rtvec_alloc (list_counter)
                    967:                                  : NULL);
                    968:          if (list_counter > 0) 
                    969:            {
                    970:              next_rtx = list_rtx;
                    971:              for (j = 0; j < list_counter; j++,
                    972:                   next_rtx = next_rtx->next)
                    973:                XVECEXP (return_rtx, i, j) = next_rtx->value;
                    974:            }
                    975:          /* close bracket gotten */
                    976:        }
                    977:        break;
                    978: 
                    979:       case 's':
                    980:        {
                    981:          int saw_paren = 0;
                    982:          register char *stringbuf;
                    983:          int stringbufsize;
                    984: 
                    985:          c = read_skip_spaces (infile);
                    986:          if (c == '(')
                    987:            {
                    988:              saw_paren = 1;
                    989:              c = read_skip_spaces (infile);
                    990:            }
                    991:          if (c != '"')
                    992:            dump_and_abort ('"', c, infile);
                    993:          j = 0;
                    994:          stringbufsize = 10;
                    995:          stringbuf = (char *) xmalloc (stringbufsize + 1);
                    996: 
                    997:          while (1)
                    998:            {
                    999:              if (j >= stringbufsize - 4)
                   1000:                {
                   1001:                  stringbufsize *= 2;
                   1002:                  stringbuf = (char *) xrealloc (stringbuf, stringbufsize + 1);
                   1003:                }
                   1004:              stringbuf[j] = getc (infile); /* Read the string  */
                   1005:              if (stringbuf[j] == '\\')
                   1006:                {
                   1007:                  stringbuf[j] = getc (infile); /* Read the string  */
                   1008:                  /* \; makes stuff for a C string constant containing
                   1009:                     newline and tab.  */
                   1010:                  if (stringbuf[j] == ';')
                   1011:                    {
                   1012:                      strcpy (&stringbuf[j], "\\n\\t");
                   1013:                      j += 3;
                   1014:                    }
                   1015:                }
                   1016:              else if (stringbuf[j] == '"')
                   1017:                break;
                   1018:              j++;
                   1019:            }
                   1020: 
                   1021:          stringbuf[j] = 0;     /* NUL terminate the string  */
                   1022:          stringbuf = (char *) xrealloc (stringbuf, j + 1);
                   1023: 
                   1024:          if (saw_paren)
                   1025:            {
                   1026:              c = read_skip_spaces (infile);
                   1027:              if (c != ')')
                   1028:                dump_and_abort (')', c, infile);
                   1029:            }
                   1030:          XSTR (return_rtx, i) = stringbuf;
                   1031:        }
                   1032:        break;
                   1033: 
                   1034:       case 'i':
                   1035:        read_name (tmp_char, infile);
                   1036:        tmp_int = atoi (tmp_char);
                   1037:        XINT (return_rtx, i) = tmp_int;
                   1038:        break;
                   1039: 
                   1040:       default:
                   1041:        fprintf (stderr,
                   1042:                 "switch format wrong in rtl.read_rtx(). format was: %c.\n",
                   1043:                 format_ptr[-1]);
                   1044:        fprintf (stderr, "\tfile position: %ld\n", ftell (infile));
                   1045:        abort ();
                   1046:       }
                   1047: 
                   1048:   c = read_skip_spaces (infile);
                   1049:   if (c != ')')
                   1050:     dump_and_abort (')', c, infile);
                   1051: 
                   1052:   return return_rtx;
                   1053: }
                   1054: 
                   1055: /* This is called once per compilation, before any rtx's are constructed.
                   1056:    It initializes the vector `rtx_length'.  */
                   1057: 
                   1058: void
                   1059: init_rtl ()
                   1060: {
                   1061:   int i;
                   1062: 
                   1063:   for (i = 0; i < NUM_RTX_CODE; i++)
                   1064:     rtx_length[i] = strlen (rtx_format[i]);
                   1065: }

unix.superglobalmegacorp.com

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