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