]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/genextract.c
Update copyrights
[thirdparty/gcc.git] / gcc / genextract.c
CommitLineData
41299f41 1/* Generate code from machine description to extract operands from insn as rtl.
9311a396 2 Copyright (C) 1987, 91-93, 97-99, 2000 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"
f8b6598e 26#include "errors.h"
9482d6de 27#include "insn-config.h"
41299f41
TW
28
29static struct obstack obstack;
30struct obstack *rtl_obstack = &obstack;
31
32#define obstack_chunk_alloc xmalloc
33#define obstack_chunk_free free
34
9482d6de
RK
35/* This structure contains all the information needed to describe one
36 set of extractions methods. Each method may be used by more than
37 one pattern if the operands are in the same place.
38
39 The string for each operand describes that path to the operand and
40 contains `0' through `9' when going into an expression and `a' through
41 `z' when going into a vector. We assume here that only the first operand
42 of an rtl expression is a vector. genrecog.c makes the same assumption
43 (and uses the same representation) and it is currently true. */
44
45struct extraction
46{
47 int op_count;
48 char *oplocs[MAX_RECOG_OPERANDS];
49 int dup_count;
50 char *duplocs[MAX_DUP_OPERANDS];
51 int dupnums[MAX_DUP_OPERANDS];
52 struct code_ptr *insns;
53 struct extraction *next;
54};
55
56/* Holds a single insn code that use an extraction method. */
57
58struct code_ptr
59{
60 int insn_code;
61 struct code_ptr *next;
62};
63
64static struct extraction *extractions;
65
8ad1aa56
ZW
66/* Holds an array of names indexed by insn_code_number. */
67static char **insn_name_ptr = 0;
68static int insn_name_ptr_size = 0;
69
41299f41
TW
70/* Number instruction patterns handled, starting at 0 for first one. */
71
72static int insn_code_number;
73
9482d6de
RK
74/* Records the large operand number in this insn. */
75
76static int op_count;
77
78/* Records the location of any operands using the string format described
79 above. */
80
81static char *oplocs[MAX_RECOG_OPERANDS];
82
41299f41
TW
83/* Number the occurrences of MATCH_DUP in each instruction,
84 starting at 0 for the first occurrence. */
85
86static int dup_count;
87
9482d6de 88/* Records the location of any MATCH_DUP operands. */
41299f41 89
9482d6de 90static char *duplocs[MAX_DUP_OPERANDS];
41299f41 91
9482d6de 92/* Record the operand number of any MATCH_DUPs. */
41299f41 93
9482d6de 94static int dupnums[MAX_DUP_OPERANDS];
41299f41 95
9482d6de 96/* Record the list of insn_codes for peepholes. */
41299f41 97
9482d6de 98static struct code_ptr *peepholes;
41299f41 99
a94ae8f5
KG
100static void gen_insn PARAMS ((rtx));
101static void walk_rtx PARAMS ((rtx, const char *));
102static void print_path PARAMS ((const char *));
103static void record_insn_name PARAMS ((int, const char *));
f8b6598e 104
41299f41
TW
105static void
106gen_insn (insn)
107 rtx insn;
108{
109 register int i;
9482d6de
RK
110 register struct extraction *p;
111 register struct code_ptr *link;
41299f41 112
9482d6de 113 op_count = 0;
41299f41
TW
114 dup_count = 0;
115
116 /* No operands seen so far in this pattern. */
efd59a33 117 memset (oplocs, 0, sizeof oplocs);
41299f41
TW
118
119 /* Walk the insn's pattern, remembering at all times the path
120 down to the walking point. */
121
122 if (XVECLEN (insn, 1) == 1)
9482d6de 123 walk_rtx (XVECEXP (insn, 1, 0), "");
41299f41
TW
124 else
125 for (i = XVECLEN (insn, 1) - 1; i >= 0; i--)
126 {
9482d6de 127 char *path = (char *) alloca (2);
41299f41 128
9482d6de
RK
129 path[0] = 'a' + i;
130 path[1] = 0;
131
132 walk_rtx (XVECEXP (insn, 1, i), path);
41299f41 133 }
41299f41 134
9482d6de
RK
135 link = (struct code_ptr *) xmalloc (sizeof (struct code_ptr));
136 link->insn_code = insn_code_number;
137
0f41302f 138 /* See if we find something that already had this extraction method. */
9482d6de
RK
139
140 for (p = extractions; p; p = p->next)
41299f41 141 {
9482d6de
RK
142 if (p->op_count != op_count || p->dup_count != dup_count)
143 continue;
144
145 for (i = 0; i < op_count; i++)
146 if (p->oplocs[i] != oplocs[i]
147 && ! (p->oplocs[i] != 0 && oplocs[i] != 0
148 && ! strcmp (p->oplocs[i], oplocs[i])))
149 break;
150
151 if (i != op_count)
152 continue;
153
154 for (i = 0; i < dup_count; i++)
155 if (p->dupnums[i] != dupnums[i]
156 || strcmp (p->duplocs[i], duplocs[i]))
157 break;
158
159 if (i != dup_count)
160 continue;
161
162 /* This extraction is the same as ours. Just link us in. */
163 link->next = p->insns;
164 p->insns = link;
165 return;
41299f41
TW
166 }
167
9482d6de 168 /* Otherwise, make a new extraction method. */
41299f41 169
9482d6de
RK
170 p = (struct extraction *) xmalloc (sizeof (struct extraction));
171 p->op_count = op_count;
172 p->dup_count = dup_count;
173 p->next = extractions;
174 extractions = p;
175 p->insns = link;
176 link->next = 0;
177
178 for (i = 0; i < op_count; i++)
179 p->oplocs[i] = oplocs[i];
180
181 for (i = 0; i < dup_count; i++)
182 p->dupnums[i] = dupnums[i], p->duplocs[i] = duplocs[i];
183}
184\f
41299f41
TW
185static void
186walk_rtx (x, path)
187 rtx x;
85fda1eb 188 const char *path;
41299f41
TW
189{
190 register RTX_CODE code;
191 register int i;
192 register int len;
6f7d635c 193 register const char *fmt;
9482d6de
RK
194 int depth = strlen (path);
195 char *newpath;
41299f41
TW
196
197 if (x == 0)
198 return;
199
200 code = GET_CODE (x);
201
202 switch (code)
203 {
204 case PC:
205 case CC0:
206 case CONST_INT:
207 case SYMBOL_REF:
208 return;
209
210 case MATCH_OPERAND:
211 case MATCH_SCRATCH:
efd59a33 212 oplocs[XINT (x, 0)] = xstrdup (path);
9482d6de 213 op_count = MAX (op_count, XINT (x, 0) + 1);
41299f41
TW
214 break;
215
216 case MATCH_DUP:
f3e0821d 217 case MATCH_PAR_DUP:
efd59a33 218 duplocs[dup_count] = xstrdup (path);
9482d6de 219 dupnums[dup_count] = XINT (x, 0);
41299f41
TW
220 dup_count++;
221 break;
222
809ffa71 223 case MATCH_OP_DUP:
efd59a33 224 duplocs[dup_count] = xstrdup (path);
809ffa71
RK
225 dupnums[dup_count] = XINT (x, 0);
226 dup_count++;
227
228 newpath = (char *) alloca (depth + 2);
229 strcpy (newpath, path);
230 newpath[depth + 1] = 0;
231
232 for (i = XVECLEN (x, 1) - 1; i >= 0; i--)
233 {
234 newpath[depth] = '0' + i;
235 walk_rtx (XVECEXP (x, 1, i), newpath);
236 }
237 return;
238
41299f41 239 case MATCH_OPERATOR:
efd59a33 240 oplocs[XINT (x, 0)] = xstrdup (path);
9482d6de
RK
241 op_count = MAX (op_count, XINT (x, 0) + 1);
242
243 newpath = (char *) alloca (depth + 2);
244 strcpy (newpath, path);
245 newpath[depth + 1] = 0;
246
41299f41
TW
247 for (i = XVECLEN (x, 2) - 1; i >= 0; i--)
248 {
9482d6de
RK
249 newpath[depth] = '0' + i;
250 walk_rtx (XVECEXP (x, 2, i), newpath);
41299f41
TW
251 }
252 return;
253
254 case MATCH_PARALLEL:
efd59a33 255 oplocs[XINT (x, 0)] = xstrdup (path);
9482d6de
RK
256 op_count = MAX (op_count, XINT (x, 0) + 1);
257
258 newpath = (char *) alloca (depth + 2);
259 strcpy (newpath, path);
260 newpath[depth + 1] = 0;
261
41299f41
TW
262 for (i = XVECLEN (x, 2) - 1; i >= 0; i--)
263 {
9482d6de
RK
264 newpath[depth] = 'a' + i;
265 walk_rtx (XVECEXP (x, 2, i), newpath);
41299f41
TW
266 }
267 return;
268
269 case ADDRESS:
270 walk_rtx (XEXP (x, 0), path);
271 return;
ccd043a9
RL
272
273 default:
274 break;
41299f41
TW
275 }
276
9482d6de
RK
277 newpath = (char *) alloca (depth + 2);
278 strcpy (newpath, path);
279 newpath[depth + 1] = 0;
280
41299f41
TW
281 fmt = GET_RTX_FORMAT (code);
282 len = GET_RTX_LENGTH (code);
283 for (i = 0; i < len; i++)
284 {
41299f41
TW
285 if (fmt[i] == 'e' || fmt[i] == 'u')
286 {
9482d6de
RK
287 newpath[depth] = '0' + i;
288 walk_rtx (XEXP (x, i), newpath);
41299f41
TW
289 }
290 else if (fmt[i] == 'E')
291 {
292 int j;
293 for (j = XVECLEN (x, i) - 1; j >= 0; j--)
294 {
21163e24 295 newpath[depth] = 'a' + j;
9482d6de 296 walk_rtx (XVECEXP (x, i, j), newpath);
41299f41
TW
297 }
298 }
299 }
300}
301
302/* Given a PATH, representing a path down the instruction's
303 pattern from the root to a certain point, output code to
304 evaluate to the rtx at that point. */
305
306static void
307print_path (path)
c1b59dce 308 const char *path;
41299f41 309{
9482d6de
RK
310 register int len = strlen (path);
311 register int i;
312
07704a9a
RE
313 if (len == 0)
314 {
315 /* Don't emit "pat", since we may try to take the address of it,
316 which isn't what is intended. */
317 printf("PATTERN (insn)");
318 return;
319 }
320
9482d6de
RK
321 /* We first write out the operations (XEXP or XVECEXP) in reverse
322 order, then write "insn", then the indices in forward order. */
323
324 for (i = len - 1; i >=0 ; i--)
41299f41 325 {
f3ad1f9c 326 if (ISLOWER(path[i]))
9482d6de 327 printf ("XVECEXP (");
f3ad1f9c 328 else if (ISDIGIT(path[i]))
9482d6de
RK
329 printf ("XEXP (");
330 else
331 abort ();
41299f41 332 }
9482d6de 333
cc30cc14 334 printf ("pat");
9482d6de
RK
335
336 for (i = 0; i < len; i++)
41299f41 337 {
f3ad1f9c 338 if (ISLOWER(path[i]))
9482d6de 339 printf (", 0, %d)", path[i] - 'a');
f3ad1f9c 340 else if (ISDIGIT(path[i]))
9482d6de
RK
341 printf (", %d)", path[i] - '0');
342 else
343 abort ();
41299f41
TW
344 }
345}
346\f
2778b98d 347PTR
41299f41 348xmalloc (size)
2778b98d 349 size_t size;
41299f41 350{
2778b98d 351 register PTR val = (PTR) malloc (size);
41299f41
TW
352
353 if (val == 0)
354 fatal ("virtual memory exhausted");
355 return val;
356}
357
2778b98d 358PTR
470b68c0
RH
359xrealloc (old, size)
360 PTR old;
2778b98d 361 size_t size;
41299f41 362{
470b68c0 363 register PTR ptr;
09d83d25 364 if (old)
470b68c0
RH
365 ptr = (PTR) realloc (old, size);
366 else
367 ptr = (PTR) malloc (size);
368 if (!ptr)
41299f41 369 fatal ("virtual memory exhausted");
470b68c0 370 return ptr;
41299f41
TW
371}
372
efd59a33 373char *
31ee9d6c 374xstrdup (input)
efd59a33 375 const char *input;
9482d6de 376{
efd59a33
KG
377 register size_t len = strlen (input) + 1;
378 register char *output = xmalloc (len);
379 memcpy (output, input, len);
380 return output;
8433ffc5 381}
41299f41 382\f
a94ae8f5 383extern int main PARAMS ((int, char **));
c1b59dce 384
41299f41
TW
385int
386main (argc, argv)
387 int argc;
388 char **argv;
389{
390 rtx desc;
391 FILE *infile;
8ad1aa56 392 int c, i;
9482d6de
RK
393 struct extraction *p;
394 struct code_ptr *link;
8ad1aa56 395 const char *name;
41299f41 396
f8b6598e 397 progname = "genextract";
41299f41
TW
398 obstack_init (rtl_obstack);
399
400 if (argc <= 1)
401 fatal ("No input file name.");
402
403 infile = fopen (argv[1], "r");
404 if (infile == 0)
405 {
406 perror (argv[1]);
c1b59dce 407 return (FATAL_EXIT_CODE);
41299f41 408 }
bcdaba58 409 read_rtx_filename = argv[1];
41299f41 410
41299f41
TW
411 /* Assign sequential codes to all entries in the machine description
412 in parallel with the tables in insn-output.c. */
413
414 insn_code_number = 0;
415
41299f41
TW
416 printf ("/* Generated automatically by the program `genextract'\n\
417from the machine description file `md'. */\n\n");
418
419 printf ("#include \"config.h\"\n");
729da3f5 420 printf ("#include \"system.h\"\n");
114791ea 421 printf ("#include \"rtl.h\"\n");
0a578fee
BS
422 printf ("#include \"insn-config.h\"\n");
423 printf ("#include \"recog.h\"\n");
114791ea 424 printf ("#include \"toplev.h\"\n\n");
41299f41
TW
425
426 /* This variable exists only so it can be the "location"
427 of any missing operand whose numbers are skipped by a given pattern. */
d6f4ec51 428 printf ("static rtx junk ATTRIBUTE_UNUSED;\n");
9482d6de 429
41299f41
TW
430 printf ("void\ninsn_extract (insn)\n");
431 printf (" rtx insn;\n");
432 printf ("{\n");
1ccbefce
RH
433 printf (" register rtx *ro = recog_data.operand;\n");
434 printf (" register rtx **ro_loc = recog_data.operand_loc;\n");
cc30cc14 435 printf (" rtx pat = PATTERN (insn);\n");
296433e1 436 printf (" int i ATTRIBUTE_UNUSED;\n\n");
99f25d8e
RH
437 printf (" memset (ro, 0, sizeof (*ro) * MAX_RECOG_OPERANDS);\n");
438 printf (" memset (ro_loc, 0, sizeof (*ro_loc) * MAX_RECOG_OPERANDS);\n");
cc30cc14 439 printf (" switch (INSN_CODE (insn))\n");
41299f41 440 printf (" {\n");
9482d6de
RK
441 printf (" case -1:\n");
442 printf (" fatal_insn_not_found (insn);\n\n");
41299f41
TW
443
444 /* Read the machine description. */
445
446 while (1)
447 {
448 c = read_skip_spaces (infile);
449 if (c == EOF)
450 break;
451 ungetc (c, infile);
452
453 desc = read_rtx (infile);
454 if (GET_CODE (desc) == DEFINE_INSN)
455 {
8ad1aa56 456 record_insn_name (insn_code_number, XSTR (desc, 0));
41299f41
TW
457 gen_insn (desc);
458 ++insn_code_number;
459 }
9482d6de
RK
460
461 else if (GET_CODE (desc) == DEFINE_PEEPHOLE)
41299f41 462 {
9482d6de
RK
463 struct code_ptr *link
464 = (struct code_ptr *) xmalloc (sizeof (struct code_ptr));
465
466 link->insn_code = insn_code_number;
467 link->next = peepholes;
468 peepholes = link;
41299f41
TW
469 ++insn_code_number;
470 }
41299f41 471
9482d6de 472 else if (GET_CODE (desc) == DEFINE_EXPAND
ede7cd44 473 || GET_CODE (desc) == DEFINE_PEEPHOLE2
9482d6de
RK
474 || GET_CODE (desc) == DEFINE_SPLIT)
475 ++insn_code_number;
476 }
41299f41 477
9482d6de
RK
478 /* Write out code to handle peepholes and the insn_codes that it should
479 be called for. */
480 if (peepholes)
41299f41 481 {
9482d6de
RK
482 for (link = peepholes; link; link = link->next)
483 printf (" case %d:\n", link->insn_code);
484
41299f41
TW
485 /* The vector in the insn says how many operands it has.
486 And all it contains are operands. In fact, the vector was
487 created just for the sake of this function. */
b7673cdb 488 printf (" for (i = XVECLEN (pat, 0) - 1; i >= 0; i--)\n");
cc38a1c3 489 printf (" ro[i] = XVECEXP (pat, 0, i);\n");
9482d6de
RK
490 printf (" break;\n\n");
491 }
492
493 /* Write out all the ways to extract insn operands. */
494 for (p = extractions; p; p = p->next)
495 {
496 for (link = p->insns; link; link = link->next)
8ad1aa56
ZW
497 {
498 i = link->insn_code;
499 name = get_insn_name (i);
500 if (name)
501 printf (" case %d: /* %s */\n", i, name);
502 else
503 printf (" case %d:\n", i);
504 }
505
9482d6de
RK
506 for (i = 0; i < p->op_count; i++)
507 {
508 if (p->oplocs[i] == 0)
509 {
510 printf (" ro[%d] = const0_rtx;\n", i);
8b5ba7f8 511 printf (" ro_loc[%d] = &junk;\n", i);
9482d6de
RK
512 }
513 else
514 {
515 printf (" ro[%d] = *(ro_loc[%d] = &", i, i);
516 print_path (p->oplocs[i]);
517 printf (");\n");
518 }
519 }
520
521 for (i = 0; i < p->dup_count; i++)
522 {
1ccbefce 523 printf (" recog_data.dup_loc[%d] = &", i);
9482d6de
RK
524 print_path (p->duplocs[i]);
525 printf (";\n");
1ccbefce 526 printf (" recog_data.dup_num[%d] = %d;\n", i, p->dupnums[i]);
9482d6de
RK
527 }
528
529 printf (" break;\n\n");
41299f41
TW
530 }
531
9482d6de
RK
532 /* This should never be reached. Note that we would also reach this abort
533 if we tried to extract something whose INSN_CODE was a DEFINE_EXPAND or
534 DEFINE_SPLIT, but that is correct. */
535 printf (" default:\n abort ();\n");
536
41299f41
TW
537 printf (" }\n}\n");
538
539 fflush (stdout);
c1b59dce 540 return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
41299f41 541}
a995e389
RH
542
543/* Define this so we can link with print-rtl.o to get debug_rtx function. */
544const char *
545get_insn_name (code)
c1b59dce 546 int code ATTRIBUTE_UNUSED;
a995e389 547{
8ad1aa56
ZW
548 if (code < insn_name_ptr_size)
549 return insn_name_ptr[code];
550 else
551 return NULL;
a995e389 552}
8ad1aa56
ZW
553
554static void
555record_insn_name (code, name)
556 int code;
557 const char *name;
558{
559 static const char *last_real_name = "insn";
560 static int last_real_code = 0;
561 char *new;
562
563 if (insn_name_ptr_size <= code)
564 {
565 int new_size;
566 new_size = (insn_name_ptr_size ? insn_name_ptr_size * 2 : 512);
567 insn_name_ptr =
568 (char **) xrealloc (insn_name_ptr, sizeof(char *) * new_size);
569 memset (insn_name_ptr + insn_name_ptr_size, 0,
570 sizeof(char *) * (new_size - insn_name_ptr_size));
571 insn_name_ptr_size = new_size;
572 }
573
574 if (!name || name[0] == '\0')
575 {
576 new = xmalloc (strlen (last_real_name) + 10);
577 sprintf (new, "%s+%d", last_real_name, code - last_real_code);
578 }
579 else
580 {
581 last_real_name = new = xstrdup (name);
582 last_real_code = code;
583 }
584
585 insn_name_ptr[code] = new;
586}