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