gengenrtl.c revision 303975
1234285Sdim/* Generate code to allocate RTL structures.
2234285Sdim   Copyright (C) 1997, 1998, 1999, 2000, 2002, 2003, 2004
3234285Sdim   Free Software Foundation, Inc.
4234285Sdim
5234285SdimThis file is part of GCC.
6234285Sdim
7234285SdimGCC is free software; you can redistribute it and/or modify it under
8234285Sdimthe terms of the GNU General Public License as published by the Free
9234285SdimSoftware Foundation; either version 2, or (at your option) any later
10234285Sdimversion.
11234285Sdim
12234285SdimGCC is distributed in the hope that it will be useful, but WITHOUT ANY
13234285SdimWARRANTY; without even the implied warranty of MERCHANTABILITY or
14249423SdimFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15234285Sdimfor more details.
16234285Sdim
17234285SdimYou should have received a copy of the GNU General Public License
18234285Sdimalong with GCC; see the file COPYING.  If not, write to the Free
19234285SdimSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
20234285Sdim02110-1301, USA.  */
21234285Sdim
22234285Sdim
23234285Sdim#include "bconfig.h"
24234285Sdim#include "system.h"
25234285Sdim
26234285Sdimstruct rtx_definition
27234285Sdim{
28234285Sdim  const char *const enumname, *const name, *const format;
29234285Sdim};
30234285Sdim
31234285Sdim/* rtl.def needs CONST_DOUBLE_FORMAT, but we don't care what
32234285Sdim   CONST_DOUBLE_FORMAT is because we're not going to be generating
33234285Sdim   anything for CONST_DOUBLE anyway.  */
34234285Sdim#define CONST_DOUBLE_FORMAT ""
35234285Sdim
36234285Sdim#define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS) { #ENUM, NAME, FORMAT },
37234285Sdim
38234285Sdimstatic const struct rtx_definition defs[] =
39234285Sdim{
40234285Sdim#include "rtl.def"		/* rtl expressions are documented here */
41234285Sdim};
42234285Sdim#define NUM_RTX_CODE ARRAY_SIZE(defs)
43234285Sdim
44234285Sdimstatic const char *formats[NUM_RTX_CODE];
45
46static const char *type_from_format	(int);
47static const char *accessor_from_format	(int);
48static int special_format		(const char *);
49static int special_rtx			(int);
50static int excluded_rtx			(int);
51static void find_formats		(void);
52static void gendecl			(const char *);
53static void genmacro			(int);
54static void gendef			(const char *);
55static void genlegend			(void);
56static void genheader			(void);
57static void gencode			(void);
58
59/* Decode a format letter into a C type string.  */
60
61static const char *
62type_from_format (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      gcc_unreachable ();
88    }
89}
90
91/* Decode a format letter into the proper accessor function.  */
92
93static const char *
94accessor_from_format (int c)
95{
96  switch (c)
97    {
98    case 'i':
99      return "XINT";
100
101    case 'w':
102      return "XWINT";
103
104    case 's':
105      return "XSTR";
106
107    case 'e':  case 'u':
108      return "XEXP";
109
110    case 'E':
111      return "XVEC";
112
113    case 'b':
114      return "XBITMAP";
115
116    case 't':
117      return "XTREE";
118
119    case 'B':
120      return "XBBDEF";
121
122    default:
123      gcc_unreachable ();
124    }
125}
126
127/* Return nonzero if we should ignore FMT, an RTL format, when making
128   the list of formats we write routines to create.  */
129
130static int
131special_format (const char *fmt)
132{
133  return (strchr (fmt, '*') != 0
134	  || strchr (fmt, 'V') != 0
135	  || strchr (fmt, 'S') != 0
136	  || strchr (fmt, 'n') != 0);
137}
138
139/* Return nonzero if the RTL code given by index IDX is one that we should
140   generate a gen_rtx_raw_FOO macro for, not gen_rtx_FOO (because gen_rtx_FOO
141   is a wrapper in emit-rtl.c).  */
142
143static int
144special_rtx (int idx)
145{
146  return (strcmp (defs[idx].enumname, "CONST_INT") == 0
147	  || strcmp (defs[idx].enumname, "REG") == 0
148	  || strcmp (defs[idx].enumname, "SUBREG") == 0
149	  || strcmp (defs[idx].enumname, "MEM") == 0
150	  || strcmp (defs[idx].enumname, "CONST_VECTOR") == 0);
151}
152
153/* Return nonzero if the RTL code given by index IDX is one that we should
154   generate no macro for at all (because gen_rtx_FOO is never used or
155   cannot have the obvious interface).  */
156
157static int
158excluded_rtx (int idx)
159{
160  return (strcmp (defs[idx].enumname, "CONST_DOUBLE") == 0);
161}
162
163/* Place a list of all format specifiers we use into the array FORMAT.  */
164
165static void
166find_formats (void)
167{
168  unsigned int i;
169
170  for (i = 0; i < NUM_RTX_CODE; i++)
171    {
172      const char **f;
173
174      if (special_format (defs[i].format))
175	continue;
176
177      for (f = formats; *f; f++)
178	if (! strcmp (*f, defs[i].format))
179	  break;
180
181      if (*f == 0)
182	*f = defs[i].format;
183    }
184}
185
186/* Write the declarations for the routine to allocate RTL with FORMAT.  */
187
188static void
189gendecl (const char *format)
190{
191  const char *p;
192  int i, pos;
193
194  printf ("extern rtx gen_rtx_fmt_%s\t (RTX_CODE, ", format);
195  printf ("enum machine_mode mode");
196
197  /* Write each parameter that is needed and start a new line when the line
198     would overflow.  */
199  for (p = format, i = 0, pos = 75; *p != 0; p++)
200    if (*p != '0')
201      {
202	int ourlen = strlen (type_from_format (*p)) + 6 + (i > 9);
203
204	printf (",");
205	if (pos + ourlen > 76)
206	  printf ("\n\t\t\t\t      "), pos = 39;
207
208	printf (" %sarg%d", type_from_format (*p), i++);
209	pos += ourlen;
210      }
211
212  printf (");\n");
213}
214
215/* Generate macros to generate RTL of code IDX using the functions we
216   write.  */
217
218static void
219genmacro (int idx)
220{
221  const char *p;
222  int i;
223
224  /* We write a macro that defines gen_rtx_RTLCODE to be an equivalent to
225     gen_rtx_fmt_FORMAT where FORMAT is the RTX_FORMAT of RTLCODE.  */
226
227  if (excluded_rtx (idx))
228    /* Don't define a macro for this code.  */
229    return;
230
231  printf ("#define gen_rtx_%s%s(MODE",
232	   special_rtx (idx) ? "raw_" : "", defs[idx].enumname);
233
234  for (p = defs[idx].format, i = 0; *p != 0; p++)
235    if (*p != '0')
236      printf (", ARG%d", i++);
237
238  printf (") \\\n  gen_rtx_fmt_%s (%s, (MODE)",
239	  defs[idx].format, defs[idx].enumname);
240
241  for (p = defs[idx].format, i = 0; *p != 0; p++)
242    if (*p != '0')
243      printf (", (ARG%d)", i++);
244
245  puts (")");
246}
247
248/* Generate the code for the function to generate RTL whose
249   format is FORMAT.  */
250
251static void
252gendef (const char *format)
253{
254  const char *p;
255  int i, j;
256
257  /* Start by writing the definition of the function name and the types
258     of the arguments.  */
259
260  printf ("rtx\ngen_rtx_fmt_%s (RTX_CODE code, enum machine_mode mode", format);
261  for (p = format, i = 0; *p != 0; p++)
262    if (*p != '0')
263      printf (",\n\t%sarg%d", type_from_format (*p), i++);
264
265  puts (")");
266
267  /* Now write out the body of the function itself, which allocates
268     the memory and initializes it.  */
269  puts ("{");
270  puts ("  rtx rt;");
271  puts ("  rt = rtx_alloc (code);\n");
272
273  puts ("  PUT_MODE (rt, mode);");
274
275  for (p = format, i = j = 0; *p ; ++p, ++i)
276    if (*p != '0')
277      printf ("  %s (rt, %d) = arg%d;\n", accessor_from_format (*p), i, j++);
278    else
279      printf ("  X0EXP (rt, %d) = NULL_RTX;\n", i);
280
281  puts ("\n  return rt;\n}\n");
282}
283
284/* Generate the documentation header for files we write.  */
285
286static void
287genlegend (void)
288{
289  puts ("/* Generated automatically by gengenrtl from rtl.def.  */\n");
290}
291
292/* Generate the text of the header file we make, genrtl.h.  */
293
294static void
295genheader (void)
296{
297  unsigned int i;
298  const char **fmt;
299
300  puts ("#ifndef GCC_GENRTL_H");
301  puts ("#define GCC_GENRTL_H\n");
302
303  for (fmt = formats; *fmt; ++fmt)
304    gendecl (*fmt);
305
306  putchar ('\n');
307
308  for (i = 0; i < NUM_RTX_CODE; i++)
309    if (! special_format (defs[i].format))
310      genmacro (i);
311
312  puts ("\n#endif /* GCC_GENRTL_H */");
313}
314
315/* Generate the text of the code file we write, genrtl.c.  */
316
317static void
318gencode (void)
319{
320  const char **fmt;
321
322  puts ("#include \"config.h\"");
323  puts ("#include \"system.h\"");
324  puts ("#include \"coretypes.h\"");
325  puts ("#include \"tm.h\"");
326  puts ("#include \"obstack.h\"");
327  puts ("#include \"rtl.h\"");
328  puts ("#include \"ggc.h\"\n");
329
330  for (fmt = formats; *fmt != 0; fmt++)
331    gendef (*fmt);
332}
333
334/* This is the main program.  We accept only one argument, "-h", which
335   says we are writing the genrtl.h file.  Otherwise we are writing the
336   genrtl.c file.  */
337
338int
339main (int argc, char **argv)
340{
341  find_formats ();
342  genlegend ();
343
344  if (argc == 2 && argv[1][0] == '-' && argv[1][1] == 'h')
345    genheader ();
346  else
347    gencode ();
348
349  if (ferror (stdout) || fflush (stdout) || fclose (stdout))
350    return FATAL_EXIT_CODE;
351
352  return SUCCESS_EXIT_CODE;
353}
354