OSDN Git Service

(c_sizeof, build_c_cast): Set TREE_OVERFLOW in addition
[pf3gnuchains/gcc-fork.git] / gcc / genflags.c
1 /* Generate from machine description:
2
3    - some flags HAVE_... saying which simple standard instructions are
4    available for this machine.
5    Copyright (C) 1987, 1991 Free Software Foundation, Inc.
6
7 This file is part of GNU CC.
8
9 GNU CC is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2, or (at your option)
12 any later version.
13
14 GNU CC is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with GNU CC; see the file COPYING.  If not, write to
21 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
22
23
24 #include <stdio.h>
25 #include "hconfig.h"
26 #include "rtl.h"
27 #include "obstack.h"
28
29 static struct obstack obstack;
30 struct obstack *rtl_obstack = &obstack;
31
32 #define obstack_chunk_alloc xmalloc
33 #define obstack_chunk_free free
34
35 extern void free ();
36 extern rtx read_rtx ();
37
38 char *xmalloc ();
39 static void fatal ();
40 void fancy_abort ();
41
42 /* Names for patterns.  Need to allow linking with print-rtl.  */
43 char **insn_name_ptr;
44
45 /* Obstacks to remember normal, and call insns.  */
46 static struct obstack call_obstack, normal_obstack;
47
48 /* Max size of names encountered.  */
49 static int max_id_len;
50
51 /* Count the number of match_operand's found.  */
52 static int
53 num_operands (x)
54      rtx x;
55 {
56   int count = 0;
57   int i, j;
58   enum rtx_code code = GET_CODE (x);
59   char *format_ptr = GET_RTX_FORMAT (code);
60
61   if (code == MATCH_OPERAND)
62     return 1;
63
64   if (code == MATCH_OPERATOR || code == MATCH_PARALLEL)
65     count++;
66
67   for (i = 0; i < GET_RTX_LENGTH (code); i++)
68     {
69       switch (*format_ptr++)
70         {
71         case 'u':
72         case 'e':
73           count += num_operands (XEXP (x, i));
74           break;
75
76         case 'E':
77           if (XVEC (x, i) != NULL)
78             for (j = 0; j < XVECLEN (x, i); j++)
79               count += num_operands (XVECEXP (x, i, j));
80
81           break;
82         }
83     }
84
85   return count;
86 }
87
88 /* Print out prototype information for a function.  */
89 static void
90 gen_proto (insn)
91      rtx insn;
92 {
93   int num = num_operands (insn);
94   printf ("extern rtx gen_%-*s PROTO((", max_id_len, XSTR (insn, 0));
95
96   if (num == 0)
97     printf ("void");
98   else
99     {
100       while (num-- > 1)
101         printf ("rtx, ");
102
103       printf ("rtx");
104     }
105
106   printf ("));\n");
107 }
108
109 /* Print out a function declaration without a prototype.  */
110 static void
111 gen_nonproto (insn)
112      rtx insn;
113 {
114   printf ("extern rtx gen_%s ();\n", XSTR (insn, 0));
115 }
116
117 static void
118 gen_insn (insn)
119      rtx insn;
120 {
121   char *name = XSTR (insn, 0);
122   char *p;
123   struct obstack *obstack_ptr;
124   int len;
125
126   /* Don't mention instructions whose names are the null string.
127      They are in the machine description just to be recognized.  */
128   len = strlen (name);
129   if (len == 0)
130     return;
131
132   if (len > max_id_len)
133     max_id_len = len;
134
135   printf ("#define HAVE_%s ", name);
136   if (strlen (XSTR (insn, 2)) == 0)
137     printf ("1\n");
138   else
139     {
140       /* Write the macro definition, putting \'s at the end of each line,
141          if more than one.  */
142       printf ("(");
143       for (p = XSTR (insn, 2); *p; p++)
144         {
145           if (*p == '\n')
146             printf (" \\\n");
147           else
148             printf ("%c", *p);
149         }
150       printf (")\n");
151     }
152
153   /* Save the current insn, so that we can later put out appropriate
154      prototypes.  At present, most md files have the wrong number of
155      arguments for the call insns (call, call_value, call_pop,
156      call_value_pop) ignoring the extra arguments that are passed for
157      some machines, so by default, turn off the prototype.  */
158
159   obstack_ptr = (name[0] == 'c'
160                  && (!strcmp (name, "call")
161                      || !strcmp (name, "call_value")
162                      || !strcmp (name, "call_pop")
163                      || !strcmp (name, "call_value_pop")))
164     ? &call_obstack : &normal_obstack;
165
166   obstack_grow (obstack_ptr, &insn, sizeof (rtx));
167 }
168 \f
169 char *
170 xmalloc (size)
171      unsigned size;
172 {
173   register char *val = (char *) malloc (size);
174
175   if (val == 0)
176     fatal ("virtual memory exhausted");
177
178   return val;
179 }
180
181 char *
182 xrealloc (ptr, size)
183      char *ptr;
184      unsigned size;
185 {
186   char *result = (char *) realloc (ptr, size);
187   if (!result)
188     fatal ("virtual memory exhausted");
189   return result;
190 }
191
192 static void
193 fatal (s, a1, a2)
194      char *s;
195 {
196   fprintf (stderr, "genflags: ");
197   fprintf (stderr, s, a1, a2);
198   fprintf (stderr, "\n");
199   exit (FATAL_EXIT_CODE);
200 }
201
202 /* More 'friendly' abort that prints the line and file.
203    config.h can #define abort fancy_abort if you like that sort of thing.  */
204
205 void
206 fancy_abort ()
207 {
208   fatal ("Internal gcc abort.");
209 }
210 \f
211 int
212 main (argc, argv)
213      int argc;
214      char **argv;
215 {
216   rtx desc;
217   rtx dummy;
218   rtx *call_insns;
219   rtx *normal_insns;
220   rtx *insn_ptr;
221   FILE *infile;
222   register int c;
223
224   obstack_init (rtl_obstack);
225   obstack_init (&call_obstack);
226   obstack_init (&normal_obstack);
227
228   if (argc <= 1)
229     fatal ("No input file name.");
230
231   infile = fopen (argv[1], "r");
232   if (infile == 0)
233     {
234       perror (argv[1]);
235       exit (FATAL_EXIT_CODE);
236     }
237
238   init_rtl ();
239
240   printf ("/* Generated automatically by the program `genflags'\n\
241 from the machine description file `md'.  */\n\n");
242
243   /* Read the machine description.  */
244
245   while (1)
246     {
247       c = read_skip_spaces (infile);
248       if (c == EOF)
249         break;
250       ungetc (c, infile);
251
252       desc = read_rtx (infile);
253       if (GET_CODE (desc) == DEFINE_INSN || GET_CODE (desc) == DEFINE_EXPAND)
254         gen_insn (desc);
255     }
256
257   /* Print out the prototypes now.  */
258   dummy = (rtx)0;
259   obstack_grow (&call_obstack, &dummy, sizeof (rtx));
260   call_insns = (rtx *) obstack_finish (&call_obstack);
261
262   obstack_grow (&normal_obstack, &dummy, sizeof (rtx));
263   normal_insns = (rtx *) obstack_finish (&normal_obstack);
264
265   printf ("\n#ifndef NO_MD_PROTOTYPES\n");
266   for (insn_ptr = normal_insns; *insn_ptr; insn_ptr++)
267     gen_proto (*insn_ptr);
268
269   printf ("\n#ifdef MD_CALL_PROTOTYPES\n");
270   for (insn_ptr = call_insns; *insn_ptr; insn_ptr++)
271     gen_proto (*insn_ptr);
272
273   printf ("\n#else /* !MD_CALL_PROTOTYPES */\n");
274   for (insn_ptr = call_insns; *insn_ptr; insn_ptr++)
275     gen_nonproto (*insn_ptr);
276
277   printf ("#endif /* !MD_CALL_PROTOTYPES */\n");
278   printf ("\n#else  /* NO_MD_PROTOTYPES */\n");
279   for (insn_ptr = normal_insns; *insn_ptr; insn_ptr++)
280     gen_nonproto (*insn_ptr);
281
282   for (insn_ptr = call_insns; *insn_ptr; insn_ptr++)
283     gen_nonproto (*insn_ptr);
284
285   printf ("#endif  /* NO_MD_PROTOTYPES */\n");
286
287   fflush (stdout);
288   exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
289   /* NOTREACHED */
290   return 0;
291 }