1 /* Generate from machine description:
2 - prototype declarations for operand predicates (tm-preds.h)
3 - function definitions of operand predicates, if defined new-style
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)
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. */
26 #include "coretypes.h"
30 #include "gensupport.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. */
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));
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
)
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. */
61 write_tm_preds_h (void)
66 /* Generated automatically by the program '%s'\n\
67 from the machine description file '%s'. */\n\n", progname
, in_fname
);
70 #ifndef GCC_TM_PREDS_H\n\
71 #define GCC_TM_PREDS_H\n\
73 #ifdef HAVE_MACHINE_MODES");
75 FOR_ALL_PREDICATES (p
)
76 printf ("extern int %s (rtx, enum machine_mode);\n", p
->name
);
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)
92 return REG_POINTER (op);
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. */
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')
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
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
;
138 printf ("static inline int\n"
139 "%s_1 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)\n",
141 print_rtx_ptr_loc (p
->c_block
);
142 if (p
->c_block
[0] == '{')
143 fputs (p
->c_block
, stdout
);
145 printf ("{\n %s\n}", p
->c_block
);
146 fputs ("\n\n", stdout
);
149 /* Given an RTL expression EXP, find all subexpressions which we may
150 assume to perform mode tests. Normal MATCH_OPERAND does;
151 MATCH_CODE does if and only if it accepts CONST_INT or
152 CONST_DOUBLE; and we have to assume that MATCH_TEST does not.
153 These combine in almost-boolean fashion - the only exception is
154 that (not X) must be assumed not to perform a mode test, whether or
157 The mark is the RTL /v flag, which is true for subexpressions which
158 do *not* perform mode tests.
160 #define NO_MODE_TEST(EXP) RTX_FLAG (EXP, volatil)
162 mark_mode_tests (rtx exp
)
164 switch (GET_CODE (exp
))
168 struct pred_data
*p
= lookup_predicate (XSTR (exp
, 1));
170 error ("reference to undefined predicate '%s'", XSTR (exp
, 1));
171 else if (p
->special
|| GET_MODE (exp
) != VOIDmode
)
172 NO_MODE_TEST (exp
) = 1;
177 if (!strstr (XSTR (exp
, 0), "const_int")
178 && !strstr (XSTR (exp
, 0), "const_double"))
179 NO_MODE_TEST (exp
) = 1;
184 NO_MODE_TEST (exp
) = 1;
188 mark_mode_tests (XEXP (exp
, 0));
189 mark_mode_tests (XEXP (exp
, 1));
191 NO_MODE_TEST (exp
) = (NO_MODE_TEST (XEXP (exp
, 0))
192 && NO_MODE_TEST (XEXP (exp
, 1)));
196 mark_mode_tests (XEXP (exp
, 0));
197 mark_mode_tests (XEXP (exp
, 1));
199 NO_MODE_TEST (exp
) = (NO_MODE_TEST (XEXP (exp
, 0))
200 || NO_MODE_TEST (XEXP (exp
, 1)));
204 /* A ? B : C does a mode test if (one of A and B) does a mode
205 test, and C does too. */
206 mark_mode_tests (XEXP (exp
, 0));
207 mark_mode_tests (XEXP (exp
, 1));
208 mark_mode_tests (XEXP (exp
, 2));
210 NO_MODE_TEST (exp
) = ((NO_MODE_TEST (XEXP (exp
, 0))
211 && NO_MODE_TEST (XEXP (exp
, 1)))
212 || NO_MODE_TEST (XEXP (exp
, 2)));
216 error ("'%s' cannot be used in a define_predicate expression",
217 GET_RTX_NAME (GET_CODE (exp
)));
221 /* Given a predicate, work out where in its RTL expression to add
222 tests for proper modes. Special predicates do not get any such
223 tests. We try to avoid adding tests when we don't have to; in
224 particular, other normal predicates can be counted on to do it for
228 add_mode_tests (struct pred_data
*p
)
230 rtx match_test_exp
, and_exp
;
233 /* Don't touch special predicates. */
237 mark_mode_tests (p
->exp
);
239 /* If the whole expression already tests the mode, we're done. */
240 if (!NO_MODE_TEST (p
->exp
))
243 match_test_exp
= rtx_alloc (MATCH_TEST
);
244 XSTR (match_test_exp
, 0) = "mode == VOIDmode || GET_MODE (op) == mode";
245 and_exp
= rtx_alloc (AND
);
246 XEXP (and_exp
, 1) = match_test_exp
;
248 /* It is always correct to rewrite p->exp as
250 (and (...) (match_test "mode == VOIDmode || GET_MODE (op) == mode"))
252 but there are a couple forms where we can do better. If the
253 top-level pattern is an IOR, and one of the two branches does test
254 the mode, we can wrap just the branch that doesn't. Likewise, if
255 we have an IF_THEN_ELSE, and one side of it tests the mode, we can
256 wrap just the side that doesn't. And, of course, we can repeat this
257 descent as many times as it works. */
264 switch (GET_CODE (subexp
))
268 int test0
= NO_MODE_TEST (XEXP (subexp
, 0));
269 int test1
= NO_MODE_TEST (XEXP (subexp
, 1));
271 gcc_assert (test0
|| test1
);
275 pos
= test0
? &XEXP (subexp
, 0) : &XEXP (subexp
, 1);
281 int test0
= NO_MODE_TEST (XEXP (subexp
, 0));
282 int test1
= NO_MODE_TEST (XEXP (subexp
, 1));
283 int test2
= NO_MODE_TEST (XEXP (subexp
, 2));
285 gcc_assert ((test0
&& test1
) || test2
);
287 if (test0
&& test1
&& test2
)
290 /* Must put it on the dependent clause, not the
291 controlling expression, or we change the meaning of
293 pos
= &XEXP (subexp
, 1);
295 pos
= &XEXP (subexp
, 2);
304 XEXP (and_exp
, 0) = *pos
;
309 /* CODES is a list of RTX codes. Write out an expression which
310 determines whether the operand has one of those codes. */
312 write_match_code (const char *codes
)
316 while ((code
= scan_comma_elt (&codes
)) != 0)
318 fputs ("GET_CODE (op) == ", stdout
);
321 putchar (TOUPPER (*code
));
326 fputs (" || ", stdout
);
330 /* EXP is an RTL (sub)expression for a predicate. Recursively
331 descend the expression and write out an equivalent C expression. */
333 write_predicate_expr (const char *name
, rtx exp
)
335 switch (GET_CODE (exp
))
339 write_predicate_expr (name
, XEXP (exp
, 0));
340 fputs (") && (", stdout
);
341 write_predicate_expr (name
, XEXP (exp
, 1));
347 write_predicate_expr (name
, XEXP (exp
, 0));
348 fputs (") || (", stdout
);
349 write_predicate_expr (name
, XEXP (exp
, 1));
354 fputs ("!(", stdout
);
355 write_predicate_expr (name
, XEXP (exp
, 0));
361 write_predicate_expr (name
, XEXP (exp
, 0));
362 fputs (") ? (", stdout
);
363 write_predicate_expr (name
, XEXP (exp
, 1));
364 fputs (") : (", stdout
);
365 write_predicate_expr (name
, XEXP (exp
, 2));
370 if (GET_MODE (exp
) == VOIDmode
)
371 printf ("%s (op, mode)", XSTR (exp
, 1));
373 printf ("%s (op, %smode)", XSTR (exp
, 1), mode_name
[GET_MODE (exp
)]);
377 write_match_code (XSTR (exp
, 0));
381 print_c_condition (XSTR (exp
, 0));
385 error ("%s: cannot use '%s' in a predicate expression",
386 name
, GET_RTX_NAME (GET_CODE (exp
)));
391 /* Given a predicate, write out a complete C function to compute it. */
393 write_one_predicate_function (struct pred_data
*p
)
398 write_predicate_subfunction (p
);
401 /* A normal predicate can legitimately not look at enum machine_mode
402 if it accepts only CONST_INTs and/or CONST_DOUBLEs. */
403 printf ("int\n%s (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)\n"
406 write_predicate_expr (p
->name
, p
->exp
);
407 fputs (";\n}\n\n", stdout
);
410 /* Write insn-preds.c.
411 N.B. the list of headers to include was copied from genrecog; it
414 FUTURE: Write #line markers referring back to the machine
415 description. (Can't practically do this now since we don't know
416 the line number of the C block - just the line number of the enclosing
419 write_insn_preds_c (void)
424 /* Generated automatically by the program '%s'\n\
425 from the machine description file '%s'. */\n\n", progname
, in_fname
);
428 #include \"config.h\"\n\
429 #include \"system.h\"\n\
430 #include \"coretypes.h\"\n\
432 #include \"rtl.h\"\n\
433 #include \"tree.h\"\n\
434 #include \"tm_p.h\"\n\
435 #include \"function.h\"\n\
436 #include \"insn-config.h\"\n\
437 #include \"recog.h\"\n\
438 #include \"real.h\"\n\
439 #include \"output.h\"\n\
440 #include \"flags.h\"\n\
441 #include \"hard-reg-set.h\"\n\
442 #include \"resource.h\"\n\
443 #include \"toplev.h\"\n\
444 #include \"reload.h\"\n\
445 #include \"regs.h\"\n");
447 FOR_ALL_PREDICATES (p
)
448 write_one_predicate_function (p
);
451 /* Argument parsing. */
452 static bool gen_header
;
454 parse_option (const char *opt
)
456 if (!strcmp (opt
, "-h"))
465 /* Master control. */
467 main (int argc
, char **argv
)
470 int pattern_lineno
, next_insn_code
= 0;
474 fatal ("no input file name");
475 if (init_md_reader_args_cb (argc
, argv
, parse_option
) != SUCCESS_EXIT_CODE
)
476 return FATAL_EXIT_CODE
;
478 while ((defn
= read_md_rtx (&pattern_lineno
, &next_insn_code
)) != 0)
480 if (GET_CODE (defn
) == DEFINE_PREDICATE
481 || GET_CODE (defn
) == DEFINE_SPECIAL_PREDICATE
)
482 process_define_predicate (defn
);
488 write_insn_preds_c ();
490 if (have_error
|| ferror (stdout
) || fflush (stdout
) || fclose (stdout
))
491 return FATAL_EXIT_CODE
;
493 return SUCCESS_EXIT_CODE
;
496 /* Dummy for debugging purposes. */
498 get_insn_name (int code ATTRIBUTE_UNUSED
)