]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/genflags.c
* system.h: Include stdarg.h/varargs.h, make sure they are ordered
[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 #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 PVPROTO ((char *, ...)) ATTRIBUTE_PRINTF_1;
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 VPROTO ((char *format, ...))
203 {
204 #ifndef __STDC__
205 char *format;
206 #endif
207 va_list ap;
208
209 VA_START (ap, format);
210
211 #ifndef __STDC__
212 format = va_arg (ap, char *);
213 #endif
214
215 fprintf (stderr, "genflags: ");
216 vfprintf (stderr, format, ap);
217 va_end (ap);
218 fprintf (stderr, "\n");
219 exit (FATAL_EXIT_CODE);
220 }
221
222 /* More 'friendly' abort that prints the line and file.
223 config.h can #define abort fancy_abort if you like that sort of thing. */
224
225 void
226 fancy_abort ()
227 {
228 fatal ("Internal gcc abort.");
229 }
230 \f
231 int
232 main (argc, argv)
233 int argc;
234 char **argv;
235 {
236 rtx desc;
237 rtx dummy;
238 rtx *call_insns;
239 rtx *normal_insns;
240 rtx *insn_ptr;
241 FILE *infile;
242 register int c;
243
244 obstack_init (rtl_obstack);
245 obstack_init (&call_obstack);
246 obstack_init (&normal_obstack);
247
248 if (argc <= 1)
249 fatal ("No input file name.");
250
251 infile = fopen (argv[1], "r");
252 if (infile == 0)
253 {
254 perror (argv[1]);
255 exit (FATAL_EXIT_CODE);
256 }
257
258 init_rtl ();
259
260 printf ("/* Generated automatically by the program `genflags'\n\
261 from the machine description file `md'. */\n\n");
262
263 /* Read the machine description. */
264
265 while (1)
266 {
267 c = read_skip_spaces (infile);
268 if (c == EOF)
269 break;
270 ungetc (c, infile);
271
272 desc = read_rtx (infile);
273 if (GET_CODE (desc) == DEFINE_INSN || GET_CODE (desc) == DEFINE_EXPAND)
274 gen_insn (desc);
275 }
276
277 /* Print out the prototypes now. */
278 dummy = (rtx) 0;
279 obstack_grow (&call_obstack, &dummy, sizeof (rtx));
280 call_insns = (rtx *) obstack_finish (&call_obstack);
281
282 obstack_grow (&normal_obstack, &dummy, sizeof (rtx));
283 normal_insns = (rtx *) obstack_finish (&normal_obstack);
284
285 printf ("\n#ifndef NO_MD_PROTOTYPES\n");
286 for (insn_ptr = normal_insns; *insn_ptr; insn_ptr++)
287 gen_proto (*insn_ptr);
288
289 printf ("\n#ifdef MD_CALL_PROTOTYPES\n");
290 for (insn_ptr = call_insns; *insn_ptr; insn_ptr++)
291 gen_proto (*insn_ptr);
292
293 printf ("\n#else /* !MD_CALL_PROTOTYPES */\n");
294 for (insn_ptr = call_insns; *insn_ptr; insn_ptr++)
295 gen_nonproto (*insn_ptr);
296
297 printf ("#endif /* !MD_CALL_PROTOTYPES */\n");
298 printf ("\n#else /* NO_MD_PROTOTYPES */\n");
299 for (insn_ptr = normal_insns; *insn_ptr; insn_ptr++)
300 gen_nonproto (*insn_ptr);
301
302 for (insn_ptr = call_insns; *insn_ptr; insn_ptr++)
303 gen_nonproto (*insn_ptr);
304
305 printf ("#endif /* NO_MD_PROTOTYPES */\n");
306
307 fflush (stdout);
308 exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
309 /* NOTREACHED */
310 return 0;
311 }