]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/genflags.c
Sibling call optimizations.
[thirdparty/gcc.git] / gcc / genflags.c
1 /* Generate from machine description:
2 - some flags HAVE_... saying which simple standard instructions are
3 available for this machine.
4 Copyright (C) 1987, 1991, 1995, 1998,
5 1999, 2000 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 #include "errors.h"
30
31 static struct obstack obstack;
32 struct obstack *rtl_obstack = &obstack;
33
34 #define obstack_chunk_alloc xmalloc
35 #define obstack_chunk_free free
36
37 /* Obstacks to remember normal, and call insns. */
38 static struct obstack call_obstack, normal_obstack;
39
40 /* Max size of names encountered. */
41 static int max_id_len;
42
43 /* Max operand encountered in a scan over some insn. */
44 static int max_opno;
45
46 static void max_operand_1 PARAMS ((rtx));
47 static int num_operands PARAMS ((rtx));
48 static void gen_proto PARAMS ((rtx));
49 static void gen_nonproto PARAMS ((rtx));
50 static void gen_insn PARAMS ((rtx));
51
52 /* Count the number of match_operand's found. */
53
54 static void
55 max_operand_1 (x)
56 rtx x;
57 {
58 register RTX_CODE code;
59 register int i;
60 register int len;
61 register const char *fmt;
62
63 if (x == 0)
64 return;
65
66 code = GET_CODE (x);
67
68 if (code == MATCH_OPERAND || code == MATCH_OPERATOR
69 || code == MATCH_PARALLEL)
70 max_opno = MAX (max_opno, XINT (x, 0));
71
72 fmt = GET_RTX_FORMAT (code);
73 len = GET_RTX_LENGTH (code);
74 for (i = 0; i < len; i++)
75 {
76 if (fmt[i] == 'e' || fmt[i] == 'u')
77 max_operand_1 (XEXP (x, i));
78 else if (fmt[i] == 'E')
79 {
80 int j;
81 for (j = 0; j < XVECLEN (x, i); j++)
82 max_operand_1 (XVECEXP (x, i, j));
83 }
84 }
85 }
86
87 static int
88 num_operands (insn)
89 rtx insn;
90 {
91 register int len = XVECLEN (insn, 1);
92 register int i;
93
94 max_opno = -1;
95
96 for (i = 0; i < len; i++)
97 max_operand_1 (XVECEXP (insn, 1, i));
98
99 return max_opno + 1;
100 }
101
102 /* Print out prototype information for a function. */
103
104 static void
105 gen_proto (insn)
106 rtx insn;
107 {
108 int num = num_operands (insn);
109 printf ("extern rtx gen_%-*s PARAMS ((", max_id_len, XSTR (insn, 0));
110
111 if (num == 0)
112 printf ("void");
113 else
114 {
115 while (num-- > 1)
116 printf ("rtx, ");
117
118 printf ("rtx");
119 }
120
121 printf ("));\n");
122 }
123
124 /* Print out a function declaration without a prototype. */
125
126 static void
127 gen_nonproto (insn)
128 rtx insn;
129 {
130 printf ("extern rtx gen_%s ();\n", XSTR (insn, 0));
131 }
132
133 static void
134 gen_insn (insn)
135 rtx insn;
136 {
137 const char *name = XSTR (insn, 0);
138 const char *p;
139 struct obstack *obstack_ptr;
140 int len;
141
142 /* Don't mention instructions whose names are the null string
143 or begin with '*'. They are in the machine description just
144 to be recognized. */
145 if (name[0] == 0 || name[0] == '*')
146 return;
147
148 len = strlen (name);
149
150 if (len > max_id_len)
151 max_id_len = len;
152
153 printf ("#define HAVE_%s ", name);
154 if (strlen (XSTR (insn, 2)) == 0)
155 printf ("1\n");
156 else
157 {
158 /* Write the macro definition, putting \'s at the end of each line,
159 if more than one. */
160 printf ("(");
161 for (p = XSTR (insn, 2); *p; p++)
162 {
163 if (*p == '\n')
164 printf (" \\\n");
165 else
166 printf ("%c", *p);
167 }
168 printf (")\n");
169 }
170
171 /* Save the current insn, so that we can later put out appropriate
172 prototypes. At present, most md files have the wrong number of
173 arguments for the call insns (call, call_value, call_pop,
174 call_value_pop) ignoring the extra arguments that are passed for
175 some machines, so by default, turn off the prototype. */
176
177 obstack_ptr = ((name[0] == 'c' || name[0] == 's')
178 && (!strcmp (name, "call")
179 || !strcmp (name, "call_value")
180 || !strcmp (name, "call_pop")
181 || !strcmp (name, "call_value_pop")
182 || !strcmp (name, "sibcall")
183 || !strcmp (name, "sibcall_value")
184 || !strcmp (name, "sibcall_pop")
185 || !strcmp (name, "sibcall_value_pop")))
186 ? &call_obstack : &normal_obstack;
187
188 obstack_grow (obstack_ptr, &insn, sizeof (rtx));
189 }
190 \f
191 PTR
192 xmalloc (size)
193 size_t size;
194 {
195 register PTR val = (PTR) malloc (size);
196
197 if (val == 0)
198 fatal ("virtual memory exhausted");
199
200 return val;
201 }
202
203 PTR
204 xrealloc (old, size)
205 PTR old;
206 size_t size;
207 {
208 register PTR ptr;
209 if (old)
210 ptr = (PTR) realloc (old, size);
211 else
212 ptr = (PTR) malloc (size);
213 if (!ptr)
214 fatal ("virtual memory exhausted");
215 return ptr;
216 }
217
218 extern int main PARAMS ((int, char **));
219
220 int
221 main (argc, argv)
222 int argc;
223 char **argv;
224 {
225 rtx desc;
226 rtx dummy;
227 rtx *call_insns;
228 rtx *normal_insns;
229 rtx *insn_ptr;
230 FILE *infile;
231 register int c;
232
233 progname = "genflags";
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 return (FATAL_EXIT_CODE);
246 }
247 read_rtx_filename = argv[1];
248
249 printf ("/* Generated automatically by the program `genflags'\n\
250 from the machine description file `md'. */\n\n");
251
252 /* Read the machine description. */
253
254 while (1)
255 {
256 c = read_skip_spaces (infile);
257 if (c == EOF)
258 break;
259 ungetc (c, infile);
260
261 desc = read_rtx (infile);
262 if (GET_CODE (desc) == DEFINE_INSN || GET_CODE (desc) == DEFINE_EXPAND)
263 gen_insn (desc);
264 }
265
266 /* Print out the prototypes now. */
267 dummy = (rtx) 0;
268 obstack_grow (&call_obstack, &dummy, sizeof (rtx));
269 call_insns = (rtx *) obstack_finish (&call_obstack);
270
271 obstack_grow (&normal_obstack, &dummy, sizeof (rtx));
272 normal_insns = (rtx *) obstack_finish (&normal_obstack);
273
274 for (insn_ptr = normal_insns; *insn_ptr; insn_ptr++)
275 gen_proto (*insn_ptr);
276
277 printf ("\n#ifdef MD_CALL_PROTOTYPES\n");
278 for (insn_ptr = call_insns; *insn_ptr; insn_ptr++)
279 gen_proto (*insn_ptr);
280
281 printf ("\n#else /* !MD_CALL_PROTOTYPES */\n");
282 for (insn_ptr = call_insns; *insn_ptr; insn_ptr++)
283 gen_nonproto (*insn_ptr);
284
285 printf ("#endif /* !MD_CALL_PROTOTYPES */\n");
286
287 fflush (stdout);
288 return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
289 }
290
291 /* Define this so we can link with print-rtl.o to get debug_rtx function. */
292 const char *
293 get_insn_name (code)
294 int code ATTRIBUTE_UNUSED;
295 {
296 return NULL;
297 }