|
|
1.1 root 1: /* Generate code from machine description to extract operands from insn as rtl.
1.1.1.6 root 2: Copyright (C) 1987, 1991, 1992, 1993 Free Software Foundation, Inc.
1.1 root 3:
4: This file is part of GNU CC.
5:
6: GNU CC is free software; you can redistribute it and/or modify
7: it under the terms of the GNU General Public License as published by
8: the Free Software Foundation; either version 2, or (at your option)
9: any later version.
10:
11: GNU CC is distributed in the hope that it will be useful,
12: but WITHOUT ANY WARRANTY; without even the implied warranty of
13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14: GNU General Public License for more details.
15:
16: You should have received a copy of the GNU General Public License
17: along with GNU CC; see the file COPYING. If not, write to
1.1.1.8 ! root 18: the Free Software Foundation, 59 Temple Place - Suite 330,
! 19: Boston, MA 02111-1307, USA. */
1.1 root 20:
21:
22: #include <stdio.h>
1.1.1.4 root 23: #include "hconfig.h"
1.1 root 24: #include "rtl.h"
25: #include "obstack.h"
1.1.1.3 root 26: #include "insn-config.h"
1.1 root 27:
28: static struct obstack obstack;
29: struct obstack *rtl_obstack = &obstack;
30:
31: #define obstack_chunk_alloc xmalloc
32: #define obstack_chunk_free free
33:
34: extern void free ();
1.1.1.3 root 35: extern rtx read_rtx ();
36:
1.1.1.6 root 37: /* Names for patterns. Need to allow linking with print-rtl. */
38: char **insn_name_ptr;
39:
1.1.1.3 root 40: /* This structure contains all the information needed to describe one
41: set of extractions methods. Each method may be used by more than
42: one pattern if the operands are in the same place.
43:
44: The string for each operand describes that path to the operand and
45: contains `0' through `9' when going into an expression and `a' through
46: `z' when going into a vector. We assume here that only the first operand
47: of an rtl expression is a vector. genrecog.c makes the same assumption
48: (and uses the same representation) and it is currently true. */
49:
50: struct extraction
51: {
52: int op_count;
53: char *oplocs[MAX_RECOG_OPERANDS];
54: int dup_count;
55: char *duplocs[MAX_DUP_OPERANDS];
56: int dupnums[MAX_DUP_OPERANDS];
57: struct code_ptr *insns;
58: struct extraction *next;
59: };
60:
61: /* Holds a single insn code that use an extraction method. */
62:
63: struct code_ptr
64: {
65: int insn_code;
66: struct code_ptr *next;
67: };
68:
69: static struct extraction *extractions;
1.1 root 70:
71: /* Number instruction patterns handled, starting at 0 for first one. */
72:
73: static int insn_code_number;
74:
1.1.1.3 root 75: /* Records the large operand number in this insn. */
76:
77: static int op_count;
78:
79: /* Records the location of any operands using the string format described
80: above. */
81:
82: static char *oplocs[MAX_RECOG_OPERANDS];
83:
1.1 root 84: /* Number the occurrences of MATCH_DUP in each instruction,
85: starting at 0 for the first occurrence. */
86:
87: static int dup_count;
88:
1.1.1.3 root 89: /* Records the location of any MATCH_DUP operands. */
1.1 root 90:
1.1.1.3 root 91: static char *duplocs[MAX_DUP_OPERANDS];
1.1 root 92:
1.1.1.3 root 93: /* Record the operand number of any MATCH_DUPs. */
1.1 root 94:
1.1.1.3 root 95: static int dupnums[MAX_DUP_OPERANDS];
1.1 root 96:
1.1.1.3 root 97: /* Record the list of insn_codes for peepholes. */
1.1 root 98:
1.1.1.3 root 99: static struct code_ptr *peepholes;
1.1 root 100:
101: static void walk_rtx ();
102: static void print_path ();
103: char *xmalloc ();
104: char *xrealloc ();
105: static void fatal ();
1.1.1.3 root 106: static char *copystr ();
1.1.1.2 root 107: static void mybzero ();
1.1 root 108: void fancy_abort ();
109:
110: static void
111: gen_insn (insn)
112: rtx insn;
113: {
114: register int i;
1.1.1.3 root 115: register struct extraction *p;
116: register struct code_ptr *link;
1.1 root 117:
1.1.1.3 root 118: op_count = 0;
1.1 root 119: dup_count = 0;
120:
121: /* No operands seen so far in this pattern. */
1.1.1.3 root 122: mybzero (oplocs, sizeof oplocs);
1.1 root 123:
124: /* Walk the insn's pattern, remembering at all times the path
125: down to the walking point. */
126:
127: if (XVECLEN (insn, 1) == 1)
1.1.1.3 root 128: walk_rtx (XVECEXP (insn, 1, 0), "");
1.1 root 129: else
130: for (i = XVECLEN (insn, 1) - 1; i >= 0; i--)
131: {
1.1.1.3 root 132: char *path = (char *) alloca (2);
1.1 root 133:
1.1.1.3 root 134: path[0] = 'a' + i;
135: path[1] = 0;
136:
137: walk_rtx (XVECEXP (insn, 1, i), path);
1.1 root 138: }
139:
1.1.1.3 root 140: link = (struct code_ptr *) xmalloc (sizeof (struct code_ptr));
141: link->insn_code = insn_code_number;
142:
143: /* See if we find something that already had this extraction method. */
144:
145: for (p = extractions; p; p = p->next)
1.1 root 146: {
1.1.1.3 root 147: if (p->op_count != op_count || p->dup_count != dup_count)
148: continue;
149:
150: for (i = 0; i < op_count; i++)
151: if (p->oplocs[i] != oplocs[i]
152: && ! (p->oplocs[i] != 0 && oplocs[i] != 0
153: && ! strcmp (p->oplocs[i], oplocs[i])))
154: break;
155:
156: if (i != op_count)
157: continue;
158:
159: for (i = 0; i < dup_count; i++)
160: if (p->dupnums[i] != dupnums[i]
161: || strcmp (p->duplocs[i], duplocs[i]))
162: break;
163:
164: if (i != dup_count)
165: continue;
166:
167: /* This extraction is the same as ours. Just link us in. */
168: link->next = p->insns;
169: p->insns = link;
170: return;
1.1 root 171: }
172:
1.1.1.3 root 173: /* Otherwise, make a new extraction method. */
1.1 root 174:
1.1.1.3 root 175: p = (struct extraction *) xmalloc (sizeof (struct extraction));
176: p->op_count = op_count;
177: p->dup_count = dup_count;
178: p->next = extractions;
179: extractions = p;
180: p->insns = link;
181: link->next = 0;
182:
183: for (i = 0; i < op_count; i++)
184: p->oplocs[i] = oplocs[i];
185:
186: for (i = 0; i < dup_count; i++)
187: p->dupnums[i] = dupnums[i], p->duplocs[i] = duplocs[i];
188: }
189:
1.1 root 190: static void
191: walk_rtx (x, path)
192: rtx x;
1.1.1.3 root 193: char *path;
1.1 root 194: {
195: register RTX_CODE code;
196: register int i;
197: register int len;
198: register char *fmt;
1.1.1.3 root 199: register struct code_ptr *link;
200: int depth = strlen (path);
201: char *newpath;
1.1 root 202:
203: if (x == 0)
204: return;
205:
206: code = GET_CODE (x);
207:
208: switch (code)
209: {
210: case PC:
211: case CC0:
212: case CONST_INT:
213: case SYMBOL_REF:
214: return;
215:
216: case MATCH_OPERAND:
217: case MATCH_SCRATCH:
1.1.1.3 root 218: oplocs[XINT (x, 0)] = copystr (path);
219: op_count = MAX (op_count, XINT (x, 0) + 1);
1.1 root 220: break;
221:
222: case MATCH_DUP:
1.1.1.4 root 223: case MATCH_PAR_DUP:
1.1.1.3 root 224: duplocs[dup_count] = copystr (path);
225: dupnums[dup_count] = XINT (x, 0);
1.1 root 226: dup_count++;
227: break;
228:
1.1.1.6 root 229: case MATCH_OP_DUP:
230: duplocs[dup_count] = copystr (path);
231: dupnums[dup_count] = XINT (x, 0);
232: dup_count++;
233:
234: newpath = (char *) alloca (depth + 2);
235: strcpy (newpath, path);
236: newpath[depth + 1] = 0;
237:
238: for (i = XVECLEN (x, 1) - 1; i >= 0; i--)
239: {
240: newpath[depth] = '0' + i;
241: walk_rtx (XVECEXP (x, 1, i), newpath);
242: }
243: return;
244:
1.1 root 245: case MATCH_OPERATOR:
1.1.1.3 root 246: oplocs[XINT (x, 0)] = copystr (path);
247: op_count = MAX (op_count, XINT (x, 0) + 1);
248:
249: newpath = (char *) alloca (depth + 2);
250: strcpy (newpath, path);
251: newpath[depth + 1] = 0;
252:
1.1 root 253: for (i = XVECLEN (x, 2) - 1; i >= 0; i--)
254: {
1.1.1.3 root 255: newpath[depth] = '0' + i;
256: walk_rtx (XVECEXP (x, 2, i), newpath);
1.1 root 257: }
258: return;
259:
260: case MATCH_PARALLEL:
1.1.1.3 root 261: oplocs[XINT (x, 0)] = copystr (path);
262: op_count = MAX (op_count, XINT (x, 0) + 1);
263:
264: newpath = (char *) alloca (depth + 2);
265: strcpy (newpath, path);
266: newpath[depth + 1] = 0;
267:
1.1 root 268: for (i = XVECLEN (x, 2) - 1; i >= 0; i--)
269: {
1.1.1.3 root 270: newpath[depth] = 'a' + i;
271: walk_rtx (XVECEXP (x, 2, i), newpath);
1.1 root 272: }
273: return;
274:
275: case ADDRESS:
276: walk_rtx (XEXP (x, 0), path);
277: return;
278: }
279:
1.1.1.3 root 280: newpath = (char *) alloca (depth + 2);
281: strcpy (newpath, path);
282: newpath[depth + 1] = 0;
283:
1.1 root 284: fmt = GET_RTX_FORMAT (code);
285: len = GET_RTX_LENGTH (code);
286: for (i = 0; i < len; i++)
287: {
288: if (fmt[i] == 'e' || fmt[i] == 'u')
289: {
1.1.1.3 root 290: newpath[depth] = '0' + i;
291: walk_rtx (XEXP (x, i), newpath);
1.1 root 292: }
293: else if (fmt[i] == 'E')
294: {
295: int j;
296: for (j = XVECLEN (x, i) - 1; j >= 0; j--)
297: {
1.1.1.3 root 298: newpath[depth] = 'a' + j;
299: walk_rtx (XVECEXP (x, i, j), newpath);
1.1 root 300: }
301: }
302: }
303: }
304:
305: /* Given a PATH, representing a path down the instruction's
306: pattern from the root to a certain point, output code to
307: evaluate to the rtx at that point. */
308:
309: static void
310: print_path (path)
1.1.1.3 root 311: char *path;
1.1 root 312: {
1.1.1.3 root 313: register int len = strlen (path);
314: register int i;
315:
316: /* We first write out the operations (XEXP or XVECEXP) in reverse
317: order, then write "insn", then the indices in forward order. */
318:
319: for (i = len - 1; i >=0 ; i--)
1.1 root 320: {
1.1.1.3 root 321: if (path[i] >= 'a' && path[i] <= 'z')
322: printf ("XVECEXP (");
323: else if (path[i] >= '0' && path[i] <= '9')
324: printf ("XEXP (");
325: else
326: abort ();
1.1 root 327: }
1.1.1.3 root 328:
329: printf ("pat");
330:
331: for (i = 0; i < len; i++)
1.1 root 332: {
1.1.1.3 root 333: if (path[i] >= 'a' && path[i] <= 'z')
334: printf (", 0, %d)", path[i] - 'a');
335: else if (path[i] >= '0' && path[i] <= '9')
336: printf (", %d)", path[i] - '0');
337: else
338: abort ();
1.1 root 339: }
340: }
341:
342: char *
343: xmalloc (size)
344: unsigned size;
345: {
346: register char *val = (char *) malloc (size);
347:
348: if (val == 0)
349: fatal ("virtual memory exhausted");
350: return val;
351: }
352:
353: char *
354: xrealloc (ptr, size)
355: char *ptr;
356: unsigned size;
357: {
358: char *result = (char *) realloc (ptr, size);
359: if (!result)
360: fatal ("virtual memory exhausted");
361: return result;
362: }
363:
364: static void
365: fatal (s, a1, a2)
366: char *s;
367: {
368: fprintf (stderr, "genextract: ");
369: fprintf (stderr, s, a1, a2);
370: fprintf (stderr, "\n");
371: exit (FATAL_EXIT_CODE);
372: }
373:
374: /* More 'friendly' abort that prints the line and file.
375: config.h can #define abort fancy_abort if you like that sort of thing. */
376:
377: void
378: fancy_abort ()
379: {
380: fatal ("Internal gcc abort.");
381: }
1.1.1.2 root 382:
1.1.1.3 root 383: static char *
384: copystr (s1)
385: char *s1;
386: {
387: register char *tem;
388:
389: if (s1 == 0)
390: return 0;
391:
392: tem = (char *) xmalloc (strlen (s1) + 1);
393: strcpy (tem, s1);
394:
395: return tem;
396: }
397:
1.1.1.2 root 398: static void
399: mybzero (b, length)
400: register char *b;
401: register unsigned length;
402: {
403: while (length-- > 0)
404: *b++ = 0;
405: }
1.1 root 406:
407: int
408: main (argc, argv)
409: int argc;
410: char **argv;
411: {
412: rtx desc;
413: FILE *infile;
414: register int c, i;
1.1.1.3 root 415: struct extraction *p;
416: struct code_ptr *link;
1.1 root 417:
418: obstack_init (rtl_obstack);
419:
420: if (argc <= 1)
421: fatal ("No input file name.");
422:
423: infile = fopen (argv[1], "r");
424: if (infile == 0)
425: {
426: perror (argv[1]);
427: exit (FATAL_EXIT_CODE);
428: }
429:
430: init_rtl ();
431:
432: /* Assign sequential codes to all entries in the machine description
433: in parallel with the tables in insn-output.c. */
434:
435: insn_code_number = 0;
436:
437: printf ("/* Generated automatically by the program `genextract'\n\
438: from the machine description file `md'. */\n\n");
439:
440: printf ("#include \"config.h\"\n");
441: printf ("#include \"rtl.h\"\n\n");
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. */
445: printf ("static rtx junk;\n");
1.1.1.3 root 446:
1.1 root 447: printf ("extern rtx recog_operand[];\n");
448: printf ("extern rtx *recog_operand_loc[];\n");
449: printf ("extern rtx *recog_dup_loc[];\n");
450: printf ("extern char recog_dup_num[];\n");
451:
452: printf ("void\ninsn_extract (insn)\n");
453: printf (" rtx insn;\n");
454: printf ("{\n");
1.1.1.3 root 455: printf (" register rtx *ro = recog_operand;\n");
456: printf (" register rtx **ro_loc = recog_operand_loc;\n");
457: printf (" rtx pat = PATTERN (insn);\n");
458: printf (" switch (INSN_CODE (insn))\n");
1.1 root 459: printf (" {\n");
1.1.1.3 root 460: printf (" case -1:\n");
461: printf (" fatal_insn_not_found (insn);\n\n");
1.1 root 462:
463: /* Read the machine description. */
464:
465: while (1)
466: {
467: c = read_skip_spaces (infile);
468: if (c == EOF)
469: break;
470: ungetc (c, infile);
471:
472: desc = read_rtx (infile);
473: if (GET_CODE (desc) == DEFINE_INSN)
474: {
475: gen_insn (desc);
476: ++insn_code_number;
477: }
1.1.1.3 root 478:
479: else if (GET_CODE (desc) == DEFINE_PEEPHOLE)
1.1 root 480: {
1.1.1.3 root 481: struct code_ptr *link
482: = (struct code_ptr *) xmalloc (sizeof (struct code_ptr));
483:
484: link->insn_code = insn_code_number;
485: link->next = peepholes;
486: peepholes = link;
1.1 root 487: ++insn_code_number;
488: }
489:
1.1.1.3 root 490: else if (GET_CODE (desc) == DEFINE_EXPAND
491: || GET_CODE (desc) == DEFINE_SPLIT)
492: ++insn_code_number;
493: }
1.1 root 494:
1.1.1.3 root 495: /* Write out code to handle peepholes and the insn_codes that it should
496: be called for. */
497: if (peepholes)
1.1 root 498: {
1.1.1.3 root 499: for (link = peepholes; link; link = link->next)
500: printf (" case %d:\n", link->insn_code);
501:
1.1 root 502: /* The vector in the insn says how many operands it has.
503: And all it contains are operands. In fact, the vector was
504: created just for the sake of this function. */
505: printf ("#if __GNUC__ > 1 && !defined (bcopy)\n");
506: printf ("#define bcopy(FROM,TO,COUNT) __builtin_memcpy(TO,FROM,COUNT)\n");
507: printf ("#endif\n");
1.1.1.3 root 508: printf (" bcopy (&XVECEXP (pat, 0, 0), ro,\n");
509: printf (" sizeof (rtx) * XVECLEN (pat, 0));\n");
510: printf (" break;\n\n");
511: }
512:
513: /* Write out all the ways to extract insn operands. */
514: for (p = extractions; p; p = p->next)
515: {
516: for (link = p->insns; link; link = link->next)
517: printf (" case %d:\n", link->insn_code);
518:
519: for (i = 0; i < p->op_count; i++)
520: {
521: if (p->oplocs[i] == 0)
522: {
523: printf (" ro[%d] = const0_rtx;\n", i);
1.1.1.5 root 524: printf (" ro_loc[%d] = &junk;\n", i);
1.1.1.3 root 525: }
526: else
527: {
528: printf (" ro[%d] = *(ro_loc[%d] = &", i, i);
529: print_path (p->oplocs[i]);
530: printf (");\n");
531: }
532: }
533:
534: for (i = 0; i < p->dup_count; i++)
535: {
536: printf (" recog_dup_loc[%d] = &", i);
537: print_path (p->duplocs[i]);
538: printf (";\n");
539: printf (" recog_dup_num[%d] = %d;\n", i, p->dupnums[i]);
540: }
541:
542: printf (" break;\n\n");
1.1 root 543: }
544:
1.1.1.3 root 545: /* This should never be reached. Note that we would also reach this abort
546: if we tried to extract something whose INSN_CODE was a DEFINE_EXPAND or
547: DEFINE_SPLIT, but that is correct. */
548: printf (" default:\n abort ();\n");
549:
1.1 root 550: printf (" }\n}\n");
551:
552: fflush (stdout);
553: exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
554: /* NOTREACHED */
555: return 0;
556: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.