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
7This file is part of GCC.
8
9GCC is free software; you can redistribute it and/or modify
10it under the terms of the GNU General Public License as published by
11the Free Software Foundation; either version 2, or (at your option)
12any later version.
13
14GCC is distributed in the hope that it will be useful,
15but WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17GNU General Public License for more details.
18
19You should have received a copy of the GNU General Public License
20along with GCC; see the file COPYING.  If not, write to
21the Free Software Foundation, 51 Franklin Street, Fifth Floor,
22Boston, 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.  */
36static void
37process_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.  */
60static void
61write_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
112static void
113write_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 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)
161static void
162mark_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
227static void
228add_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.  */
311static void
312write_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.  */
332static void
333write_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.  */
392static void
393write_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.)  */
418static void
419write_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.  */
452static bool gen_header;
453static bool
454parse_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.  */
466int
467main (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.  */
497const char *
498get_insn_name (int code ATTRIBUTE_UNUSED)
499{
500  return 0;
501}
502