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