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