OSDN Git Service

*** empty log message ***
[pf3gnuchains/gcc-fork.git] / gcc / genextract.c
1 /* Generate code from machine description to extract operands from insn as rtl.
2    Copyright (C) 1987, 1991 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 "config.h"
23 #include "rtl.h"
24 #include "obstack.h"
25
26 static struct obstack obstack;
27 struct obstack *rtl_obstack = &obstack;
28
29 #define obstack_chunk_alloc xmalloc
30 #define obstack_chunk_free free
31
32 extern void free ();
33
34 /* Number instruction patterns handled, starting at 0 for first one.  */
35
36 static int insn_code_number;
37
38 /* Number the occurrences of MATCH_DUP in each instruction,
39    starting at 0 for the first occurrence.  */
40
41 static int dup_count;
42
43 /* Record which operand numbers have been seen in the current pattern.
44    This table is made longer as needed.  */
45
46 static char *operand_seen;
47
48 /* Current allocated length of operand_seen.  */
49
50 static int operand_seen_length;
51
52 /* Have we got any peephole patterns yet?  */
53
54 static int peephole_seen;
55
56 /* While tree-walking an instruction pattern, we keep a chain
57    of these `struct link's to record how to get down to the
58    current position.  In each one, POS is the operand number,
59    and if the operand is a vector VEC is the element number.
60    VEC is -1 if the operand is not a vector.  */
61
62 struct link
63 {
64   struct link *next;
65   int pos;
66   int vecelt;
67 };
68
69 static void walk_rtx ();
70 static void print_path ();
71 char *xmalloc ();
72 char *xrealloc ();
73 static void fatal ();
74 void fancy_abort ();
75 \f
76 static void
77 gen_insn (insn)
78      rtx insn;
79 {
80   register int i;
81
82   dup_count = 0;
83
84   /* No operands seen so far in this pattern.  */
85   bzero (operand_seen, operand_seen_length);
86
87   printf ("    case %d:\n", insn_code_number);
88
89   /* Walk the insn's pattern, remembering at all times the path
90      down to the walking point.  */
91
92   if (XVECLEN (insn, 1) == 1)
93     walk_rtx (XVECEXP (insn, 1, 0), 0);
94   else
95     for (i = XVECLEN (insn, 1) - 1; i >= 0; i--)
96       {
97         struct link link;
98         link.next = 0;
99         link.pos = 0;
100         link.vecelt = i;
101         walk_rtx (XVECEXP (insn, 1, i), &link);
102       }
103
104   /* If the operand numbers used in the pattern are not consecutive,
105      don't leave an operand uninitialized.  */
106   for (i = operand_seen_length - 1; i >= 0; i--)
107     if (operand_seen[i])
108       break;
109   for (; i >= 0; i--)
110     if (!operand_seen[i])
111       {
112         printf ("      recog_operand[%d] = const0_rtx;\n", i);
113         printf ("      recog_operand_loc[%d] = &junk;\n", i);
114       }
115   printf ("      break;\n");
116 }
117 \f
118 /* Record that we have seen an operand with number OPNO in this pattern.  */
119
120 static void
121 mark_operand_seen (opno)
122      int opno;
123 {
124   if (opno >= operand_seen_length)
125     {
126       operand_seen_length *= 2;
127       operand_seen = (char *) xrealloc (operand_seen_length);
128     }
129
130   operand_seen[opno] = 1;
131 }
132
133 static void
134 walk_rtx (x, path)
135      rtx x;
136      struct link *path;
137 {
138   register RTX_CODE code;
139   register int i;
140   register int len;
141   register char *fmt;
142   struct link link;
143
144   if (x == 0)
145     return;
146
147   code = GET_CODE (x);
148
149   switch (code)
150     {
151     case PC:
152     case CC0:
153     case CONST_INT:
154     case SYMBOL_REF:
155       return;
156
157     case MATCH_OPERAND:
158     case MATCH_SCRATCH:
159       mark_operand_seen (XINT (x, 0));
160       printf ("      recog_operand[%d] = *(recog_operand_loc[%d]\n        = &",
161               XINT (x, 0), XINT (x, 0));
162       print_path (path);
163       printf (");\n");
164       break;
165
166     case MATCH_DUP:
167     case MATCH_OP_DUP:
168       printf ("      recog_dup_loc[%d] = &", dup_count);
169       print_path (path);
170       printf (";\n");
171       printf ("      recog_dup_num[%d] = %d;\n", dup_count, XINT (x, 0));
172       dup_count++;
173       break;
174
175     case MATCH_OPERATOR:
176       mark_operand_seen (XINT (x, 0));
177       printf ("      recog_operand[%d] = *(recog_operand_loc[%d]\n        = &",
178               XINT (x, 0), XINT (x, 0));
179       print_path (path);
180       printf (");\n");
181       link.next = path;
182       link.vecelt = -1;
183       for (i = XVECLEN (x, 2) - 1; i >= 0; i--)
184         {
185           link.pos = i;
186           walk_rtx (XVECEXP (x, 2, i), &link);
187         }
188       return;
189
190     case MATCH_PARALLEL:
191       mark_operand_seen (XINT (x, 0));
192       printf ("      recog_operand[%d] = *(recog_operand_loc[%d]\n        = &",
193               XINT (x, 0), XINT (x, 0));
194       print_path (path);
195       printf (");\n");
196       link.next = path;
197       link.pos = 0;
198       for (i = XVECLEN (x, 2) - 1; i >= 0; i--)
199         {
200           link.vecelt = i;
201           walk_rtx (XVECEXP (x, 2, i), &link);
202         }
203       return;
204
205     case ADDRESS:
206       walk_rtx (XEXP (x, 0), path);
207       return;
208     }
209
210   link.next = path;
211   link.vecelt = -1;
212   fmt = GET_RTX_FORMAT (code);
213   len = GET_RTX_LENGTH (code);
214   for (i = 0; i < len; i++)
215     {
216       link.pos = i;
217       if (fmt[i] == 'e' || fmt[i] == 'u')
218         {
219           walk_rtx (XEXP (x, i), &link);
220         }
221       else if (fmt[i] == 'E')
222         {
223           int j;
224           for (j = XVECLEN (x, i) - 1; j >= 0; j--)
225             {
226               link.vecelt = j;
227               walk_rtx (XVECEXP (x, i, j), &link);
228             }
229         }
230     }
231 }
232
233 /* Given a PATH, representing a path down the instruction's
234    pattern from the root to a certain point, output code to
235    evaluate to the rtx at that point.  */
236
237 static void
238 print_path (path)
239      struct link *path;
240 {
241   if (path == 0)
242     printf ("insn");
243   else if (path->vecelt >= 0)
244     {
245       printf ("XVECEXP (");
246       print_path (path->next);
247       printf (", %d, %d)", path->pos, path->vecelt);
248     }
249   else
250     {
251       printf ("XEXP (");
252       print_path (path->next);
253       printf (", %d)", path->pos);
254     }
255 }
256 \f
257 char *
258 xmalloc (size)
259      unsigned size;
260 {
261   register char *val = (char *) malloc (size);
262
263   if (val == 0)
264     fatal ("virtual memory exhausted");
265   return val;
266 }
267
268 char *
269 xrealloc (ptr, size)
270      char *ptr;
271      unsigned size;
272 {
273   char *result = (char *) realloc (ptr, size);
274   if (!result)
275     fatal ("virtual memory exhausted");
276   return result;
277 }
278
279 static void
280 fatal (s, a1, a2)
281      char *s;
282 {
283   fprintf (stderr, "genextract: ");
284   fprintf (stderr, s, a1, a2);
285   fprintf (stderr, "\n");
286   exit (FATAL_EXIT_CODE);
287 }
288
289 /* More 'friendly' abort that prints the line and file.
290    config.h can #define abort fancy_abort if you like that sort of thing.  */
291
292 void
293 fancy_abort ()
294 {
295   fatal ("Internal gcc abort.");
296 }
297 \f
298 int
299 main (argc, argv)
300      int argc;
301      char **argv;
302 {
303   rtx desc;
304   FILE *infile;
305   extern rtx read_rtx ();
306   register int c, i;
307
308   obstack_init (rtl_obstack);
309
310   if (argc <= 1)
311     fatal ("No input file name.");
312
313   infile = fopen (argv[1], "r");
314   if (infile == 0)
315     {
316       perror (argv[1]);
317       exit (FATAL_EXIT_CODE);
318     }
319
320   init_rtl ();
321
322   /* Assign sequential codes to all entries in the machine description
323      in parallel with the tables in insn-output.c.  */
324
325   insn_code_number = 0;
326
327   operand_seen_length = 40;
328   operand_seen = (char *) xmalloc (40);
329
330   printf ("/* Generated automatically by the program `genextract'\n\
331 from the machine description file `md'.  */\n\n");
332
333   printf ("#include \"config.h\"\n");
334   printf ("#include \"rtl.h\"\n\n");
335
336   /* This variable exists only so it can be the "location"
337      of any missing operand whose numbers are skipped by a given pattern.  */
338   printf ("static rtx junk;\n");
339   printf ("extern rtx recog_operand[];\n");
340   printf ("extern rtx *recog_operand_loc[];\n");
341   printf ("extern rtx *recog_dup_loc[];\n");
342   printf ("extern char recog_dup_num[];\n");
343   printf ("extern void fatal_insn_not_found ();\n\n");
344
345   printf ("void\ninsn_extract (insn)\n");
346   printf ("     rtx insn;\n");
347   printf ("{\n");
348   printf ("  int insn_code = INSN_CODE (insn);\n");
349   printf ("  if (insn_code == -1) fatal_insn_not_found (insn);\n");
350   printf ("  insn = PATTERN (insn);\n");
351   printf ("  switch (insn_code)\n");
352   printf ("    {\n");
353
354   /* Read the machine description.  */
355
356   while (1)
357     {
358       c = read_skip_spaces (infile);
359       if (c == EOF)
360         break;
361       ungetc (c, infile);
362
363       desc = read_rtx (infile);
364       if (GET_CODE (desc) == DEFINE_INSN)
365         {
366           gen_insn (desc);
367           ++insn_code_number;
368         }
369       if (GET_CODE (desc) == DEFINE_PEEPHOLE)
370         {
371           printf ("    case %d: goto peephole;\n", insn_code_number);
372           ++insn_code_number;
373           ++peephole_seen;
374         }
375       if (GET_CODE (desc) == DEFINE_EXPAND || GET_CODE (desc) == DEFINE_SPLIT)
376         {
377           printf ("    case %d: break;\n", insn_code_number);
378           ++insn_code_number;
379         }
380     }
381
382   /* This should never be reached.  */
383   printf ("\n    default:\n      abort ();\n");
384
385   if (peephole_seen)
386     {
387       /* The vector in the insn says how many operands it has.
388          And all it contains are operands.  In fact, the vector was
389          created just for the sake of this function.  */
390       printf ("    peephole:\n");
391       printf ("#if __GNUC__ > 1 && !defined (bcopy)\n");
392       printf ("#define bcopy(FROM,TO,COUNT) __builtin_memcpy(TO,FROM,COUNT)\n");
393       printf ("#endif\n");
394       printf ("      bcopy (&XVECEXP (insn, 0, 0), recog_operand,\n");
395       printf ("             sizeof (rtx) * XVECLEN (insn, 0));\n");
396       printf ("      break;\n");
397     }
398
399   printf ("    }\n}\n");
400
401   fflush (stdout);
402   exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
403   /* NOTREACHED */
404   return 0;
405 }