1117395Skan/* Process machine description and calculate constant conditions.
2169689Skan   Copyright (C) 2001, 2002, 2003, 2004, 2005 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
18169689Skan   the Free Software Foundation, 51 Franklin Street, Fifth Floor,
19169689Skan   Boston, MA 02110-1301, 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
41132718Skanstatic void write_header	(void);
42132718Skanstatic void write_conditions	(void);
43132718Skanstatic int write_one_condition	(void **, void *);
44117395Skan
45117395Skan/* Generate the header for insn-conditions.c.  */
46117395Skan
47117395Skanstatic void
48132718Skanwrite_header (void)
49117395Skan{
50117395Skan  puts ("\
51117395Skan/* Generated automatically by the program `genconditions' from the target\n\
52117395Skan   machine description file.  */\n\
53117395Skan\n\
54132718Skan#include \"bconfig.h\"\n\
55169689Skan#include \"system.h\"\n\
56169689Skan\n\
57169689Skan/* It is necessary, but not entirely safe, to include the headers below\n\
58169689Skan   in a generator program.  As a defensive measure, don't do so when the\n\
59169689Skan   table isn't going to have anything in it.  */\n\
60169689Skan#if GCC_VERSION >= 3001\n\
61169689Skan\n\
62117395Skan/* Do not allow checking to confuse the issue.  */\n\
63117395Skan#undef ENABLE_CHECKING\n\
64117395Skan#undef ENABLE_TREE_CHECKING\n\
65117395Skan#undef ENABLE_RTL_CHECKING\n\
66117395Skan#undef ENABLE_RTL_FLAG_CHECKING\n\
67117395Skan#undef ENABLE_GC_CHECKING\n\
68169689Skan#undef ENABLE_GC_ALWAYS_COLLECT\n\
69169689Skan\n\
70132718Skan#include \"coretypes.h\"\n\
71132718Skan#include \"tm.h\"\n\
72169689Skan#include \"insn-constants.h\"\n\
73117395Skan#include \"rtl.h\"\n\
74117395Skan#include \"tm_p.h\"\n\
75169689Skan#include \"function.h\"\n\
76169689Skan\n\
77117395Skan/* Fake - insn-config.h doesn't exist yet.  */\n\
78117395Skan#define MAX_RECOG_OPERANDS 10\n\
79117395Skan#define MAX_DUP_OPERANDS 10\n\
80169689Skan#define MAX_INSNS_PER_SPLIT 5\n\
81169689Skan\n\
82117395Skan#include \"regs.h\"\n\
83117395Skan#include \"recog.h\"\n\
84117395Skan#include \"real.h\"\n\
85117395Skan#include \"output.h\"\n\
86117395Skan#include \"flags.h\"\n\
87117395Skan#include \"hard-reg-set.h\"\n\
88117395Skan#include \"resource.h\"\n\
89117395Skan#include \"toplev.h\"\n\
90117395Skan#include \"reload.h\"\n\
91169689Skan#include \"tm-constrs.h\"\n");
92117395Skan
93117395Skan  if (saw_eh_return)
94117395Skan    puts ("#define HAVE_eh_return 1");
95117395Skan  puts ("#include \"except.h\"\n");
96117395Skan
97117395Skan  puts ("\
98117395Skan/* Dummy external declarations.  */\n\
99117395Skanextern rtx insn;\n\
100117395Skanextern rtx ins1;\n\
101169689Skanextern rtx operands[];\n\
102169689Skan\n\
103169689Skan#endif /* gcc >= 3.0.1 */\n");
104117395Skan}
105117395Skan
106117395Skan/* Write out one entry in the conditions table, using the data pointed
107117395Skan   to by SLOT.  Each entry looks like this:
108117395Skan
109169689Skan   { "! optimize_size && ! TARGET_READ_MODIFY_WRITE",
110169689Skan     __builtin_constant_p (! optimize_size && ! TARGET_READ_MODIFY_WRITE)
111169689Skan     ? (int) (! optimize_size && ! TARGET_READ_MODIFY_WRITE)
112169689Skan     : -1) },  */
113169689Skan
114117395Skanstatic int
115169689Skanwrite_one_condition (void **slot, void * ARG_UNUSED (dummy))
116117395Skan{
117117395Skan  const struct c_test *test = * (const struct c_test **) slot;
118117395Skan  const char *p;
119117395Skan
120169689Skan  print_rtx_ptr_loc (test->expr);
121117395Skan  fputs ("  { \"", stdout);
122117395Skan  for (p = test->expr; *p; p++)
123117395Skan    {
124169689Skan      switch (*p)
125169689Skan	{
126169689Skan	case '\n': fputs ("\\n\\", stdout); break;
127169689Skan	case '\\':
128169689Skan	case '\"': putchar ('\\'); break;
129169689Skan	default: break;
130169689Skan	}
131169689Skan      putchar (*p);
132117395Skan    }
133117395Skan
134169689Skan  fputs ("\",\n    __builtin_constant_p ", stdout);
135169689Skan  print_c_condition (test->expr);
136169689Skan  fputs ("\n    ? (int) ", stdout);
137169689Skan  print_c_condition (test->expr);
138169689Skan  fputs ("\n    : -1 },\n", stdout);
139117395Skan  return 1;
140117395Skan}
141117395Skan
142117395Skan/* Write out the complete conditions table, its size, and a flag
143117395Skan   indicating that gensupport.c can now do insn elision.  */
144117395Skanstatic void
145132718Skanwrite_conditions (void)
146117395Skan{
147117395Skan  puts ("\
148169689Skan/* Structure definition duplicated from gensupport.h rather than\n\
149169689Skan   drag in that file and its dependencies.  */\n\
150169689Skanstruct c_test\n\
151169689Skan{\n\
152169689Skan  const char *expr;\n\
153169689Skan  int value;\n\
154169689Skan};\n\
155169689Skan\n\
156117395Skan/* This table lists each condition found in the machine description.\n\
157117395Skan   Each condition is mapped to its truth value (0 or 1), or -1 if that\n\
158169689Skan   cannot be calculated at compile time.\n\
159169689Skan   If we don't have __builtin_constant_p, or it's not acceptable in array\n\
160169689Skan   initializers, fall back to assuming that all conditions potentially\n\
161169689Skan   vary at run time.  It works in 3.0.1 and later; 3.0 only when not\n\
162169689Skan   optimizing.  */\n\
163117395Skan\n\
164169689Skan#if GCC_VERSION >= 3001\n\
165169689Skanstatic const struct c_test insn_conditions[] = {\n");
166117395Skan
167169689Skan  traverse_c_tests (write_one_condition, 0);
168117395Skan
169169689Skan  puts ("\n};\n#endif /* gcc >= 3.0.1 */\n");
170169689Skan}
171117395Skan
172169689Skan/* Emit code which will convert the C-format table to a
173169689Skan   (define_conditions) form, which the MD reader can understand.
174169689Skan   The result will be added to the set of files scanned by
175169689Skan   'downstream' generators.  */
176169689Skanstatic void
177169689Skanwrite_writer (void)
178169689Skan{
179169689Skan  puts ("int\n"
180169689Skan	"main(void)\n"
181169689Skan	"{\n"
182169689Skan	"  unsigned int i;\n"
183169689Skan        "  const char *p;\n"
184169689Skan        "  puts (\"(define_conditions [\");\n"
185169689Skan	"#if GCC_VERSION >= 3001\n"
186169689Skan	"  for (i = 0; i < ARRAY_SIZE (insn_conditions); i++)\n"
187169689Skan	"    {\n"
188169689Skan	"      printf (\"  (%d \\\"\", insn_conditions[i].value);\n"
189169689Skan	"      for (p = insn_conditions[i].expr; *p; p++)\n"
190169689Skan	"        {\n"
191169689Skan	"          switch (*p)\n"
192169689Skan	"	     {\n"
193169689Skan	"	     case '\\\\':\n"
194169689Skan	"	     case '\\\"': putchar ('\\\\'); break;\n"
195169689Skan	"	     default: break;\n"
196169689Skan	"	     }\n"
197169689Skan	"          putchar (*p);\n"
198169689Skan	"        }\n"
199169689Skan        "      puts (\"\\\")\");\n"
200169689Skan        "    }\n"
201169689Skan	"#endif /* gcc >= 3.0.1 */\n"
202169689Skan	"  puts (\"])\");\n"
203169689Skan        "  fflush (stdout);\n"
204169689Skan        "return ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE;\n"
205169689Skan	"}");
206117395Skan}
207117395Skan
208117395Skanint
209132718Skanmain (int argc, char **argv)
210117395Skan{
211117395Skan  rtx desc;
212117395Skan  int pattern_lineno; /* not used */
213117395Skan  int code;
214117395Skan
215117395Skan  progname = "genconditions";
216117395Skan
217169689Skan  if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
218117395Skan    return (FATAL_EXIT_CODE);
219117395Skan
220117395Skan  /* Read the machine description.  */
221117395Skan  while (1)
222117395Skan    {
223117395Skan      desc = read_md_rtx (&pattern_lineno, &code);
224117395Skan      if (desc == NULL)
225117395Skan	break;
226117395Skan
227117395Skan      /* N.B. define_insn_and_split, define_cond_exec are handled
228117395Skan	 entirely within read_md_rtx; we never see them.  */
229117395Skan      switch (GET_CODE (desc))
230117395Skan	{
231117395Skan	default:
232117395Skan	  break;
233117395Skan
234117395Skan	case DEFINE_INSN:
235117395Skan	case DEFINE_EXPAND:
236169689Skan	  add_c_test (XSTR (desc, 2), -1);
237117395Skan	  /* except.h needs to know whether there is an eh_return
238117395Skan	     pattern in the machine description.  */
239117395Skan	  if (!strcmp (XSTR (desc, 0), "eh_return"))
240117395Skan	    saw_eh_return = 1;
241117395Skan	  break;
242117395Skan
243117395Skan	case DEFINE_SPLIT:
244117395Skan	case DEFINE_PEEPHOLE:
245117395Skan	case DEFINE_PEEPHOLE2:
246169689Skan	  add_c_test (XSTR (desc, 1), -1);
247117395Skan	  break;
248117395Skan	}
249117395Skan    }
250117395Skan
251117395Skan  write_header ();
252117395Skan  write_conditions ();
253169689Skan  write_writer ();
254117395Skan
255117395Skan  fflush (stdout);
256117395Skan  return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
257117395Skan}
258