OSDN Git Service

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