]> gcc.gnu.org Git - gcc.git/blame - gcc/genextract.c
Daily bump.
[gcc.git] / gcc / genextract.c
CommitLineData
41299f41 1/* Generate code from machine description to extract operands from insn as rtl.
efd59a33 2 Copyright (C) 1987, 91-93, 97-98, 1999 Free Software Foundation, Inc.
41299f41
TW
3
4This file is part of GNU CC.
5
6GNU CC is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11GNU CC is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU CC; see the file COPYING. If not, write to
a35311b0
RK
18the Free Software Foundation, 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA. */
41299f41
TW
20
21
0d64891c 22#include "hconfig.h"
0b93b64e 23#include "system.h"
41299f41
TW
24#include "rtl.h"
25#include "obstack.h"
9482d6de 26#include "insn-config.h"
41299f41
TW
27
28static struct obstack obstack;
29struct obstack *rtl_obstack = &obstack;
30
31#define obstack_chunk_alloc xmalloc
32#define obstack_chunk_free free
33
809ffa71
RK
34/* Names for patterns. Need to allow linking with print-rtl. */
35char **insn_name_ptr;
36
9482d6de
RK
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.
40
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. */
46
47struct extraction
48{
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;
56};
57
58/* Holds a single insn code that use an extraction method. */
59
60struct code_ptr
61{
62 int insn_code;
63 struct code_ptr *next;
64};
65
66static struct extraction *extractions;
67
41299f41
TW
68/* Number instruction patterns handled, starting at 0 for first one. */
69
70static int insn_code_number;
71
9482d6de
RK
72/* Records the large operand number in this insn. */
73
74static int op_count;
75
76/* Records the location of any operands using the string format described
77 above. */
78
79static char *oplocs[MAX_RECOG_OPERANDS];
80
41299f41
TW
81/* Number the occurrences of MATCH_DUP in each instruction,
82 starting at 0 for the first occurrence. */
83
84static int dup_count;
85
9482d6de 86/* Records the location of any MATCH_DUP operands. */
41299f41 87
9482d6de 88static char *duplocs[MAX_DUP_OPERANDS];
41299f41 89
9482d6de 90/* Record the operand number of any MATCH_DUPs. */
41299f41 91
9482d6de 92static int dupnums[MAX_DUP_OPERANDS];
41299f41 93
9482d6de 94/* Record the list of insn_codes for peepholes. */
41299f41 95
9482d6de 96static struct code_ptr *peepholes;
41299f41 97
e009aaf3 98static void gen_insn PROTO ((rtx));
85fda1eb 99static void walk_rtx PROTO ((rtx, const char *));
0b93b64e 100static void print_path PROTO ((char *));
2a611d21 101void fatal PVPROTO ((const char *, ...))
bf94d1ec 102 ATTRIBUTE_PRINTF_1 ATTRIBUTE_NORETURN;
41299f41
TW
103\f
104static void
105gen_insn (insn)
106 rtx insn;
107{
108 register int i;
9482d6de
RK
109 register struct extraction *p;
110 register struct code_ptr *link;
41299f41 111
9482d6de 112 op_count = 0;
41299f41
TW
113 dup_count = 0;
114
115 /* No operands seen so far in this pattern. */
efd59a33 116 memset (oplocs, 0, sizeof oplocs);
41299f41
TW
117
118 /* Walk the insn's pattern, remembering at all times the path
119 down to the walking point. */
120
121 if (XVECLEN (insn, 1) == 1)
9482d6de 122 walk_rtx (XVECEXP (insn, 1, 0), "");
41299f41
TW
123 else
124 for (i = XVECLEN (insn, 1) - 1; i >= 0; i--)
125 {
9482d6de 126 char *path = (char *) alloca (2);
41299f41 127
9482d6de
RK
128 path[0] = 'a' + i;
129 path[1] = 0;
130
131 walk_rtx (XVECEXP (insn, 1, i), path);
41299f41 132 }
41299f41 133
9482d6de
RK
134 link = (struct code_ptr *) xmalloc (sizeof (struct code_ptr));
135 link->insn_code = insn_code_number;
136
0f41302f 137 /* See if we find something that already had this extraction method. */
9482d6de
RK
138
139 for (p = extractions; p; p = p->next)
41299f41 140 {
9482d6de
RK
141 if (p->op_count != op_count || p->dup_count != dup_count)
142 continue;
143
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])))
148 break;
149
150 if (i != op_count)
151 continue;
152
153 for (i = 0; i < dup_count; i++)
154 if (p->dupnums[i] != dupnums[i]
155 || strcmp (p->duplocs[i], duplocs[i]))
156 break;
157
158 if (i != dup_count)
159 continue;
160
161 /* This extraction is the same as ours. Just link us in. */
162 link->next = p->insns;
163 p->insns = link;
164 return;
41299f41
TW
165 }
166
9482d6de 167 /* Otherwise, make a new extraction method. */
41299f41 168
9482d6de
RK
169 p = (struct extraction *) xmalloc (sizeof (struct extraction));
170 p->op_count = op_count;
171 p->dup_count = dup_count;
172 p->next = extractions;
173 extractions = p;
174 p->insns = link;
175 link->next = 0;
176
177 for (i = 0; i < op_count; i++)
178 p->oplocs[i] = oplocs[i];
179
180 for (i = 0; i < dup_count; i++)
181 p->dupnums[i] = dupnums[i], p->duplocs[i] = duplocs[i];
182}
183\f
41299f41
TW
184static void
185walk_rtx (x, path)
186 rtx x;
85fda1eb 187 const char *path;
41299f41
TW
188{
189 register RTX_CODE code;
190 register int i;
191 register int len;
6f7d635c 192 register const char *fmt;
9482d6de
RK
193 int depth = strlen (path);
194 char *newpath;
41299f41
TW
195
196 if (x == 0)
197 return;
198
199 code = GET_CODE (x);
200
201 switch (code)
202 {
203 case PC:
204 case CC0:
205 case CONST_INT:
206 case SYMBOL_REF:
207 return;
208
209 case MATCH_OPERAND:
210 case MATCH_SCRATCH:
efd59a33 211 oplocs[XINT (x, 0)] = xstrdup (path);
9482d6de 212 op_count = MAX (op_count, XINT (x, 0) + 1);
41299f41
TW
213 break;
214
215 case MATCH_DUP:
f3e0821d 216 case MATCH_PAR_DUP:
efd59a33 217 duplocs[dup_count] = xstrdup (path);
9482d6de 218 dupnums[dup_count] = XINT (x, 0);
41299f41
TW
219 dup_count++;
220 break;
221
809ffa71 222 case MATCH_OP_DUP:
efd59a33 223 duplocs[dup_count] = xstrdup (path);
809ffa71
RK
224 dupnums[dup_count] = XINT (x, 0);
225 dup_count++;
226
227 newpath = (char *) alloca (depth + 2);
228 strcpy (newpath, path);
229 newpath[depth + 1] = 0;
230
231 for (i = XVECLEN (x, 1) - 1; i >= 0; i--)
232 {
233 newpath[depth] = '0' + i;
234 walk_rtx (XVECEXP (x, 1, i), newpath);
235 }
236 return;
237
41299f41 238 case MATCH_OPERATOR:
efd59a33 239 oplocs[XINT (x, 0)] = xstrdup (path);
9482d6de
RK
240 op_count = MAX (op_count, XINT (x, 0) + 1);
241
242 newpath = (char *) alloca (depth + 2);
243 strcpy (newpath, path);
244 newpath[depth + 1] = 0;
245
41299f41
TW
246 for (i = XVECLEN (x, 2) - 1; i >= 0; i--)
247 {
9482d6de
RK
248 newpath[depth] = '0' + i;
249 walk_rtx (XVECEXP (x, 2, i), newpath);
41299f41
TW
250 }
251 return;
252
253 case MATCH_PARALLEL:
efd59a33 254 oplocs[XINT (x, 0)] = xstrdup (path);
9482d6de
RK
255 op_count = MAX (op_count, XINT (x, 0) + 1);
256
257 newpath = (char *) alloca (depth + 2);
258 strcpy (newpath, path);
259 newpath[depth + 1] = 0;
260
41299f41
TW
261 for (i = XVECLEN (x, 2) - 1; i >= 0; i--)
262 {
9482d6de
RK
263 newpath[depth] = 'a' + i;
264 walk_rtx (XVECEXP (x, 2, i), newpath);
41299f41
TW
265 }
266 return;
267
268 case ADDRESS:
269 walk_rtx (XEXP (x, 0), path);
270 return;
ccd043a9
RL
271
272 default:
273 break;
41299f41
TW
274 }
275
9482d6de
RK
276 newpath = (char *) alloca (depth + 2);
277 strcpy (newpath, path);
278 newpath[depth + 1] = 0;
279
41299f41
TW
280 fmt = GET_RTX_FORMAT (code);
281 len = GET_RTX_LENGTH (code);
282 for (i = 0; i < len; i++)
283 {
41299f41
TW
284 if (fmt[i] == 'e' || fmt[i] == 'u')
285 {
9482d6de
RK
286 newpath[depth] = '0' + i;
287 walk_rtx (XEXP (x, i), newpath);
41299f41
TW
288 }
289 else if (fmt[i] == 'E')
290 {
291 int j;
292 for (j = XVECLEN (x, i) - 1; j >= 0; j--)
293 {
21163e24 294 newpath[depth] = 'a' + j;
9482d6de 295 walk_rtx (XVECEXP (x, i, j), newpath);
41299f41
TW
296 }
297 }
298 }
299}
300
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. */
304
305static void
306print_path (path)
9482d6de 307 char *path;
41299f41 308{
9482d6de
RK
309 register int len = strlen (path);
310 register int i;
311
07704a9a
RE
312 if (len == 0)
313 {
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)");
317 return;
318 }
319
9482d6de
RK
320 /* We first write out the operations (XEXP or XVECEXP) in reverse
321 order, then write "insn", then the indices in forward order. */
322
323 for (i = len - 1; i >=0 ; i--)
41299f41 324 {
9482d6de
RK
325 if (path[i] >= 'a' && path[i] <= 'z')
326 printf ("XVECEXP (");
327 else if (path[i] >= '0' && path[i] <= '9')
328 printf ("XEXP (");
329 else
330 abort ();
41299f41 331 }
9482d6de 332
cc30cc14 333 printf ("pat");
9482d6de
RK
334
335 for (i = 0; i < len; i++)
41299f41 336 {
9482d6de
RK
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');
341 else
342 abort ();
41299f41
TW
343 }
344}
345\f
2778b98d 346PTR
41299f41 347xmalloc (size)
2778b98d 348 size_t size;
41299f41 349{
2778b98d 350 register PTR val = (PTR) malloc (size);
41299f41
TW
351
352 if (val == 0)
353 fatal ("virtual memory exhausted");
354 return val;
355}
356
2778b98d 357PTR
470b68c0
RH
358xrealloc (old, size)
359 PTR old;
2778b98d 360 size_t size;
41299f41 361{
470b68c0 362 register PTR ptr;
09d83d25 363 if (old)
470b68c0
RH
364 ptr = (PTR) realloc (old, size);
365 else
366 ptr = (PTR) malloc (size);
367 if (!ptr)
41299f41 368 fatal ("virtual memory exhausted");
470b68c0 369 return ptr;
41299f41
TW
370}
371
2a611d21 372void
85fda1eb 373fatal VPROTO ((const char *format, ...))
41299f41 374{
5148a72b 375#ifndef ANSI_PROTOTYPES
85fda1eb 376 const char *format;
320e7c40
KG
377#endif
378 va_list ap;
379
380 VA_START (ap, format);
381
5148a72b 382#ifndef ANSI_PROTOTYPES
85fda1eb 383 format = va_arg (ap, const char *);
320e7c40
KG
384#endif
385
41299f41 386 fprintf (stderr, "genextract: ");
320e7c40
KG
387 vfprintf (stderr, format, ap);
388 va_end (ap);
41299f41
TW
389 fprintf (stderr, "\n");
390 exit (FATAL_EXIT_CODE);
391}
392
efd59a33 393char *
31ee9d6c 394xstrdup (input)
efd59a33 395 const char *input;
9482d6de 396{
efd59a33
KG
397 register size_t len = strlen (input) + 1;
398 register char *output = xmalloc (len);
399 memcpy (output, input, len);
400 return output;
8433ffc5 401}
41299f41
TW
402\f
403int
404main (argc, argv)
405 int argc;
406 char **argv;
407{
408 rtx desc;
409 FILE *infile;
41299f41 410 register int c, i;
9482d6de
RK
411 struct extraction *p;
412 struct code_ptr *link;
41299f41
TW
413
414 obstack_init (rtl_obstack);
415
416 if (argc <= 1)
417 fatal ("No input file name.");
418
419 infile = fopen (argv[1], "r");
420 if (infile == 0)
421 {
422 perror (argv[1]);
423 exit (FATAL_EXIT_CODE);
424 }
425
426 init_rtl ();
427
428 /* Assign sequential codes to all entries in the machine description
429 in parallel with the tables in insn-output.c. */
430
431 insn_code_number = 0;
432
41299f41
TW
433 printf ("/* Generated automatically by the program `genextract'\n\
434from the machine description file `md'. */\n\n");
435
436 printf ("#include \"config.h\"\n");
729da3f5 437 printf ("#include \"system.h\"\n");
114791ea 438 printf ("#include \"rtl.h\"\n");
0a578fee
BS
439 printf ("#include \"insn-config.h\"\n");
440 printf ("#include \"recog.h\"\n");
114791ea 441 printf ("#include \"toplev.h\"\n\n");
41299f41
TW
442
443 /* This variable exists only so it can be the "location"
444 of any missing operand whose numbers are skipped by a given pattern. */
d6f4ec51 445 printf ("static rtx junk ATTRIBUTE_UNUSED;\n");
9482d6de 446
41299f41
TW
447 printf ("void\ninsn_extract (insn)\n");
448 printf (" rtx insn;\n");
449 printf ("{\n");
af929c62
RK
450 printf (" register rtx *ro = recog_operand;\n");
451 printf (" register rtx **ro_loc = recog_operand_loc;\n");
cc30cc14 452 printf (" rtx pat = PATTERN (insn);\n");
296433e1 453 printf (" int i ATTRIBUTE_UNUSED;\n\n");
99f25d8e
RH
454 printf (" memset (ro, 0, sizeof (*ro) * MAX_RECOG_OPERANDS);\n");
455 printf (" memset (ro_loc, 0, sizeof (*ro_loc) * MAX_RECOG_OPERANDS);\n");
cc30cc14 456 printf (" switch (INSN_CODE (insn))\n");
41299f41 457 printf (" {\n");
9482d6de
RK
458 printf (" case -1:\n");
459 printf (" fatal_insn_not_found (insn);\n\n");
41299f41
TW
460
461 /* Read the machine description. */
462
463 while (1)
464 {
465 c = read_skip_spaces (infile);
466 if (c == EOF)
467 break;
468 ungetc (c, infile);
469
470 desc = read_rtx (infile);
471 if (GET_CODE (desc) == DEFINE_INSN)
472 {
473 gen_insn (desc);
474 ++insn_code_number;
475 }
9482d6de
RK
476
477 else if (GET_CODE (desc) == DEFINE_PEEPHOLE)
41299f41 478 {
9482d6de
RK
479 struct code_ptr *link
480 = (struct code_ptr *) xmalloc (sizeof (struct code_ptr));
481
482 link->insn_code = insn_code_number;
483 link->next = peepholes;
484 peepholes = link;
41299f41
TW
485 ++insn_code_number;
486 }
41299f41 487
9482d6de
RK
488 else if (GET_CODE (desc) == DEFINE_EXPAND
489 || GET_CODE (desc) == DEFINE_SPLIT)
490 ++insn_code_number;
491 }
41299f41 492
9482d6de
RK
493 /* Write out code to handle peepholes and the insn_codes that it should
494 be called for. */
495 if (peepholes)
41299f41 496 {
9482d6de
RK
497 for (link = peepholes; link; link = link->next)
498 printf (" case %d:\n", link->insn_code);
499
41299f41
TW
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. */
b7673cdb 503 printf (" for (i = XVECLEN (pat, 0) - 1; i >= 0; i--)\n");
cc38a1c3 504 printf (" ro[i] = XVECEXP (pat, 0, i);\n");
9482d6de
RK
505 printf (" break;\n\n");
506 }
507
508 /* Write out all the ways to extract insn operands. */
509 for (p = extractions; p; p = p->next)
510 {
511 for (link = p->insns; link; link = link->next)
512 printf (" case %d:\n", link->insn_code);
513
514 for (i = 0; i < p->op_count; i++)
515 {
516 if (p->oplocs[i] == 0)
517 {
518 printf (" ro[%d] = const0_rtx;\n", i);
8b5ba7f8 519 printf (" ro_loc[%d] = &junk;\n", i);
9482d6de
RK
520 }
521 else
522 {
523 printf (" ro[%d] = *(ro_loc[%d] = &", i, i);
524 print_path (p->oplocs[i]);
525 printf (");\n");
526 }
527 }
528
529 for (i = 0; i < p->dup_count; i++)
530 {
531 printf (" recog_dup_loc[%d] = &", i);
532 print_path (p->duplocs[i]);
533 printf (";\n");
534 printf (" recog_dup_num[%d] = %d;\n", i, p->dupnums[i]);
535 }
536
537 printf (" break;\n\n");
41299f41
TW
538 }
539
9482d6de
RK
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");
544
41299f41
TW
545 printf (" }\n}\n");
546
547 fflush (stdout);
548 exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
549 /* NOTREACHED */
550 return 0;
551}
This page took 0.773902 seconds and 5 git commands to generate.