OSDN Git Service

Oops - forgot to include ChangeLog entry for m32r patch
[pf3gnuchains/gcc-fork.git] / gcc / genpreds.c
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.
6
7 This file is part of GCC.
8
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.
13
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.
18
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.  */
23
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"
32
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)
38 {
39   struct pred_data *pred;
40   if (XEXP (defn, 1) == 0)
41     {
42       error ("%s: must give a predicate expression", XSTR (defn, 0));
43       return;
44     }
45
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);
50
51   if (GET_CODE (defn) == DEFINE_SPECIAL_PREDICATE)
52     pred->special = true;
53
54   add_predicate (pred);
55 }
56
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)
62 {
63   struct pred_data *p;
64
65   printf ("\
66 /* Generated automatically by the program '%s'\n\
67    from the machine description file '%s'.  */\n\n", progname, in_fname);
68
69   puts ("\
70 #ifndef GCC_TM_PREDS_H\n\
71 #define GCC_TM_PREDS_H\n\
72 \n\
73 #ifdef HAVE_MACHINE_MODES");
74
75   FOR_ALL_PREDICATES (p)
76     printf ("extern int %s (rtx, enum machine_mode);\n", p->name);
77
78   puts ("\
79 #endif /* HAVE_MACHINE_MODES */\n\
80 #endif /* tm-preds.h */");
81 }
82
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,
86
87        (define_predicate "basereg_operand"
88          (match_operand 0 "register_operand")
89        {
90          if (GET_CODE (op) == SUBREG)
91            op = SUBREG_REG (op);
92          return REG_POINTER (op);
93        })
94
95    becomes
96
97        static inline int basereg_operand_1(rtx op, enum machine_mode mode)
98        {
99          if (GET_CODE (op) == SUBREG)
100            op = SUBREG_REG (op);
101          return REG_POINTER (op);
102        }
103
104        (define_predicate "basereg_operand"
105          (and (match_operand 0 "register_operand")
106               (match_test "basereg_operand_1 (op, mode)")))
107
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.  */
110
111    
112 static void
113 write_predicate_subfunction (struct pred_data *p)
114 {
115   const char *match_test_str;
116   rtx match_test_exp, and_exp;
117
118   if (p->c_block[0] == '\0')
119     return;
120
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);
126
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;
131
132   and_exp = rtx_alloc (AND);
133   XEXP (and_exp, 0) = p->exp;
134   XEXP (and_exp, 1) = match_test_exp;
135
136   p->exp = and_exp;
137
138   printf ("static inline int\n"
139           "%s_1 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)\n",
140           p->name);
141   print_rtx_ptr_loc (p->c_block);
142   if (p->c_block[0] == '{')
143     fputs (p->c_block, stdout);
144   else
145     printf ("{\n  %s\n}", p->c_block);
146   fputs ("\n\n", stdout);
147 }
148
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
155    not X does.
156
157    The mark is the RTL /v flag, which is true for subexpressions which
158    do *not* perform mode tests.
159 */
160 #define NO_MODE_TEST(EXP) RTX_FLAG (EXP, volatil)
161 static void
162 mark_mode_tests (rtx exp)
163 {
164   switch (GET_CODE (exp))
165     {
166     case MATCH_OPERAND:
167       {
168         struct pred_data *p = lookup_predicate (XSTR (exp, 1));
169         if (!p)
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;
173       }
174       break;
175
176     case MATCH_CODE:
177       if (!strstr (XSTR (exp, 0), "const_int")
178           && !strstr (XSTR (exp, 0), "const_double"))
179         NO_MODE_TEST (exp) = 1;
180       break;
181
182     case MATCH_TEST:
183     case NOT:
184       NO_MODE_TEST (exp) = 1;
185       break;
186
187     case AND:
188       mark_mode_tests (XEXP (exp, 0));
189       mark_mode_tests (XEXP (exp, 1));
190
191       NO_MODE_TEST (exp) = (NO_MODE_TEST (XEXP (exp, 0))
192                             && NO_MODE_TEST (XEXP (exp, 1)));
193       break;
194       
195     case IOR:
196       mark_mode_tests (XEXP (exp, 0));
197       mark_mode_tests (XEXP (exp, 1));
198
199       NO_MODE_TEST (exp) = (NO_MODE_TEST (XEXP (exp, 0))
200                             || NO_MODE_TEST (XEXP (exp, 1)));
201       break;
202
203     case IF_THEN_ELSE:
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));
209
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)));
213       break;
214
215     default:
216       error ("'%s' cannot be used in a define_predicate expression",
217              GET_RTX_NAME (GET_CODE (exp)));
218     }
219 }
220
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
225    us.  */
226
227 static void
228 add_mode_tests (struct pred_data *p)
229 {
230   rtx match_test_exp, and_exp;
231   rtx *pos;
232
233   /* Don't touch special predicates.  */
234   if (p->special)
235     return;
236
237   mark_mode_tests (p->exp);
238
239   /* If the whole expression already tests the mode, we're done.  */
240   if (!NO_MODE_TEST (p->exp))
241     return;
242
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;
247
248   /* It is always correct to rewrite p->exp as
249
250         (and (...) (match_test "mode == VOIDmode || GET_MODE (op) == mode"))
251
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.  */
258
259   pos = &p->exp;
260   for (;;)
261     {
262       rtx subexp = *pos;
263
264       switch (GET_CODE (subexp))
265         {
266         case IOR:
267           {
268             int test0 = NO_MODE_TEST (XEXP (subexp, 0));
269             int test1 = NO_MODE_TEST (XEXP (subexp, 1));
270             
271             gcc_assert (test0 || test1);
272             
273             if (test0 && test1)
274               goto break_loop;
275             pos = test0 ? &XEXP (subexp, 0) : &XEXP (subexp, 1);
276           }
277           break;
278           
279         case IF_THEN_ELSE:
280           {
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));
284             
285             gcc_assert ((test0 && test1) || test2);
286             
287             if (test0 && test1 && test2)
288               goto break_loop;
289             if (test0 && test1)
290               /* Must put it on the dependent clause, not the
291                  controlling expression, or we change the meaning of
292                  the test.  */
293               pos = &XEXP (subexp, 1);
294             else
295               pos = &XEXP (subexp, 2);
296           }
297           break;
298           
299         default:
300           goto break_loop;
301         }
302     }
303  break_loop:
304   XEXP (and_exp, 0) = *pos;
305   *pos = and_exp;
306 }
307
308
309 /* CODES is a list of RTX codes.  Write out an expression which
310    determines whether the operand has one of those codes.  */
311 static void
312 write_match_code (const char *codes)
313 {
314   const char *code;
315
316   while ((code = scan_comma_elt (&codes)) != 0)
317     {
318       fputs ("GET_CODE (op) == ", stdout);
319       while (code < codes)
320         {
321           putchar (TOUPPER (*code));
322           code++;
323         }
324       
325       if (*codes == ',')
326         fputs (" || ", stdout);
327     }
328 }
329
330 /* EXP is an RTL (sub)expression for a predicate.  Recursively
331    descend the expression and write out an equivalent C expression.  */
332 static void
333 write_predicate_expr (const char *name, rtx exp)
334 {
335   switch (GET_CODE (exp))
336     {
337     case AND:
338       putchar ('(');
339       write_predicate_expr (name, XEXP (exp, 0));
340       fputs (") && (", stdout);
341       write_predicate_expr (name, XEXP (exp, 1));
342       putchar (')');
343       break;
344   
345     case IOR:
346       putchar ('(');
347       write_predicate_expr (name, XEXP (exp, 0));
348       fputs (") || (", stdout);
349       write_predicate_expr (name, XEXP (exp, 1));
350       putchar (')');
351       break;
352
353     case NOT:
354       fputs ("!(", stdout);
355       write_predicate_expr (name, XEXP (exp, 0));
356       putchar (')');
357       break;
358
359     case IF_THEN_ELSE:
360       putchar ('(');
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));
366       putchar (')');
367       break;
368
369     case MATCH_OPERAND:
370       if (GET_MODE (exp) == VOIDmode)
371         printf ("%s (op, mode)", XSTR (exp, 1));
372       else
373         printf ("%s (op, %smode)", XSTR (exp, 1), mode_name[GET_MODE (exp)]);
374       break;
375
376     case MATCH_CODE:
377       write_match_code (XSTR (exp, 0));
378       break;
379
380     case MATCH_TEST:
381       print_c_condition (XSTR (exp, 0));
382       break;
383
384     default:
385       error ("%s: cannot use '%s' in a predicate expression",
386              name, GET_RTX_NAME (GET_CODE (exp)));
387       putchar ('0');
388     }
389 }
390
391 /* Given a predicate, write out a complete C function to compute it.  */
392 static void
393 write_one_predicate_function (struct pred_data *p)
394 {
395   if (!p->exp)
396     return;
397
398   write_predicate_subfunction (p);
399   add_mode_tests (p);
400
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"
404           "{\n  return ",
405           p->name);
406   write_predicate_expr (p->name, p->exp);
407   fputs (";\n}\n\n", stdout);
408 }
409
410 /* Write insn-preds.c.  
411    N.B. the list of headers to include was copied from genrecog; it
412    may not be ideal.
413
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
417    expression.)  */
418 static void
419 write_insn_preds_c (void)
420 {
421   struct pred_data *p;
422
423   printf ("\
424 /* Generated automatically by the program '%s'\n\
425    from the machine description file '%s'.  */\n\n", progname, in_fname);
426
427   puts ("\
428 #include \"config.h\"\n\
429 #include \"system.h\"\n\
430 #include \"coretypes.h\"\n\
431 #include \"tm.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");
446
447   FOR_ALL_PREDICATES (p)
448     write_one_predicate_function (p);
449 }
450
451 /* Argument parsing.  */
452 static bool gen_header;
453 static bool
454 parse_option (const char *opt)
455 {
456   if (!strcmp (opt, "-h"))
457     {
458       gen_header = true;
459       return 1;
460     }
461   else
462     return 0;
463 }
464
465 /* Master control.  */
466 int
467 main (int argc, char **argv)
468 {
469   rtx defn;
470   int pattern_lineno, next_insn_code = 0;
471
472   progname = argv[0];
473   if (argc <= 1)
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;
477
478   while ((defn = read_md_rtx (&pattern_lineno, &next_insn_code)) != 0)
479     {
480       if (GET_CODE (defn) == DEFINE_PREDICATE
481           || GET_CODE (defn) == DEFINE_SPECIAL_PREDICATE)
482         process_define_predicate (defn);
483     }
484
485   if (gen_header)
486     write_tm_preds_h ();
487   else
488     write_insn_preds_c ();
489
490   if (have_error || ferror (stdout) || fflush (stdout) || fclose (stdout))
491     return FATAL_EXIT_CODE;
492
493   return SUCCESS_EXIT_CODE;
494 }
495
496 /* Dummy for debugging purposes.  */
497 const char *
498 get_insn_name (int code ATTRIBUTE_UNUSED)
499 {
500   return 0;
501 }