386BSD 0.0 development
[unix-history] / usr / src / usr.bin / gcc / cc1 / genextract.c
CommitLineData
eb08ff26
WJ
1/* Generate code from machine description to extract operands from insn as rtl.
2 Copyright (C) 1987 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 1, 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, 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
26struct obstack obstack;
27struct obstack *rtl_obstack = &obstack;
28
29#define obstack_chunk_alloc xmalloc
30#define obstack_chunk_free free
31extern int xmalloc ();
32extern void free ();
33
34/* Number instruction patterns handled, starting at 0 for first one. */
35
36int insn_code_number;
37
38/* Number the occurrences of MATCH_DUP in each instruction,
39 starting at 0 for the first occurrence. */
40
41int dup_count;
42
43/* While tree-walking an instruction pattern, we keep a chain
44 of these `struct link's to record how to get down to the
45 current position. In each one, POS is the operand number,
46 and if the operand is a vector VEC is the element number.
47 VEC is -1 if the operand is not a vector. */
48
49struct link
50{
51 struct link *next;
52 int pos;
53 int vecelt;
54};
55
56void walk_rtx ();
57void print_path ();
58void fatal ();
59void fancy_abort ();
60\f
61void
62gen_insn (insn)
63 rtx insn;
64{
65 register int i;
66
67 dup_count = 0;
68
69 /* Output the function name and argument declaration. */
70 /* It would be cleaner to make `void' the return type
71 but 4.2 vax compiler doesn't accept that in the array
72 that these functions are supposed to go in. */
73 printf ("VOID\nextract_%d (insn)\n rtx insn;\n", insn_code_number);
74 printf ("{\n");
75
76 /* Walk the insn's pattern, remembering at all times the path
77 down to the walking point. */
78
79 if (XVECLEN (insn, 1) == 1)
80 walk_rtx (XVECEXP (insn, 1, 0), 0);
81 else
82 for (i = XVECLEN (insn, 1) - 1; i >= 0; i--)
83 {
84 struct link link;
85 link.next = 0;
86 link.pos = 0;
87 link.vecelt = i;
88 walk_rtx (XVECEXP (insn, 1, i), &link);
89 }
90 printf ("}\n\n");
91}
92
93/* Like gen_insn but handles `define_peephole'. */
94
95void
96gen_peephole (peep)
97 rtx peep;
98{
99 /* Output the function name and argument declaration. */
100 printf ("VOID\nextract_%d (insn)\n rtx insn;\n", insn_code_number);
101 printf ("{\n");
102 /* The vector in the insn says how many operands it has.
103 And all it contains are operands. In fact, the vector was
104 created just for the sake of this function. */
105 printf ("\
106 bcopy (&XVECEXP (insn, 0, 0), recog_operand,\
107 sizeof (rtx) * XVECLEN (insn, 0));\n");
108 printf ("}\n\n");
109}
110\f
111void
112walk_rtx (x, path)
113 rtx x;
114 struct link *path;
115{
116 register RTX_CODE code;
117 register int i;
118 register int len;
119 register char *fmt;
120 struct link link;
121
122 if (x == 0)
123 return;
124
125 code = GET_CODE (x);
126
127 switch (code)
128 {
129 case PC:
130 case CC0:
131 case CONST_INT:
132 case SYMBOL_REF:
133 return;
134
135 case MATCH_OPERAND:
136 printf (" recog_operand[%d] = *(recog_operand_loc[%d]\n = &",
137 XINT (x, 0), XINT (x, 0));
138 print_path (path);
139 printf (");\n");
140 break;
141
142 case MATCH_DUP:
143 printf (" recog_dup_loc[%d] = &", dup_count);
144 print_path (path);
145 printf (";\n");
146 printf (" recog_dup_num[%d] = %d;\n", dup_count, XINT (x, 0));
147 dup_count++;
148 break;
149
150 case MATCH_OPERATOR:
151 printf (" recog_operand[%d] = *(recog_operand_loc[%d]\n = &",
152 XINT (x, 0), XINT (x, 0));
153 print_path (path);
154 printf (");\n");
155 link.next = path;
156 link.vecelt = -1;
157 for (i = XVECLEN (x, 2) - 1; i >= 0; i--)
158 {
159 link.pos = i;
160 walk_rtx (XVECEXP (x, 2, i), &link);
161 }
162 return;
163
164 case ADDRESS:
165 walk_rtx (XEXP (x, 0), path);
166 return;
167 }
168
169 link.next = path;
170 link.vecelt = -1;
171 fmt = GET_RTX_FORMAT (code);
172 len = GET_RTX_LENGTH (code);
173 for (i = 0; i < len; i++)
174 {
175 link.pos = i;
176 if (fmt[i] == 'e' || fmt[i] == 'u')
177 {
178 walk_rtx (XEXP (x, i), &link);
179 }
180 else if (fmt[i] == 'E')
181 {
182 int j;
183 for (j = XVECLEN (x, i) - 1; j >= 0; j--)
184 {
185 link.vecelt = j;
186 walk_rtx (XVECEXP (x, i, j), &link);
187 }
188 }
189 }
190}
191
192/* Given a PATH, representing a path down the instruction's
193 pattern from the root to a certain point, output code to
194 evaluate to the rtx at that point. */
195
196void
197print_path (path)
198 struct link *path;
199{
200 if (path == 0)
201 printf ("insn");
202 else if (path->vecelt >= 0)
203 {
204 printf ("XVECEXP (");
205 print_path (path->next);
206 printf (", %d, %d)", path->pos, path->vecelt);
207 }
208 else
209 {
210 printf ("XEXP (");
211 print_path (path->next);
212 printf (", %d)", path->pos);
213 }
214}
215\f
216int
217xmalloc (size)
218{
219 register int val = malloc (size);
220
221 if (val == 0)
222 fatal ("virtual memory exhausted");
223 return val;
224}
225
226int
227xrealloc (ptr, size)
228 char *ptr;
229 int size;
230{
231 int result = realloc (ptr, size);
232 if (!result)
233 fatal ("virtual memory exhausted");
234 return result;
235}
236
237void
238fatal (s, a1, a2)
239 char *s;
240{
241 fprintf (stderr, "genextract: ");
242 fprintf (stderr, s, a1, a2);
243 fprintf (stderr, "\n");
244 exit (FATAL_EXIT_CODE);
245}
246
247/* More 'friendly' abort that prints the line and file.
248 config.h can #define abort fancy_abort if you like that sort of thing. */
249
250void
251fancy_abort ()
252{
253 fatal ("Internal gcc abort.");
254}
255\f
256int
257main (argc, argv)
258 int argc;
259 char **argv;
260{
261 rtx desc;
262 FILE *infile;
263 extern rtx read_rtx ();
264 register int c, i;
265
266 obstack_init (rtl_obstack);
267
268 if (argc <= 1)
269 fatal ("No input file name.");
270
271 infile = fopen (argv[1], "r");
272 if (infile == 0)
273 {
274 perror (argv[1]);
275 exit (FATAL_EXIT_CODE);
276 }
277
278 init_rtl ();
279
280 /* Assign sequential codes to all entries in the machine description
281 in parallel with the tables in insn-output.c. */
282
283 insn_code_number = 0;
284
285 printf ("/* Generated automatically by the program `genextract'\n\
286from the machine description file `md'. */\n\n");
287
288 printf ("#include \"config.h\"\n");
289 printf ("#include \"rtl.h\"\n\n");
290
291 printf ("extern rtx recog_operand[];\n");
292 printf ("extern rtx *recog_operand_loc[];\n");
293 printf ("extern rtx *recog_dup_loc[];\n");
294 printf ("extern char recog_dup_num[];\n\n");
295
296 /* The extractor functions really should return `void';
297 but old C compilers don't seem to be able to handle the array
298 definition if `void' is used. So use `int' in non-ANSI C compilers. */
299
300 printf ("#ifdef __STDC__\n#define VOID void\n#else\n#define VOID int\n#endif\n\n");
301
302 /* Read the machine description. */
303
304 while (1)
305 {
306 c = read_skip_spaces (infile);
307 if (c == EOF)
308 break;
309 ungetc (c, infile);
310
311 desc = read_rtx (infile);
312 if (GET_CODE (desc) == DEFINE_INSN)
313 {
314 gen_insn (desc);
315 ++insn_code_number;
316 }
317 if (GET_CODE (desc) == DEFINE_PEEPHOLE)
318 {
319 gen_peephole (desc);
320 ++insn_code_number;
321 }
322 if (GET_CODE (desc) == DEFINE_EXPAND)
323 {
324 printf ("VOID extract_%d () {}\n\n", insn_code_number);
325 ++insn_code_number;
326 }
327 }
328
329 printf ("VOID (*insn_extract_fn[]) () =\n{ ");
330 for (i = 0; i < insn_code_number; i++)
331 {
332 if (i % 4 != 0)
333 printf (", ");
334 else if (i != 0)
335 printf (",\n ");
336 printf ("extract_%d", i);
337 }
338 printf ("\n};\n\n");
339
340 printf ("void fatal_insn_not_found ();\n\n");
341 printf ("void\ninsn_extract (insn)\n");
342 printf (" rtx insn;\n");
343 printf ("{\n if (INSN_CODE (insn) == -1) fatal_insn_not_found (insn);\n");
344 printf (" (*insn_extract_fn[INSN_CODE (insn)]) (PATTERN (insn));\n}\n");
345
346 fflush (stdout);
347 exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
348}