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