Merge from the pain train
[official-gcc.git] / gcc / genpreds.c
blob30fd3899bcae835640bf19214e4ba0588dabaae3
1 /* Generate from machine description:
2 - prototype declarations for operand predicates (tm-preds.h)
3 - function definitions of operand predicates, if defined new-style
4 (insn-preds.c)
5 Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
7 This file is part of GCC.
9 GCC 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.
14 GCC 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.
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING. If not, write to
21 the Free Software Foundation, 59 Temple Place - Suite 330,
22 Boston, MA 02111-1307, USA. */
24 #include "bconfig.h"
25 #include "system.h"
26 #include "coretypes.h"
27 #include "tm.h"
28 #include "rtl.h"
29 #include "errors.h"
30 #include "gensupport.h"
31 #include "obstack.h"
33 /* The new way to declare predicates is with (define_predicate) or
34 (define_special_predicate) expressions in the machine description.
35 This provides a function body as well as a name. */
36 static void
37 process_define_predicate (rtx defn)
39 struct pred_data *pred;
40 if (XEXP (defn, 1) == 0)
42 error ("%s: must give a predicate expression", XSTR (defn, 0));
43 return;
46 pred = xcalloc (sizeof (struct pred_data), 1);
47 pred->name = XSTR (defn, 0);
48 pred->exp = XEXP (defn, 1);
49 pred->c_block = XSTR (defn, 2);
51 if (GET_CODE (defn) == DEFINE_SPECIAL_PREDICATE)
52 pred->special = true;
54 add_predicate (pred);
57 /* Write tm-preds.h. Unfortunately, it is impossible to forward-declare
58 an enumeration in portable C, so we have to condition all these
59 prototypes on HAVE_MACHINE_MODES. */
60 static void
61 write_tm_preds_h (void)
63 struct pred_data *p;
65 printf ("\
66 /* Generated automatically by the program '%s'\n\
67 from the machine description file '%s'. */\n\n", progname, in_fname);
69 puts ("\
70 #ifndef GCC_TM_PREDS_H\n\
71 #define GCC_TM_PREDS_H\n\
72 \n\
73 #ifdef HAVE_MACHINE_MODES");
75 FOR_ALL_PREDICATES (p)
76 printf ("extern int %s (rtx, enum machine_mode);\n", p->name);
78 puts ("\
79 #endif /* HAVE_MACHINE_MODES */\n\
80 #endif /* tm-preds.h */");
83 /* Given a predicate, if it has an embedded C block, write the block
84 out as a static inline subroutine, and augment the RTL test with a
85 match_test that calls that subroutine. For instance,
87 (define_predicate "basereg_operand"
88 (match_operand 0 "register_operand")
90 if (GET_CODE (op) == SUBREG)
91 op = SUBREG_REG (op);
92 return REG_POINTER (op);
95 becomes
97 static inline int basereg_operand_1(rtx op, enum machine_mode mode)
99 if (GET_CODE (op) == SUBREG)
100 op = SUBREG_REG (op);
101 return REG_POINTER (op);
104 (define_predicate "basereg_operand"
105 (and (match_operand 0 "register_operand")
106 (match_test "basereg_operand_1 (op, mode)")))
108 The only wart is that there's no way to insist on a { } string in
109 an RTL template, so we have to handle "" strings. */
112 static void
113 write_predicate_subfunction (struct pred_data *p)
115 const char *match_test_str;
116 rtx match_test_exp, and_exp;
118 if (p->c_block[0] == '\0')
119 return;
121 /* Construct the function-call expression. */
122 obstack_grow (rtl_obstack, p->name, strlen (p->name));
123 obstack_grow (rtl_obstack, "_1 (op, mode)",
124 sizeof "_1 (op, mode)");
125 match_test_str = obstack_finish (rtl_obstack);
127 /* Add the function-call expression to the complete expression to be
128 evaluated. */
129 match_test_exp = rtx_alloc (MATCH_TEST);
130 XSTR (match_test_exp, 0) = match_test_str;
132 and_exp = rtx_alloc (AND);
133 XEXP (and_exp, 0) = p->exp;
134 XEXP (and_exp, 1) = match_test_exp;
136 p->exp = and_exp;
138 printf ("static inline int\n"
139 "%s_1 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)\n",
140 p->name);
141 if (p->c_block[0] == '{')
142 fputs (p->c_block, stdout);
143 else
144 printf ("{\n %s\n}", p->c_block);
145 fputs ("\n\n", stdout);
148 /* Given an RTL expression EXP, find all subexpressions which we may
149 assume to perform mode tests. Normal MATCH_OPERAND does;
150 MATCH_CODE does if and only if it accepts CONST_INT or
151 CONST_DOUBLE; and we have to assume that MATCH_TEST does not.
152 These combine in almost-boolean fashion - the only exception is
153 that (not X) must be assumed not to perform a mode test, whether or
154 not X does.
156 The mark is the RTL /v flag, which is true for subexpressions which
157 do *not* perform mode tests.
159 #define NO_MODE_TEST(EXP) RTX_FLAG (EXP, volatil)
160 static void
161 mark_mode_tests (rtx exp)
163 switch (GET_CODE (exp))
165 case MATCH_OPERAND:
167 struct pred_data *p = lookup_predicate (XSTR (exp, 1));
168 if (!p)
169 error ("reference to undefined predicate '%s'", XSTR (exp, 1));
170 else if (p->special || GET_MODE (exp) != VOIDmode)
171 NO_MODE_TEST (exp) = 1;
173 break;
175 case MATCH_CODE:
176 if (!strstr (XSTR (exp, 0), "const_int")
177 && !strstr (XSTR (exp, 0), "const_double"))
178 NO_MODE_TEST (exp) = 1;
179 break;
181 case MATCH_TEST:
182 case NOT:
183 NO_MODE_TEST (exp) = 1;
184 break;
186 case AND:
187 mark_mode_tests (XEXP (exp, 0));
188 mark_mode_tests (XEXP (exp, 1));
190 NO_MODE_TEST (exp) = (NO_MODE_TEST (XEXP (exp, 0))
191 && NO_MODE_TEST (XEXP (exp, 1)));
192 break;
194 case IOR:
195 mark_mode_tests (XEXP (exp, 0));
196 mark_mode_tests (XEXP (exp, 1));
198 NO_MODE_TEST (exp) = (NO_MODE_TEST (XEXP (exp, 0))
199 || NO_MODE_TEST (XEXP (exp, 1)));
200 break;
202 case IF_THEN_ELSE:
203 /* A ? B : C does a mode test if (one of A and B) does a mode
204 test, and C does too. */
205 mark_mode_tests (XEXP (exp, 0));
206 mark_mode_tests (XEXP (exp, 1));
207 mark_mode_tests (XEXP (exp, 2));
209 NO_MODE_TEST (exp) = ((NO_MODE_TEST (XEXP (exp, 0))
210 && NO_MODE_TEST (XEXP (exp, 1)))
211 || NO_MODE_TEST (XEXP (exp, 2)));
212 break;
214 default:
215 error ("'%s' cannot be used in a define_predicate expression",
216 GET_RTX_NAME (GET_CODE (exp)));
220 /* Given a predicate, work out where in its RTL expression to add
221 tests for proper modes. Special predicates do not get any such
222 tests. We try to avoid adding tests when we don't have to; in
223 particular, other normal predicates can be counted on to do it for
224 us. */
226 static void
227 add_mode_tests (struct pred_data *p)
229 rtx match_test_exp, and_exp;
230 rtx *pos;
232 /* Don't touch special predicates. */
233 if (p->special)
234 return;
236 mark_mode_tests (p->exp);
238 /* If the whole expression already tests the mode, we're done. */
239 if (!NO_MODE_TEST (p->exp))
240 return;
242 match_test_exp = rtx_alloc (MATCH_TEST);
243 XSTR (match_test_exp, 0) = "mode == VOIDmode || GET_MODE (op) == mode";
244 and_exp = rtx_alloc (AND);
245 XEXP (and_exp, 1) = match_test_exp;
247 /* It is always correct to rewrite p->exp as
249 (and (...) (match_test "mode == VOIDmode || GET_MODE (op) == mode"))
251 but there are a couple forms where we can do better. If the
252 top-level pattern is an IOR, and one of the two branches does test
253 the mode, we can wrap just the branch that doesn't. Likewise, if
254 we have an IF_THEN_ELSE, and one side of it tests the mode, we can
255 wrap just the side that doesn't. And, of course, we can repeat this
256 descent as many times as it works. */
258 pos = &p->exp;
259 for (;;)
261 rtx subexp = *pos;
263 switch (GET_CODE (subexp))
265 case IOR:
267 int test0 = NO_MODE_TEST (XEXP (subexp, 0));
268 int test1 = NO_MODE_TEST (XEXP (subexp, 1));
270 gcc_assert (test0 || test1);
272 if (test0 && test1)
273 goto break_loop;
274 pos = test0 ? &XEXP (subexp, 0) : &XEXP (subexp, 1);
276 break;
278 case IF_THEN_ELSE:
280 int test0 = NO_MODE_TEST (XEXP (subexp, 0));
281 int test1 = NO_MODE_TEST (XEXP (subexp, 1));
282 int test2 = NO_MODE_TEST (XEXP (subexp, 2));
284 gcc_assert ((test0 && test1) || test2);
286 if (test0 && test1 && test2)
287 goto break_loop;
288 if (test0 && test1)
289 /* Must put it on the dependent clause, not the
290 controlling expression, or we change the meaning of
291 the test. */
292 pos = &XEXP (subexp, 1);
293 else
294 pos = &XEXP (subexp, 2);
296 break;
298 default:
299 goto break_loop;
302 break_loop:
303 XEXP (and_exp, 0) = *pos;
304 *pos = and_exp;
308 /* CODES is a list of RTX codes. Write out an expression which
309 determines whether the operand has one of those codes. */
310 static void
311 write_match_code (const char *codes)
313 const char *code;
315 while ((code = scan_comma_elt (&codes)) != 0)
317 fputs ("GET_CODE (op) == ", stdout);
318 while (code < codes)
320 putchar (TOUPPER (*code));
321 code++;
324 if (*codes == ',')
325 fputs (" || ", stdout);
329 /* EXP is an RTL (sub)expression for a predicate. Recursively
330 descend the expression and write out an equivalent C expression. */
331 static void
332 write_predicate_expr (const char *name, rtx exp)
334 switch (GET_CODE (exp))
336 case AND:
337 putchar ('(');
338 write_predicate_expr (name, XEXP (exp, 0));
339 fputs (") && (", stdout);
340 write_predicate_expr (name, XEXP (exp, 1));
341 putchar (')');
342 break;
344 case IOR:
345 putchar ('(');
346 write_predicate_expr (name, XEXP (exp, 0));
347 fputs (") || (", stdout);
348 write_predicate_expr (name, XEXP (exp, 1));
349 putchar (')');
350 break;
352 case NOT:
353 fputs ("!(", stdout);
354 write_predicate_expr (name, XEXP (exp, 0));
355 putchar (')');
356 break;
358 case IF_THEN_ELSE:
359 putchar ('(');
360 write_predicate_expr (name, XEXP (exp, 0));
361 fputs (") ? (", stdout);
362 write_predicate_expr (name, XEXP (exp, 1));
363 fputs (") : (", stdout);
364 write_predicate_expr (name, XEXP (exp, 2));
365 putchar (')');
366 break;
368 case MATCH_OPERAND:
369 if (GET_MODE (exp) == VOIDmode)
370 printf ("%s (op, mode)", XSTR (exp, 1));
371 else
372 printf ("%s (op, %smode)", XSTR (exp, 1), mode_name[GET_MODE (exp)]);
373 break;
375 case MATCH_CODE:
376 write_match_code (XSTR (exp, 0));
377 break;
379 case MATCH_TEST:
380 fputs (XSTR (exp, 0), stdout);
381 break;
383 default:
384 error ("%s: cannot use '%s' in a predicate expression",
385 name, GET_RTX_NAME (GET_CODE (exp)));
386 putchar ('0');
390 /* Given a predicate, write out a complete C function to compute it. */
391 static void
392 write_one_predicate_function (struct pred_data *p)
394 if (!p->exp)
395 return;
397 write_predicate_subfunction (p);
398 add_mode_tests (p);
400 /* A normal predicate can legitimately not look at enum machine_mode
401 if it accepts only CONST_INTs and/or CONST_DOUBLEs. */
402 printf ("int\n%s (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)\n"
403 "{\n return ",
404 p->name);
405 write_predicate_expr (p->name, p->exp);
406 fputs (";\n}\n\n", stdout);
409 /* Write insn-preds.c.
410 N.B. the list of headers to include was copied from genrecog; it
411 may not be ideal.
413 FUTURE: Write #line markers referring back to the machine
414 description. (Can't practically do this now since we don't know
415 the line number of the C block - just the line number of the enclosing
416 expression.) */
417 static void
418 write_insn_preds_c (void)
420 struct pred_data *p;
422 printf ("\
423 /* Generated automatically by the program '%s'\n\
424 from the machine description file '%s'. */\n\n", progname, in_fname);
426 puts ("\
427 #include \"config.h\"\n\
428 #include \"system.h\"\n\
429 #include \"coretypes.h\"\n\
430 #include \"tm.h\"\n\
431 #include \"rtl.h\"\n\
432 #include \"tree.h\"\n\
433 #include \"tm_p.h\"\n\
434 #include \"function.h\"\n\
435 #include \"insn-config.h\"\n\
436 #include \"recog.h\"\n\
437 #include \"real.h\"\n\
438 #include \"output.h\"\n\
439 #include \"flags.h\"\n\
440 #include \"hard-reg-set.h\"\n\
441 #include \"resource.h\"\n\
442 #include \"toplev.h\"\n\
443 #include \"reload.h\"\n\
444 #include \"regs.h\"\n");
446 FOR_ALL_PREDICATES (p)
447 write_one_predicate_function (p);
450 /* Argument parsing. */
451 static bool gen_header;
452 static bool
453 parse_option (const char *opt)
455 if (!strcmp (opt, "-h"))
457 gen_header = true;
458 return 1;
460 else
461 return 0;
464 /* Master control. */
466 main (int argc, char **argv)
468 rtx defn;
469 int pattern_lineno, next_insn_code = 0;
471 progname = argv[0];
472 if (argc <= 1)
473 fatal ("no input file name");
474 if (init_md_reader_args_cb (argc, argv, parse_option) != SUCCESS_EXIT_CODE)
475 return FATAL_EXIT_CODE;
477 while ((defn = read_md_rtx (&pattern_lineno, &next_insn_code)) != 0)
479 if (GET_CODE (defn) == DEFINE_PREDICATE
480 || GET_CODE (defn) == DEFINE_SPECIAL_PREDICATE)
481 process_define_predicate (defn);
484 if (gen_header)
485 write_tm_preds_h ();
486 else
487 write_insn_preds_c ();
489 if (have_error || ferror (stdout) || fflush (stdout) || fclose (stdout))
490 return FATAL_EXIT_CODE;
492 return SUCCESS_EXIT_CODE;
495 /* Dummy for debugging purposes. */
496 const char *
497 get_insn_name (int code ATTRIBUTE_UNUSED)
499 return 0;