1/* Generate code to allocate RTL structures.
2   Copyright (C) 1997, 1998, 1999, 2000, 2002 Free Software Foundation, Inc.
3
4This file is part of GCC.
5
6GCC is free software; you can redistribute it and/or modify it under
7the terms of the GNU General Public License as published by the Free
8Software Foundation; either version 2, or (at your option) any later
9version.
10
11GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12WARRANTY; without even the implied warranty of MERCHANTABILITY or
13FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14for more details.
15
16You should have received a copy of the GNU General Public License
17along with GCC; see the file COPYING.  If not, write to the Free
18Software Foundation, 59 Temple Place - Suite 330, Boston, MA
1902111-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
31struct rtx_definition
32{
33  const char *const enumname, *const name, *const format;
34};
35
36#define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS) { STRINGX(ENUM), NAME, FORMAT },
37
38static const struct rtx_definition defs[] =
39{
40#include "rtl.def"		/* rtl expressions are documented here */
41};
42
43static const char *formats[NUM_RTX_CODE];
44
45static const char *type_from_format	PARAMS ((int));
46static const char *accessor_from_format	PARAMS ((int));
47static int special_format		PARAMS ((const char *));
48static int special_rtx			PARAMS ((int));
49static int excluded_rtx			PARAMS ((int));
50static void find_formats		PARAMS ((void));
51static void gendecl			PARAMS ((const char *));
52static void genmacro			PARAMS ((int));
53static void gendef			PARAMS ((const char *));
54static void genlegend			PARAMS ((void));
55static void genheader			PARAMS ((void));
56static void gencode			PARAMS ((void));
57
58/* Decode a format letter into a C type string.  */
59
60static const char *
61type_from_format (c)
62     int c;
63{
64  switch (c)
65    {
66    case 'i':
67      return "int ";
68
69    case 'w':
70      return "HOST_WIDE_INT ";
71
72    case 's':
73      return "const char *";
74
75    case 'e':  case 'u':
76      return "rtx ";
77
78    case 'E':
79      return "rtvec ";
80    case 'b':
81      return "struct bitmap_head_def *";  /* bitmap - typedef not available */
82    case 't':
83      return "union tree_node *";  /* tree - typedef not available */
84    case 'B':
85      return "struct basic_block_def *";  /* basic block - typedef not available */
86    default:
87      abort ();
88    }
89}
90
91/* Decode a format letter into the proper accessor function.  */
92
93static const char *
94accessor_from_format (c)
95     int c;
96{
97  switch (c)
98    {
99    case 'i':
100      return "XINT";
101
102    case 'w':
103      return "XWINT";
104
105    case 's':
106      return "XSTR";
107
108    case 'e':  case 'u':
109      return "XEXP";
110
111    case 'E':
112      return "XVEC";
113
114    case 'b':
115      return "XBITMAP";
116
117    case 't':
118      return "XTREE";
119
120    case 'B':
121      return "XBBDEF";
122
123    default:
124      abort ();
125    }
126}
127
128/* Return nonzero if we should ignore FMT, an RTL format, when making
129   the list of formats we write routines to create.  */
130
131static int
132special_format (fmt)
133     const char *fmt;
134{
135  return (strchr (fmt, '*') != 0
136	  || strchr (fmt, 'V') != 0
137	  || strchr (fmt, 'S') != 0
138	  || strchr (fmt, 'n') != 0);
139}
140
141/* Return nonzero if the RTL code given by index IDX is one that we should
142   generate a gen_rtx_raw_FOO macro for, not gen_rtx_FOO (because gen_rtx_FOO
143   is a wrapper in emit-rtl.c).  */
144
145static int
146special_rtx (idx)
147     int idx;
148{
149  return (strcmp (defs[idx].enumname, "CONST_INT") == 0
150	  || strcmp (defs[idx].enumname, "REG") == 0
151	  || strcmp (defs[idx].enumname, "SUBREG") == 0
152	  || strcmp (defs[idx].enumname, "MEM") == 0
153	  || strcmp (defs[idx].enumname, "CONST_VECTOR") == 0);
154}
155
156/* Return nonzero if the RTL code given by index IDX is one that we should
157   generate no macro for at all (because gen_rtx_FOO is never used or
158   cannot have the obvious interface).  */
159
160static int
161excluded_rtx (idx)
162     int idx;
163{
164  return (strcmp (defs[idx].enumname, "CONST_DOUBLE") == 0);
165}
166
167/* Place a list of all format specifiers we use into the array FORMAT.  */
168
169static void
170find_formats ()
171{
172  int i;
173
174  for (i = 0; i < NUM_RTX_CODE; i++)
175    {
176      const char **f;
177
178      if (special_format (defs[i].format))
179	continue;
180
181      for (f = formats; *f; f++)
182	if (! strcmp (*f, defs[i].format))
183	  break;
184
185      if (*f == 0)
186	*f = defs[i].format;
187    }
188}
189
190/* Write the declarations for the routine to allocate RTL with FORMAT.  */
191
192static void
193gendecl (format)
194     const char *format;
195{
196  const char *p;
197  int i, pos;
198
199  printf ("extern rtx gen_rtx_fmt_%s\tPARAMS ((RTX_CODE, ", format);
200  printf ("enum machine_mode mode");
201
202  /* Write each parameter that is needed and start a new line when the line
203     would overflow.  */
204  for (p = format, i = 0, pos = 75; *p != 0; p++)
205    if (*p != '0')
206      {
207	int ourlen = strlen (type_from_format (*p)) + 6 + (i > 9);
208
209	printf (",");
210	if (pos + ourlen > 76)
211	  printf ("\n\t\t\t\t      "), pos = 39;
212
213	printf (" %sarg%d", type_from_format (*p), i++);
214	pos += ourlen;
215      }
216
217  printf ("));\n");
218}
219
220/* Generate macros to generate RTL of code IDX using the functions we
221   write.  */
222
223static void
224genmacro (idx)
225     int idx;
226{
227  const char *p;
228  int i;
229
230  /* We write a macro that defines gen_rtx_RTLCODE to be an equivalent to
231     gen_rtx_fmt_FORMAT where FORMAT is the RTX_FORMAT of RTLCODE.  */
232
233  if (excluded_rtx (idx))
234    /* Don't define a macro for this code.  */
235    return;
236
237  printf ("#define gen_rtx_%s%s(MODE",
238	   special_rtx (idx) ? "raw_" : "", defs[idx].enumname);
239
240  for (p = defs[idx].format, i = 0; *p != 0; p++)
241    if (*p != '0')
242      printf (", ARG%d", i++);
243
244  printf (") \\\n  gen_rtx_fmt_%s (%s, (MODE)",
245	  defs[idx].format, defs[idx].enumname);
246
247  for (p = defs[idx].format, i = 0; *p != 0; p++)
248    if (*p != '0')
249      printf (", (ARG%d)", i++);
250
251  puts (")");
252}
253
254/* Generate the code for the function to generate RTL whose
255   format is FORMAT.  */
256
257static void
258gendef (format)
259     const char *format;
260{
261  const char *p;
262  int i, j;
263
264  /* Start by writing the definition of the function name and the types
265     of the arguments.  */
266
267  printf ("rtx\ngen_rtx_fmt_%s (code, mode", format);
268  for (p = format, i = 0; *p != 0; p++)
269    if (*p != '0')
270      printf (", arg%d", i++);
271
272  puts (")\n     RTX_CODE code;\n     enum machine_mode mode;");
273  for (p = format, i = 0; *p != 0; p++)
274    if (*p != '0')
275      printf ("     %sarg%d;\n", type_from_format (*p), i++);
276
277  /* Now write out the body of the function itself, which allocates
278     the memory and initializes it.  */
279  puts ("{");
280  puts ("  rtx rt;");
281  printf ("  rt = ggc_alloc_rtx (%d);\n", (int) strlen (format));
282
283  puts ("  memset (rt, 0, sizeof (struct rtx_def) - sizeof (rtunion));\n");
284  puts ("  PUT_CODE (rt, code);");
285  puts ("  PUT_MODE (rt, mode);");
286
287  for (p = format, i = j = 0; *p ; ++p, ++i)
288    if (*p != '0')
289      printf ("  %s (rt, %d) = arg%d;\n", accessor_from_format (*p), i, j++);
290    else
291      printf ("  X0EXP (rt, %d) = NULL_RTX;\n", i);
292
293  puts ("\n  return rt;\n}\n");
294}
295
296/* Generate the documentation header for files we write.  */
297
298static void
299genlegend ()
300{
301  puts ("/* Generated automatically by gengenrtl from rtl.def.  */\n");
302}
303
304/* Generate the text of the header file we make, genrtl.h.  */
305
306static void
307genheader ()
308{
309  int i;
310  const char **fmt;
311
312  puts ("#ifndef GCC_GENRTL_H");
313  puts ("#define GCC_GENRTL_H\n");
314
315  for (fmt = formats; *fmt; ++fmt)
316    gendecl (*fmt);
317
318  putchar ('\n');
319
320  for (i = 0; i < NUM_RTX_CODE; i++)
321    if (! special_format (defs[i].format))
322      genmacro (i);
323
324  puts ("\n#endif /* GCC_GENRTL_H */");
325}
326
327/* Generate the text of the code file we write, genrtl.c.  */
328
329static void
330gencode ()
331{
332  const char **fmt;
333
334  puts ("#include \"config.h\"");
335  puts ("#include \"system.h\"");
336  puts ("#include \"obstack.h\"");
337  puts ("#include \"rtl.h\"");
338  puts ("#include \"ggc.h\"\n");
339  puts ("extern struct obstack *rtl_obstack;\n");
340
341  for (fmt = formats; *fmt != 0; fmt++)
342    gendef (*fmt);
343}
344
345/* This is the main program.  We accept only one argument, "-h", which
346   says we are writing the genrtl.h file.  Otherwise we are writing the
347   genrtl.c file.  */
348extern int main PARAMS ((int, char **));
349
350int
351main (argc, argv)
352     int argc;
353     char **argv;
354{
355  find_formats ();
356  genlegend ();
357
358  if (argc == 2 && argv[1][0] == '-' && argv[1][1] == 'h')
359    genheader ();
360  else
361    gencode ();
362
363  if (ferror (stdout) || fflush (stdout) || fclose (stdout))
364    return FATAL_EXIT_CODE;
365
366  return SUCCESS_EXIT_CODE;
367}
368