]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/genextract.c
aclocal.m4 (libiberty_AC_FUNC_C_ALLOCA): New.
[thirdparty/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 25#include "rtl.h"
f8b6598e 26#include "errors.h"
9482d6de 27#include "insn-config.h"
c88c0d42 28#include "gensupport.h"
41299f41 29
41299f41 30
9482d6de
RK
31/* This structure contains all the information needed to describe one
32 set of extractions methods. Each method may be used by more than
33 one pattern if the operands are in the same place.
34
35 The string for each operand describes that path to the operand and
36 contains `0' through `9' when going into an expression and `a' through
37 `z' when going into a vector. We assume here that only the first operand
38 of an rtl expression is a vector. genrecog.c makes the same assumption
39 (and uses the same representation) and it is currently true. */
40
41struct extraction
42{
43 int op_count;
44 char *oplocs[MAX_RECOG_OPERANDS];
45 int dup_count;
46 char *duplocs[MAX_DUP_OPERANDS];
47 int dupnums[MAX_DUP_OPERANDS];
48 struct code_ptr *insns;
49 struct extraction *next;
50};
51
52/* Holds a single insn code that use an extraction method. */
53
54struct code_ptr
55{
56 int insn_code;
57 struct code_ptr *next;
58};
59
60static struct extraction *extractions;
61
8ad1aa56
ZW
62/* Holds an array of names indexed by insn_code_number. */
63static char **insn_name_ptr = 0;
64static int insn_name_ptr_size = 0;
65
41299f41
TW
66/* Number instruction patterns handled, starting at 0 for first one. */
67
68static int insn_code_number;
69
9482d6de
RK
70/* Records the large operand number in this insn. */
71
72static int op_count;
73
74/* Records the location of any operands using the string format described
75 above. */
76
77static char *oplocs[MAX_RECOG_OPERANDS];
78
41299f41
TW
79/* Number the occurrences of MATCH_DUP in each instruction,
80 starting at 0 for the first occurrence. */
81
82static int dup_count;
83
9482d6de 84/* Records the location of any MATCH_DUP operands. */
41299f41 85
9482d6de 86static char *duplocs[MAX_DUP_OPERANDS];
41299f41 87
9482d6de 88/* Record the operand number of any MATCH_DUPs. */
41299f41 89
9482d6de 90static int dupnums[MAX_DUP_OPERANDS];
41299f41 91
9482d6de 92/* Record the list of insn_codes for peepholes. */
41299f41 93
9482d6de 94static struct code_ptr *peepholes;
41299f41 95
a94ae8f5
KG
96static void gen_insn PARAMS ((rtx));
97static void walk_rtx PARAMS ((rtx, const char *));
98static void print_path PARAMS ((const char *));
99static void record_insn_name PARAMS ((int, const char *));
f8b6598e 100
41299f41
TW
101static void
102gen_insn (insn)
103 rtx insn;
104{
105 register int i;
9482d6de
RK
106 register struct extraction *p;
107 register struct code_ptr *link;
41299f41 108
9482d6de 109 op_count = 0;
41299f41
TW
110 dup_count = 0;
111
112 /* No operands seen so far in this pattern. */
efd59a33 113 memset (oplocs, 0, sizeof oplocs);
41299f41
TW
114
115 /* Walk the insn's pattern, remembering at all times the path
116 down to the walking point. */
117
118 if (XVECLEN (insn, 1) == 1)
9482d6de 119 walk_rtx (XVECEXP (insn, 1, 0), "");
41299f41
TW
120 else
121 for (i = XVECLEN (insn, 1) - 1; i >= 0; i--)
122 {
b548dffb 123 char path[2];
41299f41 124
9482d6de
RK
125 path[0] = 'a' + i;
126 path[1] = 0;
127
128 walk_rtx (XVECEXP (insn, 1, i), path);
41299f41 129 }
41299f41 130
9482d6de
RK
131 link = (struct code_ptr *) xmalloc (sizeof (struct code_ptr));
132 link->insn_code = insn_code_number;
133
0f41302f 134 /* See if we find something that already had this extraction method. */
9482d6de
RK
135
136 for (p = extractions; p; p = p->next)
41299f41 137 {
9482d6de
RK
138 if (p->op_count != op_count || p->dup_count != dup_count)
139 continue;
140
141 for (i = 0; i < op_count; i++)
142 if (p->oplocs[i] != oplocs[i]
143 && ! (p->oplocs[i] != 0 && oplocs[i] != 0
144 && ! strcmp (p->oplocs[i], oplocs[i])))
145 break;
146
147 if (i != op_count)
148 continue;
149
150 for (i = 0; i < dup_count; i++)
151 if (p->dupnums[i] != dupnums[i]
152 || strcmp (p->duplocs[i], duplocs[i]))
153 break;
154
155 if (i != dup_count)
156 continue;
157
158 /* This extraction is the same as ours. Just link us in. */
159 link->next = p->insns;
160 p->insns = link;
161 return;
41299f41
TW
162 }
163
9482d6de 164 /* Otherwise, make a new extraction method. */
41299f41 165
9482d6de
RK
166 p = (struct extraction *) xmalloc (sizeof (struct extraction));
167 p->op_count = op_count;
168 p->dup_count = dup_count;
169 p->next = extractions;
170 extractions = p;
171 p->insns = link;
172 link->next = 0;
173
174 for (i = 0; i < op_count; i++)
175 p->oplocs[i] = oplocs[i];
176
177 for (i = 0; i < dup_count; i++)
178 p->dupnums[i] = dupnums[i], p->duplocs[i] = duplocs[i];
179}
180\f
41299f41
TW
181static void
182walk_rtx (x, path)
183 rtx x;
85fda1eb 184 const char *path;
41299f41
TW
185{
186 register RTX_CODE code;
187 register int i;
188 register int len;
6f7d635c 189 register const char *fmt;
9482d6de
RK
190 int depth = strlen (path);
191 char *newpath;
41299f41
TW
192
193 if (x == 0)
194 return;
195
196 code = GET_CODE (x);
197
198 switch (code)
199 {
200 case PC:
201 case CC0:
202 case CONST_INT:
203 case SYMBOL_REF:
204 return;
205
206 case MATCH_OPERAND:
207 case MATCH_SCRATCH:
efd59a33 208 oplocs[XINT (x, 0)] = xstrdup (path);
9482d6de 209 op_count = MAX (op_count, XINT (x, 0) + 1);
41299f41
TW
210 break;
211
212 case MATCH_DUP:
f3e0821d 213 case MATCH_PAR_DUP:
efd59a33 214 duplocs[dup_count] = xstrdup (path);
9482d6de 215 dupnums[dup_count] = XINT (x, 0);
41299f41
TW
216 dup_count++;
217 break;
218
809ffa71 219 case MATCH_OP_DUP:
efd59a33 220 duplocs[dup_count] = xstrdup (path);
809ffa71
RK
221 dupnums[dup_count] = XINT (x, 0);
222 dup_count++;
223
b548dffb 224 newpath = (char *) xmalloc (depth + 2);
809ffa71
RK
225 strcpy (newpath, path);
226 newpath[depth + 1] = 0;
227
228 for (i = XVECLEN (x, 1) - 1; i >= 0; i--)
229 {
230 newpath[depth] = '0' + i;
231 walk_rtx (XVECEXP (x, 1, i), newpath);
232 }
b548dffb 233 free (newpath);
809ffa71
RK
234 return;
235
41299f41 236 case MATCH_OPERATOR:
efd59a33 237 oplocs[XINT (x, 0)] = xstrdup (path);
9482d6de
RK
238 op_count = MAX (op_count, XINT (x, 0) + 1);
239
b548dffb 240 newpath = (char *) xmalloc (depth + 2);
9482d6de
RK
241 strcpy (newpath, path);
242 newpath[depth + 1] = 0;
243
41299f41
TW
244 for (i = XVECLEN (x, 2) - 1; i >= 0; i--)
245 {
9482d6de
RK
246 newpath[depth] = '0' + i;
247 walk_rtx (XVECEXP (x, 2, i), newpath);
41299f41 248 }
b548dffb 249 free (newpath);
41299f41
TW
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
b548dffb 256 newpath = (char *) xmalloc (depth + 2);
9482d6de
RK
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 264 }
b548dffb 265 free (newpath);
41299f41
TW
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
b548dffb 276 newpath = (char *) xmalloc (depth + 2);
9482d6de
RK
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 }
b548dffb 299 free (newpath);
41299f41
TW
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
a94ae8f5 347extern int main PARAMS ((int, char **));
c1b59dce 348
41299f41
TW
349int
350main (argc, argv)
351 int argc;
352 char **argv;
353{
354 rtx desc;
c88c0d42 355 int i;
9482d6de
RK
356 struct extraction *p;
357 struct code_ptr *link;
8ad1aa56 358 const char *name;
41299f41 359
f8b6598e 360 progname = "genextract";
41299f41
TW
361
362 if (argc <= 1)
363 fatal ("No input file name.");
364
c88c0d42
CP
365 if (init_md_reader (argv[1]) != SUCCESS_EXIT_CODE)
366 return (FATAL_EXIT_CODE);
41299f41 367
41299f41
TW
368 /* Assign sequential codes to all entries in the machine description
369 in parallel with the tables in insn-output.c. */
370
371 insn_code_number = 0;
372
41299f41
TW
373 printf ("/* Generated automatically by the program `genextract'\n\
374from the machine description file `md'. */\n\n");
375
376 printf ("#include \"config.h\"\n");
729da3f5 377 printf ("#include \"system.h\"\n");
114791ea 378 printf ("#include \"rtl.h\"\n");
0a578fee
BS
379 printf ("#include \"insn-config.h\"\n");
380 printf ("#include \"recog.h\"\n");
114791ea 381 printf ("#include \"toplev.h\"\n\n");
41299f41
TW
382
383 /* This variable exists only so it can be the "location"
384 of any missing operand whose numbers are skipped by a given pattern. */
d6f4ec51 385 printf ("static rtx junk ATTRIBUTE_UNUSED;\n");
9482d6de 386
41299f41
TW
387 printf ("void\ninsn_extract (insn)\n");
388 printf (" rtx insn;\n");
389 printf ("{\n");
1ccbefce
RH
390 printf (" register rtx *ro = recog_data.operand;\n");
391 printf (" register rtx **ro_loc = recog_data.operand_loc;\n");
cc30cc14 392 printf (" rtx pat = PATTERN (insn);\n");
296433e1 393 printf (" int i ATTRIBUTE_UNUSED;\n\n");
99f25d8e
RH
394 printf (" memset (ro, 0, sizeof (*ro) * MAX_RECOG_OPERANDS);\n");
395 printf (" memset (ro_loc, 0, sizeof (*ro_loc) * MAX_RECOG_OPERANDS);\n");
cc30cc14 396 printf (" switch (INSN_CODE (insn))\n");
41299f41 397 printf (" {\n");
9482d6de
RK
398 printf (" case -1:\n");
399 printf (" fatal_insn_not_found (insn);\n\n");
41299f41
TW
400
401 /* Read the machine description. */
402
403 while (1)
404 {
c88c0d42
CP
405 int line_no;
406
407 desc = read_md_rtx (&line_no, &insn_code_number);
408 if (desc == NULL)
41299f41 409 break;
41299f41 410
c88c0d42 411 if (GET_CODE (desc) == DEFINE_INSN)
41299f41 412 {
8ad1aa56 413 record_insn_name (insn_code_number, XSTR (desc, 0));
41299f41 414 gen_insn (desc);
41299f41 415 }
9482d6de
RK
416
417 else if (GET_CODE (desc) == DEFINE_PEEPHOLE)
41299f41 418 {
9482d6de
RK
419 struct code_ptr *link
420 = (struct code_ptr *) xmalloc (sizeof (struct code_ptr));
421
422 link->insn_code = insn_code_number;
423 link->next = peepholes;
424 peepholes = link;
41299f41 425 }
9482d6de 426 }
41299f41 427
9482d6de
RK
428 /* Write out code to handle peepholes and the insn_codes that it should
429 be called for. */
430 if (peepholes)
41299f41 431 {
9482d6de
RK
432 for (link = peepholes; link; link = link->next)
433 printf (" case %d:\n", link->insn_code);
434
41299f41
TW
435 /* The vector in the insn says how many operands it has.
436 And all it contains are operands. In fact, the vector was
437 created just for the sake of this function. */
b7673cdb 438 printf (" for (i = XVECLEN (pat, 0) - 1; i >= 0; i--)\n");
cc38a1c3 439 printf (" ro[i] = XVECEXP (pat, 0, i);\n");
9482d6de
RK
440 printf (" break;\n\n");
441 }
442
443 /* Write out all the ways to extract insn operands. */
444 for (p = extractions; p; p = p->next)
445 {
446 for (link = p->insns; link; link = link->next)
8ad1aa56
ZW
447 {
448 i = link->insn_code;
449 name = get_insn_name (i);
450 if (name)
451 printf (" case %d: /* %s */\n", i, name);
452 else
453 printf (" case %d:\n", i);
454 }
455
9482d6de
RK
456 for (i = 0; i < p->op_count; i++)
457 {
458 if (p->oplocs[i] == 0)
459 {
460 printf (" ro[%d] = const0_rtx;\n", i);
8b5ba7f8 461 printf (" ro_loc[%d] = &junk;\n", i);
9482d6de
RK
462 }
463 else
464 {
465 printf (" ro[%d] = *(ro_loc[%d] = &", i, i);
466 print_path (p->oplocs[i]);
467 printf (");\n");
468 }
469 }
470
471 for (i = 0; i < p->dup_count; i++)
472 {
1ccbefce 473 printf (" recog_data.dup_loc[%d] = &", i);
9482d6de
RK
474 print_path (p->duplocs[i]);
475 printf (";\n");
1ccbefce 476 printf (" recog_data.dup_num[%d] = %d;\n", i, p->dupnums[i]);
9482d6de
RK
477 }
478
479 printf (" break;\n\n");
41299f41
TW
480 }
481
9482d6de
RK
482 /* This should never be reached. Note that we would also reach this abort
483 if we tried to extract something whose INSN_CODE was a DEFINE_EXPAND or
484 DEFINE_SPLIT, but that is correct. */
485 printf (" default:\n abort ();\n");
486
41299f41
TW
487 printf (" }\n}\n");
488
489 fflush (stdout);
c1b59dce 490 return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
41299f41 491}
a995e389
RH
492
493/* Define this so we can link with print-rtl.o to get debug_rtx function. */
494const char *
495get_insn_name (code)
c1b59dce 496 int code ATTRIBUTE_UNUSED;
a995e389 497{
8ad1aa56
ZW
498 if (code < insn_name_ptr_size)
499 return insn_name_ptr[code];
500 else
501 return NULL;
a995e389 502}
8ad1aa56
ZW
503
504static void
505record_insn_name (code, name)
506 int code;
507 const char *name;
508{
509 static const char *last_real_name = "insn";
510 static int last_real_code = 0;
511 char *new;
512
513 if (insn_name_ptr_size <= code)
514 {
515 int new_size;
516 new_size = (insn_name_ptr_size ? insn_name_ptr_size * 2 : 512);
517 insn_name_ptr =
518 (char **) xrealloc (insn_name_ptr, sizeof(char *) * new_size);
519 memset (insn_name_ptr + insn_name_ptr_size, 0,
520 sizeof(char *) * (new_size - insn_name_ptr_size));
521 insn_name_ptr_size = new_size;
522 }
523
524 if (!name || name[0] == '\0')
525 {
526 new = xmalloc (strlen (last_real_name) + 10);
527 sprintf (new, "%s+%d", last_real_name, code - last_real_code);
528 }
529 else
530 {
531 last_real_name = new = xstrdup (name);
532 last_real_code = code;
533 }
534
535 insn_name_ptr[code] = new;
536}