xref: /dflybsd-src/contrib/gcc-8.0/gcc/genconditions.c (revision 38fd149817dfbff97799f62fcb70be98c4e32523)
1*38fd1498Szrj /* Process machine description and calculate constant conditions.
2*38fd1498Szrj    Copyright (C) 2001-2018 Free Software Foundation, Inc.
3*38fd1498Szrj 
4*38fd1498Szrj    This file is part of GCC.
5*38fd1498Szrj 
6*38fd1498Szrj    GCC is free software; you can redistribute it and/or modify
7*38fd1498Szrj    it under the terms of the GNU General Public License as published by
8*38fd1498Szrj    the Free Software Foundation; either version 3, or (at your option)
9*38fd1498Szrj    any later version.
10*38fd1498Szrj 
11*38fd1498Szrj    GCC is distributed in the hope that it will be useful,
12*38fd1498Szrj    but WITHOUT ANY WARRANTY; without even the implied warranty of
13*38fd1498Szrj    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14*38fd1498Szrj    GNU General Public License for more details.
15*38fd1498Szrj 
16*38fd1498Szrj    You should have received a copy of the GNU General Public License
17*38fd1498Szrj    along with GCC; see the file COPYING3.  If not see
18*38fd1498Szrj    <http://www.gnu.org/licenses/>.  */
19*38fd1498Szrj 
20*38fd1498Szrj /* In a machine description, all of the insn patterns - define_insn,
21*38fd1498Szrj    define_expand, define_split, define_peephole, define_peephole2 -
22*38fd1498Szrj    contain an optional C expression which makes the final decision
23*38fd1498Szrj    about whether or not this pattern is usable.  That expression may
24*38fd1498Szrj    turn out to be always false when the compiler is built.  If it is,
25*38fd1498Szrj    most of the programs that generate code from the machine
26*38fd1498Szrj    description can simply ignore the entire pattern.  */
27*38fd1498Szrj 
28*38fd1498Szrj #include "bconfig.h"
29*38fd1498Szrj #include "system.h"
30*38fd1498Szrj #include "coretypes.h"
31*38fd1498Szrj #include "tm.h"
32*38fd1498Szrj #include "rtl.h"
33*38fd1498Szrj #include "errors.h"
34*38fd1498Szrj #include "read-md.h"
35*38fd1498Szrj #include "gensupport.h"
36*38fd1498Szrj 
37*38fd1498Szrj /* so we can include except.h in the generated file.  */
38*38fd1498Szrj static int saw_eh_return;
39*38fd1498Szrj 
40*38fd1498Szrj static void write_header	(void);
41*38fd1498Szrj static void write_conditions	(void);
42*38fd1498Szrj static int write_one_condition	(void **, void *);
43*38fd1498Szrj 
44*38fd1498Szrj /* Generate the header for insn-conditions.c.  */
45*38fd1498Szrj 
46*38fd1498Szrj static void
write_header(void)47*38fd1498Szrj write_header (void)
48*38fd1498Szrj {
49*38fd1498Szrj   puts ("\
50*38fd1498Szrj /* Generated automatically by the program `genconditions' from the target\n\
51*38fd1498Szrj    machine description file.  */\n\
52*38fd1498Szrj \n\
53*38fd1498Szrj #define IN_TARGET_CODE 1\n\
54*38fd1498Szrj #include \"bconfig.h\"\n\
55*38fd1498Szrj #define INCLUDE_STRING\n\
56*38fd1498Szrj #include \"system.h\"\n\
57*38fd1498Szrj \n\
58*38fd1498Szrj /* It is necessary, but not entirely safe, to include the headers below\n\
59*38fd1498Szrj    in a generator program.  As a defensive measure, don't do so when the\n\
60*38fd1498Szrj    table isn't going to have anything in it.  */\n\
61*38fd1498Szrj #if GCC_VERSION >= 3001\n\
62*38fd1498Szrj \n\
63*38fd1498Szrj /* Do not allow checking to confuse the issue.  */\n\
64*38fd1498Szrj #undef CHECKING_P\n\
65*38fd1498Szrj #define CHECKING_P 0\n\
66*38fd1498Szrj #undef ENABLE_TREE_CHECKING\n\
67*38fd1498Szrj #undef ENABLE_RTL_CHECKING\n\
68*38fd1498Szrj #undef ENABLE_RTL_FLAG_CHECKING\n\
69*38fd1498Szrj #undef ENABLE_GC_CHECKING\n\
70*38fd1498Szrj #undef ENABLE_GC_ALWAYS_COLLECT\n\
71*38fd1498Szrj #define USE_ENUM_MODES\n\
72*38fd1498Szrj \n\
73*38fd1498Szrj #include \"coretypes.h\"\n\
74*38fd1498Szrj #include \"tm.h\"\n\
75*38fd1498Szrj #include \"insn-constants.h\"\n\
76*38fd1498Szrj #include \"rtl.h\"\n\
77*38fd1498Szrj #include \"memmodel.h\"\n\
78*38fd1498Szrj #include \"tm_p.h\"\n\
79*38fd1498Szrj #include \"hard-reg-set.h\"\n\
80*38fd1498Szrj #include \"function.h\"\n\
81*38fd1498Szrj #include \"emit-rtl.h\"\n\
82*38fd1498Szrj \n\
83*38fd1498Szrj /* Fake - insn-config.h doesn't exist yet.  */\n\
84*38fd1498Szrj #define MAX_RECOG_OPERANDS 10\n\
85*38fd1498Szrj #define MAX_DUP_OPERANDS 10\n\
86*38fd1498Szrj #define MAX_INSNS_PER_SPLIT 5\n\
87*38fd1498Szrj \n\
88*38fd1498Szrj #include \"regs.h\"\n\
89*38fd1498Szrj #include \"recog.h\"\n\
90*38fd1498Szrj #include \"output.h\"\n\
91*38fd1498Szrj #include \"flags.h\"\n\
92*38fd1498Szrj #include \"hard-reg-set.h\"\n\
93*38fd1498Szrj #include \"predict.h\"\n\
94*38fd1498Szrj #include \"basic-block.h\"\n\
95*38fd1498Szrj #include \"bitmap.h\"\n\
96*38fd1498Szrj #include \"df.h\"\n\
97*38fd1498Szrj #include \"resource.h\"\n\
98*38fd1498Szrj #include \"diagnostic-core.h\"\n\
99*38fd1498Szrj #include \"reload.h\"\n\
100*38fd1498Szrj #include \"tm-constrs.h\"\n");
101*38fd1498Szrj 
102*38fd1498Szrj   if (saw_eh_return)
103*38fd1498Szrj     puts ("#define HAVE_eh_return 1");
104*38fd1498Szrj   puts ("#include \"except.h\"\n");
105*38fd1498Szrj 
106*38fd1498Szrj   puts ("\
107*38fd1498Szrj /* Dummy external declarations.  */\n\
108*38fd1498Szrj extern rtx_insn *insn;\n\
109*38fd1498Szrj extern rtx ins1;\n\
110*38fd1498Szrj extern rtx operands[];\n\
111*38fd1498Szrj \n\
112*38fd1498Szrj #endif /* gcc >= 3.0.1 */\n");
113*38fd1498Szrj }
114*38fd1498Szrj 
115*38fd1498Szrj /* Write out one entry in the conditions table, using the data pointed
116*38fd1498Szrj    to by SLOT.  Each entry looks like this:
117*38fd1498Szrj 
118*38fd1498Szrj    { "! optimize_size && ! TARGET_READ_MODIFY_WRITE",
119*38fd1498Szrj      __builtin_constant_p (! optimize_size && ! TARGET_READ_MODIFY_WRITE)
120*38fd1498Szrj      ? (int) (! optimize_size && ! TARGET_READ_MODIFY_WRITE)
121*38fd1498Szrj      : -1) },  */
122*38fd1498Szrj 
123*38fd1498Szrj static int
write_one_condition(void ** slot,void * ARG_UNUSED (dummy))124*38fd1498Szrj write_one_condition (void **slot, void * ARG_UNUSED (dummy))
125*38fd1498Szrj {
126*38fd1498Szrj   const struct c_test *test = * (const struct c_test **) slot;
127*38fd1498Szrj   const char *p;
128*38fd1498Szrj 
129*38fd1498Szrj   rtx_reader_ptr->print_md_ptr_loc (test->expr);
130*38fd1498Szrj   fputs ("  { \"", stdout);
131*38fd1498Szrj   for (p = test->expr; *p; p++)
132*38fd1498Szrj     {
133*38fd1498Szrj       switch (*p)
134*38fd1498Szrj 	{
135*38fd1498Szrj 	case '\n': fputs ("\\n\\", stdout); break;
136*38fd1498Szrj 	case '\\':
137*38fd1498Szrj 	case '\"': putchar ('\\'); break;
138*38fd1498Szrj 	default: break;
139*38fd1498Szrj 	}
140*38fd1498Szrj       putchar (*p);
141*38fd1498Szrj     }
142*38fd1498Szrj 
143*38fd1498Szrj   fputs ("\",\n    __builtin_constant_p ", stdout);
144*38fd1498Szrj   rtx_reader_ptr->print_c_condition (test->expr);
145*38fd1498Szrj   fputs ("\n    ? (int) ", stdout);
146*38fd1498Szrj   rtx_reader_ptr->print_c_condition (test->expr);
147*38fd1498Szrj   fputs ("\n    : -1 },\n", stdout);
148*38fd1498Szrj   return 1;
149*38fd1498Szrj }
150*38fd1498Szrj 
151*38fd1498Szrj /* Write out the complete conditions table, its size, and a flag
152*38fd1498Szrj    indicating that gensupport.c can now do insn elision.  */
153*38fd1498Szrj static void
write_conditions(void)154*38fd1498Szrj write_conditions (void)
155*38fd1498Szrj {
156*38fd1498Szrj   puts ("\
157*38fd1498Szrj /* Structure definition duplicated from gensupport.h rather than\n\
158*38fd1498Szrj    drag in that file and its dependencies.  */\n\
159*38fd1498Szrj struct c_test\n\
160*38fd1498Szrj {\n\
161*38fd1498Szrj   const char *expr;\n\
162*38fd1498Szrj   int value;\n\
163*38fd1498Szrj };\n\
164*38fd1498Szrj \n\
165*38fd1498Szrj /* This table lists each condition found in the machine description.\n\
166*38fd1498Szrj    Each condition is mapped to its truth value (0 or 1), or -1 if that\n\
167*38fd1498Szrj    cannot be calculated at compile time.\n\
168*38fd1498Szrj    If we don't have __builtin_constant_p, or it's not acceptable in array\n\
169*38fd1498Szrj    initializers, fall back to assuming that all conditions potentially\n\
170*38fd1498Szrj    vary at run time.  It works in 3.0.1 and later; 3.0 only when not\n\
171*38fd1498Szrj    optimizing.  */\n\
172*38fd1498Szrj \n\
173*38fd1498Szrj #if GCC_VERSION >= 3001\n\
174*38fd1498Szrj static const struct c_test insn_conditions[] = {\n");
175*38fd1498Szrj 
176*38fd1498Szrj   traverse_c_tests (write_one_condition, 0);
177*38fd1498Szrj 
178*38fd1498Szrj   puts ("\n};\n#endif /* gcc >= 3.0.1 */\n");
179*38fd1498Szrj }
180*38fd1498Szrj 
181*38fd1498Szrj /* Emit code which will convert the C-format table to a
182*38fd1498Szrj    (define_conditions) form, which the MD reader can understand.
183*38fd1498Szrj    The result will be added to the set of files scanned by
184*38fd1498Szrj    'downstream' generators.  */
185*38fd1498Szrj static void
write_writer(void)186*38fd1498Szrj write_writer (void)
187*38fd1498Szrj {
188*38fd1498Szrj   puts ("int\n"
189*38fd1498Szrj 	"main(void)\n"
190*38fd1498Szrj 	"{\n"
191*38fd1498Szrj 	"  unsigned int i;\n"
192*38fd1498Szrj         "  const char *p;\n"
193*38fd1498Szrj         "  puts (\"(define_conditions [\");\n"
194*38fd1498Szrj 	"#if GCC_VERSION >= 3001\n"
195*38fd1498Szrj 	"  for (i = 0; i < ARRAY_SIZE (insn_conditions); i++)\n"
196*38fd1498Szrj 	"    {\n"
197*38fd1498Szrj 	"      printf (\"  (%d \\\"\", insn_conditions[i].value);\n"
198*38fd1498Szrj 	"      for (p = insn_conditions[i].expr; *p; p++)\n"
199*38fd1498Szrj 	"        {\n"
200*38fd1498Szrj 	"          switch (*p)\n"
201*38fd1498Szrj 	"	     {\n"
202*38fd1498Szrj 	"	     case '\\\\':\n"
203*38fd1498Szrj 	"	     case '\\\"': putchar ('\\\\'); break;\n"
204*38fd1498Szrj 	"	     default: break;\n"
205*38fd1498Szrj 	"	     }\n"
206*38fd1498Szrj 	"          putchar (*p);\n"
207*38fd1498Szrj 	"        }\n"
208*38fd1498Szrj         "      puts (\"\\\")\");\n"
209*38fd1498Szrj         "    }\n"
210*38fd1498Szrj 	"#endif /* gcc >= 3.0.1 */\n"
211*38fd1498Szrj 	"  puts (\"])\");\n"
212*38fd1498Szrj         "  fflush (stdout);\n"
213*38fd1498Szrj         "return ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE;\n"
214*38fd1498Szrj 	"}");
215*38fd1498Szrj }
216*38fd1498Szrj 
217*38fd1498Szrj int
main(int argc,const char ** argv)218*38fd1498Szrj main (int argc, const char **argv)
219*38fd1498Szrj {
220*38fd1498Szrj   progname = "genconditions";
221*38fd1498Szrj 
222*38fd1498Szrj   if (!init_rtx_reader_args (argc, argv))
223*38fd1498Szrj     return (FATAL_EXIT_CODE);
224*38fd1498Szrj 
225*38fd1498Szrj   /* Read the machine description.  */
226*38fd1498Szrj   md_rtx_info info;
227*38fd1498Szrj   while (read_md_rtx (&info))
228*38fd1498Szrj     {
229*38fd1498Szrj       rtx def = info.def;
230*38fd1498Szrj       add_c_test (get_c_test (def), -1);
231*38fd1498Szrj       switch (GET_CODE (def))
232*38fd1498Szrj 	{
233*38fd1498Szrj 	case DEFINE_INSN:
234*38fd1498Szrj 	case DEFINE_EXPAND:
235*38fd1498Szrj 	  /* except.h needs to know whether there is an eh_return
236*38fd1498Szrj 	     pattern in the machine description.  */
237*38fd1498Szrj 	  if (!strcmp (XSTR (def, 0), "eh_return"))
238*38fd1498Szrj 	    saw_eh_return = 1;
239*38fd1498Szrj 	  break;
240*38fd1498Szrj 
241*38fd1498Szrj 	default:
242*38fd1498Szrj 	  break;
243*38fd1498Szrj 	}
244*38fd1498Szrj     }
245*38fd1498Szrj 
246*38fd1498Szrj   write_header ();
247*38fd1498Szrj   write_conditions ();
248*38fd1498Szrj   write_writer ();
249*38fd1498Szrj 
250*38fd1498Szrj   fflush (stdout);
251*38fd1498Szrj   return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
252*38fd1498Szrj }
253