1 /* Generate code from machine description to extract operands from insn as rtl.
2 Copyright (C) 1987, 91-93, 97-98, 1999 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)
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. */
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. */
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. */
50 char *oplocs[MAX_RECOG_OPERANDS];
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. */
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. */
76 /* Records the location of any operands using the string format described
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. */
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, const char *));
100 static void print_path PROTO ((char *));
101 void fatal PVPROTO ((const char *, ...))
102 ATTRIBUTE_PRINTF_1 ATTRIBUTE_NORETURN;
109 register struct extraction *p;
110 register struct code_ptr *link;
115 /* No operands seen so far in this pattern. */
116 memset (oplocs, 0, sizeof oplocs);
118 /* Walk the insn's pattern, remembering at all times the path
119 down to the walking point. */
121 if (XVECLEN (insn, 1) == 1)
122 walk_rtx (XVECEXP (insn, 1, 0), "");
124 for (i = XVECLEN (insn, 1) - 1; i >= 0; i--)
126 char *path = (char *) alloca (2);
131 walk_rtx (XVECEXP (insn, 1, i), path);
134 link = (struct code_ptr *) xmalloc (sizeof (struct code_ptr));
135 link->insn_code = insn_code_number;
137 /* See if we find something that already had this extraction method. */
139 for (p = extractions; p; p = p->next)
141 if (p->op_count != op_count || p->dup_count != dup_count)
144 for (i = 0; i < op_count; i++)
145 if (p->oplocs[i] != oplocs[i]
146 && ! (p->oplocs[i] != 0 && oplocs[i] != 0
147 && ! strcmp (p->oplocs[i], oplocs[i])))
153 for (i = 0; i < dup_count; i++)
154 if (p->dupnums[i] != dupnums[i]
155 || strcmp (p->duplocs[i], duplocs[i]))
161 /* This extraction is the same as ours. Just link us in. */
162 link->next = p->insns;
167 /* Otherwise, make a new extraction method. */
169 p = (struct extraction *) xmalloc (sizeof (struct extraction));
170 p->op_count = op_count;
171 p->dup_count = dup_count;
172 p->next = extractions;
177 for (i = 0; i < op_count; i++)
178 p->oplocs[i] = oplocs[i];
180 for (i = 0; i < dup_count; i++)
181 p->dupnums[i] = dupnums[i], p->duplocs[i] = duplocs[i];
189 register RTX_CODE code;
192 register const char *fmt;
193 int depth = strlen (path);
211 oplocs[XINT (x, 0)] = xstrdup (path);
212 op_count = MAX (op_count, XINT (x, 0) + 1);
217 duplocs[dup_count] = xstrdup (path);
218 dupnums[dup_count] = XINT (x, 0);
223 duplocs[dup_count] = xstrdup (path);
224 dupnums[dup_count] = XINT (x, 0);
227 newpath = (char *) alloca (depth + 2);
228 strcpy (newpath, path);
229 newpath[depth + 1] = 0;
231 for (i = XVECLEN (x, 1) - 1; i >= 0; i--)
233 newpath[depth] = '0' + i;
234 walk_rtx (XVECEXP (x, 1, i), newpath);
239 oplocs[XINT (x, 0)] = xstrdup (path);
240 op_count = MAX (op_count, XINT (x, 0) + 1);
242 newpath = (char *) alloca (depth + 2);
243 strcpy (newpath, path);
244 newpath[depth + 1] = 0;
246 for (i = XVECLEN (x, 2) - 1; i >= 0; i--)
248 newpath[depth] = '0' + i;
249 walk_rtx (XVECEXP (x, 2, i), newpath);
254 oplocs[XINT (x, 0)] = xstrdup (path);
255 op_count = MAX (op_count, XINT (x, 0) + 1);
257 newpath = (char *) alloca (depth + 2);
258 strcpy (newpath, path);
259 newpath[depth + 1] = 0;
261 for (i = XVECLEN (x, 2) - 1; i >= 0; i--)
263 newpath[depth] = 'a' + i;
264 walk_rtx (XVECEXP (x, 2, i), newpath);
269 walk_rtx (XEXP (x, 0), path);
276 newpath = (char *) alloca (depth + 2);
277 strcpy (newpath, path);
278 newpath[depth + 1] = 0;
280 fmt = GET_RTX_FORMAT (code);
281 len = GET_RTX_LENGTH (code);
282 for (i = 0; i < len; i++)
284 if (fmt[i] == 'e' || fmt[i] == 'u')
286 newpath[depth] = '0' + i;
287 walk_rtx (XEXP (x, i), newpath);
289 else if (fmt[i] == 'E')
292 for (j = XVECLEN (x, i) - 1; j >= 0; j--)
294 newpath[depth] = 'a' + j;
295 walk_rtx (XVECEXP (x, i, j), newpath);
301 /* Given a PATH, representing a path down the instruction's
302 pattern from the root to a certain point, output code to
303 evaluate to the rtx at that point. */
309 register int len = strlen (path);
314 /* Don't emit "pat", since we may try to take the address of it,
315 which isn't what is intended. */
316 printf("PATTERN (insn)");
320 /* We first write out the operations (XEXP or XVECEXP) in reverse
321 order, then write "insn", then the indices in forward order. */
323 for (i = len - 1; i >=0 ; i--)
325 if (path[i] >= 'a' && path[i] <= 'z')
326 printf ("XVECEXP (");
327 else if (path[i] >= '0' && path[i] <= '9')
335 for (i = 0; i < len; i++)
337 if (path[i] >= 'a' && path[i] <= 'z')
338 printf (", 0, %d)", path[i] - 'a');
339 else if (path[i] >= '0' && path[i] <= '9')
340 printf (", %d)", path[i] - '0');
350 register PTR val = (PTR) malloc (size);
353 fatal ("virtual memory exhausted");
364 ptr = (PTR) realloc (old, size);
366 ptr = (PTR) malloc (size);
368 fatal ("virtual memory exhausted");
373 fatal VPROTO ((const char *format, ...))
375 #ifndef ANSI_PROTOTYPES
380 VA_START (ap, format);
382 #ifndef ANSI_PROTOTYPES
383 format = va_arg (ap, const char *);
386 fprintf (stderr, "genextract: ");
387 vfprintf (stderr, format, ap);
389 fprintf (stderr, "\n");
390 exit (FATAL_EXIT_CODE);
397 register size_t len = strlen (input) + 1;
398 register char *output = xmalloc (len);
399 memcpy (output, input, len);
411 struct extraction *p;
412 struct code_ptr *link;
414 obstack_init (rtl_obstack);
417 fatal ("No input file name.");
419 infile = fopen (argv[1], "r");
423 exit (FATAL_EXIT_CODE);
428 /* Assign sequential codes to all entries in the machine description
429 in parallel with the tables in insn-output.c. */
431 insn_code_number = 0;
433 printf ("/* Generated automatically by the program `genextract'\n\
434 from the machine description file `md'. */\n\n");
436 printf ("#include \"config.h\"\n");
437 printf ("#include \"system.h\"\n");
438 printf ("#include \"rtl.h\"\n");
439 printf ("#include \"insn-config.h\"\n");
440 printf ("#include \"recog.h\"\n");
441 printf ("#include \"toplev.h\"\n\n");
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 ATTRIBUTE_UNUSED;\n");
447 printf ("void\ninsn_extract (insn)\n");
448 printf (" rtx insn;\n");
450 printf (" register rtx *ro = recog_operand;\n");
451 printf (" register rtx **ro_loc = recog_operand_loc;\n");
452 printf (" rtx pat = PATTERN (insn);\n");
453 printf (" int i ATTRIBUTE_UNUSED;\n\n");
454 printf (" memset (ro, 0, sizeof (*ro) * MAX_RECOG_OPERANDS);\n");
455 printf (" memset (ro_loc, 0, sizeof (*ro_loc) * MAX_RECOG_OPERANDS);\n");
456 printf (" switch (INSN_CODE (insn))\n");
458 printf (" case -1:\n");
459 printf (" fatal_insn_not_found (insn);\n\n");
461 /* Read the machine description. */
465 c = read_skip_spaces (infile);
470 desc = read_rtx (infile);
471 if (GET_CODE (desc) == DEFINE_INSN)
477 else if (GET_CODE (desc) == DEFINE_PEEPHOLE)
479 struct code_ptr *link
480 = (struct code_ptr *) xmalloc (sizeof (struct code_ptr));
482 link->insn_code = insn_code_number;
483 link->next = peepholes;
488 else if (GET_CODE (desc) == DEFINE_EXPAND
489 || GET_CODE (desc) == DEFINE_SPLIT)
493 /* Write out code to handle peepholes and the insn_codes that it should
497 for (link = peepholes; link; link = link->next)
498 printf (" case %d:\n", link->insn_code);
500 /* The vector in the insn says how many operands it has.
501 And all it contains are operands. In fact, the vector was
502 created just for the sake of this function. */
503 printf (" for (i = XVECLEN (pat, 0) - 1; i >= 0; i--)\n");
504 printf (" ro[i] = XVECEXP (pat, 0, i);\n");
505 printf (" break;\n\n");
508 /* Write out all the ways to extract insn operands. */
509 for (p = extractions; p; p = p->next)
511 for (link = p->insns; link; link = link->next)
512 printf (" case %d:\n", link->insn_code);
514 for (i = 0; i < p->op_count; i++)
516 if (p->oplocs[i] == 0)
518 printf (" ro[%d] = const0_rtx;\n", i);
519 printf (" ro_loc[%d] = &junk;\n", i);
523 printf (" ro[%d] = *(ro_loc[%d] = &", i, i);
524 print_path (p->oplocs[i]);
529 for (i = 0; i < p->dup_count; i++)
531 printf (" recog_dup_loc[%d] = &", i);
532 print_path (p->duplocs[i]);
534 printf (" recog_dup_num[%d] = %d;\n", i, p->dupnums[i]);
537 printf (" break;\n\n");
540 /* This should never be reached. Note that we would also reach this abort
541 if we tried to extract something whose INSN_CODE was a DEFINE_EXPAND or
542 DEFINE_SPLIT, but that is correct. */
543 printf (" default:\n abort ();\n");
548 exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);