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