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