genconditions.c revision 132718
1117395Skan/* Process machine description and calculate constant conditions.
2132718Skan   Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
3117395Skan
4132718Skan   This file is part of GCC.
5117395Skan
6132718Skan   GCC is free software; you can redistribute it and/or modify
7117395Skan   it under the terms of the GNU General Public License as published by
8117395Skan   the Free Software Foundation; either version 2, or (at your option)
9117395Skan   any later version.
10117395Skan
11132718Skan   GCC is distributed in the hope that it will be useful,
12117395Skan   but WITHOUT ANY WARRANTY; without even the implied warranty of
13117395Skan   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14117395Skan   GNU General Public License for more details.
15117395Skan
16117395Skan   You should have received a copy of the GNU General Public License
17132718Skan   along with GCC; see the file COPYING.  If not, write to
18117395Skan   the Free Software Foundation, 59 Temple Place - Suite 330,
19117395Skan   Boston, MA 02111-1307, USA.  */
20117395Skan
21117395Skan/* In a machine description, all of the insn patterns - define_insn,
22117395Skan   define_expand, define_split, define_peephole, define_peephole2 -
23117395Skan   contain an optional C expression which makes the final decision
24117395Skan   about whether or not this pattern is usable.  That expression may
25117395Skan   turn out to be always false when the compiler is built.  If it is,
26117395Skan   most of the programs that generate code from the machine
27117395Skan   description can simply ignore the entire pattern.  */
28117395Skan
29132718Skan#include "bconfig.h"
30117395Skan#include "system.h"
31132718Skan#include "coretypes.h"
32132718Skan#include "tm.h"
33117395Skan#include "rtl.h"
34117395Skan#include "errors.h"
35117395Skan#include "hashtab.h"
36117395Skan#include "gensupport.h"
37117395Skan
38132718Skan/* so we can include except.h in the generated file.  */
39117395Skanstatic int saw_eh_return;
40117395Skan
41117395Skanstatic htab_t condition_table;
42117395Skan
43132718Skanstatic void add_condition	(const char *);
44132718Skanstatic void write_header	(void);
45132718Skanstatic void write_conditions	(void);
46132718Skanstatic int write_one_condition	(void **, void *);
47117395Skan
48117395Skan/* Record the C test expression EXPR in the condition_table.
49117395Skan   Duplicates clobber previous entries, which leaks memory, but
50117395Skan   we don't care for this application.  */
51117395Skan
52117395Skanstatic void
53132718Skanadd_condition (const char *expr)
54117395Skan{
55117395Skan  struct c_test *test;
56117395Skan
57117395Skan  if (expr[0] == 0)
58117395Skan    return;
59117395Skan
60132718Skan  test = xmalloc (sizeof (struct c_test));
61117395Skan  test->expr = expr;
62117395Skan
63117395Skan  *(htab_find_slot (condition_table, test, INSERT)) = test;
64117395Skan}
65117395Skan
66117395Skan/* Generate the header for insn-conditions.c.  */
67117395Skan
68117395Skanstatic void
69132718Skanwrite_header (void)
70117395Skan{
71117395Skan  puts ("\
72117395Skan/* Generated automatically by the program `genconditions' from the target\n\
73117395Skan   machine description file.  */\n\
74117395Skan\n\
75132718Skan#include \"bconfig.h\"\n\
76117395Skan#include \"insn-constants.h\"\n");
77117395Skan
78117395Skan  puts ("\
79117395Skan/* Do not allow checking to confuse the issue.  */\n\
80117395Skan#undef ENABLE_CHECKING\n\
81117395Skan#undef ENABLE_TREE_CHECKING\n\
82117395Skan#undef ENABLE_RTL_CHECKING\n\
83117395Skan#undef ENABLE_RTL_FLAG_CHECKING\n\
84117395Skan#undef ENABLE_GC_CHECKING\n\
85117395Skan#undef ENABLE_GC_ALWAYS_COLLECT\n");
86117395Skan
87117395Skan  puts ("\
88117395Skan#include \"system.h\"\n\
89132718Skan#include \"coretypes.h\"\n\
90132718Skan#include \"tm.h\"\n\
91117395Skan#include \"rtl.h\"\n\
92117395Skan#include \"tm_p.h\"\n\
93117395Skan#include \"function.h\"\n");
94117395Skan
95117395Skan  puts ("\
96117395Skan/* Fake - insn-config.h doesn't exist yet.  */\n\
97117395Skan#define MAX_RECOG_OPERANDS 10\n\
98117395Skan#define MAX_DUP_OPERANDS 10\n\
99117395Skan#define MAX_INSNS_PER_SPLIT 5\n");
100117395Skan
101117395Skan  puts ("\
102117395Skan#include \"regs.h\"\n\
103117395Skan#include \"recog.h\"\n\
104117395Skan#include \"real.h\"\n\
105117395Skan#include \"output.h\"\n\
106117395Skan#include \"flags.h\"\n\
107117395Skan#include \"hard-reg-set.h\"\n\
108117395Skan#include \"resource.h\"\n\
109117395Skan#include \"toplev.h\"\n\
110117395Skan#include \"reload.h\"\n\
111117395Skan#include \"gensupport.h\"\n");
112117395Skan
113117395Skan  if (saw_eh_return)
114117395Skan    puts ("#define HAVE_eh_return 1");
115117395Skan  puts ("#include \"except.h\"\n");
116117395Skan
117117395Skan  puts ("\
118117395Skan/* Dummy external declarations.  */\n\
119117395Skanextern rtx insn;\n\
120117395Skanextern rtx ins1;\n\
121132718Skanextern rtx operands[];\n");
122117395Skan
123117395Skan  puts ("\
124117395Skan/* If we don't have __builtin_constant_p, or it's not acceptable in\n\
125117395Skan   array initializers, fall back to assuming that all conditions\n\
126117395Skan   potentially vary at run time.  It works in 3.0.1 and later; 3.0\n\
127117395Skan   only when not optimizing.  */\n\
128117395Skan#if (GCC_VERSION >= 3001) || ((GCC_VERSION == 3000) && !__OPTIMIZE__)\n\
129117395Skan# define MAYBE_EVAL(expr) (__builtin_constant_p(expr) ? (int) (expr) : -1)\n\
130117395Skan#else\n\
131117395Skan# define MAYBE_EVAL(expr) -1\n\
132117395Skan#endif\n");
133117395Skan}
134117395Skan
135117395Skan/* Write out one entry in the conditions table, using the data pointed
136117395Skan   to by SLOT.  Each entry looks like this:
137117395Skan  { "! optimize_size && ! TARGET_READ_MODIFY_WRITE",
138117395Skan    MAYBE_EVAL (! optimize_size && ! TARGET_READ_MODIFY_WRITE) },  */
139117395Skan
140117395Skanstatic int
141132718Skanwrite_one_condition (void **slot, void *dummy ATTRIBUTE_UNUSED)
142117395Skan{
143117395Skan  const struct c_test *test = * (const struct c_test **) slot;
144117395Skan  const char *p;
145117395Skan
146117395Skan  fputs ("  { \"", stdout);
147117395Skan  for (p = test->expr; *p; p++)
148117395Skan    {
149117395Skan      if (*p == '\n')
150117395Skan	fputs ("\\n\\\n", stdout);
151117395Skan      else if (*p == '"')
152117395Skan	fputs ("\\\"", stdout);
153117395Skan      else
154117395Skan	putchar (*p);
155117395Skan    }
156117395Skan
157117395Skan  printf ("\",\n    MAYBE_EVAL (%s) },\n", test->expr);
158117395Skan  return 1;
159117395Skan}
160117395Skan
161117395Skan/* Write out the complete conditions table, its size, and a flag
162117395Skan   indicating that gensupport.c can now do insn elision.  */
163117395Skanstatic void
164132718Skanwrite_conditions (void)
165117395Skan{
166117395Skan  puts ("\
167117395Skan/* This table lists each condition found in the machine description.\n\
168117395Skan   Each condition is mapped to its truth value (0 or 1), or -1 if that\n\
169117395Skan   cannot be calculated at compile time. */\n\
170117395Skan\n\
171117395Skanconst struct c_test insn_conditions[] = {");
172117395Skan
173117395Skan  htab_traverse (condition_table, write_one_condition, 0);
174117395Skan
175117395Skan  puts ("};\n");
176117395Skan
177117395Skan  printf ("const size_t n_insn_conditions = %lu;\n",
178117395Skan	  (unsigned long) htab_elements (condition_table));
179117395Skan  puts ("const int insn_elision_unavailable = 0;");
180117395Skan}
181117395Skan
182117395Skanint
183132718Skanmain (int argc, char **argv)
184117395Skan{
185117395Skan  rtx desc;
186117395Skan  int pattern_lineno; /* not used */
187117395Skan  int code;
188117395Skan
189117395Skan  progname = "genconditions";
190117395Skan
191117395Skan  if (argc <= 1)
192117395Skan    fatal ("No input file name.");
193117395Skan
194117395Skan  if (init_md_reader (argv[1]) != SUCCESS_EXIT_CODE)
195117395Skan    return (FATAL_EXIT_CODE);
196117395Skan
197117395Skan  condition_table = htab_create (1000, hash_c_test, cmp_c_test, NULL);
198117395Skan
199117395Skan  /* Read the machine description.  */
200117395Skan
201117395Skan  while (1)
202117395Skan    {
203117395Skan      desc = read_md_rtx (&pattern_lineno, &code);
204117395Skan      if (desc == NULL)
205117395Skan	break;
206117395Skan
207117395Skan      /* N.B. define_insn_and_split, define_cond_exec are handled
208117395Skan	 entirely within read_md_rtx; we never see them.  */
209117395Skan      switch (GET_CODE (desc))
210117395Skan	{
211117395Skan	default:
212117395Skan	  break;
213117395Skan
214117395Skan	case DEFINE_INSN:
215117395Skan	case DEFINE_EXPAND:
216117395Skan	  add_condition (XSTR (desc, 2));
217117395Skan	  /* except.h needs to know whether there is an eh_return
218117395Skan	     pattern in the machine description.  */
219117395Skan	  if (!strcmp (XSTR (desc, 0), "eh_return"))
220117395Skan	    saw_eh_return = 1;
221117395Skan	  break;
222117395Skan
223117395Skan	case DEFINE_SPLIT:
224117395Skan	case DEFINE_PEEPHOLE:
225117395Skan	case DEFINE_PEEPHOLE2:
226117395Skan	  add_condition (XSTR (desc, 1));
227117395Skan	  break;
228117395Skan	}
229117395Skan    }
230117395Skan
231117395Skan  write_header ();
232117395Skan  write_conditions ();
233117395Skan
234117395Skan  fflush (stdout);
235117395Skan  return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
236117395Skan}
237