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