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