1/* Generate code to allocate RTL structures.
2   Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc.
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"
23#include "system.h"
24#undef abort
25
26#define NO_GENRTL_H
27#include "rtl.h"
28
29
30struct 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
37struct rtx_definition defs[] =
38{
39#include "rtl.def"		/* rtl expressions are documented here */
40};
41
42const char *formats[NUM_RTX_CODE];
43
44static const char *type_from_format PROTO((int));
45static const char *accessor_from_format PROTO((int));
46static int special_format PROTO((const char *));
47static int special_rtx PROTO((int));
48static void find_formats PROTO((void));
49static void gendecl PROTO((FILE *, const char *));
50static void genmacro PROTO((FILE *, int));
51static void gendef PROTO((FILE *, const char *));
52static void genlegend PROTO((FILE *));
53static void genheader PROTO((FILE *));
54static void gencode PROTO((FILE *));
55
56/* Decode a format letter into a C type string.  */
57
58static const char *
59type_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
92static const char *
93accessor_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
120static int
121special_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
132static int
133special_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
144static void
145find_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
167static void
168gendecl (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
185static void
186genmacro (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
210static void
211gendef (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
248static void
249genlegend (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
258static void
259genheader (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
280static void
281gencode (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)
303PTR
304xmalloc (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
320int
321main(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}
354