gengenrtl.c (gencode): Always use bzero to clear memory instead of dangerous casts...
[gcc.git] / gcc / gengenrtl.c
1 /* Generate code to allocate RTL structures.
2 Copyright (C) 1997 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 static const char *
56 type_from_format (c)
57 int c;
58 {
59 switch (c)
60 {
61 case 'i':
62 return "int";
63 case 'w':
64 return "HOST_WIDE_INT";
65 case 's':
66 return "char *";
67 case 'e':
68 case 'u':
69 return "rtx";
70 case 'E':
71 return "rtvec";
72 /* ?!? These should be bitmap and tree respectively, but those types
73 are not available in many of the files which include the output
74 of gengenrtl.
75
76 These are only used in prototypes, so I think we can assume that
77 void * is useable. */
78 case 'b':
79 return "void *";
80 case 't':
81 return "void *";
82 default:
83 abort ();
84 }
85 }
86
87 static const char *
88 accessor_from_format (c)
89 int c;
90 {
91 switch (c)
92 {
93 case 'i':
94 return "XINT";
95 case 'w':
96 return "XWINT";
97 case 's':
98 return "XSTR";
99 case 'e':
100 case 'u':
101 return "XEXP";
102 case 'E':
103 return "XVEC";
104 case 'b':
105 return "XBITMAP";
106 case 't':
107 return "XTREE";
108 default:
109 abort ();
110 }
111 }
112
113 static int
114 special_format (fmt)
115 const char *fmt;
116 {
117 return (strchr (fmt, '*') != 0
118 || strchr (fmt, 'V') != 0
119 || strchr (fmt, 'S') != 0
120 || strchr (fmt, 'n') != 0);
121 }
122
123 static int
124 special_rtx (idx)
125 int idx;
126 {
127 return (strcmp (defs[idx].enumname, "CONST_INT") == 0
128 || strcmp (defs[idx].enumname, "REG") == 0
129 || strcmp (defs[idx].enumname, "MEM") == 0);
130 }
131
132 static void
133 find_formats ()
134 {
135 int i;
136
137 for (i = 0; i < NUM_RTX_CODE; ++i)
138 {
139 const char **f;
140
141 if (special_format (defs[i].format))
142 continue;
143
144 for (f = formats; *f ; ++f)
145 if (!strcmp(*f, defs[i].format))
146 break;
147
148 if (!*f)
149 *f = defs[i].format;
150 }
151 }
152
153 static void
154 gendecl (f, format)
155 FILE *f;
156 const char *format;
157 {
158 const char *p;
159 int i;
160
161 fprintf (f, "extern rtx gen_rtx_fmt_%s PROTO((RTX_CODE, enum machine_mode mode",
162 format);
163 for (p = format, i = 0; *p ; ++p)
164 if (*p != '0')
165 fprintf (f, ", %s arg%d", type_from_format (*p), i++);
166 fprintf (f, "));\n");
167 }
168
169 static void
170 genmacro (f, idx)
171 FILE *f;
172 int idx;
173 {
174 const char *p;
175 int i;
176
177 fprintf (f, "#define gen_rtx_%s%s(mode",
178 (special_rtx (idx) ? "raw_" : ""), defs[idx].enumname);
179
180 for (p = defs[idx].format, i = 0; *p ; ++p)
181 if (*p != '0')
182 fprintf (f, ", arg%d", i++);
183 fprintf (f, ") ");
184
185 fprintf (f, "gen_rtx_fmt_%s(%s,(mode)", defs[idx].format, defs[idx].enumname);
186 for (p = defs[idx].format, i = 0; *p ; ++p)
187 if (*p != '0')
188 fprintf (f, ",(arg%d)", i++);
189 fprintf (f, ")\n");
190 }
191
192 static void
193 gendef (f, format)
194 FILE *f;
195 const char *format;
196 {
197 const char *p;
198 int i, j;
199
200 fprintf (f, "rtx\ngen_rtx_fmt_%s (code, mode", format);
201 for (p = format, i = 0; *p ; ++p)
202 if (*p != '0')
203 fprintf (f, ", arg%d", i++);
204
205 fprintf (f, ")\n RTX_CODE code;\n enum machine_mode mode;\n");
206 for (p = format, i = 0; *p ; ++p)
207 if (*p != '0')
208 fprintf (f, " %s arg%d;\n", type_from_format (*p), i++);
209
210 /* See rtx_alloc in rtl.c for comments. */
211 fprintf (f, "{\n");
212 fprintf (f, " rtx rt = obstack_alloc_rtx (sizeof (struct rtx_def) + %d * sizeof (rtunion));\n",
213 (int) strlen (format) - 1);
214
215 fprintf (f, " PUT_CODE (rt, code);\n");
216 fprintf (f, " PUT_MODE (rt, mode);\n");
217
218 for (p = format, i = j = 0; *p ; ++p, ++i)
219 if (*p != '0')
220 {
221 fprintf (f, " %s (rt, %d) = arg%d;\n",
222 accessor_from_format (*p), i, j++);
223 }
224
225 fprintf (f, "\n return rt;\n}\n\n");
226 }
227
228 static void
229 genlegend (f)
230 FILE *f;
231 {
232 fprintf (f, "/* Generated automaticaly by the program `gengenrtl'\n");
233 fprintf (f, " from the RTL description file `rtl.def' */\n\n");
234 }
235
236 static void
237 genheader (f)
238 FILE *f;
239 {
240 int i;
241 const char **fmt;
242
243 for (fmt = formats; *fmt; ++fmt)
244 gendecl (f, *fmt);
245
246 fprintf(f, "\n");
247
248 for (i = 0; i < NUM_RTX_CODE; i++)
249 {
250 if (special_format (defs[i].format))
251 continue;
252 genmacro (f, i);
253 }
254 }
255
256 static void
257 gencode (f)
258 FILE *f;
259 {
260 const char **fmt;
261
262 fputs ("#include \"config.h\"\n", f);
263 fputs ("#include \"system.h\"\n", f);
264 fputs ("#include \"obstack.h\"\n", f);
265 fputs ("#include \"rtl.h\"\n\n", f);
266 fputs ("extern struct obstack *rtl_obstack;\n\n", f);
267 fputs ("static rtx obstack_alloc_rtx PROTO((int length));\n", f);
268 fputs ("static rtx obstack_alloc_rtx (length)\n", f);
269 fputs (" register int length;\n{\n", f);
270 fputs (" rtx rt = (rtx) obstack_alloc (rtl_obstack, length);\n\n", f);
271 fputs (" bzero((char *) rt, sizeof(struct rtx_def) - sizeof(rtunion));\n\n", f);
272 fputs (" return rt;\n}\n\n", f);
273
274 for (fmt = formats; *fmt; ++fmt)
275 gendef (f, *fmt);
276 }
277
278 #if defined(USE_C_ALLOCA)
279 PTR
280 xmalloc (nbytes)
281 size_t nbytes;
282 {
283 register PTR tmp = (PTR) malloc (nbytes);
284
285 if (!tmp)
286 {
287 fprintf (stderr, "can't allocate %d bytes (out of virtual memory)\n",
288 nbytes);
289 exit (FATAL_EXIT_CODE);
290 }
291
292 return tmp;
293 }
294 #endif /* USE_C_ALLOCA */
295
296 int
297 main(argc, argv)
298 int argc;
299 char **argv;
300 {
301 FILE *f;
302
303 if (argc != 3)
304 exit (1);
305
306 find_formats ();
307
308 f = fopen (argv[1], "w");
309 if (f == NULL)
310 {
311 perror(argv[1]);
312 exit (1);
313 }
314 genlegend (f);
315 genheader (f);
316 fclose(f);
317
318 f = fopen (argv[2], "w");
319 if (f == NULL)
320 {
321 perror(argv[2]);
322 exit (1);
323 }
324 genlegend (f);
325 gencode (f);
326 fclose(f);
327
328 exit (0);
329 }