OSDN Git Service

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