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