Annotation of gcc/genextract.c, revision 1.1.1.8

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

unix.superglobalmegacorp.com

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