* gjavah.c (main): Handle --output-class-directory argument.
[official-gcc.git] / gcc / genextract.c
blob00bc571c99133ee7a8f700641c1517b408fcecac
1 /* Generate code from machine description to extract operands from insn as rtl.
2 Copyright (C) 1987, 91, 92, 93, 97, 1998 Free Software Foundation, Inc.
4 This file is part of GNU CC.
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.
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.
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, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
22 #include "hconfig.h"
23 #include "system.h"
24 #include "rtl.h"
25 #include "obstack.h"
26 #include "insn-config.h"
28 static struct obstack obstack;
29 struct obstack *rtl_obstack = &obstack;
31 #define obstack_chunk_alloc xmalloc
32 #define obstack_chunk_free free
34 /* Names for patterns. Need to allow linking with print-rtl. */
35 char **insn_name_ptr;
37 /* This structure contains all the information needed to describe one
38 set of extractions methods. Each method may be used by more than
39 one pattern if the operands are in the same place.
41 The string for each operand describes that path to the operand and
42 contains `0' through `9' when going into an expression and `a' through
43 `z' when going into a vector. We assume here that only the first operand
44 of an rtl expression is a vector. genrecog.c makes the same assumption
45 (and uses the same representation) and it is currently true. */
47 struct extraction
49 int op_count;
50 char *oplocs[MAX_RECOG_OPERANDS];
51 int dup_count;
52 char *duplocs[MAX_DUP_OPERANDS];
53 int dupnums[MAX_DUP_OPERANDS];
54 struct code_ptr *insns;
55 struct extraction *next;
58 /* Holds a single insn code that use an extraction method. */
60 struct code_ptr
62 int insn_code;
63 struct code_ptr *next;
66 static struct extraction *extractions;
68 /* Number instruction patterns handled, starting at 0 for first one. */
70 static int insn_code_number;
72 /* Records the large operand number in this insn. */
74 static int op_count;
76 /* Records the location of any operands using the string format described
77 above. */
79 static char *oplocs[MAX_RECOG_OPERANDS];
81 /* Number the occurrences of MATCH_DUP in each instruction,
82 starting at 0 for the first occurrence. */
84 static int dup_count;
86 /* Records the location of any MATCH_DUP operands. */
88 static char *duplocs[MAX_DUP_OPERANDS];
90 /* Record the operand number of any MATCH_DUPs. */
92 static int dupnums[MAX_DUP_OPERANDS];
94 /* Record the list of insn_codes for peepholes. */
96 static struct code_ptr *peepholes;
98 static void gen_insn PROTO ((rtx));
99 static void walk_rtx PROTO ((rtx, char *));
100 static void print_path PROTO ((char *));
101 char *xmalloc PROTO ((unsigned));
102 char *xrealloc PROTO ((char *, unsigned));
103 static void fatal PVPROTO ((char *, ...))
104 ATTRIBUTE_PRINTF_1 ATTRIBUTE_NORETURN;
105 static char *copystr PROTO ((char *));
106 static void mybzero ();
107 void fancy_abort PROTO ((void)) ATTRIBUTE_NORETURN;
109 static void
110 gen_insn (insn)
111 rtx insn;
113 register int i;
114 register struct extraction *p;
115 register struct code_ptr *link;
117 op_count = 0;
118 dup_count = 0;
120 /* No operands seen so far in this pattern. */
121 mybzero (oplocs, sizeof oplocs);
123 /* Walk the insn's pattern, remembering at all times the path
124 down to the walking point. */
126 if (XVECLEN (insn, 1) == 1)
127 walk_rtx (XVECEXP (insn, 1, 0), "");
128 else
129 for (i = XVECLEN (insn, 1) - 1; i >= 0; i--)
131 char *path = (char *) alloca (2);
133 path[0] = 'a' + i;
134 path[1] = 0;
136 walk_rtx (XVECEXP (insn, 1, i), path);
139 link = (struct code_ptr *) xmalloc (sizeof (struct code_ptr));
140 link->insn_code = insn_code_number;
142 /* See if we find something that already had this extraction method. */
144 for (p = extractions; p; p = p->next)
146 if (p->op_count != op_count || p->dup_count != dup_count)
147 continue;
149 for (i = 0; i < op_count; i++)
150 if (p->oplocs[i] != oplocs[i]
151 && ! (p->oplocs[i] != 0 && oplocs[i] != 0
152 && ! strcmp (p->oplocs[i], oplocs[i])))
153 break;
155 if (i != op_count)
156 continue;
158 for (i = 0; i < dup_count; i++)
159 if (p->dupnums[i] != dupnums[i]
160 || strcmp (p->duplocs[i], duplocs[i]))
161 break;
163 if (i != dup_count)
164 continue;
166 /* This extraction is the same as ours. Just link us in. */
167 link->next = p->insns;
168 p->insns = link;
169 return;
172 /* Otherwise, make a new extraction method. */
174 p = (struct extraction *) xmalloc (sizeof (struct extraction));
175 p->op_count = op_count;
176 p->dup_count = dup_count;
177 p->next = extractions;
178 extractions = p;
179 p->insns = link;
180 link->next = 0;
182 for (i = 0; i < op_count; i++)
183 p->oplocs[i] = oplocs[i];
185 for (i = 0; i < dup_count; i++)
186 p->dupnums[i] = dupnums[i], p->duplocs[i] = duplocs[i];
189 static void
190 walk_rtx (x, path)
191 rtx x;
192 char *path;
194 register RTX_CODE code;
195 register int i;
196 register int len;
197 register char *fmt;
198 int depth = strlen (path);
199 char *newpath;
201 if (x == 0)
202 return;
204 code = GET_CODE (x);
206 switch (code)
208 case PC:
209 case CC0:
210 case CONST_INT:
211 case SYMBOL_REF:
212 return;
214 case MATCH_OPERAND:
215 case MATCH_SCRATCH:
216 oplocs[XINT (x, 0)] = copystr (path);
217 op_count = MAX (op_count, XINT (x, 0) + 1);
218 break;
220 case MATCH_DUP:
221 case MATCH_PAR_DUP:
222 duplocs[dup_count] = copystr (path);
223 dupnums[dup_count] = XINT (x, 0);
224 dup_count++;
225 break;
227 case MATCH_OP_DUP:
228 duplocs[dup_count] = copystr (path);
229 dupnums[dup_count] = XINT (x, 0);
230 dup_count++;
232 newpath = (char *) alloca (depth + 2);
233 strcpy (newpath, path);
234 newpath[depth + 1] = 0;
236 for (i = XVECLEN (x, 1) - 1; i >= 0; i--)
238 newpath[depth] = '0' + i;
239 walk_rtx (XVECEXP (x, 1, i), newpath);
241 return;
243 case MATCH_OPERATOR:
244 oplocs[XINT (x, 0)] = copystr (path);
245 op_count = MAX (op_count, XINT (x, 0) + 1);
247 newpath = (char *) alloca (depth + 2);
248 strcpy (newpath, path);
249 newpath[depth + 1] = 0;
251 for (i = XVECLEN (x, 2) - 1; i >= 0; i--)
253 newpath[depth] = '0' + i;
254 walk_rtx (XVECEXP (x, 2, i), newpath);
256 return;
258 case MATCH_PARALLEL:
259 oplocs[XINT (x, 0)] = copystr (path);
260 op_count = MAX (op_count, XINT (x, 0) + 1);
262 newpath = (char *) alloca (depth + 2);
263 strcpy (newpath, path);
264 newpath[depth + 1] = 0;
266 for (i = XVECLEN (x, 2) - 1; i >= 0; i--)
268 newpath[depth] = 'a' + i;
269 walk_rtx (XVECEXP (x, 2, i), newpath);
271 return;
273 case ADDRESS:
274 walk_rtx (XEXP (x, 0), path);
275 return;
277 default:
278 break;
281 newpath = (char *) alloca (depth + 2);
282 strcpy (newpath, path);
283 newpath[depth + 1] = 0;
285 fmt = GET_RTX_FORMAT (code);
286 len = GET_RTX_LENGTH (code);
287 for (i = 0; i < len; i++)
289 if (fmt[i] == 'e' || fmt[i] == 'u')
291 newpath[depth] = '0' + i;
292 walk_rtx (XEXP (x, i), newpath);
294 else if (fmt[i] == 'E')
296 int j;
297 for (j = XVECLEN (x, i) - 1; j >= 0; j--)
299 newpath[depth] = 'a' + j;
300 walk_rtx (XVECEXP (x, i, j), newpath);
306 /* Given a PATH, representing a path down the instruction's
307 pattern from the root to a certain point, output code to
308 evaluate to the rtx at that point. */
310 static void
311 print_path (path)
312 char *path;
314 register int len = strlen (path);
315 register int i;
317 if (len == 0)
319 /* Don't emit "pat", since we may try to take the address of it,
320 which isn't what is intended. */
321 printf("PATTERN (insn)");
322 return;
325 /* We first write out the operations (XEXP or XVECEXP) in reverse
326 order, then write "insn", then the indices in forward order. */
328 for (i = len - 1; i >=0 ; i--)
330 if (path[i] >= 'a' && path[i] <= 'z')
331 printf ("XVECEXP (");
332 else if (path[i] >= '0' && path[i] <= '9')
333 printf ("XEXP (");
334 else
335 abort ();
338 printf ("pat");
340 for (i = 0; i < len; i++)
342 if (path[i] >= 'a' && path[i] <= 'z')
343 printf (", 0, %d)", path[i] - 'a');
344 else if (path[i] >= '0' && path[i] <= '9')
345 printf (", %d)", path[i] - '0');
346 else
347 abort ();
351 char *
352 xmalloc (size)
353 unsigned size;
355 register char *val = (char *) malloc (size);
357 if (val == 0)
358 fatal ("virtual memory exhausted");
359 return val;
362 char *
363 xrealloc (ptr, size)
364 char *ptr;
365 unsigned size;
367 char *result = (char *) realloc (ptr, size);
368 if (!result)
369 fatal ("virtual memory exhausted");
370 return result;
373 static void
374 fatal VPROTO ((char *format, ...))
376 #ifndef ANSI_PROTOTYPES
377 char *format;
378 #endif
379 va_list ap;
381 VA_START (ap, format);
383 #ifndef ANSI_PROTOTYPES
384 format = va_arg (ap, char *);
385 #endif
387 fprintf (stderr, "genextract: ");
388 vfprintf (stderr, format, ap);
389 va_end (ap);
390 fprintf (stderr, "\n");
391 exit (FATAL_EXIT_CODE);
394 /* More 'friendly' abort that prints the line and file.
395 config.h can #define abort fancy_abort if you like that sort of thing. */
397 void
398 fancy_abort ()
400 fatal ("Internal gcc abort.");
403 static char *
404 copystr (s1)
405 char *s1;
407 register char *tem;
409 if (s1 == 0)
410 return 0;
412 tem = (char *) xmalloc (strlen (s1) + 1);
413 strcpy (tem, s1);
415 return tem;
418 static void
419 mybzero (b, length)
420 register char *b;
421 register unsigned length;
423 while (length-- > 0)
424 *b++ = 0;
428 main (argc, argv)
429 int argc;
430 char **argv;
432 rtx desc;
433 FILE *infile;
434 register int c, i;
435 struct extraction *p;
436 struct code_ptr *link;
438 obstack_init (rtl_obstack);
440 if (argc <= 1)
441 fatal ("No input file name.");
443 infile = fopen (argv[1], "r");
444 if (infile == 0)
446 perror (argv[1]);
447 exit (FATAL_EXIT_CODE);
450 init_rtl ();
452 /* Assign sequential codes to all entries in the machine description
453 in parallel with the tables in insn-output.c. */
455 insn_code_number = 0;
457 printf ("/* Generated automatically by the program `genextract'\n\
458 from the machine description file `md'. */\n\n");
460 printf ("#include \"config.h\"\n");
461 printf ("#include \"system.h\"\n");
462 printf ("#include \"rtl.h\"\n");
463 printf ("#include \"insn-config.h\"\n");
464 printf ("#include \"recog.h\"\n");
465 printf ("#include \"toplev.h\"\n\n");
467 /* This variable exists only so it can be the "location"
468 of any missing operand whose numbers are skipped by a given pattern. */
469 printf ("static rtx junk ATTRIBUTE_UNUSED;\n");
471 printf ("void\ninsn_extract (insn)\n");
472 printf (" rtx insn;\n");
473 printf ("{\n");
474 printf (" register rtx *ro = recog_operand;\n");
475 printf (" register rtx **ro_loc = recog_operand_loc;\n");
476 printf (" rtx pat = PATTERN (insn);\n");
477 printf (" int i ATTRIBUTE_UNUSED;\n\n");
478 printf (" switch (INSN_CODE (insn))\n");
479 printf (" {\n");
480 printf (" case -1:\n");
481 printf (" fatal_insn_not_found (insn);\n\n");
483 /* Read the machine description. */
485 while (1)
487 c = read_skip_spaces (infile);
488 if (c == EOF)
489 break;
490 ungetc (c, infile);
492 desc = read_rtx (infile);
493 if (GET_CODE (desc) == DEFINE_INSN)
495 gen_insn (desc);
496 ++insn_code_number;
499 else if (GET_CODE (desc) == DEFINE_PEEPHOLE)
501 struct code_ptr *link
502 = (struct code_ptr *) xmalloc (sizeof (struct code_ptr));
504 link->insn_code = insn_code_number;
505 link->next = peepholes;
506 peepholes = link;
507 ++insn_code_number;
510 else if (GET_CODE (desc) == DEFINE_EXPAND
511 || GET_CODE (desc) == DEFINE_SPLIT)
512 ++insn_code_number;
515 /* Write out code to handle peepholes and the insn_codes that it should
516 be called for. */
517 if (peepholes)
519 for (link = peepholes; link; link = link->next)
520 printf (" case %d:\n", link->insn_code);
522 /* The vector in the insn says how many operands it has.
523 And all it contains are operands. In fact, the vector was
524 created just for the sake of this function. */
525 printf (" for (i = XVECLEN (pat, 0) - 1; i >= 0; i--)\n");
526 printf (" ro[i] = XVECEXP (pat, 0, i);\n");
527 printf (" break;\n\n");
530 /* Write out all the ways to extract insn operands. */
531 for (p = extractions; p; p = p->next)
533 for (link = p->insns; link; link = link->next)
534 printf (" case %d:\n", link->insn_code);
536 for (i = 0; i < p->op_count; i++)
538 if (p->oplocs[i] == 0)
540 printf (" ro[%d] = const0_rtx;\n", i);
541 printf (" ro_loc[%d] = &junk;\n", i);
543 else
545 printf (" ro[%d] = *(ro_loc[%d] = &", i, i);
546 print_path (p->oplocs[i]);
547 printf (");\n");
551 for (i = 0; i < p->dup_count; i++)
553 printf (" recog_dup_loc[%d] = &", i);
554 print_path (p->duplocs[i]);
555 printf (";\n");
556 printf (" recog_dup_num[%d] = %d;\n", i, p->dupnums[i]);
559 printf (" break;\n\n");
562 /* This should never be reached. Note that we would also reach this abort
563 if we tried to extract something whose INSN_CODE was a DEFINE_EXPAND or
564 DEFINE_SPLIT, but that is correct. */
565 printf (" default:\n abort ();\n");
567 printf (" }\n}\n");
569 fflush (stdout);
570 exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
571 /* NOTREACHED */
572 return 0;