|
|
1.1 root 1: /* Generate code from machine description to emit insns as rtl.
2: Copyright (C) 1987 Free Software Foundation, Inc.
3:
4: This file is part of GNU CC.
5:
6: GNU CC is distributed in the hope that it will be useful,
7: but WITHOUT ANY WARRANTY. No author or distributor
8: accepts responsibility to anyone for the consequences of using it
9: or for whether it serves any particular purpose or works at all,
10: unless he says so in writing. Refer to the GNU CC General Public
11: License for full details.
12:
13: Everyone is granted permission to copy, modify and redistribute
14: GNU CC, but only under the conditions described in the
15: GNU CC General Public License. A copy of this license is
16: supposed to have been given to you along with GNU CC so you
17: can know your rights and responsibilities. It should be in a
18: file named COPYING. Among other things, the copyright notice
19: and this notice must be preserved on all copies. */
20:
21:
22: #include <stdio.h>
23: #include "config.h"
24: #include "rtl.h"
25: #include "obstack.h"
26:
27: struct obstack obstack;
28: struct obstack *rtl_obstack = &obstack;
29:
30: #define obstack_chunk_alloc xmalloc
31: #define obstack_chunk_free free
32: extern int xmalloc ();
33: extern void free ();
34:
35: void fatal ();
36:
37: int max_opno;
38: int max_dup_opno;
39: int register_constraints;
40: int insn_code_number;
41:
42: #define max(a, b) ((a) > (b) ? (a) : (b))
43:
44: void
45: max_operand_1 (x)
46: rtx x;
47: {
48: register RTX_CODE code;
49: register int i;
50: register int len;
51: register char *fmt;
52:
53: if (x == 0)
54: return;
55:
56: code = GET_CODE (x);
57:
58: if (code == MATCH_OPERAND && XSTR (x, 2) != 0)
59: register_constraints = 1;
60: if (code == MATCH_OPERAND)
61: max_opno = max (max_opno, XINT (x, 0));
62: if (code == MATCH_DUP)
63: max_dup_opno = max (max_dup_opno, XINT (x, 0));
64:
65: fmt = GET_RTX_FORMAT (code);
66: len = GET_RTX_LENGTH (code);
67: for (i = 0; i < len; i++)
68: {
69: if (fmt[i] == 'e' || fmt[i] == 'u')
70: max_operand_1 (XEXP (x, i));
71: else if (fmt[i] == 'E')
72: {
73: int j;
74: for (j = 0; j < XVECLEN (x, i); j++)
75: max_operand_1 (XVECEXP (x, i, j));
76: }
77: }
78: }
79:
80: int
81: max_operand_vec (insn, arg)
82: rtx insn;
83: int arg;
84: {
85: register int len = XVECLEN (insn, arg);
86: register int i;
87:
88: max_opno = -1;
89: max_dup_opno = -1;
90:
91: for (i = 0; i < len; i++)
92: max_operand_1 (XVECEXP (insn, arg, i));
93:
94: return max_opno + 1;
95: }
96:
97: void
98: print_code (code)
99: RTX_CODE code;
100: {
101: register char *p1;
102: for (p1 = GET_RTX_NAME (code); *p1; p1++)
103: {
104: if (*p1 >= 'a' && *p1 <= 'z')
105: putchar (*p1 + 'A' - 'a');
106: else
107: putchar (*p1);
108: }
109: }
110:
111: /* Print a C expression to construct an RTX just like X,
112: substituting any operand references appearing within. */
113:
114: void
115: gen_exp (x)
116: rtx x;
117: {
118: register RTX_CODE code;
119: register int i;
120: register int len;
121: register char *fmt;
122:
123: if (x == 0)
124: {
125: printf ("0");
126: return;
127: }
128:
129: code = GET_CODE (x);
130:
131: switch (code)
132: {
133: case MATCH_OPERAND:
134: case MATCH_DUP:
135: printf ("operand%d", XINT (x, 0));
136: return;
137:
138: case ADDRESS:
139: fatal ("ADDRESS expression code used in named instruction pattern");
140:
141: case PC:
142: printf ("pc_rtx");
143: return;
144:
145: case CC0:
146: printf ("cc0_rtx");
147: return;
148:
149: case CONST_INT:
150: if (INTVAL (x) == 0)
151: {
152: printf ("const0_rtx");
153: return;
154: }
155: if (INTVAL (x) == 1)
156: {
157: printf ("const1_rtx");
158: return;
159: }
160: }
161:
162: printf ("gen_rtx (");
163: print_code (code);
164: printf (", %smode", GET_MODE_NAME (GET_MODE (x)));
165:
166: fmt = GET_RTX_FORMAT (code);
167: len = GET_RTX_LENGTH (code);
168: for (i = 0; i < len; i++)
169: {
170: if (fmt[i] == '0')
171: break;
172: printf (", ");
173: if (fmt[i] == 'e' || fmt[i] == 'u')
174: gen_exp (XEXP (x, i));
175: else if (fmt[i] == 'i')
176: printf ("%d", XINT (x, i));
177: else if (fmt[i] == 's')
178: printf ("\"%s\"", XSTR (x, i));
179: else if (fmt[i] == 'E')
180: {
181: int j;
182: printf ("gen_rtvec (%d", XVECLEN (x, i));
183: for (j = 0; j < XVECLEN (x, i); j++)
184: {
185: printf (", ");
186: gen_exp (XVECEXP (x, i, j));
187: }
188: printf (")");
189: }
190: else
191: abort ();
192: }
193: printf (")");
194: }
195:
196: /* Generate the `gen_...' function for a DEFINE_INSN. */
197:
198: void
199: gen_insn (insn)
200: rtx insn;
201: {
202: int operands;
203: register int i;
204:
205: /* Don't mention instructions whose names are the null string.
206: They are in the machine description just to be recognized. */
207: if (strlen (XSTR (insn, 0)) == 0)
208: return;
209:
210: /* Find out how many operands this function has,
211: and also whether any of them have register constraints. */
212: register_constraints = 0;
213: operands = max_operand_vec (insn, 1);
214: if (max_dup_opno >= operands)
215: fatal ("match_dup operand number has no match_operand");
216:
217: /* Output the function name and argument declarations. */
218: printf ("rtx\ngen_%s (", XSTR (insn, 0));
219: for (i = 0; i < operands; i++)
220: printf (i ? ", operand%d" : "operand%d", i);
221: printf (")\n");
222: for (i = 0; i < operands; i++)
223: printf (" rtx operand%d;\n", i);
224: printf ("{\n");
225:
226: /* Output code to construct and return the rtl for the instruction body */
227:
228: if (XVECLEN (insn, 1) == 1)
229: {
230: printf (" return ");
231: gen_exp (XVECEXP (insn, 1, 0));
232: printf (";\n}\n\n");
233: }
234: else
235: {
236: printf (" return gen_rtx (PARALLEL, VOIDmode, gen_rtvec (%d", XVECLEN (insn, 1));
237: for (i = 0; i < XVECLEN (insn, 1); i++)
238: {
239: printf (",\n\t\t");
240: gen_exp (XVECEXP (insn, 1, i));
241: }
242: printf ("));\n}\n\n");
243: }
244: }
245:
246: /* Generate the `gen_...' function for a DEFINE_EXPAND. */
247:
248: void
249: gen_expand (expand)
250: rtx expand;
251: {
252: int operands;
253: register int i;
254:
255: if (strlen (XSTR (expand, 0)) == 0)
256: fatal ("define_expand lacks a name");
257: if (XVEC (expand, 1) == 0)
258: fatal ("define_expand for %s lacks a pattern", XSTR (expand, 0));
259:
260: /* Find out how many operands this function has,
261: and also whether any of them have register constraints. */
262: register_constraints = 0;
263:
264: operands = max_operand_vec (expand, 1);
265:
266: /* Output the function name and argument declarations. */
267: printf ("rtx\ngen_%s (", XSTR (expand, 0));
268: for (i = 0; i < operands; i++)
269: printf (i ? ", operand%d" : "operand%d", i);
270: printf (")\n");
271: for (i = 0; i < operands; i++)
272: printf (" rtx operand%d;\n", i);
273: printf ("{\n");
274:
275: /* For each operand referred to only with MATCH_DUPs,
276: make a local variable. */
277: for (i = operands; i <= max_dup_opno; i++)
278: printf (" rtx operand%d;\n", i);
279: printf (" rtx operands[%d];\n\n", max (operands, max_dup_opno + 1));
280: printf (" extern rtx gen_sequence ();\n");
281: printf (" extern int emit_to_sequence;\n\n");
282: printf (" emit_to_sequence++;\n");
283:
284: /* The fourth operand of DEFINE_EXPAND is some code to be executed
285: before the actual construction.
286: This code expects to refer to `operands'
287: just as the output-code in a DEFINE_INSN does,
288: but here `operands' is an automatic array.
289: So copy the operand values there before executing it. */
290: if (XSTR (expand, 3))
291: {
292: /* Output code to copy the arguments into `operands'. */
293: for (i = 0; i < operands; i++)
294: printf (" operands[%d] = operand%d;\n", i, i);
295:
296: /* Output the special code to be executed before the sequence
297: is generated. */
298: printf ("%s\n", XSTR (expand, 3));
299:
300: /* Output code to copy the arguments back out of `operands'
301: (unless we aren't going to use them at all). */
302: if (XVEC (expand, 1) != 0)
303: {
304: for (i = 0; i < operands; i++)
305: printf (" operand%d = operands[%d];\n", i, i);
306: for (; i <= max_dup_opno; i++)
307: printf (" operand%d = operands[%d];\n", i, i);
308: }
309: }
310:
311: /* Output code to construct the rtl for the instruction bodies.
312: Use emit_insn to add them to the sequence being accumulated.
313: But don't do this if the user's code has set `no_more' nonzero. */
314:
315: for (i = 0; i < XVECLEN (expand, 1); i++)
316: {
317: rtx next = XVECEXP (expand, 1, i);
318: if ((GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC)
319: || (GET_CODE (next) == PARALLEL
320: && GET_CODE (XVECEXP (next, 0, 0)) == SET
321: && GET_CODE (SET_DEST (XVECEXP (next, 0, 0))) == PC)
322: || GET_CODE (next) == RETURN)
323: printf (" emit_jump_insn (");
324: else if ((GET_CODE (next) == SET && GET_CODE (SET_SRC (next)) == CALL)
325: || GET_CODE (next) == CALL)
326: printf (" emit_call_insn (");
327: else if (GET_CODE (next) == CODE_LABEL)
328: printf (" emit_label (");
329: else if (GET_CODE (next) == MATCH_OPERAND
330: || GET_CODE (next) == MATCH_DUP)
331: printf (" emit (");
332: else
333: printf (" emit_insn (");
334: gen_exp (next);
335: printf (");\n");
336: if (GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC
337: && GET_CODE (SET_SRC (next)) == LABEL_REF)
338: printf (" emit_barrier ();");
339: }
340:
341: printf (" emit_to_sequence--;\n");
342:
343: /* Call `gen_sequence' to make a SEQUENCE out of all the
344: insns emitted within this gen_... function. */
345:
346: printf (" return gen_sequence ();\n}\n\n");
347: }
348:
349: int
350: xmalloc (size)
351: {
352: register int val = malloc (size);
353:
354: if (val == 0)
355: fatal ("virtual memory exhausted");
356:
357: return val;
358: }
359:
360: int
361: xrealloc (ptr, size)
362: char *ptr;
363: int size;
364: {
365: int result = realloc (ptr, size);
366: if (!result)
367: fatal ("virtual memory exhausted");
368: return result;
369: }
370:
371: void
372: fatal (s, a1, a2)
373: {
374: fprintf (stderr, "genemit: ");
375: fprintf (stderr, s, a1, a2);
376: fprintf (stderr, "\n");
377: exit (FATAL_EXIT_CODE);
378: }
379:
380: int
381: main (argc, argv)
382: int argc;
383: char **argv;
384: {
385: rtx desc;
386: FILE *infile;
387: extern rtx read_rtx ();
388: register int c;
389:
390: obstack_init (rtl_obstack);
391:
392: if (argc <= 1)
393: fatal ("No input file name.");
394:
395: infile = fopen (argv[1], "r");
396: if (infile == 0)
397: {
398: perror (argv[1]);
399: exit (FATAL_EXIT_CODE);
400: }
401:
402: init_rtl ();
403:
404: /* Assign sequential codes to all entries in the machine description
405: in parallel with the tables in insn-output.c. */
406:
407: insn_code_number = 0;
408:
409: printf ("/* Generated automatically by the program `genemit'\n\
410: from the machine description file `md'. */\n\n");
411:
412: printf ("#include \"config.h\"\n");
413: printf ("#include \"rtl.h\"\n");
414: printf ("#include \"expr.h\"\n");
415: printf ("#include \"insn-config.h\"\n\n");
416: printf ("extern char *insn_operand_constraint[][MAX_RECOG_OPERANDS];\n\n");
417: printf ("extern rtx recog_operand[];\n");
418: printf ("#define operands recog_operand\n\n");
419: printf ("#define FAIL do { emit_to_sequence--; return 0;} while (0)\n\n");
420: printf ("#define DONE do { emit_to_sequence--; return gen_sequence ();} while (0)\n\n");
421:
422: /* Read the machine description. */
423:
424: while (1)
425: {
426: c = read_skip_spaces (infile);
427: if (c == EOF)
428: break;
429: ungetc (c, infile);
430:
431: desc = read_rtx (infile);
432: if (GET_CODE (desc) == DEFINE_INSN)
433: {
434: gen_insn (desc);
435: ++insn_code_number;
436: }
437: if (GET_CODE (desc) == DEFINE_EXPAND)
438: {
439: gen_expand (desc);
440: ++insn_code_number;
441: }
442: if (GET_CODE (desc) == DEFINE_PEEPHOLE)
443: {
444: ++insn_code_number;
445: }
446: }
447:
448: fflush (stdout);
449: exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
450: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.