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