]>
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. | |
b6b4c6c6 RH |
33 | |
34 | We need to go out to e0wwwww, since REAL_ARITHMETIC assumes 16-bits | |
35 | per element in REAL_VALUE_TYPE. | |
36 | ||
37 | This is duplicated in rtl.c. | |
38 | ||
aa0b4465 ZW |
39 | A number of places assume that there are always at least two 'w' |
40 | slots in a CONST_DOUBLE, so we provide them even if one would suffice. */ | |
b6b4c6c6 RH |
41 | |
42 | #ifdef REAL_ARITHMETIC | |
43 | #if LONG_DOUBLE_TYPE_SIZE == 96 | |
44 | #define REAL_WIDTH (11*8 + HOST_BITS_PER_WIDE_INT)/HOST_BITS_PER_WIDE_INT | |
45 | #elif LONG_DOUBLE_TYPE_SIZE == 128 | |
46 | #define REAL_WIDTH (19*8 + HOST_BITS_PER_WIDE_INT)/HOST_BITS_PER_WIDE_INT | |
47 | #elif HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT | |
48 | #define REAL_WIDTH (7*8 + HOST_BITS_PER_WIDE_INT)/HOST_BITS_PER_WIDE_INT | |
49 | #endif | |
50 | #endif /* REAL_ARITHMETIC */ | |
51 | ||
52 | #ifndef REAL_WIDTH | |
53 | #if HOST_BITS_PER_WIDE_INT*2 >= LONG_DOUBLE_TYPE_SIZE | |
54 | #define REAL_WIDTH 2 | |
55 | #elif HOST_BITS_PER_WIDE_INT*3 >= LONG_DOUBLE_TYPE_SIZE | |
56 | #define REAL_WIDTH 3 | |
57 | #elif HOST_BITS_PER_WIDE_INT*4 >= LONG_DOUBLE_TYPE_SIZE | |
58 | #define REAL_WIDTH 4 | |
59 | #endif | |
60 | #endif /* REAL_WIDTH */ | |
61 | ||
62 | #if REAL_WIDTH == 1 | |
aa0b4465 | 63 | #define CONST_DOUBLE_FORMAT "e0ww" |
b6b4c6c6 | 64 | #elif REAL_WIDTH == 2 |
aa0b4465 | 65 | #define CONST_DOUBLE_FORMAT "e0ww" |
b6b4c6c6 | 66 | #elif REAL_WIDTH == 3 |
aa0b4465 | 67 | #define CONST_DOUBLE_FORMAT "e0www" |
b6b4c6c6 | 68 | #elif REAL_WIDTH == 4 |
aa0b4465 | 69 | #define CONST_DOUBLE_FORMAT "e0wwww" |
b6b4c6c6 RH |
70 | #elif REAL_WIDTH == 5 |
71 | #define CONST_DOUBLE_FORMAT "e0wwwww" | |
aa0b4465 ZW |
72 | #else |
73 | #define CONST_DOUBLE_FORMAT /* nothing - will cause syntax error */ | |
74 | #endif | |
75 | ||
3b80f6ca RH |
76 | |
77 | struct rtx_definition | |
78 | { | |
79 | const char *enumname, *name, *format; | |
80 | }; | |
81 | ||
d4ba0ead | 82 | #define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS) { STRINGIFY(ENUM), NAME, FORMAT }, |
3b80f6ca RH |
83 | |
84 | struct rtx_definition defs[] = | |
85 | { | |
86 | #include "rtl.def" /* rtl expressions are documented here */ | |
87 | }; | |
88 | ||
89 | const char *formats[NUM_RTX_CODE]; | |
90 | ||
a94ae8f5 KG |
91 | static const char *type_from_format PARAMS ((int)); |
92 | static const char *accessor_from_format PARAMS ((int)); | |
93 | static int special_format PARAMS ((const char *)); | |
94 | static int special_rtx PARAMS ((int)); | |
95 | static void find_formats PARAMS ((void)); | |
96 | static void gendecl PARAMS ((const char *)); | |
97 | static void genmacro PARAMS ((int)); | |
98 | static void gendef PARAMS ((const char *)); | |
99 | static void genlegend PARAMS ((void)); | |
100 | static void genheader PARAMS ((void)); | |
101 | static void gencode PARAMS ((void)); | |
c5c76735 | 102 | \f |
0133b7d9 RH |
103 | /* Decode a format letter into a C type string. */ |
104 | ||
3b80f6ca | 105 | static const char * |
982255c8 | 106 | type_from_format (c) |
fd97443c | 107 | int c; |
3b80f6ca RH |
108 | { |
109 | switch (c) | |
110 | { | |
111 | case 'i': | |
c5c76735 JL |
112 | return "int "; |
113 | ||
3b80f6ca | 114 | case 'w': |
c5c76735 JL |
115 | return "HOST_WIDE_INT "; |
116 | ||
3b80f6ca RH |
117 | case 's': |
118 | return "char *"; | |
c5c76735 JL |
119 | |
120 | case 'e': case 'u': | |
121 | return "rtx "; | |
122 | ||
3b80f6ca | 123 | case 'E': |
c5c76735 | 124 | return "rtvec "; |
0dfa1860 | 125 | case 'b': |
8f985ec4 | 126 | return "struct bitmap_head_def *"; /* bitmap - typedef not available */ |
0dfa1860 | 127 | case 't': |
8f985ec4 | 128 | return "union tree_node *"; /* tree - typedef not available */ |
3b80f6ca RH |
129 | default: |
130 | abort (); | |
131 | } | |
132 | } | |
133 | ||
0133b7d9 RH |
134 | /* Decode a format letter into the proper accessor function. */ |
135 | ||
3b80f6ca | 136 | static const char * |
982255c8 | 137 | accessor_from_format (c) |
fd97443c | 138 | int c; |
3b80f6ca RH |
139 | { |
140 | switch (c) | |
141 | { | |
142 | case 'i': | |
143 | return "XINT"; | |
c5c76735 | 144 | |
3b80f6ca RH |
145 | case 'w': |
146 | return "XWINT"; | |
c5c76735 | 147 | |
3b80f6ca RH |
148 | case 's': |
149 | return "XSTR"; | |
c5c76735 JL |
150 | |
151 | case 'e': case 'u': | |
3b80f6ca | 152 | return "XEXP"; |
c5c76735 | 153 | |
3b80f6ca RH |
154 | case 'E': |
155 | return "XVEC"; | |
c5c76735 | 156 | |
0dfa1860 MM |
157 | case 'b': |
158 | return "XBITMAP"; | |
c5c76735 | 159 | |
0dfa1860 MM |
160 | case 't': |
161 | return "XTREE"; | |
c5c76735 | 162 | |
3b80f6ca RH |
163 | default: |
164 | abort (); | |
165 | } | |
166 | } | |
167 | ||
c5c76735 JL |
168 | /* Return nonzero if we should ignore FMT, an RTL format, when making |
169 | the list of formats we write routines to create. */ | |
0133b7d9 | 170 | |
3b80f6ca RH |
171 | static int |
172 | special_format (fmt) | |
173 | const char *fmt; | |
174 | { | |
175 | return (strchr (fmt, '*') != 0 | |
176 | || strchr (fmt, 'V') != 0 | |
177 | || strchr (fmt, 'S') != 0 | |
178 | || strchr (fmt, 'n') != 0); | |
179 | } | |
180 | ||
c5c76735 JL |
181 | /* Return nonzero if the RTL code given by index IDX is one that we should not |
182 | generate a gen_RTX_FOO function foo (because that function is present | |
183 | elsewhere in the compiler. */ | |
0133b7d9 | 184 | |
3b80f6ca RH |
185 | static int |
186 | special_rtx (idx) | |
187 | int idx; | |
188 | { | |
189 | return (strcmp (defs[idx].enumname, "CONST_INT") == 0 | |
0133b7d9 | 190 | || strcmp (defs[idx].enumname, "CONST_DOUBLE") == 0 |
41472af8 MM |
191 | || strcmp (defs[idx].enumname, "REG") == 0 |
192 | || strcmp (defs[idx].enumname, "MEM") == 0); | |
3b80f6ca RH |
193 | } |
194 | ||
c5c76735 | 195 | /* Place a list of all format specifiers we use into the array FORMAT. */ |
0133b7d9 | 196 | |
3b80f6ca RH |
197 | static void |
198 | find_formats () | |
199 | { | |
200 | int i; | |
201 | ||
c5c76735 | 202 | for (i = 0; i < NUM_RTX_CODE; i++) |
3b80f6ca RH |
203 | { |
204 | const char **f; | |
205 | ||
206 | if (special_format (defs[i].format)) | |
207 | continue; | |
208 | ||
c5c76735 | 209 | for (f = formats; *f; f++) |
0133b7d9 | 210 | if (! strcmp (*f, defs[i].format)) |
3b80f6ca RH |
211 | break; |
212 | ||
c5c76735 | 213 | if (*f == 0) |
3b80f6ca RH |
214 | *f = defs[i].format; |
215 | } | |
216 | } | |
217 | ||
c5c76735 | 218 | /* Write the declarations for the routine to allocate RTL with FORMAT. */ |
0133b7d9 | 219 | |
3b80f6ca | 220 | static void |
c5c76735 | 221 | gendecl (format) |
3b80f6ca RH |
222 | const char *format; |
223 | { | |
224 | const char *p; | |
c5c76735 | 225 | int i, pos; |
3b80f6ca | 226 | |
a94ae8f5 | 227 | printf ("extern rtx gen_rtx_fmt_%s\tPARAMS ((RTX_CODE, ", format); |
c5c76735 JL |
228 | printf ("enum machine_mode mode"); |
229 | ||
230 | /* Write each parameter that is needed and start a new line when the line | |
231 | would overflow. */ | |
232 | for (p = format, i = 0, pos = 75; *p != 0; p++) | |
3b80f6ca | 233 | if (*p != '0') |
c5c76735 JL |
234 | { |
235 | int ourlen = strlen (type_from_format (*p)) + 6 + (i > 9); | |
236 | ||
237 | printf (","); | |
238 | if (pos + ourlen > 76) | |
239 | printf ("\n\t\t\t\t "), pos = 39; | |
240 | ||
241 | printf (" %sarg%d", type_from_format (*p), i++); | |
242 | pos += ourlen; | |
243 | } | |
244 | ||
245 | printf ("));\n"); | |
3b80f6ca RH |
246 | } |
247 | ||
c5c76735 JL |
248 | /* Generate macros to generate RTL of code IDX using the functions we |
249 | write. */ | |
0133b7d9 | 250 | |
3b80f6ca | 251 | static void |
c5c76735 | 252 | genmacro (idx) |
3b80f6ca RH |
253 | int idx; |
254 | { | |
255 | const char *p; | |
256 | int i; | |
257 | ||
c5c76735 JL |
258 | /* We write a macro that defines gen_rtx_RTLCODE to be an equivalent to |
259 | gen_rtx_fmt_FORMAT where FORMAT is the RTX_FORMAT of RTLCODE. */ | |
3b80f6ca | 260 | |
c5c76735 JL |
261 | printf ("#define gen_rtx_%s%s(MODE", |
262 | special_rtx (idx) ? "raw_" : "", defs[idx].enumname); | |
263 | ||
264 | for (p = defs[idx].format, i = 0; *p != 0; p++) | |
3b80f6ca | 265 | if (*p != '0') |
c5c76735 JL |
266 | printf (", ARG%d", i++); |
267 | ||
268 | printf (") \\\n gen_rtx_fmt_%s (%s, (MODE)", | |
269 | defs[idx].format, defs[idx].enumname); | |
3b80f6ca | 270 | |
c5c76735 | 271 | for (p = defs[idx].format, i = 0; *p != 0; p++) |
3b80f6ca | 272 | if (*p != '0') |
c5c76735 JL |
273 | printf (", (ARG%d)", i++); |
274 | ||
275 | printf (")\n"); | |
3b80f6ca RH |
276 | } |
277 | ||
c5c76735 JL |
278 | /* Generate the code for the function to generate RTL whose |
279 | format is FORMAT. */ | |
0133b7d9 | 280 | |
3b80f6ca | 281 | static void |
c5c76735 | 282 | gendef (format) |
3b80f6ca RH |
283 | const char *format; |
284 | { | |
285 | const char *p; | |
286 | int i, j; | |
287 | ||
c5c76735 JL |
288 | /* Start by writing the definition of the function name and the types |
289 | of the arguments. */ | |
3b80f6ca | 290 | |
c5c76735 JL |
291 | printf ("rtx\ngen_rtx_fmt_%s (code, mode", format); |
292 | for (p = format, i = 0; *p != 0; p++) | |
3b80f6ca | 293 | if (*p != '0') |
c5c76735 | 294 | printf (", arg%d", i++); |
3b80f6ca | 295 | |
c5c76735 JL |
296 | printf (")\n RTX_CODE code;\n enum machine_mode mode;\n"); |
297 | for (p = format, i = 0; *p != 0; p++) | |
298 | if (*p != '0') | |
299 | printf (" %sarg%d;\n", type_from_format (*p), i++); | |
300 | ||
301 | /* Now write out the body of the function itself, which allocates | |
302 | the memory and initializes it. */ | |
303 | printf ("{\n"); | |
304 | printf (" rtx rt;\n"); | |
305 | printf (" if (ggc_p)\n"); | |
306 | printf (" rt = ggc_alloc_rtx (%d);\n", | |
2168d24a | 307 | (int) strlen (format)); |
c5c76735 JL |
308 | printf (" else\n"); |
309 | printf (" rt = obstack_alloc_rtx (sizeof (struct rtx_def) + %d * sizeof (rtunion));\n", | |
4b8140a6 | 310 | (int) strlen (format) - 1); |
3b80f6ca | 311 | |
c5c76735 JL |
312 | printf (" PUT_CODE (rt, code);\n"); |
313 | printf (" PUT_MODE (rt, mode);\n"); | |
3b80f6ca RH |
314 | |
315 | for (p = format, i = j = 0; *p ; ++p, ++i) | |
316 | if (*p != '0') | |
c5c76735 | 317 | printf (" %s (rt, %d) = arg%d;\n", accessor_from_format (*p), i, j++); |
3b80f6ca | 318 | |
c5c76735 | 319 | printf ("\n return rt;\n}\n\n"); |
3b80f6ca RH |
320 | } |
321 | ||
c5c76735 | 322 | /* Generate the documentation header for files we write. */ |
0133b7d9 | 323 | |
3b80f6ca | 324 | static void |
c5c76735 | 325 | genlegend () |
3b80f6ca | 326 | { |
c5c76735 JL |
327 | printf ("/* Generated automaticaly by the program `gengenrtl'\n"); |
328 | printf (" from the RTL description file `rtl.def' */\n\n"); | |
3b80f6ca RH |
329 | } |
330 | ||
c5c76735 | 331 | /* Generate the text of the header file we make, genrtl.h. */ |
0133b7d9 | 332 | |
3b80f6ca | 333 | static void |
c5c76735 | 334 | genheader () |
3b80f6ca RH |
335 | { |
336 | int i; | |
337 | const char **fmt; | |
c5c76735 | 338 | |
3b80f6ca | 339 | for (fmt = formats; *fmt; ++fmt) |
c5c76735 | 340 | gendecl (*fmt); |
3b80f6ca | 341 | |
c5c76735 | 342 | printf ("\n"); |
3b80f6ca RH |
343 | |
344 | for (i = 0; i < NUM_RTX_CODE; i++) | |
c5c76735 JL |
345 | if (! special_format (defs[i].format)) |
346 | genmacro (i); | |
3b80f6ca RH |
347 | } |
348 | ||
c5c76735 | 349 | /* Generate the text of the code file we write, genrtl.c. */ |
0133b7d9 | 350 | |
3b80f6ca | 351 | static void |
c5c76735 | 352 | gencode () |
3b80f6ca RH |
353 | { |
354 | const char **fmt; | |
355 | ||
c5c76735 JL |
356 | puts ("#include \"config.h\"\n"); |
357 | puts ("#include \"system.h\"\n"); | |
358 | puts ("#include \"obstack.h\"\n"); | |
359 | puts ("#include \"rtl.h\"\n"); | |
360 | puts ("#include \"ggc.h\"\n\n"); | |
361 | puts ("extern struct obstack *rtl_obstack;\n\n"); | |
a94ae8f5 | 362 | puts ("static rtx obstack_alloc_rtx PARAMS ((int length));\n"); |
c5c76735 JL |
363 | puts ("static rtx obstack_alloc_rtx (length)\n"); |
364 | puts (" register int length;\n{\n"); | |
365 | puts (" rtx rt = (rtx) obstack_alloc (rtl_obstack, length);\n\n"); | |
366 | puts (" memset(rt, 0, sizeof(struct rtx_def) - sizeof(rtunion));\n\n"); | |
367 | puts (" return rt;\n}\n\n"); | |
368 | ||
369 | for (fmt = formats; *fmt != 0; fmt++) | |
370 | gendef (*fmt); | |
3b80f6ca RH |
371 | } |
372 | ||
402cdad5 | 373 | #if defined(USE_C_ALLOCA) |
2778b98d | 374 | PTR |
982255c8 | 375 | xmalloc (nbytes) |
2778b98d | 376 | size_t nbytes; |
982255c8 | 377 | { |
2778b98d | 378 | register PTR tmp = (PTR) malloc (nbytes); |
982255c8 KG |
379 | |
380 | if (!tmp) | |
381 | { | |
402cdad5 RH |
382 | fprintf (stderr, "can't allocate %d bytes (out of virtual memory)\n", |
383 | nbytes); | |
982255c8 KG |
384 | exit (FATAL_EXIT_CODE); |
385 | } | |
386 | ||
387 | return tmp; | |
388 | } | |
402cdad5 | 389 | #endif /* USE_C_ALLOCA */ |
982255c8 | 390 | |
c5c76735 JL |
391 | /* This is the main program. We accept only one argument, "-h", which |
392 | says we are writing the genrtl.h file. Otherwise we are writing the | |
393 | genrtl.c file. */ | |
a94ae8f5 | 394 | extern int main PARAMS ((int, char **)); |
c5c76735 | 395 | |
3b80f6ca | 396 | int |
c5c76735 | 397 | main (argc, argv) |
3b80f6ca RH |
398 | int argc; |
399 | char **argv; | |
400 | { | |
3b80f6ca | 401 | find_formats (); |
c5c76735 | 402 | genlegend (); |
3b80f6ca | 403 | |
c5c76735 JL |
404 | if (argc == 2 && argv[1][0] == '-' && argv[1][1] == 'h') |
405 | genheader (); | |
406 | else | |
407 | gencode (); | |
3b80f6ca | 408 | |
c5c76735 | 409 | fflush (stdout); |
c1b59dce | 410 | return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE); |
3b80f6ca | 411 | } |