]>
Commit | Line | Data |
---|---|---|
3b80f6ca | 1 | /* Generate code to allocate RTL structures. |
0133b7d9 | 2 | Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc. |
3b80f6ca RH |
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" | |
b04cd507 | 23 | #include "system.h" |
3b80f6ca | 24 | |
3b80f6ca RH |
25 | #define NO_GENRTL_H |
26 | #include "rtl.h" | |
987009bf | 27 | #undef abort |
3b80f6ca | 28 | |
aa0b4465 ZW |
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 | ||
3b80f6ca RH |
50 | |
51 | struct rtx_definition | |
52 | { | |
53 | const char *enumname, *name, *format; | |
54 | }; | |
55 | ||
d4ba0ead | 56 | #define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS) { STRINGIFY(ENUM), NAME, FORMAT }, |
3b80f6ca RH |
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 | ||
fd97443c KG |
65 | static const char *type_from_format PROTO((int)); |
66 | static const char *accessor_from_format PROTO((int)); | |
56c0e996 BS |
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 | ||
0133b7d9 RH |
77 | /* Decode a format letter into a C type string. */ |
78 | ||
3b80f6ca | 79 | static const char * |
982255c8 | 80 | type_from_format (c) |
fd97443c | 81 | int c; |
3b80f6ca RH |
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"; | |
0dfa1860 | 96 | case 'b': |
8f985ec4 | 97 | return "struct bitmap_head_def *"; /* bitmap - typedef not available */ |
0dfa1860 | 98 | case 't': |
8f985ec4 | 99 | return "union tree_node *"; /* tree - typedef not available */ |
3b80f6ca RH |
100 | default: |
101 | abort (); | |
102 | } | |
103 | } | |
104 | ||
0133b7d9 RH |
105 | /* Decode a format letter into the proper accessor function. */ |
106 | ||
3b80f6ca | 107 | static const char * |
982255c8 | 108 | accessor_from_format (c) |
fd97443c | 109 | int c; |
3b80f6ca RH |
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"; | |
0dfa1860 MM |
124 | case 'b': |
125 | return "XBITMAP"; | |
126 | case 't': | |
127 | return "XTREE"; | |
3b80f6ca RH |
128 | default: |
129 | abort (); | |
130 | } | |
131 | } | |
132 | ||
0133b7d9 RH |
133 | /* Return true if a format character doesn't need normal processing. */ |
134 | ||
3b80f6ca RH |
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 | ||
0133b7d9 RH |
145 | /* Return true if an rtx requires special processing. */ |
146 | ||
3b80f6ca RH |
147 | static int |
148 | special_rtx (idx) | |
149 | int idx; | |
150 | { | |
151 | return (strcmp (defs[idx].enumname, "CONST_INT") == 0 | |
0133b7d9 | 152 | || strcmp (defs[idx].enumname, "CONST_DOUBLE") == 0 |
41472af8 MM |
153 | || strcmp (defs[idx].enumname, "REG") == 0 |
154 | || strcmp (defs[idx].enumname, "MEM") == 0); | |
3b80f6ca RH |
155 | } |
156 | ||
0133b7d9 RH |
157 | /* Fill `formats' with all unique format strings. */ |
158 | ||
3b80f6ca RH |
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) | |
0133b7d9 | 172 | if (! strcmp (*f, defs[i].format)) |
3b80f6ca RH |
173 | break; |
174 | ||
175 | if (!*f) | |
176 | *f = defs[i].format; | |
177 | } | |
178 | } | |
179 | ||
0133b7d9 RH |
180 | /* Emit a prototype for the rtx generator for a format. */ |
181 | ||
3b80f6ca RH |
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 | ||
0133b7d9 RH |
198 | /* Emit a define mapping an rtx code to the generator for its format. */ |
199 | ||
3b80f6ca RH |
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 | ||
0133b7d9 RH |
223 | /* Emit the implementation for the rtx generator for a format. */ |
224 | ||
3b80f6ca RH |
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"); | |
4b8140a6 JC |
245 | fprintf (f, " rtx rt = obstack_alloc_rtx (sizeof (struct rtx_def) + %d * sizeof (rtunion));\n", |
246 | (int) strlen (format) - 1); | |
3b80f6ca RH |
247 | |
248 | fprintf (f, " PUT_CODE (rt, code);\n"); | |
249 | fprintf (f, " PUT_MODE (rt, mode);\n"); | |
250 | ||
251 | for (p = format, i = j = 0; *p ; ++p, ++i) | |
252 | if (*p != '0') | |
253 | { | |
254 | fprintf (f, " %s (rt, %d) = arg%d;\n", | |
255 | accessor_from_format (*p), i, j++); | |
256 | } | |
257 | ||
258 | fprintf (f, "\n return rt;\n}\n\n"); | |
259 | } | |
260 | ||
0133b7d9 RH |
261 | /* Emit the `do not edit' banner. */ |
262 | ||
3b80f6ca RH |
263 | static void |
264 | genlegend (f) | |
265 | FILE *f; | |
266 | { | |
0133b7d9 RH |
267 | fputs ("/* Generated automaticaly by the program `gengenrtl'\n", f); |
268 | fputs (" from the RTL description file `rtl.def' */\n\n", f); | |
3b80f6ca RH |
269 | } |
270 | ||
0133b7d9 RH |
271 | /* Emit "genrtl.h". */ |
272 | ||
3b80f6ca RH |
273 | static void |
274 | genheader (f) | |
275 | FILE *f; | |
276 | { | |
277 | int i; | |
278 | const char **fmt; | |
279 | ||
280 | for (fmt = formats; *fmt; ++fmt) | |
281 | gendecl (f, *fmt); | |
282 | ||
0133b7d9 | 283 | fprintf (f, "\n"); |
3b80f6ca RH |
284 | |
285 | for (i = 0; i < NUM_RTX_CODE; i++) | |
286 | { | |
287 | if (special_format (defs[i].format)) | |
288 | continue; | |
289 | genmacro (f, i); | |
290 | } | |
291 | } | |
292 | ||
0133b7d9 RH |
293 | /* Emit "genrtl.c". */ |
294 | ||
3b80f6ca RH |
295 | static void |
296 | gencode (f) | |
297 | FILE *f; | |
298 | { | |
299 | const char **fmt; | |
300 | ||
4b8140a6 | 301 | fputs ("#include \"config.h\"\n", f); |
560bd19e | 302 | fputs ("#include \"system.h\"\n", f); |
4b8140a6 JC |
303 | fputs ("#include \"obstack.h\"\n", f); |
304 | fputs ("#include \"rtl.h\"\n\n", f); | |
305 | fputs ("extern struct obstack *rtl_obstack;\n\n", f); | |
306 | fputs ("static rtx obstack_alloc_rtx PROTO((int length));\n", f); | |
307 | fputs ("static rtx obstack_alloc_rtx (length)\n", f); | |
308 | fputs (" register int length;\n{\n", f); | |
309 | fputs (" rtx rt = (rtx) obstack_alloc (rtl_obstack, length);\n\n", f); | |
0133b7d9 | 310 | fputs (" memset(rt, 0, sizeof(struct rtx_def) - sizeof(rtunion));\n\n", f); |
4b8140a6 | 311 | fputs (" return rt;\n}\n\n", f); |
3b80f6ca RH |
312 | |
313 | for (fmt = formats; *fmt; ++fmt) | |
314 | gendef (f, *fmt); | |
315 | } | |
316 | ||
402cdad5 | 317 | #if defined(USE_C_ALLOCA) |
2778b98d | 318 | PTR |
982255c8 | 319 | xmalloc (nbytes) |
2778b98d | 320 | size_t nbytes; |
982255c8 | 321 | { |
2778b98d | 322 | register PTR tmp = (PTR) malloc (nbytes); |
982255c8 KG |
323 | |
324 | if (!tmp) | |
325 | { | |
402cdad5 RH |
326 | fprintf (stderr, "can't allocate %d bytes (out of virtual memory)\n", |
327 | nbytes); | |
982255c8 KG |
328 | exit (FATAL_EXIT_CODE); |
329 | } | |
330 | ||
331 | return tmp; | |
332 | } | |
402cdad5 | 333 | #endif /* USE_C_ALLOCA */ |
982255c8 | 334 | |
3b80f6ca RH |
335 | int |
336 | main(argc, argv) | |
337 | int argc; | |
338 | char **argv; | |
339 | { | |
340 | FILE *f; | |
341 | ||
342 | if (argc != 3) | |
343 | exit (1); | |
344 | ||
345 | find_formats (); | |
346 | ||
347 | f = fopen (argv[1], "w"); | |
348 | if (f == NULL) | |
349 | { | |
0133b7d9 | 350 | perror (argv[1]); |
3b80f6ca RH |
351 | exit (1); |
352 | } | |
353 | genlegend (f); | |
354 | genheader (f); | |
0133b7d9 | 355 | fclose (f); |
3b80f6ca RH |
356 | |
357 | f = fopen (argv[2], "w"); | |
358 | if (f == NULL) | |
359 | { | |
0133b7d9 | 360 | perror (argv[2]); |
3b80f6ca RH |
361 | exit (1); |
362 | } | |
363 | genlegend (f); | |
364 | gencode (f); | |
0133b7d9 | 365 | fclose (f); |
3b80f6ca RH |
366 | |
367 | exit (0); | |
368 | } |