OSDN Git Service

762c96fa4e42e398b8e043172ed9433c74682b78
[pf3gnuchains/gcc-fork.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 = obstack_alloc_rtx (sizeof (struct rtx_def) + %d * sizeof (rtunion));\n",
246            (int) strlen (format) - 1);
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
261 /* Emit the `do not edit' banner.  */
262
263 static void
264 genlegend (f)
265      FILE *f;
266 {
267   fputs ("/* Generated automaticaly by the program `gengenrtl'\n", f);
268   fputs ("   from the RTL description file `rtl.def' */\n\n", f);
269 }
270
271 /* Emit "genrtl.h".  */
272
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
283   fprintf (f, "\n");
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
293 /* Emit "genrtl.c".  */
294
295 static void
296 gencode (f)
297      FILE *f;
298 {
299   const char **fmt;
300
301   fputs ("#include \"config.h\"\n", f);
302   fputs ("#include \"system.h\"\n", f);
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);
310   fputs ("  memset(rt, 0, sizeof(struct rtx_def) - sizeof(rtunion));\n\n", f);
311   fputs ("  return rt;\n}\n\n", f);
312
313   for (fmt = formats; *fmt; ++fmt)
314     gendef (f, *fmt);
315 }
316
317 #if defined(USE_C_ALLOCA)
318 PTR
319 xmalloc (nbytes)
320   size_t nbytes;
321 {
322   register PTR tmp = (PTR) malloc (nbytes);
323
324   if (!tmp)
325     {
326       fprintf (stderr, "can't allocate %d bytes (out of virtual memory)\n",
327                nbytes);
328       exit (FATAL_EXIT_CODE);
329     }
330
331   return tmp;
332 }
333 #endif /* USE_C_ALLOCA */
334
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     {
350       perror (argv[1]);
351       exit (1);
352     }
353   genlegend (f);
354   genheader (f);
355   fclose (f);
356
357   f = fopen (argv[2], "w");
358   if (f == NULL)
359     {
360       perror (argv[2]);
361       exit (1);
362     }
363   genlegend (f);
364   gencode (f);
365   fclose (f);
366
367   exit (0);
368 }