Annotation of gcc/genextract.c, revision 1.1.1.3

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

unix.superglobalmegacorp.com

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