source: trunk/third/gcc/genextract.c @ 11288

Revision 11288, 12.8 KB checked in by ghudson, 26 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r11287, which included commits to RCS files with non-trunk default branches.
Line 
1/* Generate code from machine description to extract operands from insn as rtl.
2   Copyright (C) 1987, 1991, 1992, 1993, 1997 Free Software Foundation, Inc.
3
4This file is part of GNU CC.
5
6GNU CC is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11GNU CC is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU CC; see the file COPYING.  If not, write to
18the Free Software Foundation, 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA.  */
20
21
22#include <stdio.h>
23#include "hconfig.h"
24#include "rtl.h"
25#include "obstack.h"
26#include "insn-config.h"
27
28static struct obstack obstack;
29struct obstack *rtl_obstack = &obstack;
30
31#define obstack_chunk_alloc xmalloc
32#define obstack_chunk_free free
33
34extern void free ();
35extern rtx read_rtx ();
36
37/* Names for patterns.  Need to allow linking with print-rtl.  */
38char **insn_name_ptr;
39
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
50struct 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
63struct code_ptr
64{
65  int insn_code;
66  struct code_ptr *next;
67};
68
69static struct extraction *extractions;
70
71/* Number instruction patterns handled, starting at 0 for first one.  */
72
73static int insn_code_number;
74
75/* Records the large operand number in this insn.  */
76
77static int op_count;
78
79/* Records the location of any operands using the string format described
80   above.  */
81
82static char *oplocs[MAX_RECOG_OPERANDS];
83
84/* Number the occurrences of MATCH_DUP in each instruction,
85   starting at 0 for the first occurrence.  */
86
87static int dup_count;
88
89/* Records the location of any MATCH_DUP operands.  */
90
91static char *duplocs[MAX_DUP_OPERANDS];
92
93/* Record the operand number of any MATCH_DUPs.  */
94
95static int dupnums[MAX_DUP_OPERANDS];
96
97/* Record the list of insn_codes for peepholes.  */
98
99static struct code_ptr *peepholes;
100
101static void walk_rtx ();
102static void print_path ();
103char *xmalloc ();
104char *xrealloc ();
105static void fatal ();
106static char *copystr ();
107static void mybzero ();
108void fancy_abort ();
109
110static void
111gen_insn (insn)
112     rtx insn;
113{
114  register int i;
115  register struct extraction *p;
116  register struct code_ptr *link;
117
118  op_count = 0;
119  dup_count = 0;
120
121  /* No operands seen so far in this pattern.  */
122  mybzero (oplocs, sizeof oplocs);
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)
128    walk_rtx (XVECEXP (insn, 1, 0), "");
129  else
130    for (i = XVECLEN (insn, 1) - 1; i >= 0; i--)
131      {
132        char *path = (char *) alloca (2);
133
134        path[0] = 'a' + i;
135        path[1] = 0;
136
137        walk_rtx (XVECEXP (insn, 1, i), path);
138      }
139
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)
146    {
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;
171    }
172
173  /* Otherwise, make a new extraction method.  */
174
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
190static void
191walk_rtx (x, path)
192     rtx x;
193     char *path;
194{
195  register RTX_CODE code;
196  register int i;
197  register int len;
198  register char *fmt;
199  register struct code_ptr *link;
200  int depth = strlen (path);
201  char *newpath;
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:
218      oplocs[XINT (x, 0)] = copystr (path);
219      op_count = MAX (op_count, XINT (x, 0) + 1);
220      break;
221
222    case MATCH_DUP:
223    case MATCH_PAR_DUP:
224      duplocs[dup_count] = copystr (path);
225      dupnums[dup_count] = XINT (x, 0);
226      dup_count++;
227      break;
228
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     
245    case MATCH_OPERATOR:
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
253      for (i = XVECLEN (x, 2) - 1; i >= 0; i--)
254        {
255          newpath[depth] = '0' + i;
256          walk_rtx (XVECEXP (x, 2, i), newpath);
257        }
258      return;
259
260    case MATCH_PARALLEL:
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
268      for (i = XVECLEN (x, 2) - 1; i >= 0; i--)
269        {
270          newpath[depth] = 'a' + i;
271          walk_rtx (XVECEXP (x, 2, i), newpath);
272        }
273      return;
274
275    case ADDRESS:
276      walk_rtx (XEXP (x, 0), path);
277      return;
278
279    default:
280      break;
281    }
282
283  newpath = (char *) alloca (depth + 2);
284  strcpy (newpath, path);
285  newpath[depth + 1] = 0;
286
287  fmt = GET_RTX_FORMAT (code);
288  len = GET_RTX_LENGTH (code);
289  for (i = 0; i < len; i++)
290    {
291      if (fmt[i] == 'e' || fmt[i] == 'u')
292        {
293          newpath[depth] = '0' + i;
294          walk_rtx (XEXP (x, i), newpath);
295        }
296      else if (fmt[i] == 'E')
297        {
298          int j;
299          for (j = XVECLEN (x, i) - 1; j >= 0; j--)
300            {
301              newpath[depth] = 'a' + j;
302              walk_rtx (XVECEXP (x, i, j), newpath);
303            }
304        }
305    }
306}
307
308/* Given a PATH, representing a path down the instruction's
309   pattern from the root to a certain point, output code to
310   evaluate to the rtx at that point.  */
311
312static void
313print_path (path)
314     char *path;
315{
316  register int len = strlen (path);
317  register int i;
318
319  /* We first write out the operations (XEXP or XVECEXP) in reverse
320     order, then write "insn", then the indices in forward order.  */
321
322  for (i = len - 1; i >=0 ; i--)
323    {
324      if (path[i] >= 'a' && path[i] <= 'z')
325        printf ("XVECEXP (");
326      else if (path[i] >= '0' && path[i] <= '9')
327        printf ("XEXP (");
328      else
329        abort ();
330    }
331 
332  printf ("pat");
333
334  for (i = 0; i < len; i++)
335    {
336      if (path[i] >= 'a' && path[i] <= 'z')
337        printf (", 0, %d)", path[i] - 'a');
338      else if (path[i] >= '0' && path[i] <= '9')
339        printf (", %d)", path[i] - '0');
340      else
341        abort ();
342    }
343}
344
345char *
346xmalloc (size)
347     unsigned size;
348{
349  register char *val = (char *) malloc (size);
350
351  if (val == 0)
352    fatal ("virtual memory exhausted");
353  return val;
354}
355
356char *
357xrealloc (ptr, size)
358     char *ptr;
359     unsigned size;
360{
361  char *result = (char *) realloc (ptr, size);
362  if (!result)
363    fatal ("virtual memory exhausted");
364  return result;
365}
366
367static void
368fatal (s, a1, a2)
369     char *s;
370{
371  fprintf (stderr, "genextract: ");
372  fprintf (stderr, s, a1, a2);
373  fprintf (stderr, "\n");
374  exit (FATAL_EXIT_CODE);
375}
376
377/* More 'friendly' abort that prints the line and file.
378   config.h can #define abort fancy_abort if you like that sort of thing.  */
379
380void
381fancy_abort ()
382{
383  fatal ("Internal gcc abort.");
384}
385
386static char *
387copystr (s1)
388     char *s1;
389{
390  register char *tem;
391
392  if (s1 == 0)
393    return 0;
394
395  tem = (char *) xmalloc (strlen (s1) + 1);
396  strcpy (tem, s1);
397
398  return tem;
399}
400
401static void
402mybzero (b, length)
403     register char *b;
404     register unsigned length;
405{
406  while (length-- > 0)
407    *b++ = 0;
408}
409
410int
411main (argc, argv)
412     int argc;
413     char **argv;
414{
415  rtx desc;
416  FILE *infile;
417  register int c, i;
418  struct extraction *p;
419  struct code_ptr *link;
420
421  obstack_init (rtl_obstack);
422
423  if (argc <= 1)
424    fatal ("No input file name.");
425
426  infile = fopen (argv[1], "r");
427  if (infile == 0)
428    {
429      perror (argv[1]);
430      exit (FATAL_EXIT_CODE);
431    }
432
433  init_rtl ();
434
435  /* Assign sequential codes to all entries in the machine description
436     in parallel with the tables in insn-output.c.  */
437
438  insn_code_number = 0;
439
440  printf ("/* Generated automatically by the program `genextract'\n\
441from the machine description file `md'.  */\n\n");
442
443  printf ("#include \"config.h\"\n");
444  printf ("#include <stdio.h>\n");
445  printf ("#include \"rtl.h\"\n\n");
446
447  /* This variable exists only so it can be the "location"
448     of any missing operand whose numbers are skipped by a given pattern.  */
449  printf ("static rtx junk;\n");
450
451  printf ("extern rtx recog_operand[];\n");
452  printf ("extern rtx *recog_operand_loc[];\n");
453  printf ("extern rtx *recog_dup_loc[];\n");
454  printf ("extern char recog_dup_num[];\n");
455
456  printf ("void\ninsn_extract (insn)\n");
457  printf ("     rtx insn;\n");
458  printf ("{\n");
459  printf ("  register rtx *ro = recog_operand;\n");
460  printf ("  register rtx **ro_loc = recog_operand_loc;\n");
461  printf ("  rtx pat = PATTERN (insn);\n");
462  printf ("  int i;\n\n");
463  printf ("  switch (INSN_CODE (insn))\n");
464  printf ("    {\n");
465  printf ("    case -1:\n");
466  printf ("      fatal_insn_not_found (insn);\n\n");
467
468  /* Read the machine description.  */
469
470  while (1)
471    {
472      c = read_skip_spaces (infile);
473      if (c == EOF)
474        break;
475      ungetc (c, infile);
476
477      desc = read_rtx (infile);
478      if (GET_CODE (desc) == DEFINE_INSN)
479        {
480          gen_insn (desc);
481          ++insn_code_number;
482        }
483
484      else if (GET_CODE (desc) == DEFINE_PEEPHOLE)
485        {
486          struct code_ptr *link
487            = (struct code_ptr *) xmalloc (sizeof (struct code_ptr));
488
489          link->insn_code = insn_code_number;
490          link->next = peepholes;
491          peepholes = link;
492          ++insn_code_number;
493        }
494
495      else if (GET_CODE (desc) == DEFINE_EXPAND
496               || GET_CODE (desc) == DEFINE_SPLIT)
497        ++insn_code_number;
498    }
499
500  /* Write out code to handle peepholes and the insn_codes that it should
501     be called for.  */
502  if (peepholes)
503    {
504      for (link = peepholes; link; link = link->next)
505        printf ("    case %d:\n", link->insn_code);
506
507      /* The vector in the insn says how many operands it has.
508         And all it contains are operands.  In fact, the vector was
509         created just for the sake of this function.  */
510      printf ("      for (i = XVECLEN (pat, 0); i >= 0; i--)\n");
511      printf ("          ro[i] = XVECEXP (pat, 0, i);\n");
512      printf ("      break;\n\n");
513    }
514
515  /* Write out all the ways to extract insn operands.  */
516  for (p = extractions; p; p = p->next)
517    {
518      for (link = p->insns; link; link = link->next)
519        printf ("    case %d:\n", link->insn_code);
520
521      for (i = 0; i < p->op_count; i++)
522        {
523          if (p->oplocs[i] == 0)
524            {
525              printf ("      ro[%d] = const0_rtx;\n", i);
526              printf ("      ro_loc[%d] = &junk;\n", i);
527            }
528          else
529            {
530              printf ("      ro[%d] = *(ro_loc[%d] = &", i, i);
531              print_path (p->oplocs[i]);
532              printf (");\n");
533            }
534        }
535
536      for (i = 0; i < p->dup_count; i++)
537        {
538          printf ("      recog_dup_loc[%d] = &", i);
539          print_path (p->duplocs[i]);
540          printf (";\n");
541          printf ("      recog_dup_num[%d] = %d;\n", i, p->dupnums[i]);
542        }
543
544      printf ("      break;\n\n");
545    }
546
547  /* This should never be reached.  Note that we would also reach this abort
548   if we tried to extract something whose INSN_CODE was a DEFINE_EXPAND or
549   DEFINE_SPLIT, but that is correct.  */
550  printf ("    default:\n      abort ();\n");
551
552  printf ("    }\n}\n");
553
554  fflush (stdout);
555  exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
556  /* NOTREACHED */
557  return 0;
558}
Note: See TracBrowser for help on using the repository browser.