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