]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/genflags.c
gcc/
[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-2015 Free Software Foundation, Inc.
5
6 This file is part of GCC.
7
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 3, or (at your option) any later
11 version.
12
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
21
22
23 #include "bconfig.h"
24 #include "system.h"
25 #include "coretypes.h"
26 #include "tm.h"
27 #include "rtl.h"
28 #include "obstack.h"
29 #include "errors.h"
30 #include "read-md.h"
31 #include "gensupport.h"
32
33 /* Obstack to remember insns with. */
34 static struct obstack obstack;
35
36 /* Max size of names encountered. */
37 static int max_id_len;
38
39 /* Max operand encountered in a scan over some insn. */
40 static int max_opno;
41
42 static void max_operand_1 (rtx);
43 static int num_operands (rtx);
44 static void gen_proto (rtx);
45 static void gen_macro (const char *, int, int);
46
47 /* Count the number of match_operand's found. */
48
49 static void
50 max_operand_1 (rtx x)
51 {
52 RTX_CODE code;
53 int i;
54 int len;
55 const char *fmt;
56
57 if (x == 0)
58 return;
59
60 code = GET_CODE (x);
61
62 if (code == MATCH_OPERAND || code == MATCH_OPERATOR
63 || code == MATCH_PARALLEL)
64 max_opno = MAX (max_opno, XINT (x, 0));
65
66 fmt = GET_RTX_FORMAT (code);
67 len = GET_RTX_LENGTH (code);
68 for (i = 0; i < len; i++)
69 {
70 if (fmt[i] == 'e' || fmt[i] == 'u')
71 max_operand_1 (XEXP (x, i));
72 else if (fmt[i] == 'E')
73 {
74 int j;
75 for (j = 0; j < XVECLEN (x, i); j++)
76 max_operand_1 (XVECEXP (x, i, j));
77 }
78 }
79 }
80
81 static int
82 num_operands (rtx insn)
83 {
84 int len = XVECLEN (insn, 1);
85 int i;
86
87 max_opno = -1;
88
89 for (i = 0; i < len; i++)
90 max_operand_1 (XVECEXP (insn, 1, i));
91
92 return max_opno + 1;
93 }
94
95 /* Print out a wrapper macro for a function which corrects the number
96 of arguments it takes. Any missing arguments are assumed to be at
97 the end. */
98 static void
99 gen_macro (const char *name, int real, int expect)
100 {
101 int i;
102
103 gcc_assert (real <= expect);
104 gcc_assert (real);
105
106 /* #define GEN_CALL(A, B, C, D) gen_call((A), (B)) */
107 fputs ("#define GEN_", stdout);
108 for (i = 0; name[i]; i++)
109 putchar (TOUPPER (name[i]));
110
111 putchar ('(');
112 for (i = 0; i < expect - 1; i++)
113 printf ("%c, ", i + 'A');
114 printf ("%c) gen_%s (", i + 'A', name);
115
116 for (i = 0; i < real - 1; i++)
117 printf ("(%c), ", i + 'A');
118 printf ("(%c))\n", i + 'A');
119 }
120
121 /* Print out prototype information for a generator function. If the
122 insn pattern has been elided, print out a dummy generator that
123 does nothing. */
124
125 static void
126 gen_proto (rtx insn)
127 {
128 int num = num_operands (insn);
129 int i;
130 const char *name = XSTR (insn, 0);
131 int truth = maybe_eval_c_test (XSTR (insn, 2));
132
133 /* Many md files don't refer to the last two operands passed to the
134 call patterns. This means their generator functions will be two
135 arguments too short. Instead of changing every md file to touch
136 those operands, we wrap the prototypes in macros that take the
137 correct number of arguments. */
138 if (name[0] == 'c' || name[0] == 's')
139 {
140 if (!strcmp (name, "call")
141 || !strcmp (name, "call_pop")
142 || !strcmp (name, "sibcall")
143 || !strcmp (name, "sibcall_pop"))
144 gen_macro (name, num, 4);
145 else if (!strcmp (name, "call_value")
146 || !strcmp (name, "call_value_pop")
147 || !strcmp (name, "sibcall_value")
148 || !strcmp (name, "sibcall_value_pop"))
149 gen_macro (name, num, 5);
150 }
151
152 if (truth != 0)
153 printf ("extern rtx gen_%-*s (", max_id_len, name);
154 else
155 printf ("static inline rtx gen_%-*s (", max_id_len, name);
156
157 if (num == 0)
158 fputs ("void", stdout);
159 else
160 {
161 for (i = 1; i < num; i++)
162 fputs ("rtx, ", stdout);
163
164 fputs ("rtx", stdout);
165 }
166
167 puts (");");
168
169 /* Some back ends want to take the address of generator functions,
170 so we cannot simply use #define for these dummy definitions. */
171 if (truth == 0)
172 {
173 printf ("static inline rtx\ngen_%s", name);
174 if (num > 0)
175 {
176 putchar ('(');
177 for (i = 0; i < num-1; i++)
178 printf ("rtx ARG_UNUSED (%c), ", 'a' + i);
179 printf ("rtx ARG_UNUSED (%c))\n", 'a' + i);
180 }
181 else
182 puts ("(void)");
183 puts ("{\n return 0;\n}");
184 }
185
186 }
187
188 static void
189 gen_insn (md_rtx_info *info)
190 {
191 rtx insn = info->def;
192 const char *name = XSTR (insn, 0);
193 const char *p;
194 const char *lt, *gt;
195 int len;
196 int truth = maybe_eval_c_test (XSTR (insn, 2));
197
198 lt = strchr (name, '<');
199 if (lt && strchr (lt + 1, '>'))
200 {
201 error_at (info->loc, "unresolved iterator");
202 return;
203 }
204
205 gt = strchr (name, '>');
206 if (lt || gt)
207 {
208 error_at (info->loc, "unmatched angle brackets, likely "
209 "an error in iterator syntax");
210 return;
211 }
212
213 /* Don't mention instructions whose names are the null string
214 or begin with '*'. They are in the machine description just
215 to be recognized. */
216 if (name[0] == 0 || name[0] == '*')
217 return;
218
219 len = strlen (name);
220
221 if (len > max_id_len)
222 max_id_len = len;
223
224 if (truth == 0)
225 /* Emit nothing. */;
226 else if (truth == 1)
227 printf ("#define HAVE_%s 1\n", name);
228 else
229 {
230 /* Write the macro definition, putting \'s at the end of each line,
231 if more than one. */
232 printf ("#define HAVE_%s (", name);
233 for (p = XSTR (insn, 2); *p; p++)
234 {
235 if (IS_VSPACE (*p))
236 fputs (" \\\n", stdout);
237 else
238 putchar (*p);
239 }
240 fputs (")\n", stdout);
241 }
242
243 obstack_grow (&obstack, &insn, sizeof (rtx));
244 }
245
246 int
247 main (int argc, char **argv)
248 {
249 rtx dummy;
250 rtx *insns;
251 rtx *insn_ptr;
252
253 progname = "genflags";
254 obstack_init (&obstack);
255
256 /* We need to see all the possibilities. Elided insns may have
257 direct calls to their generators in C code. */
258 insn_elision = 0;
259
260 if (!init_rtx_reader_args (argc, argv))
261 return (FATAL_EXIT_CODE);
262
263 puts ("/* Generated automatically by the program `genflags'");
264 puts (" from the machine description file `md'. */\n");
265 puts ("#ifndef GCC_INSN_FLAGS_H");
266 puts ("#define GCC_INSN_FLAGS_H\n");
267
268 /* Read the machine description. */
269
270 md_rtx_info info;
271 while (read_md_rtx (&info))
272 switch (GET_CODE (info.def))
273 {
274 case DEFINE_INSN:
275 case DEFINE_EXPAND:
276 gen_insn (&info);
277 break;
278
279 default:
280 break;
281 }
282
283 /* Print out the prototypes now. */
284 dummy = (rtx) 0;
285 obstack_grow (&obstack, &dummy, sizeof (rtx));
286 insns = XOBFINISH (&obstack, rtx *);
287
288 for (insn_ptr = insns; *insn_ptr; insn_ptr++)
289 gen_proto (*insn_ptr);
290
291 puts ("\n#endif /* GCC_INSN_FLAGS_H */");
292
293 if (have_error || ferror (stdout) || fflush (stdout) || fclose (stdout))
294 return FATAL_EXIT_CODE;
295
296 return SUCCESS_EXIT_CODE;
297 }