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