OSDN Git Service

2004-08-24 Jonathan Wakely <redi@gcc.gnu.org>
[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 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   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);
146 }
147
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.
155
156    The mark is the RTL /v flag, which is true for subexpressions which
157    do *not* perform mode tests.
158 */
159 #define NO_MODE_TEST(EXP) RTX_FLAG (EXP, volatil)
160 static void
161 mark_mode_tests (rtx exp)
162 {
163   switch (GET_CODE (exp))
164     {
165     case MATCH_OPERAND:
166       {
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)
171           NO_MODE_TEST (exp) = 1;
172       }
173       break;
174
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;
180
181     case MATCH_TEST:
182     case NOT:
183       NO_MODE_TEST (exp) = 1;
184       break;
185
186     case AND:
187       mark_mode_tests (XEXP (exp, 0));
188       mark_mode_tests (XEXP (exp, 1));
189
190       NO_MODE_TEST (exp) = (NO_MODE_TEST (XEXP (exp, 0))
191                             && NO_MODE_TEST (XEXP (exp, 1)));
192       break;
193       
194     case IOR:
195       mark_mode_tests (XEXP (exp, 0));
196       mark_mode_tests (XEXP (exp, 1));
197
198       NO_MODE_TEST (exp) = (NO_MODE_TEST (XEXP (exp, 0))
199                             || NO_MODE_TEST (XEXP (exp, 1)));
200       break;
201
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));
208
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;
213
214     default:
215       error ("'%s' cannot be used in a define_predicate expression",
216              GET_RTX_NAME (GET_CODE (exp)));
217     }
218 }
219
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.  */
225
226 static void
227 add_mode_tests (struct pred_data *p)
228 {
229   rtx match_test_exp, and_exp;
230   rtx *pos;
231
232   /* Don't touch special predicates.  */
233   if (p->special)
234     return;
235
236   mark_mode_tests (p->exp);
237
238   /* If the whole expression already tests the mode, we're done.  */
239   if (!NO_MODE_TEST (p->exp))
240     return;
241
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;
246
247   /* It is always correct to rewrite p->exp as
248
249         (and (...) (match_test "mode == VOIDmode || GET_MODE (op) == mode"))
250
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.  */
257
258   pos = &p->exp;
259   for (;;)
260     {
261       rtx subexp = *pos;
262       if (GET_CODE (subexp) == IOR)
263         {
264           if (NO_MODE_TEST (XEXP (subexp, 0))
265               && NO_MODE_TEST (XEXP (subexp, 1)))
266             break;
267           else if (NO_MODE_TEST (XEXP (subexp, 0)))
268             pos = &XEXP (subexp, 0);
269           else if (NO_MODE_TEST (XEXP (subexp, 1)))
270             pos = &XEXP (subexp, 1);
271           else
272             abort ();
273         }
274       else if (GET_CODE (subexp) == IF_THEN_ELSE)
275         {
276           if (NO_MODE_TEST (XEXP (subexp, 0))
277               && NO_MODE_TEST (XEXP (subexp, 1))
278               && NO_MODE_TEST (XEXP (subexp, 2)))
279             break;
280           else if (NO_MODE_TEST (XEXP (subexp, 0))
281                    && NO_MODE_TEST (XEXP (subexp, 1)))
282             /* Must put it on the dependent clause, not the controlling
283                expression, or we change the meaning of the test. */
284             pos = &XEXP (subexp, 1);
285           else if (NO_MODE_TEST (XEXP (subexp, 2)))
286             pos = &XEXP (subexp, 2);
287           else
288             abort ();
289         }
290       else
291         break;
292     }
293
294   XEXP (and_exp, 0) = *pos;
295   *pos = and_exp;
296 }
297
298
299 /* CODES is a list of RTX codes.  Write out an expression which
300    determines whether the operand has one of those codes.  */
301 static void
302 write_match_code (const char *codes)
303 {
304   const char *code;
305
306   while ((code = scan_comma_elt (&codes)) != 0)
307     {
308       fputs ("GET_CODE (op) == ", stdout);
309       while (code < codes)
310         {
311           putchar (TOUPPER (*code));
312           code++;
313         }
314       
315       if (*codes == ',')
316         fputs (" || ", stdout);
317     }
318 }
319
320 /* EXP is an RTL (sub)expression for a predicate.  Recursively
321    descend the expression and write out an equivalent C expression.  */
322 static void
323 write_predicate_expr (const char *name, rtx exp)
324 {
325   switch (GET_CODE (exp))
326     {
327     case AND:
328       putchar ('(');
329       write_predicate_expr (name, XEXP (exp, 0));
330       fputs (") && (", stdout);
331       write_predicate_expr (name, XEXP (exp, 1));
332       putchar (')');
333       break;
334   
335     case IOR:
336       putchar ('(');
337       write_predicate_expr (name, XEXP (exp, 0));
338       fputs (") || (", stdout);
339       write_predicate_expr (name, XEXP (exp, 1));
340       putchar (')');
341       break;
342
343     case NOT:
344       fputs ("!(", stdout);
345       write_predicate_expr (name, XEXP (exp, 0));
346       putchar (')');
347       break;
348
349     case IF_THEN_ELSE:
350       putchar ('(');
351       write_predicate_expr (name, XEXP (exp, 0));
352       fputs (") ? (", stdout);
353       write_predicate_expr (name, XEXP (exp, 1));
354       fputs (") : (", stdout);
355       write_predicate_expr (name, XEXP (exp, 2));
356       putchar (')');
357       break;
358
359     case MATCH_OPERAND:
360       printf ("%s (op, mode)", XSTR (exp, 1));
361       break;
362
363     case MATCH_CODE:
364       write_match_code (XSTR (exp, 0));
365       break;
366
367     case MATCH_TEST:
368       fputs (XSTR (exp, 0), stdout);
369       break;
370
371     default:
372       error ("%s: cannot use '%s' in a predicate expression",
373              name, GET_RTX_NAME (GET_CODE (exp)));
374       putchar ('0');
375     }
376 }
377
378 /* Given a predicate, write out a complete C function to compute it.  */
379 static void
380 write_one_predicate_function (struct pred_data *p)
381 {
382   if (!p->exp)
383     return;
384
385   write_predicate_subfunction (p);
386   add_mode_tests (p);
387
388   /* A normal predicate can legitimately not look at enum machine_mode
389      if it accepts only CONST_INTs and/or CONST_DOUBLEs.  */
390   printf ("int\n%s (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)\n"
391           "{\n  return ",
392           p->name);
393   write_predicate_expr (p->name, p->exp);
394   fputs (";\n}\n\n", stdout);
395 }
396
397 /* Write insn-preds.c.  
398    N.B. the list of headers to include was copied from genrecog; it
399    may not be ideal.
400
401    FUTURE: Write #line markers referring back to the machine
402    description.  (Can't practically do this now since we don't know
403    the line number of the C block - just the line number of the enclosing
404    expression.)  */
405 static void
406 write_insn_preds_c (void)
407 {
408   struct pred_data *p;
409
410   printf ("\
411 /* Generated automatically by the program '%s'\n\
412    from the machine description file '%s'.  */\n\n", progname, in_fname);
413
414   puts ("\
415 #include \"config.h\"\n\
416 #include \"system.h\"\n\
417 #include \"coretypes.h\"\n\
418 #include \"tm.h\"\n\
419 #include \"rtl.h\"\n\
420 #include \"tree.h\"\n\
421 #include \"tm_p.h\"\n\
422 #include \"function.h\"\n\
423 #include \"insn-config.h\"\n\
424 #include \"recog.h\"\n\
425 #include \"real.h\"\n\
426 #include \"output.h\"\n\
427 #include \"flags.h\"\n\
428 #include \"hard-reg-set.h\"\n\
429 #include \"resource.h\"\n\
430 #include \"toplev.h\"\n\
431 #include \"reload.h\"\n");
432
433   FOR_ALL_PREDICATES (p)
434     write_one_predicate_function (p);
435 }
436
437 /* Argument parsing.  */
438 static bool gen_header;
439 static bool
440 parse_option (const char *opt)
441 {
442   if (!strcmp (opt, "-h"))
443     {
444       gen_header = true;
445       return 1;
446     }
447   else
448     return 0;
449 }
450
451 /* Master control.  */
452 int
453 main (int argc, char **argv)
454 {
455   rtx defn;
456   int pattern_lineno, next_insn_code = 0;
457
458   progname = argv[0];
459   if (argc <= 1)
460     fatal ("no input file name");
461   if (init_md_reader_args_cb (argc, argv, parse_option) != SUCCESS_EXIT_CODE)
462     return FATAL_EXIT_CODE;
463
464   while ((defn = read_md_rtx (&pattern_lineno, &next_insn_code)) != 0)
465     {
466       if (GET_CODE (defn) == DEFINE_PREDICATE
467           || GET_CODE (defn) == DEFINE_SPECIAL_PREDICATE)
468         process_define_predicate (defn);
469     }
470
471   if (gen_header)
472     write_tm_preds_h ();
473   else
474     write_insn_preds_c ();
475
476   if (have_error || ferror (stdout) || fflush (stdout) || fclose (stdout))
477     return FATAL_EXIT_CODE;
478
479   return SUCCESS_EXIT_CODE;
480 }
481
482 /* Dummy for debugging purposes.  */
483 const char *
484 get_insn_name (int code ATTRIBUTE_UNUSED)
485 {
486   return 0;
487 }