]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/gengenrtl.c
Oops, missed ChangeLog in last checkin...
[thirdparty/gcc.git] / gcc / gengenrtl.c
CommitLineData
3b80f6ca 1/* Generate code to allocate RTL structures.
9311a396 2 Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
3b80f6ca
RH
3
4This file is part of GNU CC.
5
6GNU CC is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11GNU CC is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU CC; see the file COPYING. If not, write to
18the Free Software Foundation, 59 Temple Place - Suite 330,
19Boston, 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
4710d3eb 43#if MAX_LONG_DOUBLE_TYPE_SIZE == 96
b6b4c6c6 44#define REAL_WIDTH (11*8 + HOST_BITS_PER_WIDE_INT)/HOST_BITS_PER_WIDE_INT
4710d3eb 45#elif MAX_LONG_DOUBLE_TYPE_SIZE == 128
b6b4c6c6
RH
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
4710d3eb 53#if HOST_BITS_PER_WIDE_INT*2 >= MAX_LONG_DOUBLE_TYPE_SIZE
b6b4c6c6 54#define REAL_WIDTH 2
4710d3eb 55#elif HOST_BITS_PER_WIDE_INT*3 >= MAX_LONG_DOUBLE_TYPE_SIZE
b6b4c6c6 56#define REAL_WIDTH 3
4710d3eb 57#elif HOST_BITS_PER_WIDE_INT*4 >= MAX_LONG_DOUBLE_TYPE_SIZE
b6b4c6c6
RH
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
77struct 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
84struct rtx_definition defs[] =
85{
86#include "rtl.def" /* rtl expressions are documented here */
87};
88
89const char *formats[NUM_RTX_CODE];
90
a94ae8f5
KG
91static const char *type_from_format PARAMS ((int));
92static const char *accessor_from_format PARAMS ((int));
93static int special_format PARAMS ((const char *));
94static int special_rtx PARAMS ((int));
95static void find_formats PARAMS ((void));
96static void gendecl PARAMS ((const char *));
97static void genmacro PARAMS ((int));
98static void gendef PARAMS ((const char *));
99static void genlegend PARAMS ((void));
100static void genheader PARAMS ((void));
101static void gencode PARAMS ((void));
c5c76735 102\f
0133b7d9
RH
103/* Decode a format letter into a C type string. */
104
3b80f6ca 105static const char *
982255c8 106type_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 117 case 's':
3cce094d 118 return "const 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 136static const char *
982255c8 137accessor_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
171static int
172special_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
185static int
186special_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
197static void
198find_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 220static void
c5c76735 221gendecl (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 251static void
c5c76735 252genmacro (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 281static void
c5c76735 282gendef (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 324static void
c5c76735 325genlegend ()
3b80f6ca 326{
616ce8db 327 printf ("/* Generated automatically by the program `gengenrtl'\n");
c5c76735 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 333static void
c5c76735 334genheader ()
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 351static void
c5c76735 352gencode ()
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");
cdd83c31
RK
363 puts ("static rtx\n");
364 puts ("obstack_alloc_rtx (length)\n");
c5c76735
JL
365 puts (" register int length;\n{\n");
366 puts (" rtx rt = (rtx) obstack_alloc (rtl_obstack, length);\n\n");
367 puts (" memset(rt, 0, sizeof(struct rtx_def) - sizeof(rtunion));\n\n");
368 puts (" return rt;\n}\n\n");
369
370 for (fmt = formats; *fmt != 0; fmt++)
371 gendef (*fmt);
3b80f6ca
RH
372}
373
402cdad5 374#if defined(USE_C_ALLOCA)
2778b98d 375PTR
982255c8 376xmalloc (nbytes)
2778b98d 377 size_t nbytes;
982255c8 378{
2778b98d 379 register PTR tmp = (PTR) malloc (nbytes);
982255c8
KG
380
381 if (!tmp)
382 {
402cdad5
RH
383 fprintf (stderr, "can't allocate %d bytes (out of virtual memory)\n",
384 nbytes);
982255c8
KG
385 exit (FATAL_EXIT_CODE);
386 }
387
388 return tmp;
389}
402cdad5 390#endif /* USE_C_ALLOCA */
982255c8 391
c5c76735
JL
392/* This is the main program. We accept only one argument, "-h", which
393 says we are writing the genrtl.h file. Otherwise we are writing the
394 genrtl.c file. */
a94ae8f5 395extern int main PARAMS ((int, char **));
c5c76735 396
3b80f6ca 397int
c5c76735 398main (argc, argv)
3b80f6ca
RH
399 int argc;
400 char **argv;
401{
3b80f6ca 402 find_formats ();
c5c76735 403 genlegend ();
3b80f6ca 404
c5c76735
JL
405 if (argc == 2 && argv[1][0] == '-' && argv[1][1] == 'h')
406 genheader ();
407 else
408 gencode ();
3b80f6ca 409
c5c76735 410 fflush (stdout);
c1b59dce 411 return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
3b80f6ca 412}