1 /* Generate code from machine description to extract operands from insn as rtl.
2 Copyright (C) 1987, 1991 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
26 static struct obstack obstack;
27 struct obstack *rtl_obstack = &obstack;
29 #define obstack_chunk_alloc xmalloc
30 #define obstack_chunk_free free
34 /* Number instruction patterns handled, starting at 0 for first one. */
36 static int insn_code_number;
38 /* Number the occurrences of MATCH_DUP in each instruction,
39 starting at 0 for the first occurrence. */
43 /* Record which operand numbers have been seen in the current pattern.
44 This table is made longer as needed. */
46 static char *operand_seen;
48 /* Current allocated length of operand_seen. */
50 static int operand_seen_length;
52 /* Have we got any peephole patterns yet? */
54 static int peephole_seen;
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. */
69 static void walk_rtx ();
70 static void print_path ();
84 /* No operands seen so far in this pattern. */
85 bzero (operand_seen, operand_seen_length);
87 printf (" case %d:\n", insn_code_number);
89 /* Walk the insn's pattern, remembering at all times the path
90 down to the walking point. */
92 if (XVECLEN (insn, 1) == 1)
93 walk_rtx (XVECEXP (insn, 1, 0), 0);
95 for (i = XVECLEN (insn, 1) - 1; i >= 0; i--)
101 walk_rtx (XVECEXP (insn, 1, i), &link);
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--)
110 if (!operand_seen[i])
112 printf (" recog_operand[%d] = const0_rtx;\n", i);
113 printf (" recog_operand_loc[%d] = &junk;\n", i);
115 printf (" break;\n");
118 /* Record that we have seen an operand with number OPNO in this pattern. */
121 mark_operand_seen (opno)
124 if (opno >= operand_seen_length)
126 operand_seen_length *= 2;
127 operand_seen = (char *) xrealloc (operand_seen_length);
130 operand_seen[opno] = 1;
138 register RTX_CODE code;
159 mark_operand_seen (XINT (x, 0));
160 printf (" recog_operand[%d] = *(recog_operand_loc[%d]\n = &",
161 XINT (x, 0), XINT (x, 0));
168 printf (" recog_dup_loc[%d] = &", dup_count);
171 printf (" recog_dup_num[%d] = %d;\n", dup_count, XINT (x, 0));
176 mark_operand_seen (XINT (x, 0));
177 printf (" recog_operand[%d] = *(recog_operand_loc[%d]\n = &",
178 XINT (x, 0), XINT (x, 0));
183 for (i = XVECLEN (x, 2) - 1; i >= 0; i--)
186 walk_rtx (XVECEXP (x, 2, i), &link);
191 mark_operand_seen (XINT (x, 0));
192 printf (" recog_operand[%d] = *(recog_operand_loc[%d]\n = &",
193 XINT (x, 0), XINT (x, 0));
198 for (i = XVECLEN (x, 2) - 1; i >= 0; i--)
201 walk_rtx (XVECEXP (x, 2, i), &link);
206 walk_rtx (XEXP (x, 0), path);
212 fmt = GET_RTX_FORMAT (code);
213 len = GET_RTX_LENGTH (code);
214 for (i = 0; i < len; i++)
217 if (fmt[i] == 'e' || fmt[i] == 'u')
219 walk_rtx (XEXP (x, i), &link);
221 else if (fmt[i] == 'E')
224 for (j = XVECLEN (x, i) - 1; j >= 0; j--)
227 walk_rtx (XVECEXP (x, i, j), &link);
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. */
243 else if (path->vecelt >= 0)
245 printf ("XVECEXP (");
246 print_path (path->next);
247 printf (", %d, %d)", path->pos, path->vecelt);
252 print_path (path->next);
253 printf (", %d)", path->pos);
261 register char *val = (char *) malloc (size);
264 fatal ("virtual memory exhausted");
273 char *result = (char *) realloc (ptr, size);
275 fatal ("virtual memory exhausted");
283 fprintf (stderr, "genextract: ");
284 fprintf (stderr, s, a1, a2);
285 fprintf (stderr, "\n");
286 exit (FATAL_EXIT_CODE);
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. */
295 fatal ("Internal gcc abort.");
305 extern rtx read_rtx ();
308 obstack_init (rtl_obstack);
311 fatal ("No input file name.");
313 infile = fopen (argv[1], "r");
317 exit (FATAL_EXIT_CODE);
322 /* Assign sequential codes to all entries in the machine description
323 in parallel with the tables in insn-output.c. */
325 insn_code_number = 0;
327 operand_seen_length = 40;
328 operand_seen = (char *) xmalloc (40);
330 printf ("/* Generated automatically by the program `genextract'\n\
331 from the machine description file `md'. */\n\n");
333 printf ("#include \"config.h\"\n");
334 printf ("#include \"rtl.h\"\n\n");
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");
345 printf ("void\ninsn_extract (insn)\n");
346 printf (" rtx insn;\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");
354 /* Read the machine description. */
358 c = read_skip_spaces (infile);
363 desc = read_rtx (infile);
364 if (GET_CODE (desc) == DEFINE_INSN)
369 if (GET_CODE (desc) == DEFINE_PEEPHOLE)
371 printf (" case %d: goto peephole;\n", insn_code_number);
375 if (GET_CODE (desc) == DEFINE_EXPAND || GET_CODE (desc) == DEFINE_SPLIT)
377 printf (" case %d: break;\n", insn_code_number);
382 /* This should never be reached. */
383 printf ("\n default:\n abort ();\n");
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");
394 printf (" bcopy (&XVECEXP (insn, 0, 0), recog_operand,\n");
395 printf (" sizeof (rtx) * XVECLEN (insn, 0));\n");
396 printf (" break;\n");
402 exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);