|
|
1.1 root 1: /* Generate code from machine description to extract operands from insn as rtl.
2: Copyright (C) 1987 Free Software Foundation, Inc.
3:
4: This file is part of GNU CC.
5:
1.1.1.4 root 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 1, or (at your option)
9: any later version.
10:
1.1 root 11: GNU CC is distributed in the hope that it will be useful,
1.1.1.4 root 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. */
1.1 root 19:
20:
21: #include <stdio.h>
1.1.1.2 root 22: #include "config.h"
1.1 root 23: #include "rtl.h"
1.1.1.2 root 24: #include "obstack.h"
1.1 root 25:
26: struct obstack obstack;
1.1.1.2 root 27: struct obstack *rtl_obstack = &obstack;
1.1 root 28:
29: #define obstack_chunk_alloc xmalloc
30: #define obstack_chunk_free free
31: extern int xmalloc ();
32: extern void free ();
33:
34: /* Number instruction patterns handled, starting at 0 for first one. */
35:
36: int insn_code_number;
37:
38: /* Number the occurrences of MATCH_DUP in each instruction,
39: starting at 0 for the first occurrence. */
40:
41: int dup_count;
42:
43: /* While tree-walking an instruction pattern, we keep a chain
44: of these `struct link's to record how to get down to the
1.1.1.2 root 45: current position. In each one, POS is the operand number,
46: and if the operand is a vector VEC is the element number.
47: VEC is -1 if the operand is not a vector. */
1.1 root 48:
49: struct link
50: {
51: struct link *next;
52: int pos;
1.1.1.2 root 53: int vecelt;
1.1 root 54: };
55:
1.1.1.5 root 56: void walk_rtx ();
57: void print_path ();
58: void fatal ();
59: void fancy_abort ();
60:
1.1 root 61: void
62: gen_insn (insn)
63: rtx insn;
64: {
65: register int i;
66:
67: dup_count = 0;
68:
69: /* Output the function name and argument declaration. */
1.1.1.4 root 70: /* It would be cleaner to make `void' the return type
1.1 root 71: but 4.2 vax compiler doesn't accept that in the array
72: that these functions are supposed to go in. */
1.1.1.2 root 73: printf ("VOID\nextract_%d (insn)\n rtx insn;\n", insn_code_number);
1.1 root 74: printf ("{\n");
75:
76: /* Walk the insn's pattern, remembering at all times the path
77: down to the walking point. */
78:
79: if (XVECLEN (insn, 1) == 1)
80: walk_rtx (XVECEXP (insn, 1, 0), 0);
81: else
82: for (i = XVECLEN (insn, 1) - 1; i >= 0; i--)
83: {
84: struct link link;
85: link.next = 0;
1.1.1.2 root 86: link.pos = 0;
87: link.vecelt = i;
1.1 root 88: walk_rtx (XVECEXP (insn, 1, i), &link);
89: }
90: printf ("}\n\n");
91: }
92:
1.1.1.2 root 93: /* Like gen_insn but handles `define_peephole'. */
94:
95: void
96: gen_peephole (peep)
97: rtx peep;
98: {
99: /* Output the function name and argument declaration. */
100: printf ("VOID\nextract_%d (insn)\n rtx insn;\n", insn_code_number);
101: printf ("{\n");
102: /* The vector in the insn says how many operands it has.
103: And all it contains are operands. In fact, the vector was
104: created just for the sake of this function. */
105: printf ("\
106: bcopy (&XVECEXP (insn, 0, 0), recog_operand,\
1.1.1.6 ! root 107: sizeof (rtx) * XVECLEN (insn, 0));\n");
1.1.1.2 root 108: printf ("}\n\n");
109: }
1.1.1.5 root 110:
1.1.1.2 root 111: void
1.1 root 112: walk_rtx (x, path)
113: rtx x;
114: struct link *path;
115: {
1.1.1.2 root 116: register RTX_CODE code;
1.1 root 117: register int i;
118: register int len;
119: register char *fmt;
120: struct link link;
121:
1.1.1.2 root 122: if (x == 0)
123: return;
124:
125: code = GET_CODE (x);
126:
1.1 root 127: switch (code)
128: {
129: case PC:
130: case CC0:
131: case CONST_INT:
132: case SYMBOL_REF:
133: return;
134:
135: case MATCH_OPERAND:
136: printf (" recog_operand[%d] = *(recog_operand_loc[%d]\n = &",
137: XINT (x, 0), XINT (x, 0));
138: print_path (path);
139: printf (");\n");
140: break;
141:
142: case MATCH_DUP:
143: printf (" recog_dup_loc[%d] = &", dup_count);
144: print_path (path);
145: printf (";\n");
146: printf (" recog_dup_num[%d] = %d;\n", dup_count, XINT (x, 0));
147: dup_count++;
148: break;
149:
1.1.1.3 root 150: case MATCH_OPERATOR:
151: printf (" recog_operand[%d] = *(recog_operand_loc[%d]\n = &",
152: XINT (x, 0), XINT (x, 0));
153: print_path (path);
154: printf (");\n");
155: link.next = path;
156: link.vecelt = -1;
157: for (i = XVECLEN (x, 2) - 1; i >= 0; i--)
158: {
159: link.pos = i;
160: walk_rtx (XVECEXP (x, 2, i), &link);
161: }
162: return;
163:
1.1 root 164: case ADDRESS:
165: walk_rtx (XEXP (x, 0), path);
166: return;
167: }
168:
169: link.next = path;
1.1.1.2 root 170: link.vecelt = -1;
1.1 root 171: fmt = GET_RTX_FORMAT (code);
172: len = GET_RTX_LENGTH (code);
173: for (i = 0; i < len; i++)
1.1.1.2 root 174: {
175: link.pos = i;
176: if (fmt[i] == 'e' || fmt[i] == 'u')
177: {
178: walk_rtx (XEXP (x, i), &link);
179: }
180: else if (fmt[i] == 'E')
181: {
182: int j;
183: for (j = XVECLEN (x, i) - 1; j >= 0; j--)
184: {
185: link.vecelt = j;
186: walk_rtx (XVECEXP (x, i, j), &link);
187: }
188: }
189: }
1.1 root 190: }
191:
192: /* Given a PATH, representing a path down the instruction's
193: pattern from the root to a certain point, output code to
194: evaluate to the rtx at that point. */
195:
1.1.1.2 root 196: void
1.1 root 197: print_path (path)
198: struct link *path;
199: {
200: if (path == 0)
201: printf ("insn");
1.1.1.2 root 202: else if (path->vecelt >= 0)
1.1 root 203: {
204: printf ("XVECEXP (");
205: print_path (path->next);
1.1.1.2 root 206: printf (", %d, %d)", path->pos, path->vecelt);
1.1 root 207: }
208: else
209: {
210: printf ("XEXP (");
211: print_path (path->next);
212: printf (", %d)", path->pos);
213: }
214: }
215:
1.1.1.2 root 216: int
1.1 root 217: xmalloc (size)
218: {
219: register int val = malloc (size);
220:
221: if (val == 0)
1.1.1.2 root 222: fatal ("virtual memory exhausted");
1.1 root 223: return val;
224: }
225:
226: int
227: xrealloc (ptr, size)
228: char *ptr;
229: int size;
230: {
231: int result = realloc (ptr, size);
232: if (!result)
1.1.1.2 root 233: fatal ("virtual memory exhausted");
1.1 root 234: return result;
235: }
236:
237: void
238: fatal (s, a1, a2)
1.1.1.5 root 239: char *s;
1.1 root 240: {
1.1.1.2 root 241: fprintf (stderr, "genextract: ");
1.1 root 242: fprintf (stderr, s, a1, a2);
243: fprintf (stderr, "\n");
1.1.1.2 root 244: exit (FATAL_EXIT_CODE);
1.1 root 245: }
1.1.1.5 root 246:
247: /* More 'friendly' abort that prints the line and file.
248: config.h can #define abort fancy_abort if you like that sort of thing. */
249:
250: void
251: fancy_abort ()
252: {
253: fatal ("Internal gcc abort.");
254: }
1.1 root 255:
1.1.1.2 root 256: int
1.1 root 257: main (argc, argv)
258: int argc;
259: char **argv;
260: {
261: rtx desc;
262: FILE *infile;
263: extern rtx read_rtx ();
264: register int c, i;
265:
1.1.1.2 root 266: obstack_init (rtl_obstack);
1.1 root 267:
268: if (argc <= 1)
269: fatal ("No input file name.");
270:
271: infile = fopen (argv[1], "r");
272: if (infile == 0)
273: {
274: perror (argv[1]);
1.1.1.2 root 275: exit (FATAL_EXIT_CODE);
1.1 root 276: }
277:
278: init_rtl ();
279:
280: /* Assign sequential codes to all entries in the machine description
281: in parallel with the tables in insn-output.c. */
282:
283: insn_code_number = 0;
284:
285: printf ("/* Generated automatically by the program `genextract'\n\
286: from the machine description file `md'. */\n\n");
287:
1.1.1.2 root 288: printf ("#include \"config.h\"\n");
1.1 root 289: printf ("#include \"rtl.h\"\n\n");
290:
291: printf ("extern rtx recog_operand[];\n");
292: printf ("extern rtx *recog_operand_loc[];\n");
293: printf ("extern rtx *recog_dup_loc[];\n");
294: printf ("extern char recog_dup_num[];\n\n");
295:
1.1.1.2 root 296: /* The extractor functions really should return `void';
297: but old C compilers don't seem to be able to handle the array
298: definition if `void' is used. So use `int' in non-ANSI C compilers. */
299:
300: printf ("#ifdef __STDC__\n#define VOID void\n#else\n#define VOID int\n#endif\n\n");
301:
1.1 root 302: /* Read the machine description. */
303:
304: while (1)
305: {
306: c = read_skip_spaces (infile);
307: if (c == EOF)
308: break;
309: ungetc (c, infile);
310:
311: desc = read_rtx (infile);
1.1.1.2 root 312: if (GET_CODE (desc) == DEFINE_INSN)
313: {
314: gen_insn (desc);
315: ++insn_code_number;
316: }
317: if (GET_CODE (desc) == DEFINE_PEEPHOLE)
318: {
319: gen_peephole (desc);
320: ++insn_code_number;
321: }
322: if (GET_CODE (desc) == DEFINE_EXPAND)
323: {
324: printf ("VOID extract_%d () {}\n\n", insn_code_number);
325: ++insn_code_number;
326: }
1.1 root 327: }
328:
1.1.1.2 root 329: printf ("VOID (*insn_extract_fn[]) () =\n{ ");
1.1 root 330: for (i = 0; i < insn_code_number; i++)
331: {
332: if (i % 4 != 0)
333: printf (", ");
334: else if (i != 0)
335: printf (",\n ");
336: printf ("extract_%d", i);
337: }
338: printf ("\n};\n\n");
339:
1.1.1.5 root 340: printf ("void fatal_insn_not_found ();\n\n");
1.1 root 341: printf ("void\ninsn_extract (insn)\n");
342: printf (" rtx insn;\n");
1.1.1.5 root 343: printf ("{\n if (INSN_CODE (insn) == -1) fatal_insn_not_found (insn);\n");
1.1 root 344: printf (" (*insn_extract_fn[INSN_CODE (insn)]) (PATTERN (insn));\n}\n");
1.1.1.2 root 345:
346: fflush (stdout);
347: exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
1.1 root 348: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.