* rtl.h (rtunion_def): Constify member `rtstr'.
[official-gcc.git] / gcc / genextract.c
blob9e291c9bc46bfce4276b0875d94cd39f28598c13
1 /* Generate code from machine description to extract operands from insn as rtl.
2 Copyright (C) 1987, 1991, 1992, 1993, 1997, 1998,
3 1999, 2000 Free Software Foundation, Inc.
5 This file is part of GNU CC.
7 GNU CC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
12 GNU CC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU CC; see the file COPYING. If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
23 #include "hconfig.h"
24 #include "system.h"
25 #include "rtl.h"
26 #include "obstack.h"
27 #include "errors.h"
28 #include "insn-config.h"
30 static struct obstack obstack;
31 struct obstack *rtl_obstack = &obstack;
33 #define obstack_chunk_alloc xmalloc
34 #define obstack_chunk_free free
36 /* This structure contains all the information needed to describe one
37 set of extractions methods. Each method may be used by more than
38 one pattern if the operands are in the same place.
40 The string for each operand describes that path to the operand and
41 contains `0' through `9' when going into an expression and `a' through
42 `z' when going into a vector. We assume here that only the first operand
43 of an rtl expression is a vector. genrecog.c makes the same assumption
44 (and uses the same representation) and it is currently true. */
46 struct extraction
48 int op_count;
49 char *oplocs[MAX_RECOG_OPERANDS];
50 int dup_count;
51 char *duplocs[MAX_DUP_OPERANDS];
52 int dupnums[MAX_DUP_OPERANDS];
53 struct code_ptr *insns;
54 struct extraction *next;
57 /* Holds a single insn code that use an extraction method. */
59 struct code_ptr
61 int insn_code;
62 struct code_ptr *next;
65 static struct extraction *extractions;
67 /* Holds an array of names indexed by insn_code_number. */
68 static char **insn_name_ptr = 0;
69 static int insn_name_ptr_size = 0;
71 /* Number instruction patterns handled, starting at 0 for first one. */
73 static int insn_code_number;
75 /* Records the large operand number in this insn. */
77 static int op_count;
79 /* Records the location of any operands using the string format described
80 above. */
82 static char *oplocs[MAX_RECOG_OPERANDS];
84 /* Number the occurrences of MATCH_DUP in each instruction,
85 starting at 0 for the first occurrence. */
87 static int dup_count;
89 /* Records the location of any MATCH_DUP operands. */
91 static char *duplocs[MAX_DUP_OPERANDS];
93 /* Record the operand number of any MATCH_DUPs. */
95 static int dupnums[MAX_DUP_OPERANDS];
97 /* Record the list of insn_codes for peepholes. */
99 static struct code_ptr *peepholes;
101 static void gen_insn PARAMS ((rtx));
102 static void walk_rtx PARAMS ((rtx, const char *));
103 static void print_path PARAMS ((const char *));
104 static void record_insn_name PARAMS ((int, const char *));
106 static void
107 gen_insn (insn)
108 rtx insn;
110 register int i;
111 register struct extraction *p;
112 register struct code_ptr *link;
114 op_count = 0;
115 dup_count = 0;
117 /* No operands seen so far in this pattern. */
118 memset (oplocs, 0, sizeof oplocs);
120 /* Walk the insn's pattern, remembering at all times the path
121 down to the walking point. */
123 if (XVECLEN (insn, 1) == 1)
124 walk_rtx (XVECEXP (insn, 1, 0), "");
125 else
126 for (i = XVECLEN (insn, 1) - 1; i >= 0; i--)
128 char *path = (char *) alloca (2);
130 path[0] = 'a' + i;
131 path[1] = 0;
133 walk_rtx (XVECEXP (insn, 1, i), path);
136 link = (struct code_ptr *) xmalloc (sizeof (struct code_ptr));
137 link->insn_code = insn_code_number;
139 /* See if we find something that already had this extraction method. */
141 for (p = extractions; p; p = p->next)
143 if (p->op_count != op_count || p->dup_count != dup_count)
144 continue;
146 for (i = 0; i < op_count; i++)
147 if (p->oplocs[i] != oplocs[i]
148 && ! (p->oplocs[i] != 0 && oplocs[i] != 0
149 && ! strcmp (p->oplocs[i], oplocs[i])))
150 break;
152 if (i != op_count)
153 continue;
155 for (i = 0; i < dup_count; i++)
156 if (p->dupnums[i] != dupnums[i]
157 || strcmp (p->duplocs[i], duplocs[i]))
158 break;
160 if (i != dup_count)
161 continue;
163 /* This extraction is the same as ours. Just link us in. */
164 link->next = p->insns;
165 p->insns = link;
166 return;
169 /* Otherwise, make a new extraction method. */
171 p = (struct extraction *) xmalloc (sizeof (struct extraction));
172 p->op_count = op_count;
173 p->dup_count = dup_count;
174 p->next = extractions;
175 extractions = p;
176 p->insns = link;
177 link->next = 0;
179 for (i = 0; i < op_count; i++)
180 p->oplocs[i] = oplocs[i];
182 for (i = 0; i < dup_count; i++)
183 p->dupnums[i] = dupnums[i], p->duplocs[i] = duplocs[i];
186 static void
187 walk_rtx (x, path)
188 rtx x;
189 const char *path;
191 register RTX_CODE code;
192 register int i;
193 register int len;
194 register const char *fmt;
195 int depth = strlen (path);
196 char *newpath;
198 if (x == 0)
199 return;
201 code = GET_CODE (x);
203 switch (code)
205 case PC:
206 case CC0:
207 case CONST_INT:
208 case SYMBOL_REF:
209 return;
211 case MATCH_OPERAND:
212 case MATCH_SCRATCH:
213 oplocs[XINT (x, 0)] = xstrdup (path);
214 op_count = MAX (op_count, XINT (x, 0) + 1);
215 break;
217 case MATCH_DUP:
218 case MATCH_PAR_DUP:
219 duplocs[dup_count] = xstrdup (path);
220 dupnums[dup_count] = XINT (x, 0);
221 dup_count++;
222 break;
224 case MATCH_OP_DUP:
225 duplocs[dup_count] = xstrdup (path);
226 dupnums[dup_count] = XINT (x, 0);
227 dup_count++;
229 newpath = (char *) alloca (depth + 2);
230 strcpy (newpath, path);
231 newpath[depth + 1] = 0;
233 for (i = XVECLEN (x, 1) - 1; i >= 0; i--)
235 newpath[depth] = '0' + i;
236 walk_rtx (XVECEXP (x, 1, i), newpath);
238 return;
240 case MATCH_OPERATOR:
241 oplocs[XINT (x, 0)] = xstrdup (path);
242 op_count = MAX (op_count, XINT (x, 0) + 1);
244 newpath = (char *) alloca (depth + 2);
245 strcpy (newpath, path);
246 newpath[depth + 1] = 0;
248 for (i = XVECLEN (x, 2) - 1; i >= 0; i--)
250 newpath[depth] = '0' + i;
251 walk_rtx (XVECEXP (x, 2, i), newpath);
253 return;
255 case MATCH_PARALLEL:
256 oplocs[XINT (x, 0)] = xstrdup (path);
257 op_count = MAX (op_count, XINT (x, 0) + 1);
259 newpath = (char *) alloca (depth + 2);
260 strcpy (newpath, path);
261 newpath[depth + 1] = 0;
263 for (i = XVECLEN (x, 2) - 1; i >= 0; i--)
265 newpath[depth] = 'a' + i;
266 walk_rtx (XVECEXP (x, 2, i), newpath);
268 return;
270 case ADDRESS:
271 walk_rtx (XEXP (x, 0), path);
272 return;
274 default:
275 break;
278 newpath = (char *) alloca (depth + 2);
279 strcpy (newpath, path);
280 newpath[depth + 1] = 0;
282 fmt = GET_RTX_FORMAT (code);
283 len = GET_RTX_LENGTH (code);
284 for (i = 0; i < len; i++)
286 if (fmt[i] == 'e' || fmt[i] == 'u')
288 newpath[depth] = '0' + i;
289 walk_rtx (XEXP (x, i), newpath);
291 else if (fmt[i] == 'E')
293 int j;
294 for (j = XVECLEN (x, i) - 1; j >= 0; j--)
296 newpath[depth] = 'a' + j;
297 walk_rtx (XVECEXP (x, i, j), newpath);
303 /* Given a PATH, representing a path down the instruction's
304 pattern from the root to a certain point, output code to
305 evaluate to the rtx at that point. */
307 static void
308 print_path (path)
309 const char *path;
311 register int len = strlen (path);
312 register int i;
314 if (len == 0)
316 /* Don't emit "pat", since we may try to take the address of it,
317 which isn't what is intended. */
318 printf("PATTERN (insn)");
319 return;
322 /* We first write out the operations (XEXP or XVECEXP) in reverse
323 order, then write "insn", then the indices in forward order. */
325 for (i = len - 1; i >=0 ; i--)
327 if (ISLOWER(path[i]))
328 printf ("XVECEXP (");
329 else if (ISDIGIT(path[i]))
330 printf ("XEXP (");
331 else
332 abort ();
335 printf ("pat");
337 for (i = 0; i < len; i++)
339 if (ISLOWER(path[i]))
340 printf (", 0, %d)", path[i] - 'a');
341 else if (ISDIGIT(path[i]))
342 printf (", %d)", path[i] - '0');
343 else
344 abort ();
349 xmalloc (size)
350 size_t size;
352 register PTR val = (PTR) malloc (size);
354 if (val == 0)
355 fatal ("virtual memory exhausted");
356 return val;
360 xrealloc (old, size)
361 PTR old;
362 size_t size;
364 register PTR ptr;
365 if (old)
366 ptr = (PTR) realloc (old, size);
367 else
368 ptr = (PTR) malloc (size);
369 if (!ptr)
370 fatal ("virtual memory exhausted");
371 return ptr;
374 char *
375 xstrdup (input)
376 const char *input;
378 register size_t len = strlen (input) + 1;
379 register char *output = xmalloc (len);
380 memcpy (output, input, len);
381 return output;
384 extern int main PARAMS ((int, char **));
387 main (argc, argv)
388 int argc;
389 char **argv;
391 rtx desc;
392 FILE *infile;
393 int c, i;
394 struct extraction *p;
395 struct code_ptr *link;
396 const char *name;
398 progname = "genextract";
399 obstack_init (rtl_obstack);
401 if (argc <= 1)
402 fatal ("No input file name.");
404 infile = fopen (argv[1], "r");
405 if (infile == 0)
407 perror (argv[1]);
408 return (FATAL_EXIT_CODE);
410 read_rtx_filename = argv[1];
412 /* Assign sequential codes to all entries in the machine description
413 in parallel with the tables in insn-output.c. */
415 insn_code_number = 0;
417 printf ("/* Generated automatically by the program `genextract'\n\
418 from the machine description file `md'. */\n\n");
420 printf ("#include \"config.h\"\n");
421 printf ("#include \"system.h\"\n");
422 printf ("#include \"rtl.h\"\n");
423 printf ("#include \"insn-config.h\"\n");
424 printf ("#include \"recog.h\"\n");
425 printf ("#include \"toplev.h\"\n\n");
427 /* This variable exists only so it can be the "location"
428 of any missing operand whose numbers are skipped by a given pattern. */
429 printf ("static rtx junk ATTRIBUTE_UNUSED;\n");
431 printf ("void\ninsn_extract (insn)\n");
432 printf (" rtx insn;\n");
433 printf ("{\n");
434 printf (" register rtx *ro = recog_data.operand;\n");
435 printf (" register rtx **ro_loc = recog_data.operand_loc;\n");
436 printf (" rtx pat = PATTERN (insn);\n");
437 printf (" int i ATTRIBUTE_UNUSED;\n\n");
438 printf (" memset (ro, 0, sizeof (*ro) * MAX_RECOG_OPERANDS);\n");
439 printf (" memset (ro_loc, 0, sizeof (*ro_loc) * MAX_RECOG_OPERANDS);\n");
440 printf (" switch (INSN_CODE (insn))\n");
441 printf (" {\n");
442 printf (" case -1:\n");
443 printf (" fatal_insn_not_found (insn);\n\n");
445 /* Read the machine description. */
447 while (1)
449 c = read_skip_spaces (infile);
450 if (c == EOF)
451 break;
452 ungetc (c, infile);
454 desc = read_rtx (infile);
455 if (GET_CODE (desc) == DEFINE_INSN)
457 record_insn_name (insn_code_number, XSTR (desc, 0));
458 gen_insn (desc);
459 ++insn_code_number;
462 else if (GET_CODE (desc) == DEFINE_PEEPHOLE)
464 struct code_ptr *link
465 = (struct code_ptr *) xmalloc (sizeof (struct code_ptr));
467 link->insn_code = insn_code_number;
468 link->next = peepholes;
469 peepholes = link;
470 ++insn_code_number;
473 else if (GET_CODE (desc) == DEFINE_EXPAND
474 || GET_CODE (desc) == DEFINE_PEEPHOLE2
475 || GET_CODE (desc) == DEFINE_SPLIT)
476 ++insn_code_number;
479 /* Write out code to handle peepholes and the insn_codes that it should
480 be called for. */
481 if (peepholes)
483 for (link = peepholes; link; link = link->next)
484 printf (" case %d:\n", link->insn_code);
486 /* The vector in the insn says how many operands it has.
487 And all it contains are operands. In fact, the vector was
488 created just for the sake of this function. */
489 printf (" for (i = XVECLEN (pat, 0) - 1; i >= 0; i--)\n");
490 printf (" ro[i] = XVECEXP (pat, 0, i);\n");
491 printf (" break;\n\n");
494 /* Write out all the ways to extract insn operands. */
495 for (p = extractions; p; p = p->next)
497 for (link = p->insns; link; link = link->next)
499 i = link->insn_code;
500 name = get_insn_name (i);
501 if (name)
502 printf (" case %d: /* %s */\n", i, name);
503 else
504 printf (" case %d:\n", i);
507 for (i = 0; i < p->op_count; i++)
509 if (p->oplocs[i] == 0)
511 printf (" ro[%d] = const0_rtx;\n", i);
512 printf (" ro_loc[%d] = &junk;\n", i);
514 else
516 printf (" ro[%d] = *(ro_loc[%d] = &", i, i);
517 print_path (p->oplocs[i]);
518 printf (");\n");
522 for (i = 0; i < p->dup_count; i++)
524 printf (" recog_data.dup_loc[%d] = &", i);
525 print_path (p->duplocs[i]);
526 printf (";\n");
527 printf (" recog_data.dup_num[%d] = %d;\n", i, p->dupnums[i]);
530 printf (" break;\n\n");
533 /* This should never be reached. Note that we would also reach this abort
534 if we tried to extract something whose INSN_CODE was a DEFINE_EXPAND or
535 DEFINE_SPLIT, but that is correct. */
536 printf (" default:\n abort ();\n");
538 printf (" }\n}\n");
540 fflush (stdout);
541 return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
544 /* Define this so we can link with print-rtl.o to get debug_rtx function. */
545 const char *
546 get_insn_name (code)
547 int code ATTRIBUTE_UNUSED;
549 if (code < insn_name_ptr_size)
550 return insn_name_ptr[code];
551 else
552 return NULL;
555 static void
556 record_insn_name (code, name)
557 int code;
558 const char *name;
560 static const char *last_real_name = "insn";
561 static int last_real_code = 0;
562 char *new;
564 if (insn_name_ptr_size <= code)
566 int new_size;
567 new_size = (insn_name_ptr_size ? insn_name_ptr_size * 2 : 512);
568 insn_name_ptr =
569 (char **) xrealloc (insn_name_ptr, sizeof(char *) * new_size);
570 memset (insn_name_ptr + insn_name_ptr_size, 0,
571 sizeof(char *) * (new_size - insn_name_ptr_size));
572 insn_name_ptr_size = new_size;
575 if (!name || name[0] == '\0')
577 new = xmalloc (strlen (last_real_name) + 10);
578 sprintf (new, "%s+%d", last_real_name, code - last_real_code);
580 else
582 last_real_name = new = xstrdup (name);
583 last_real_code = code;
586 insn_name_ptr[code] = new;