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