Annotation of GNUtools/cc/genextract.c, revision 1.1.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.