Annotation of GNUtools/cc/genextract.c, revision 1.1

1.1     ! root        1: /* Generate code from machine description to extract operands from insn as rtl.
        !             2:    Copyright (C) 1987, 1991, 1992, 1993 Free Software Foundation, Inc.
        !             3: 
        !             4: This file is part of GNU CC.
        !             5: 
        !             6: GNU CC is free software; you can redistribute it and/or modify
        !             7: it under the terms of the GNU General Public License as published by
        !             8: the Free Software Foundation; either version 2, or (at your option)
        !             9: any later version.
        !            10: 
        !            11: GNU CC is distributed in the hope that it will be useful,
        !            12: but WITHOUT ANY WARRANTY; without even the implied warranty of
        !            13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        !            14: GNU General Public License for more details.
        !            15: 
        !            16: You should have received a copy of the GNU General Public License
        !            17: along with GNU CC; see the file COPYING.  If not, write to
        !            18: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
        !            19: 
        !            20: 
        !            21: #include <stdio.h>
        !            22: #include "hconfig.h"
        !            23: #include "rtl.h"
        !            24: #include "obstack.h"
        !            25: #include "insn-config.h"
        !            26: 
        !            27: static struct obstack obstack;
        !            28: struct obstack *rtl_obstack = &obstack;
        !            29: 
        !            30: #define obstack_chunk_alloc xmalloc
        !            31: #define obstack_chunk_free free
        !            32: 
        !            33: extern void free ();
        !            34: extern rtx read_rtx ();
        !            35: 
        !            36: /* Names for patterns.  Need to allow linking with print-rtl.  */
        !            37: char **insn_name_ptr;
        !            38: 
        !            39: /* This structure contains all the information needed to describe one
        !            40:    set of extractions methods.  Each method may be used by more than 
        !            41:    one pattern if the operands are in the same place.
        !            42: 
        !            43:    The string for each operand describes that path to the operand and
        !            44:    contains `0' through `9' when going into an expression and `a' through
        !            45:    `z' when going into a vector.  We assume here that only the first operand
        !            46:    of an rtl expression is a vector.  genrecog.c makes the same assumption
        !            47:    (and uses the same representation) and it is currently true.  */
        !            48: 
        !            49: struct extraction
        !            50: {
        !            51:   int op_count;
        !            52:   char *oplocs[MAX_RECOG_OPERANDS];
        !            53:   int dup_count;
        !            54:   char *duplocs[MAX_DUP_OPERANDS];
        !            55:   int dupnums[MAX_DUP_OPERANDS];
        !            56:   struct code_ptr *insns;
        !            57:   struct extraction *next;
        !            58: };
        !            59: 
        !            60: /* Holds a single insn code that use an extraction method.  */
        !            61: 
        !            62: struct code_ptr
        !            63: {
        !            64:   int insn_code;
        !            65:   struct code_ptr *next;
        !            66: };
        !            67: 
        !            68: static struct extraction *extractions;
        !            69: 
        !            70: /* Number instruction patterns handled, starting at 0 for first one.  */
        !            71: 
        !            72: static int insn_code_number;
        !            73: 
        !            74: /* Records the large operand number in this insn.  */
        !            75: 
        !            76: static int op_count;
        !            77: 
        !            78: /* Records the location of any operands using the string format described
        !            79:    above.  */
        !            80: 
        !            81: static char *oplocs[MAX_RECOG_OPERANDS];
        !            82: 
        !            83: /* Number the occurrences of MATCH_DUP in each instruction,
        !            84:    starting at 0 for the first occurrence.  */
        !            85: 
        !            86: static int dup_count;
        !            87: 
        !            88: /* Records the location of any MATCH_DUP operands.  */
        !            89: 
        !            90: static char *duplocs[MAX_DUP_OPERANDS];
        !            91: 
        !            92: /* Record the operand number of any MATCH_DUPs.  */
        !            93: 
        !            94: static int dupnums[MAX_DUP_OPERANDS];
        !            95: 
        !            96: /* Record the list of insn_codes for peepholes.  */
        !            97: 
        !            98: static struct code_ptr *peepholes;
        !            99: 
        !           100: static void walk_rtx ();
        !           101: static void print_path ();
        !           102: char *xmalloc ();
        !           103: char *xrealloc ();
        !           104: static void fatal ();
        !           105: static char *copystr ();
        !           106: static void mybzero ();
        !           107: void fancy_abort ();
        !           108: 
        !           109: static void
        !           110: gen_insn (insn)
        !           111:      rtx insn;
        !           112: {
        !           113:   register int i;
        !           114:   register struct extraction *p;
        !           115:   register struct code_ptr *link;
        !           116: 
        !           117:   op_count = 0;
        !           118:   dup_count = 0;
        !           119: 
        !           120:   /* No operands seen so far in this pattern.  */
        !           121:   mybzero (oplocs, sizeof oplocs);
        !           122: 
        !           123:   /* Walk the insn's pattern, remembering at all times the path
        !           124:      down to the walking point.  */
        !           125: 
        !           126:   if (XVECLEN (insn, 1) == 1)
        !           127:     walk_rtx (XVECEXP (insn, 1, 0), "");
        !           128:   else
        !           129:     for (i = XVECLEN (insn, 1) - 1; i >= 0; i--)
        !           130:       {
        !           131:        char *path = (char *) alloca (2);
        !           132: 
        !           133:        path[0] = 'a' + i;
        !           134:        path[1] = 0;
        !           135: 
        !           136:        walk_rtx (XVECEXP (insn, 1, i), path);
        !           137:       }
        !           138: 
        !           139:   link = (struct code_ptr *) xmalloc (sizeof (struct code_ptr));
        !           140:   link->insn_code = insn_code_number;
        !           141: 
        !           142:   /* See if we find something that already had this extraction method. */
        !           143: 
        !           144:   for (p = extractions; p; p = p->next)
        !           145:     {
        !           146:       if (p->op_count != op_count || p->dup_count != dup_count)
        !           147:        continue;
        !           148: 
        !           149:       for (i = 0; i < op_count; i++)
        !           150:        if (p->oplocs[i] != oplocs[i]
        !           151:            && ! (p->oplocs[i] != 0 && oplocs[i] != 0
        !           152:                  && ! strcmp (p->oplocs[i], oplocs[i])))
        !           153:          break;
        !           154: 
        !           155:       if (i != op_count)
        !           156:        continue;
        !           157: 
        !           158:       for (i = 0; i < dup_count; i++)
        !           159:        if (p->dupnums[i] != dupnums[i]
        !           160:            || strcmp (p->duplocs[i], duplocs[i]))
        !           161:          break;
        !           162: 
        !           163:       if (i != dup_count)
        !           164:        continue;
        !           165: 
        !           166:       /* This extraction is the same as ours.  Just link us in.  */
        !           167:       link->next = p->insns;
        !           168:       p->insns = link;
        !           169:       return;
        !           170:     }
        !           171: 
        !           172:   /* Otherwise, make a new extraction method.  */
        !           173: 
        !           174:   p = (struct extraction *) xmalloc (sizeof (struct extraction));
        !           175:   p->op_count = op_count;
        !           176:   p->dup_count = dup_count;
        !           177:   p->next = extractions;
        !           178:   extractions = p;
        !           179:   p->insns = link;
        !           180:   link->next = 0;
        !           181: 
        !           182:   for (i = 0; i < op_count; i++)
        !           183:     p->oplocs[i] = oplocs[i];
        !           184: 
        !           185:   for (i = 0; i < dup_count; i++)
        !           186:     p->dupnums[i] = dupnums[i], p->duplocs[i] = duplocs[i];
        !           187: }
        !           188: 
        !           189: static void
        !           190: walk_rtx (x, path)
        !           191:      rtx x;
        !           192:      char *path;
        !           193: {
        !           194:   register RTX_CODE code;
        !           195:   register int i;
        !           196:   register int len;
        !           197:   register char *fmt;
        !           198:   register struct code_ptr *link;
        !           199:   int depth = strlen (path);
        !           200:   char *newpath;
        !           201: 
        !           202:   if (x == 0)
        !           203:     return;
        !           204: 
        !           205:   code = GET_CODE (x);
        !           206: 
        !           207:   switch (code)
        !           208:     {
        !           209:     case PC:
        !           210:     case CC0:
        !           211:     case CONST_INT:
        !           212:     case SYMBOL_REF:
        !           213:       return;
        !           214: 
        !           215:     case MATCH_OPERAND:
        !           216:     case MATCH_SCRATCH:
        !           217:       oplocs[XINT (x, 0)] = copystr (path);
        !           218:       op_count = MAX (op_count, XINT (x, 0) + 1);
        !           219:       break;
        !           220: 
        !           221:     case MATCH_DUP:
        !           222:     case MATCH_PAR_DUP:
        !           223:       duplocs[dup_count] = copystr (path);
        !           224:       dupnums[dup_count] = XINT (x, 0);
        !           225:       dup_count++;
        !           226:       break;
        !           227: 
        !           228:     case MATCH_OP_DUP:
        !           229:       duplocs[dup_count] = copystr (path);
        !           230:       dupnums[dup_count] = XINT (x, 0);
        !           231:       dup_count++;
        !           232:       
        !           233:       newpath = (char *) alloca (depth + 2);
        !           234:       strcpy (newpath, path);
        !           235:       newpath[depth + 1] = 0;
        !           236:       
        !           237:       for (i = XVECLEN (x, 1) - 1; i >= 0; i--)
        !           238:         {
        !           239:          newpath[depth] = '0' + i;
        !           240:          walk_rtx (XVECEXP (x, 1, i), newpath);
        !           241:         }
        !           242:       return;
        !           243:       
        !           244:     case MATCH_OPERATOR:
        !           245:       oplocs[XINT (x, 0)] = copystr (path);
        !           246:       op_count = MAX (op_count, XINT (x, 0) + 1);
        !           247: 
        !           248:       newpath = (char *) alloca (depth + 2);
        !           249:       strcpy (newpath, path);
        !           250:       newpath[depth + 1] = 0;
        !           251: 
        !           252:       for (i = XVECLEN (x, 2) - 1; i >= 0; i--)
        !           253:        {
        !           254:          newpath[depth] = '0' + i;
        !           255:          walk_rtx (XVECEXP (x, 2, i), newpath);
        !           256:        }
        !           257:       return;
        !           258: 
        !           259:     case MATCH_PARALLEL:
        !           260:       oplocs[XINT (x, 0)] = copystr (path);
        !           261:       op_count = MAX (op_count, XINT (x, 0) + 1);
        !           262: 
        !           263:       newpath = (char *) alloca (depth + 2);
        !           264:       strcpy (newpath, path);
        !           265:       newpath[depth + 1] = 0;
        !           266: 
        !           267:       for (i = XVECLEN (x, 2) - 1; i >= 0; i--)
        !           268:        {
        !           269:          newpath[depth] = 'a' + i;
        !           270:          walk_rtx (XVECEXP (x, 2, i), newpath);
        !           271:        }
        !           272:       return;
        !           273: 
        !           274:     case ADDRESS:
        !           275:       walk_rtx (XEXP (x, 0), path);
        !           276:       return;
        !           277:     }
        !           278: 
        !           279:   newpath = (char *) alloca (depth + 2);
        !           280:   strcpy (newpath, path);
        !           281:   newpath[depth + 1] = 0;
        !           282: 
        !           283:   fmt = GET_RTX_FORMAT (code);
        !           284:   len = GET_RTX_LENGTH (code);
        !           285:   for (i = 0; i < len; i++)
        !           286:     {
        !           287:       if (fmt[i] == 'e' || fmt[i] == 'u')
        !           288:        {
        !           289:          newpath[depth] = '0' + i;
        !           290:          walk_rtx (XEXP (x, i), newpath);
        !           291:        }
        !           292:       else if (fmt[i] == 'E')
        !           293:        {
        !           294:          int j;
        !           295:          for (j = XVECLEN (x, i) - 1; j >= 0; j--)
        !           296:            {
        !           297:              newpath[depth] = 'a' + j;
        !           298:              walk_rtx (XVECEXP (x, i, j), newpath);
        !           299:            }
        !           300:        }
        !           301:     }
        !           302: }
        !           303: 
        !           304: /* Given a PATH, representing a path down the instruction's
        !           305:    pattern from the root to a certain point, output code to
        !           306:    evaluate to the rtx at that point.  */
        !           307: 
        !           308: static void
        !           309: print_path (path)
        !           310:      char *path;
        !           311: {
        !           312:   register int len = strlen (path);
        !           313:   register int i;
        !           314: 
        !           315:   /* We first write out the operations (XEXP or XVECEXP) in reverse
        !           316:      order, then write "insn", then the indices in forward order.  */
        !           317: 
        !           318:   for (i = len - 1; i >=0 ; i--)
        !           319:     {
        !           320:       if (path[i] >= 'a' && path[i] <= 'z')
        !           321:        printf ("XVECEXP (");
        !           322:       else if (path[i] >= '0' && path[i] <= '9')
        !           323:        printf ("XEXP (");
        !           324:       else
        !           325:        abort ();
        !           326:     }
        !           327:   
        !           328:   printf ("pat");
        !           329: 
        !           330:   for (i = 0; i < len; i++)
        !           331:     {
        !           332:       if (path[i] >= 'a' && path[i] <= 'z')
        !           333:        printf (", 0, %d)", path[i] - 'a');
        !           334:       else if (path[i] >= '0' && path[i] <= '9')
        !           335:        printf (", %d)", path[i] - '0');
        !           336:       else
        !           337:        abort ();
        !           338:     }
        !           339: }
        !           340: 
        !           341: char *
        !           342: xmalloc (size)
        !           343:      unsigned size;
        !           344: {
        !           345:   register char *val = (char *) malloc (size);
        !           346: 
        !           347:   if (val == 0)
        !           348:     fatal ("virtual memory exhausted");
        !           349:   return val;
        !           350: }
        !           351: 
        !           352: char *
        !           353: xrealloc (ptr, size)
        !           354:      char *ptr;
        !           355:      unsigned size;
        !           356: {
        !           357:   char *result = (char *) realloc (ptr, size);
        !           358:   if (!result)
        !           359:     fatal ("virtual memory exhausted");
        !           360:   return result;
        !           361: }
        !           362: 
        !           363: static void
        !           364: fatal (s, a1, a2)
        !           365:      char *s;
        !           366: {
        !           367:   fprintf (stderr, "genextract: ");
        !           368:   fprintf (stderr, s, a1, a2);
        !           369:   fprintf (stderr, "\n");
        !           370:   exit (FATAL_EXIT_CODE);
        !           371: }
        !           372: 
        !           373: /* More 'friendly' abort that prints the line and file.
        !           374:    config.h can #define abort fancy_abort if you like that sort of thing.  */
        !           375: 
        !           376: void
        !           377: fancy_abort ()
        !           378: {
        !           379:   fatal ("Internal gcc abort.");
        !           380: }
        !           381: 
        !           382: static char *
        !           383: copystr (s1)
        !           384:      char *s1;
        !           385: {
        !           386:   register char *tem;
        !           387: 
        !           388:   if (s1 == 0)
        !           389:     return 0;
        !           390: 
        !           391:   tem = (char *) xmalloc (strlen (s1) + 1);
        !           392:   strcpy (tem, s1);
        !           393: 
        !           394:   return tem;
        !           395: }
        !           396: 
        !           397: static void
        !           398: mybzero (b, length)
        !           399:      register char *b;
        !           400:      register unsigned length;
        !           401: {
        !           402:   while (length-- > 0)
        !           403:     *b++ = 0;
        !           404: }
        !           405: 
        !           406: int
        !           407: main (argc, argv)
        !           408:      int argc;
        !           409:      char **argv;
        !           410: {
        !           411:   rtx desc;
        !           412:   FILE *infile;
        !           413:   register int c, i;
        !           414:   struct extraction *p;
        !           415:   struct code_ptr *link;
        !           416: 
        !           417:   obstack_init (rtl_obstack);
        !           418: 
        !           419:   if (argc <= 1)
        !           420:     fatal ("No input file name.");
        !           421: 
        !           422:   infile = fopen (argv[1], "r");
        !           423:   if (infile == 0)
        !           424:     {
        !           425:       perror (argv[1]);
        !           426:       exit (FATAL_EXIT_CODE);
        !           427:     }
        !           428: 
        !           429:   init_rtl ();
        !           430: 
        !           431:   /* Assign sequential codes to all entries in the machine description
        !           432:      in parallel with the tables in insn-output.c.  */
        !           433: 
        !           434:   insn_code_number = 0;
        !           435: 
        !           436:   printf ("/* Generated automatically by the program `genextract'\n\
        !           437: from the machine description file `md'.  */\n\n");
        !           438: 
        !           439:   printf ("#include \"config.h\"\n");
        !           440:   printf ("#include \"rtl.h\"\n\n");
        !           441: 
        !           442:   /* This variable exists only so it can be the "location"
        !           443:      of any missing operand whose numbers are skipped by a given pattern.  */
        !           444:   printf ("static rtx junk;\n");
        !           445: 
        !           446:   printf ("extern rtx recog_operand[];\n");
        !           447:   printf ("extern rtx *recog_operand_loc[];\n");
        !           448:   printf ("extern rtx *recog_dup_loc[];\n");
        !           449:   printf ("extern char recog_dup_num[];\n");
        !           450:   printf ("extern\n#ifdef __GNUC__\n__volatile__\n#endif\n");
        !           451:   printf ("void fatal_insn_not_found ();\n\n");
        !           452: 
        !           453:   printf ("void\ninsn_extract (insn)\n");
        !           454:   printf ("     rtx insn;\n");
        !           455:   printf ("{\n");
        !           456:   printf ("  register rtx *ro = recog_operand;\n");
        !           457:   printf ("  register rtx **ro_loc = recog_operand_loc;\n");
        !           458:   printf ("  rtx pat = PATTERN (insn);\n");
        !           459:   printf ("  switch (INSN_CODE (insn))\n");
        !           460:   printf ("    {\n");
        !           461:   printf ("    case -1:\n");
        !           462:   printf ("      fatal_insn_not_found (insn);\n\n");
        !           463: 
        !           464:   /* Read the machine description.  */
        !           465: 
        !           466:   while (1)
        !           467:     {
        !           468:       c = read_skip_spaces (infile);
        !           469:       if (c == EOF)
        !           470:        break;
        !           471:       ungetc (c, infile);
        !           472: 
        !           473:       desc = read_rtx (infile);
        !           474:       if (GET_CODE (desc) == DEFINE_INSN)
        !           475:        {
        !           476:          gen_insn (desc);
        !           477:          ++insn_code_number;
        !           478:        }
        !           479: 
        !           480:       else if (GET_CODE (desc) == DEFINE_PEEPHOLE)
        !           481:        {
        !           482:          struct code_ptr *link
        !           483:            = (struct code_ptr *) xmalloc (sizeof (struct code_ptr));
        !           484: 
        !           485:          link->insn_code = insn_code_number;
        !           486:          link->next = peepholes;
        !           487:          peepholes = link;
        !           488:          ++insn_code_number;
        !           489:        }
        !           490: 
        !           491:       else if (GET_CODE (desc) == DEFINE_EXPAND
        !           492:               || GET_CODE (desc) == DEFINE_SPLIT)
        !           493:        ++insn_code_number;
        !           494:     }
        !           495: 
        !           496:   /* Write out code to handle peepholes and the insn_codes that it should
        !           497:      be called for.  */
        !           498:   if (peepholes)
        !           499:     {
        !           500:       for (link = peepholes; link; link = link->next)
        !           501:        printf ("    case %d:\n", link->insn_code);
        !           502: 
        !           503:       /* The vector in the insn says how many operands it has.
        !           504:         And all it contains are operands.  In fact, the vector was
        !           505:         created just for the sake of this function.  */
        !           506:       printf ("#if __GNUC__ > 1 && !defined (bcopy)\n");
        !           507:       printf ("#define bcopy(FROM,TO,COUNT) __builtin_memcpy(TO,FROM,COUNT)\n");
        !           508:       printf ("#endif\n");
        !           509:       printf ("      bcopy (&XVECEXP (pat, 0, 0), ro,\n");
        !           510:       printf ("             sizeof (rtx) * XVECLEN (pat, 0));\n");
        !           511:       printf ("      break;\n\n");
        !           512:     }
        !           513: 
        !           514:   /* Write out all the ways to extract insn operands.  */
        !           515:   for (p = extractions; p; p = p->next)
        !           516:     {
        !           517:       for (link = p->insns; link; link = link->next)
        !           518:        printf ("    case %d:\n", link->insn_code);
        !           519: 
        !           520:       for (i = 0; i < p->op_count; i++)
        !           521:        {
        !           522:          if (p->oplocs[i] == 0)
        !           523:            {
        !           524:              printf ("      ro[%d] = const0_rtx;\n", i);
        !           525:              printf ("      ro_loc[%d] = &junk;\n", i);
        !           526:            }
        !           527:          else
        !           528:            {
        !           529:              printf ("      ro[%d] = *(ro_loc[%d] = &", i, i);
        !           530:              print_path (p->oplocs[i]);
        !           531:              printf (");\n");
        !           532:            }
        !           533:        }
        !           534: 
        !           535:       for (i = 0; i < p->dup_count; i++)
        !           536:        {
        !           537:          printf ("      recog_dup_loc[%d] = &", i);
        !           538:          print_path (p->duplocs[i]);
        !           539:          printf (";\n");
        !           540:          printf ("      recog_dup_num[%d] = %d;\n", i, p->dupnums[i]);
        !           541:        }
        !           542: 
        !           543:       printf ("      break;\n\n");
        !           544:     }
        !           545: 
        !           546:   /* This should never be reached.  Note that we would also reach this abort
        !           547:    if we tried to extract something whose INSN_CODE was a DEFINE_EXPAND or
        !           548:    DEFINE_SPLIT, but that is correct.  */
        !           549:   printf ("    default:\n      abort ();\n");
        !           550: 
        !           551:   printf ("    }\n}\n");
        !           552: 
        !           553:   fflush (stdout);
        !           554:   exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
        !           555:   /* NOTREACHED */
        !           556:   return 0;
        !           557: }

unix.superglobalmegacorp.com

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