Move over patch from Bernd Schmidt from GC branch:
[gcc.git] / gcc / gengenrtl.c
1 /* Generate code to allocate RTL structures.
2 Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc.
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, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
20
21
22 #include "hconfig.h"
23 #include "system.h"
24
25 #define NO_GENRTL_H
26 #include "rtl.h"
27
28
29 struct rtx_definition
30 {
31 const char *enumname, *name, *format;
32 };
33
34 #define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS) { STRINGIFY(ENUM), NAME, FORMAT },
35
36 struct rtx_definition defs[] =
37 {
38 #include "rtl.def" /* rtl expressions are documented here */
39 };
40
41 const char *formats[NUM_RTX_CODE];
42
43 static const char *type_from_format PROTO((int));
44 static const char *accessor_from_format PROTO((int));
45 static int special_format PROTO((const char *));
46 static int special_rtx PROTO((int));
47 static void find_formats PROTO((void));
48 static void gendecl PROTO((FILE *, const char *));
49 static void genmacro PROTO((FILE *, int));
50 static void gendef PROTO((FILE *, const char *));
51 static void genlegend PROTO((FILE *));
52 static void genheader PROTO((FILE *));
53 static void gencode PROTO((FILE *));
54
55 /* Decode a format letter into a C type string. */
56
57 static const char *
58 type_from_format (c)
59 int c;
60 {
61 switch (c)
62 {
63 case 'i':
64 return "int";
65 case 'w':
66 return "HOST_WIDE_INT";
67 case 's':
68 return "char *";
69 case 'e':
70 case 'u':
71 return "rtx";
72 case 'E':
73 return "rtvec";
74 /* ?!? These should be bitmap and tree respectively, but those types
75 are not available in many of the files which include the output
76 of gengenrtl.
77
78 These are only used in prototypes, so I think we can assume that
79 void * is useable. */
80 case 'b':
81 return "void *";
82 case 't':
83 return "void *";
84 default:
85 abort ();
86 }
87 }
88
89 /* Decode a format letter into the proper accessor function. */
90
91 static const char *
92 accessor_from_format (c)
93 int c;
94 {
95 switch (c)
96 {
97 case 'i':
98 return "XINT";
99 case 'w':
100 return "XWINT";
101 case 's':
102 return "XSTR";
103 case 'e':
104 case 'u':
105 return "XEXP";
106 case 'E':
107 return "XVEC";
108 case 'b':
109 return "XBITMAP";
110 case 't':
111 return "XTREE";
112 default:
113 abort ();
114 }
115 }
116
117 /* Return true if a format character doesn't need normal processing. */
118
119 static int
120 special_format (fmt)
121 const char *fmt;
122 {
123 return (strchr (fmt, '*') != 0
124 || strchr (fmt, 'V') != 0
125 || strchr (fmt, 'S') != 0
126 || strchr (fmt, 'n') != 0);
127 }
128
129 /* Return true if an rtx requires special processing. */
130
131 static int
132 special_rtx (idx)
133 int idx;
134 {
135 return (strcmp (defs[idx].enumname, "CONST_INT") == 0
136 || strcmp (defs[idx].enumname, "CONST_DOUBLE") == 0
137 || strcmp (defs[idx].enumname, "REG") == 0
138 || strcmp (defs[idx].enumname, "MEM") == 0);
139 }
140
141 /* Fill `formats' with all unique format strings. */
142
143 static void
144 find_formats ()
145 {
146 int i;
147
148 for (i = 0; i < NUM_RTX_CODE; ++i)
149 {
150 const char **f;
151
152 if (special_format (defs[i].format))
153 continue;
154
155 for (f = formats; *f ; ++f)
156 if (! strcmp (*f, defs[i].format))
157 break;
158
159 if (!*f)
160 *f = defs[i].format;
161 }
162 }
163
164 /* Emit a prototype for the rtx generator for a format. */
165
166 static void
167 gendecl (f, format)
168 FILE *f;
169 const char *format;
170 {
171 const char *p;
172 int i;
173
174 fprintf (f, "extern rtx gen_rtx_fmt_%s PROTO((RTX_CODE, enum machine_mode mode",
175 format);
176 for (p = format, i = 0; *p ; ++p)
177 if (*p != '0')
178 fprintf (f, ", %s arg%d", type_from_format (*p), i++);
179 fprintf (f, "));\n");
180 }
181
182 /* Emit a define mapping an rtx code to the generator for its format. */
183
184 static void
185 genmacro (f, idx)
186 FILE *f;
187 int idx;
188 {
189 const char *p;
190 int i;
191
192 fprintf (f, "#define gen_rtx_%s%s(mode",
193 (special_rtx (idx) ? "raw_" : ""), defs[idx].enumname);
194
195 for (p = defs[idx].format, i = 0; *p ; ++p)
196 if (*p != '0')
197 fprintf (f, ", arg%d", i++);
198 fprintf (f, ") ");
199
200 fprintf (f, "gen_rtx_fmt_%s(%s,(mode)", defs[idx].format, defs[idx].enumname);
201 for (p = defs[idx].format, i = 0; *p ; ++p)
202 if (*p != '0')
203 fprintf (f, ",(arg%d)", i++);
204 fprintf (f, ")\n");
205 }
206
207 /* Emit the implementation for the rtx generator for a format. */
208
209 static void
210 gendef (f, format)
211 FILE *f;
212 const char *format;
213 {
214 const char *p;
215 int i, j;
216
217 fprintf (f, "rtx\ngen_rtx_fmt_%s (code, mode", format);
218 for (p = format, i = 0; *p ; ++p)
219 if (*p != '0')
220 fprintf (f, ", arg%d", i++);
221
222 fprintf (f, ")\n RTX_CODE code;\n enum machine_mode mode;\n");
223 for (p = format, i = 0; *p ; ++p)
224 if (*p != '0')
225 fprintf (f, " %s arg%d;\n", type_from_format (*p), i++);
226
227 /* See rtx_alloc in rtl.c for comments. */
228 fprintf (f, "{\n");
229 fprintf (f, " rtx rt = obstack_alloc_rtx (sizeof (struct rtx_def) + %d * sizeof (rtunion));\n",
230 (int) strlen (format) - 1);
231
232 fprintf (f, " PUT_CODE (rt, code);\n");
233 fprintf (f, " PUT_MODE (rt, mode);\n");
234
235 for (p = format, i = j = 0; *p ; ++p, ++i)
236 if (*p != '0')
237 {
238 fprintf (f, " %s (rt, %d) = arg%d;\n",
239 accessor_from_format (*p), i, j++);
240 }
241
242 fprintf (f, "\n return rt;\n}\n\n");
243 }
244
245 /* Emit the `do not edit' banner. */
246
247 static void
248 genlegend (f)
249 FILE *f;
250 {
251 fputs ("/* Generated automaticaly by the program `gengenrtl'\n", f);
252 fputs (" from the RTL description file `rtl.def' */\n\n", f);
253 }
254
255 /* Emit "genrtl.h". */
256
257 static void
258 genheader (f)
259 FILE *f;
260 {
261 int i;
262 const char **fmt;
263
264 for (fmt = formats; *fmt; ++fmt)
265 gendecl (f, *fmt);
266
267 fprintf (f, "\n");
268
269 for (i = 0; i < NUM_RTX_CODE; i++)
270 {
271 if (special_format (defs[i].format))
272 continue;
273 genmacro (f, i);
274 }
275 }
276
277 /* Emit "genrtl.c". */
278
279 static void
280 gencode (f)
281 FILE *f;
282 {
283 const char **fmt;
284
285 fputs ("#include \"config.h\"\n", f);
286 fputs ("#include \"system.h\"\n", f);
287 fputs ("#include \"obstack.h\"\n", f);
288 fputs ("#include \"rtl.h\"\n\n", f);
289 fputs ("extern struct obstack *rtl_obstack;\n\n", f);
290 fputs ("static rtx obstack_alloc_rtx PROTO((int length));\n", f);
291 fputs ("static rtx obstack_alloc_rtx (length)\n", f);
292 fputs (" register int length;\n{\n", f);
293 fputs (" rtx rt = (rtx) obstack_alloc (rtl_obstack, length);\n\n", f);
294 fputs (" memset(rt, 0, sizeof(struct rtx_def) - sizeof(rtunion));\n\n", f);
295 fputs (" return rt;\n}\n\n", f);
296
297 for (fmt = formats; *fmt; ++fmt)
298 gendef (f, *fmt);
299 }
300
301 #if defined(USE_C_ALLOCA)
302 PTR
303 xmalloc (nbytes)
304 size_t nbytes;
305 {
306 register PTR tmp = (PTR) malloc (nbytes);
307
308 if (!tmp)
309 {
310 fprintf (stderr, "can't allocate %d bytes (out of virtual memory)\n",
311 nbytes);
312 exit (FATAL_EXIT_CODE);
313 }
314
315 return tmp;
316 }
317 #endif /* USE_C_ALLOCA */
318
319 int
320 main(argc, argv)
321 int argc;
322 char **argv;
323 {
324 FILE *f;
325
326 if (argc != 3)
327 exit (1);
328
329 find_formats ();
330
331 f = fopen (argv[1], "w");
332 if (f == NULL)
333 {
334 perror (argv[1]);
335 exit (1);
336 }
337 genlegend (f);
338 genheader (f);
339 fclose (f);
340
341 f = fopen (argv[2], "w");
342 if (f == NULL)
343 {
344 perror (argv[2]);
345 exit (1);
346 }
347 genlegend (f);
348 gencode (f);
349 fclose (f);
350
351 exit (0);
352 }