]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/genflags.c
mkconfig.sh: Include insn-flags.h.
[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 /* Obstack to remember insns with. */
37 static struct obstack 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_macro PARAMS ((const char *, int, int));
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 a wrapper macro for a function which corrects the number
102 of arguments it takes. Any missing arguments are assumed to be at
103 the end. */
104 static void
105 gen_macro (name, real, expect)
106 const char *name;
107 int real, expect;
108 {
109 int i;
110
111 if (real > expect)
112 abort ();
113 if (real == 0)
114 abort ();
115
116 /* #define GEN_CALL(A, B, C, D) gen_call((A), (B)) */
117 fputs ("#define GEN_", stdout);
118 for (i = 0; name[i]; i++)
119 putchar (TOUPPER (name[i]));
120
121 putchar('(');
122 for (i = 0; i < expect - 1; i++)
123 printf ("%c, ", i + 'A');
124 printf ("%c) gen_%s (", i + 'A', name);
125
126 for (i = 0; i < real - 1; i++)
127 printf ("(%c), ", i + 'A');
128 printf ("(%c))\n", i + 'A');
129 }
130
131 /* Print out prototype information for a function. */
132
133 static void
134 gen_proto (insn)
135 rtx insn;
136 {
137 int num = num_operands (insn);
138 const char *name = XSTR (insn, 0);
139
140 /* Many md files don't refer to the last two operands passed to the
141 call patterns. This means their generator functions will be two
142 arguments too short. Instead of changing every md file to touch
143 those operands, we wrap the prototypes in macros that take the
144 correct number of arguments. */
145 if (name[0] == 'c' || name[0] == 's')
146 {
147 if (!strcmp (name, "call")
148 || !strcmp (name, "call_pop")
149 || !strcmp (name, "sibcall")
150 || !strcmp (name, "sibcall_pop"))
151 gen_macro (name, num, 4);
152 else if (!strcmp (name, "call_value")
153 || !strcmp (name, "call_value_pop")
154 || !strcmp (name, "sibcall_value")
155 || !strcmp (name, "sibcall_value_pop"))
156 gen_macro (name, num, 5);
157 }
158
159 printf ("extern struct rtx_def *gen_%-*s PARAMS ((", max_id_len, name);
160
161 if (num == 0)
162 printf ("void");
163 else
164 {
165 while (num-- > 1)
166 printf ("struct rtx_def *, ");
167
168 printf ("struct rtx_def *");
169 }
170
171 printf ("));\n");
172
173 }
174
175 static void
176 gen_insn (insn)
177 rtx insn;
178 {
179 const char *name = XSTR (insn, 0);
180 const char *p;
181 int len;
182
183 /* Don't mention instructions whose names are the null string
184 or begin with '*'. They are in the machine description just
185 to be recognized. */
186 if (name[0] == 0 || name[0] == '*')
187 return;
188
189 len = strlen (name);
190
191 if (len > max_id_len)
192 max_id_len = len;
193
194 printf ("#define HAVE_%s ", name);
195 if (strlen (XSTR (insn, 2)) == 0)
196 printf ("1\n");
197 else
198 {
199 /* Write the macro definition, putting \'s at the end of each line,
200 if more than one. */
201 printf ("(");
202 for (p = XSTR (insn, 2); *p; p++)
203 {
204 if (*p == '\n')
205 printf (" \\\n");
206 else
207 printf ("%c", *p);
208 }
209 printf (")\n");
210 }
211
212 obstack_grow (&obstack, &insn, sizeof (rtx));
213 }
214
215 extern int main PARAMS ((int, char **));
216
217 int
218 main (argc, argv)
219 int argc;
220 char **argv;
221 {
222 rtx desc;
223 rtx dummy;
224 rtx *insns;
225 rtx *insn_ptr;
226
227 progname = "genflags";
228 obstack_init (&obstack);
229
230 if (argc <= 1)
231 fatal ("No input file name.");
232
233 if (init_md_reader (argv[1]) != SUCCESS_EXIT_CODE)
234 return (FATAL_EXIT_CODE);
235
236 printf ("/* Generated automatically by the program `genflags'\n\
237 from the machine description file `md'. */\n\n");
238
239 /* Read the machine description. */
240
241 while (1)
242 {
243 int line_no, insn_code_number = 0;
244
245 desc = read_md_rtx (&line_no, &insn_code_number);
246 if (desc == NULL)
247 break;
248 if (GET_CODE (desc) == DEFINE_INSN || GET_CODE (desc) == DEFINE_EXPAND)
249 gen_insn (desc);
250 }
251
252 /* Print out the prototypes now. */
253 dummy = (rtx) 0;
254 obstack_grow (&obstack, &dummy, sizeof (rtx));
255 insns = (rtx *) obstack_finish (&obstack);
256
257 printf ("struct rtx_def;\n");
258 for (insn_ptr = insns; *insn_ptr; insn_ptr++)
259 gen_proto (*insn_ptr);
260
261 fflush (stdout);
262 return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
263 }
264
265 /* Define this so we can link with print-rtl.o to get debug_rtx function. */
266 const char *
267 get_insn_name (code)
268 int code ATTRIBUTE_UNUSED;
269 {
270 return NULL;
271 }