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