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 ();
74 static void mybzero ();
85 /* No operands seen so far in this pattern. */
86 mybzero (operand_seen, operand_seen_length);
88 printf (" case %d:\n", insn_code_number);
90 /* Walk the insn's pattern, remembering at all times the path
91 down to the walking point. */
93 if (XVECLEN (insn, 1) == 1)
94 walk_rtx (XVECEXP (insn, 1, 0), 0);
96 for (i = XVECLEN (insn, 1) - 1; i >= 0; i--)
102 walk_rtx (XVECEXP (insn, 1, i), &link);
105 /* If the operand numbers used in the pattern are not consecutive,
106 don't leave an operand uninitialized. */
107 for (i = operand_seen_length - 1; i >= 0; i--)
111 if (!operand_seen[i])
113 printf (" ro[%d] = const0_rtx;\n", i);
114 printf (" ro_loc[%d] = &junk;\n", i);
116 printf (" break;\n");
119 /* Record that we have seen an operand with number OPNO in this pattern. */
122 mark_operand_seen (opno)
125 if (opno >= operand_seen_length)
127 operand_seen_length *= 2;
128 operand_seen = (char *) xrealloc (operand_seen, operand_seen_length);
131 operand_seen[opno] = 1;
139 register RTX_CODE code;
160 mark_operand_seen (XINT (x, 0));
161 printf (" ro[%d] = *(ro_loc[%d] = &",
162 XINT (x, 0), XINT (x, 0));
169 printf (" recog_dup_loc[%d] = &", dup_count);
172 printf (" recog_dup_num[%d] = %d;\n", dup_count, XINT (x, 0));
177 mark_operand_seen (XINT (x, 0));
178 printf (" ro[%d] = *(ro_loc[%d]\n = &",
179 XINT (x, 0), XINT (x, 0));
184 for (i = XVECLEN (x, 2) - 1; i >= 0; i--)
187 walk_rtx (XVECEXP (x, 2, i), &link);
192 mark_operand_seen (XINT (x, 0));
193 printf (" ro[%d] = *(ro_loc[%d]\n = &",
194 XINT (x, 0), XINT (x, 0));
199 for (i = XVECLEN (x, 2) - 1; i >= 0; i--)
202 walk_rtx (XVECEXP (x, 2, i), &link);
207 walk_rtx (XEXP (x, 0), path);
213 fmt = GET_RTX_FORMAT (code);
214 len = GET_RTX_LENGTH (code);
215 for (i = 0; i < len; i++)
218 if (fmt[i] == 'e' || fmt[i] == 'u')
220 walk_rtx (XEXP (x, i), &link);
222 else if (fmt[i] == 'E')
225 for (j = XVECLEN (x, i) - 1; j >= 0; j--)
228 walk_rtx (XVECEXP (x, i, j), &link);
234 /* Given a PATH, representing a path down the instruction's
235 pattern from the root to a certain point, output code to
236 evaluate to the rtx at that point. */
244 else if (path->vecelt >= 0)
246 printf ("XVECEXP (");
247 print_path (path->next);
248 printf (", %d, %d)", path->pos, path->vecelt);
253 print_path (path->next);
254 printf (", %d)", path->pos);
262 register char *val = (char *) malloc (size);
265 fatal ("virtual memory exhausted");
274 char *result = (char *) realloc (ptr, size);
276 fatal ("virtual memory exhausted");
284 fprintf (stderr, "genextract: ");
285 fprintf (stderr, s, a1, a2);
286 fprintf (stderr, "\n");
287 exit (FATAL_EXIT_CODE);
290 /* More 'friendly' abort that prints the line and file.
291 config.h can #define abort fancy_abort if you like that sort of thing. */
296 fatal ("Internal gcc abort.");
302 register unsigned length;
315 extern rtx read_rtx ();
318 obstack_init (rtl_obstack);
321 fatal ("No input file name.");
323 infile = fopen (argv[1], "r");
327 exit (FATAL_EXIT_CODE);
332 /* Assign sequential codes to all entries in the machine description
333 in parallel with the tables in insn-output.c. */
335 insn_code_number = 0;
337 operand_seen_length = 40;
338 operand_seen = (char *) xmalloc (40);
340 printf ("/* Generated automatically by the program `genextract'\n\
341 from the machine description file `md'. */\n\n");
343 printf ("#include \"config.h\"\n");
344 printf ("#include \"rtl.h\"\n\n");
346 /* This variable exists only so it can be the "location"
347 of any missing operand whose numbers are skipped by a given pattern. */
348 printf ("static rtx junk;\n");
349 printf ("extern rtx recog_operand[];\n");
350 printf ("extern rtx *recog_operand_loc[];\n");
351 printf ("extern rtx *recog_dup_loc[];\n");
352 printf ("extern char recog_dup_num[];\n");
353 printf ("extern\n#ifdef __GNUC__\nvolatile\n#endif\n");
354 printf ("void fatal_insn_not_found ();\n\n");
356 printf ("void\ninsn_extract (insn)\n");
357 printf (" rtx insn;\n");
359 printf (" register rtx *ro = recog_operand;\n");
360 printf (" register rtx **ro_loc = recog_operand_loc;\n");
361 printf (" int insn_code = INSN_CODE (insn);\n");
362 printf (" if (insn_code == -1) fatal_insn_not_found (insn);\n");
363 printf (" insn = PATTERN (insn);\n");
364 printf (" switch (insn_code)\n");
367 /* Read the machine description. */
371 c = read_skip_spaces (infile);
376 desc = read_rtx (infile);
377 if (GET_CODE (desc) == DEFINE_INSN)
382 if (GET_CODE (desc) == DEFINE_PEEPHOLE)
384 printf (" case %d: goto peephole;\n", insn_code_number);
388 if (GET_CODE (desc) == DEFINE_EXPAND || GET_CODE (desc) == DEFINE_SPLIT)
390 printf (" case %d: break;\n", insn_code_number);
395 /* This should never be reached. */
396 printf ("\n default:\n abort ();\n");
400 /* The vector in the insn says how many operands it has.
401 And all it contains are operands. In fact, the vector was
402 created just for the sake of this function. */
403 printf (" peephole:\n");
404 printf ("#if __GNUC__ > 1 && !defined (bcopy)\n");
405 printf ("#define bcopy(FROM,TO,COUNT) __builtin_memcpy(TO,FROM,COUNT)\n");
407 printf (" bcopy (&XVECEXP (insn, 0, 0), ro,\n");
408 printf (" sizeof (rtx) * XVECLEN (insn, 0));\n");
409 printf (" break;\n");
415 exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);