OSDN Git Service

r110130@banpei: zack | 2006-01-22 14:52:43 -0800
[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, 51 Franklin Street, Fifth Floor,
22 Boston, MA 02110-1301, 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 = XCNEW (struct pred_data);
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 = XOBFINISH (rtl_obstack, const char *);
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 it applies to the whole expression and accepts
152    CONST_INT or CONST_DOUBLE; and we have to assume that MATCH_TEST
153    does not.  These combine in almost-boolean fashion - the only
154    exception is that (not X) must be assumed not to perform a mode
155    test, whether or 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 (XSTR (exp, 1)[0] != '\0'
178           || (!strstr (XSTR (exp, 0), "const_int")
179               && !strstr (XSTR (exp, 0), "const_double")))
180         NO_MODE_TEST (exp) = 1;
181       break;
182
183     case MATCH_TEST:
184     case NOT:
185       NO_MODE_TEST (exp) = 1;
186       break;
187
188     case AND:
189       mark_mode_tests (XEXP (exp, 0));
190       mark_mode_tests (XEXP (exp, 1));
191
192       NO_MODE_TEST (exp) = (NO_MODE_TEST (XEXP (exp, 0))
193                             && NO_MODE_TEST (XEXP (exp, 1)));
194       break;
195       
196     case IOR:
197       mark_mode_tests (XEXP (exp, 0));
198       mark_mode_tests (XEXP (exp, 1));
199
200       NO_MODE_TEST (exp) = (NO_MODE_TEST (XEXP (exp, 0))
201                             || NO_MODE_TEST (XEXP (exp, 1)));
202       break;
203
204     case IF_THEN_ELSE:
205       /* A ? B : C does a mode test if (one of A and B) does a mode
206          test, and C does too.  */
207       mark_mode_tests (XEXP (exp, 0));
208       mark_mode_tests (XEXP (exp, 1));
209       mark_mode_tests (XEXP (exp, 2));
210
211       NO_MODE_TEST (exp) = ((NO_MODE_TEST (XEXP (exp, 0))
212                              && NO_MODE_TEST (XEXP (exp, 1)))
213                             || NO_MODE_TEST (XEXP (exp, 2)));
214       break;
215
216     default:
217       error ("'%s' cannot be used in a define_predicate expression",
218              GET_RTX_NAME (GET_CODE (exp)));
219     }
220 }
221
222 /* Given a predicate, work out where in its RTL expression to add
223    tests for proper modes.  Special predicates do not get any such
224    tests.  We try to avoid adding tests when we don't have to; in
225    particular, other normal predicates can be counted on to do it for
226    us.  */
227
228 static void
229 add_mode_tests (struct pred_data *p)
230 {
231   rtx match_test_exp, and_exp;
232   rtx *pos;
233
234   /* Don't touch special predicates.  */
235   if (p->special)
236     return;
237
238   mark_mode_tests (p->exp);
239
240   /* If the whole expression already tests the mode, we're done.  */
241   if (!NO_MODE_TEST (p->exp))
242     return;
243
244   match_test_exp = rtx_alloc (MATCH_TEST);
245   XSTR (match_test_exp, 0) = "mode == VOIDmode || GET_MODE (op) == mode";
246   and_exp = rtx_alloc (AND);
247   XEXP (and_exp, 1) = match_test_exp;
248
249   /* It is always correct to rewrite p->exp as
250
251         (and (...) (match_test "mode == VOIDmode || GET_MODE (op) == mode"))
252
253      but there are a couple forms where we can do better.  If the
254      top-level pattern is an IOR, and one of the two branches does test
255      the mode, we can wrap just the branch that doesn't.  Likewise, if
256      we have an IF_THEN_ELSE, and one side of it tests the mode, we can
257      wrap just the side that doesn't.  And, of course, we can repeat this
258      descent as many times as it works.  */
259
260   pos = &p->exp;
261   for (;;)
262     {
263       rtx subexp = *pos;
264
265       switch (GET_CODE (subexp))
266         {
267         case IOR:
268           {
269             int test0 = NO_MODE_TEST (XEXP (subexp, 0));
270             int test1 = NO_MODE_TEST (XEXP (subexp, 1));
271             
272             gcc_assert (test0 || test1);
273             
274             if (test0 && test1)
275               goto break_loop;
276             pos = test0 ? &XEXP (subexp, 0) : &XEXP (subexp, 1);
277           }
278           break;
279           
280         case IF_THEN_ELSE:
281           {
282             int test0 = NO_MODE_TEST (XEXP (subexp, 0));
283             int test1 = NO_MODE_TEST (XEXP (subexp, 1));
284             int test2 = NO_MODE_TEST (XEXP (subexp, 2));
285             
286             gcc_assert ((test0 && test1) || test2);
287             
288             if (test0 && test1 && test2)
289               goto break_loop;
290             if (test0 && test1)
291               /* Must put it on the dependent clause, not the
292                  controlling expression, or we change the meaning of
293                  the test.  */
294               pos = &XEXP (subexp, 1);
295             else
296               pos = &XEXP (subexp, 2);
297           }
298           break;
299           
300         default:
301           goto break_loop;
302         }
303     }
304  break_loop:
305   XEXP (and_exp, 0) = *pos;
306   *pos = and_exp;
307 }
308
309 /* PATH is a string describing a path from the root of an RTL
310    expression to an inner subexpression to be tested.  Output
311    code which computes the subexpression from the variable
312    holding the root of the expression.  */
313 static void
314 write_extract_subexp (const char *path)
315 {
316   int len = strlen (path);
317   int i;
318
319   /* We first write out the operations (XEXP or XVECEXP) in reverse
320      order, then write "op", then the indices in forward order.  */
321   for (i = len - 1; i >= 0; i--)
322     {
323       if (ISLOWER (path[i]))
324         fputs ("XVECEXP (", stdout);
325       else if (ISDIGIT (path[i]))
326         fputs ("XEXP (", stdout);
327       else
328         {
329           error ("bad character in path string '%s'", path);
330           return;
331         }
332     }
333
334   fputs ("op", stdout);
335
336   for (i = 0; i < len; i++)
337     {
338       if (ISLOWER (path[i]))
339         printf (", 0, %d)", path[i] - 'a');
340       else if (ISDIGIT (path[i]))
341         printf (", %d)", path[i] - '0');
342       else
343         gcc_unreachable ();
344     }
345 }
346
347 /* CODES is a list of RTX codes.  Write out an expression which
348    determines whether the operand has one of those codes.  */
349 static void
350 write_match_code (const char *path, const char *codes)
351 {
352   const char *code;
353
354   while ((code = scan_comma_elt (&codes)) != 0)
355     {
356       fputs ("GET_CODE (", stdout);
357       write_extract_subexp (path);
358       fputs (") == ", stdout);
359       while (code < codes)
360         {
361           putchar (TOUPPER (*code));
362           code++;
363         }
364       
365       if (*codes == ',')
366         fputs (" || ", stdout);
367     }
368 }
369
370 /* EXP is an RTL (sub)expression for a predicate.  Recursively
371    descend the expression and write out an equivalent C expression.  */
372 static void
373 write_predicate_expr (const char *name, rtx exp)
374 {
375   switch (GET_CODE (exp))
376     {
377     case AND:
378       putchar ('(');
379       write_predicate_expr (name, XEXP (exp, 0));
380       fputs (") && (", stdout);
381       write_predicate_expr (name, XEXP (exp, 1));
382       putchar (')');
383       break;
384   
385     case IOR:
386       putchar ('(');
387       write_predicate_expr (name, XEXP (exp, 0));
388       fputs (") || (", stdout);
389       write_predicate_expr (name, XEXP (exp, 1));
390       putchar (')');
391       break;
392
393     case NOT:
394       fputs ("!(", stdout);
395       write_predicate_expr (name, XEXP (exp, 0));
396       putchar (')');
397       break;
398
399     case IF_THEN_ELSE:
400       putchar ('(');
401       write_predicate_expr (name, XEXP (exp, 0));
402       fputs (") ? (", stdout);
403       write_predicate_expr (name, XEXP (exp, 1));
404       fputs (") : (", stdout);
405       write_predicate_expr (name, XEXP (exp, 2));
406       putchar (')');
407       break;
408
409     case MATCH_OPERAND:
410       if (GET_MODE (exp) == VOIDmode)
411         printf ("%s (op, mode)", XSTR (exp, 1));
412       else
413         printf ("%s (op, %smode)", XSTR (exp, 1), mode_name[GET_MODE (exp)]);
414       break;
415
416     case MATCH_CODE:
417       write_match_code (XSTR (exp, 1), XSTR (exp, 0));
418       break;
419
420     case MATCH_TEST:
421       print_c_condition (XSTR (exp, 0));
422       break;
423
424     default:
425       error ("%s: cannot use '%s' in a predicate expression",
426              name, GET_RTX_NAME (GET_CODE (exp)));
427       putchar ('0');
428     }
429 }
430
431 /* Given a predicate, write out a complete C function to compute it.  */
432 static void
433 write_one_predicate_function (struct pred_data *p)
434 {
435   if (!p->exp)
436     return;
437
438   write_predicate_subfunction (p);
439   add_mode_tests (p);
440
441   /* A normal predicate can legitimately not look at enum machine_mode
442      if it accepts only CONST_INTs and/or CONST_DOUBLEs.  */
443   printf ("int\n%s (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)\n"
444           "{\n  return ",
445           p->name);
446   write_predicate_expr (p->name, p->exp);
447   fputs (";\n}\n\n", stdout);
448 }
449
450 /* Write insn-preds.c.  
451    N.B. the list of headers to include was copied from genrecog; it
452    may not be ideal.
453
454    FUTURE: Write #line markers referring back to the machine
455    description.  (Can't practically do this now since we don't know
456    the line number of the C block - just the line number of the enclosing
457    expression.)  */
458 static void
459 write_insn_preds_c (void)
460 {
461   struct pred_data *p;
462
463   printf ("\
464 /* Generated automatically by the program '%s'\n\
465    from the machine description file '%s'.  */\n\n", progname, in_fname);
466
467   puts ("\
468 #include \"config.h\"\n\
469 #include \"system.h\"\n\
470 #include \"coretypes.h\"\n\
471 #include \"tm.h\"\n\
472 #include \"rtl.h\"\n\
473 #include \"tree.h\"\n\
474 #include \"tm_p.h\"\n\
475 #include \"function.h\"\n\
476 #include \"insn-config.h\"\n\
477 #include \"recog.h\"\n\
478 #include \"real.h\"\n\
479 #include \"output.h\"\n\
480 #include \"flags.h\"\n\
481 #include \"hard-reg-set.h\"\n\
482 #include \"resource.h\"\n\
483 #include \"toplev.h\"\n\
484 #include \"reload.h\"\n\
485 #include \"regs.h\"\n");
486
487   FOR_ALL_PREDICATES (p)
488     write_one_predicate_function (p);
489 }
490
491 /* Argument parsing.  */
492 static bool gen_header;
493 static bool
494 parse_option (const char *opt)
495 {
496   if (!strcmp (opt, "-h"))
497     {
498       gen_header = true;
499       return 1;
500     }
501   else
502     return 0;
503 }
504
505 /* Master control.  */
506 int
507 main (int argc, char **argv)
508 {
509   rtx defn;
510   int pattern_lineno, next_insn_code = 0;
511
512   progname = argv[0];
513   if (argc <= 1)
514     fatal ("no input file name");
515   if (init_md_reader_args_cb (argc, argv, parse_option) != SUCCESS_EXIT_CODE)
516     return FATAL_EXIT_CODE;
517
518   while ((defn = read_md_rtx (&pattern_lineno, &next_insn_code)) != 0)
519     {
520       if (GET_CODE (defn) == DEFINE_PREDICATE
521           || GET_CODE (defn) == DEFINE_SPECIAL_PREDICATE)
522         process_define_predicate (defn);
523     }
524
525   if (gen_header)
526     write_tm_preds_h ();
527   else
528     write_insn_preds_c ();
529
530   if (have_error || ferror (stdout) || fflush (stdout) || fclose (stdout))
531     return FATAL_EXIT_CODE;
532
533   return SUCCESS_EXIT_CODE;
534 }