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

Revision 8834, 12.9 KB checked in by ghudson, 28 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r8833, 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 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
280  newpath = (char *) alloca (depth + 2);
281  strcpy (newpath, path);
282  newpath[depth + 1] = 0;
283
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        {
290          newpath[depth] = '0' + i;
291          walk_rtx (XEXP (x, i), newpath);
292        }
293      else if (fmt[i] == 'E')
294        {
295          int j;
296          for (j = XVECLEN (x, i) - 1; j >= 0; j--)
297            {
298              newpath[depth] = 'a' + j;
299              walk_rtx (XVECEXP (x, i, j), newpath);
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
309static void
310print_path (path)
311     char *path;
312{
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--)
320    {
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 ();
327    }
328 
329  printf ("pat");
330
331  for (i = 0; i < len; i++)
332    {
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 ();
339    }
340}
341
342char *
343xmalloc (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
353char *
354xrealloc (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
364static void
365fatal (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
377void
378fancy_abort ()
379{
380  fatal ("Internal gcc abort.");
381}
382
383static char *
384copystr (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
398static void
399mybzero (b, length)
400     register char *b;
401     register unsigned length;
402{
403  while (length-- > 0)
404    *b++ = 0;
405}
406
407int
408main (argc, argv)
409     int argc;
410     char **argv;
411{
412  rtx desc;
413  FILE *infile;
414  register int c, i;
415  struct extraction *p;
416  struct code_ptr *link;
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\
438from 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");
446
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");
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");
459  printf ("    {\n");
460  printf ("    case -1:\n");
461  printf ("      fatal_insn_not_found (insn);\n\n");
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        }
478
479      else if (GET_CODE (desc) == DEFINE_PEEPHOLE)
480        {
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;
487          ++insn_code_number;
488        }
489
490      else if (GET_CODE (desc) == DEFINE_EXPAND
491               || GET_CODE (desc) == DEFINE_SPLIT)
492        ++insn_code_number;
493    }
494
495  /* Write out code to handle peepholes and the insn_codes that it should
496     be called for.  */
497  if (peepholes)
498    {
499      for (link = peepholes; link; link = link->next)
500        printf ("    case %d:\n", link->insn_code);
501
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");
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);
524              printf ("      ro_loc[%d] = &junk;\n", i);
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");
543    }
544
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
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}
Note: See TracBrowser for help on using the repository browser.