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