OSDN Git Service

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