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