1*38fd1498Szrj /* Generate code to allocate RTL structures.
2*38fd1498Szrj Copyright (C) 1997-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 it under
7*38fd1498Szrj the terms of the GNU General Public License as published by the Free
8*38fd1498Szrj Software Foundation; either version 3, or (at your option) any later
9*38fd1498Szrj version.
10*38fd1498Szrj
11*38fd1498Szrj GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12*38fd1498Szrj WARRANTY; without even the implied warranty of MERCHANTABILITY or
13*38fd1498Szrj FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14*38fd1498Szrj 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
21*38fd1498Szrj #include "bconfig.h"
22*38fd1498Szrj #include "system.h"
23*38fd1498Szrj
24*38fd1498Szrj struct rtx_definition
25*38fd1498Szrj {
26*38fd1498Szrj const char *const enumname, *const name, *const format;
27*38fd1498Szrj };
28*38fd1498Szrj
29*38fd1498Szrj /* rtl.def needs CONST_DOUBLE_FORMAT, but we don't care what
30*38fd1498Szrj CONST_DOUBLE_FORMAT is because we're not going to be generating
31*38fd1498Szrj anything for CONST_DOUBLE anyway. */
32*38fd1498Szrj #define CONST_DOUBLE_FORMAT ""
33*38fd1498Szrj
34*38fd1498Szrj #define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS) { #ENUM, NAME, FORMAT },
35*38fd1498Szrj
36*38fd1498Szrj static const struct rtx_definition defs[] =
37*38fd1498Szrj {
38*38fd1498Szrj #include "rtl.def" /* rtl expressions are documented here */
39*38fd1498Szrj };
40*38fd1498Szrj #define NUM_RTX_CODE ARRAY_SIZE (defs)
41*38fd1498Szrj
42*38fd1498Szrj static const char *formats[NUM_RTX_CODE];
43*38fd1498Szrj
44*38fd1498Szrj /* Decode a format letter into a C type string. */
45*38fd1498Szrj
46*38fd1498Szrj static const char *
type_from_format(int c)47*38fd1498Szrj type_from_format (int c)
48*38fd1498Szrj {
49*38fd1498Szrj switch (c)
50*38fd1498Szrj {
51*38fd1498Szrj case 'i':
52*38fd1498Szrj return "int ";
53*38fd1498Szrj
54*38fd1498Szrj case 'w':
55*38fd1498Szrj return "HOST_WIDE_INT ";
56*38fd1498Szrj
57*38fd1498Szrj case 'p':
58*38fd1498Szrj return "poly_uint16 ";
59*38fd1498Szrj
60*38fd1498Szrj case 's':
61*38fd1498Szrj return "const char *";
62*38fd1498Szrj
63*38fd1498Szrj case 'e': case 'u':
64*38fd1498Szrj return "rtx ";
65*38fd1498Szrj
66*38fd1498Szrj case 'E':
67*38fd1498Szrj return "rtvec ";
68*38fd1498Szrj case 't':
69*38fd1498Szrj return "tree ";
70*38fd1498Szrj case 'B':
71*38fd1498Szrj return "basic_block ";
72*38fd1498Szrj default:
73*38fd1498Szrj gcc_unreachable ();
74*38fd1498Szrj }
75*38fd1498Szrj }
76*38fd1498Szrj
77*38fd1498Szrj /* Decode a format letter into the proper accessor function. */
78*38fd1498Szrj
79*38fd1498Szrj static const char *
accessor_from_format(int c)80*38fd1498Szrj accessor_from_format (int c)
81*38fd1498Szrj {
82*38fd1498Szrj switch (c)
83*38fd1498Szrj {
84*38fd1498Szrj case 'i':
85*38fd1498Szrj return "XINT";
86*38fd1498Szrj
87*38fd1498Szrj case 'w':
88*38fd1498Szrj return "XWINT";
89*38fd1498Szrj
90*38fd1498Szrj case 's':
91*38fd1498Szrj return "XSTR";
92*38fd1498Szrj
93*38fd1498Szrj case 'e': case 'u':
94*38fd1498Szrj return "XEXP";
95*38fd1498Szrj
96*38fd1498Szrj case 'E':
97*38fd1498Szrj return "XVEC";
98*38fd1498Szrj
99*38fd1498Szrj case 't':
100*38fd1498Szrj return "XTREE";
101*38fd1498Szrj
102*38fd1498Szrj case 'B':
103*38fd1498Szrj return "XBBDEF";
104*38fd1498Szrj
105*38fd1498Szrj default:
106*38fd1498Szrj gcc_unreachable ();
107*38fd1498Szrj }
108*38fd1498Szrj }
109*38fd1498Szrj
110*38fd1498Szrj /* Return nonzero if we should ignore FMT, an RTL format, when making
111*38fd1498Szrj the list of formats we write routines to create. */
112*38fd1498Szrj
113*38fd1498Szrj static int
special_format(const char * fmt)114*38fd1498Szrj special_format (const char *fmt)
115*38fd1498Szrj {
116*38fd1498Szrj return (strchr (fmt, '*') != 0
117*38fd1498Szrj || strchr (fmt, 'V') != 0
118*38fd1498Szrj || strchr (fmt, 'S') != 0
119*38fd1498Szrj || strchr (fmt, 'n') != 0
120*38fd1498Szrj || strchr (fmt, 'r') != 0);
121*38fd1498Szrj }
122*38fd1498Szrj
123*38fd1498Szrj /* Return true if CODE always has VOIDmode. */
124*38fd1498Szrj
125*38fd1498Szrj static inline bool
always_void_p(int idx)126*38fd1498Szrj always_void_p (int idx)
127*38fd1498Szrj {
128*38fd1498Szrj return strcmp (defs[idx].enumname, "SET") == 0;
129*38fd1498Szrj }
130*38fd1498Szrj
131*38fd1498Szrj /* Return nonzero if the RTL code given by index IDX is one that we should
132*38fd1498Szrj generate a gen_rtx_raw_FOO macro for, not gen_rtx_FOO (because gen_rtx_FOO
133*38fd1498Szrj is a wrapper in emit-rtl.c). */
134*38fd1498Szrj
135*38fd1498Szrj static int
special_rtx(int idx)136*38fd1498Szrj special_rtx (int idx)
137*38fd1498Szrj {
138*38fd1498Szrj return (strcmp (defs[idx].enumname, "EXPR_LIST") == 0
139*38fd1498Szrj || strcmp (defs[idx].enumname, "INSN_LIST") == 0
140*38fd1498Szrj || strcmp (defs[idx].enumname, "INSN") == 0
141*38fd1498Szrj || strcmp (defs[idx].enumname, "CONST_INT") == 0
142*38fd1498Szrj || strcmp (defs[idx].enumname, "REG") == 0
143*38fd1498Szrj || strcmp (defs[idx].enumname, "SUBREG") == 0
144*38fd1498Szrj || strcmp (defs[idx].enumname, "MEM") == 0
145*38fd1498Szrj || strcmp (defs[idx].enumname, "PC") == 0
146*38fd1498Szrj || strcmp (defs[idx].enumname, "CC0") == 0
147*38fd1498Szrj || strcmp (defs[idx].enumname, "RETURN") == 0
148*38fd1498Szrj || strcmp (defs[idx].enumname, "SIMPLE_RETURN") == 0
149*38fd1498Szrj || strcmp (defs[idx].enumname, "CONST_VECTOR") == 0);
150*38fd1498Szrj }
151*38fd1498Szrj
152*38fd1498Szrj /* Return nonzero if the RTL code given by index IDX is one that we should
153*38fd1498Szrj generate no macro for at all (because gen_rtx_FOO is never used or
154*38fd1498Szrj cannot have the obvious interface). */
155*38fd1498Szrj
156*38fd1498Szrj static int
excluded_rtx(int idx)157*38fd1498Szrj excluded_rtx (int idx)
158*38fd1498Szrj {
159*38fd1498Szrj return (strcmp (defs[idx].enumname, "VAR_LOCATION") == 0
160*38fd1498Szrj || strcmp (defs[idx].enumname, "CONST_DOUBLE") == 0
161*38fd1498Szrj || strcmp (defs[idx].enumname, "CONST_WIDE_INT") == 0
162*38fd1498Szrj || strcmp (defs[idx].enumname, "CONST_POLY_INT") == 0
163*38fd1498Szrj || strcmp (defs[idx].enumname, "CONST_FIXED") == 0);
164*38fd1498Szrj }
165*38fd1498Szrj
166*38fd1498Szrj /* Place a list of all format specifiers we use into the array FORMAT. */
167*38fd1498Szrj
168*38fd1498Szrj static void
find_formats(void)169*38fd1498Szrj find_formats (void)
170*38fd1498Szrj {
171*38fd1498Szrj unsigned int i;
172*38fd1498Szrj
173*38fd1498Szrj for (i = 0; i < NUM_RTX_CODE; i++)
174*38fd1498Szrj {
175*38fd1498Szrj const char **f;
176*38fd1498Szrj
177*38fd1498Szrj if (special_format (defs[i].format))
178*38fd1498Szrj continue;
179*38fd1498Szrj
180*38fd1498Szrj for (f = formats; *f; f++)
181*38fd1498Szrj if (! strcmp (*f, defs[i].format))
182*38fd1498Szrj break;
183*38fd1498Szrj
184*38fd1498Szrj if (*f == 0)
185*38fd1498Szrj *f = defs[i].format;
186*38fd1498Szrj }
187*38fd1498Szrj }
188*38fd1498Szrj
189*38fd1498Szrj
190*38fd1498Szrj /* Generate macros to generate RTL of code IDX using the functions we
191*38fd1498Szrj write. */
192*38fd1498Szrj
193*38fd1498Szrj static void
genmacro(int idx)194*38fd1498Szrj genmacro (int idx)
195*38fd1498Szrj {
196*38fd1498Szrj const char *p;
197*38fd1498Szrj const char *sep = "";
198*38fd1498Szrj int i;
199*38fd1498Szrj
200*38fd1498Szrj /* We write a macro that defines gen_rtx_RTLCODE to be an equivalent to
201*38fd1498Szrj gen_rtx_fmt_FORMAT where FORMAT is the RTX_FORMAT of RTLCODE. */
202*38fd1498Szrj
203*38fd1498Szrj if (excluded_rtx (idx))
204*38fd1498Szrj /* Don't define a macro for this code. */
205*38fd1498Szrj return;
206*38fd1498Szrj
207*38fd1498Szrj bool has_mode_p = !always_void_p (idx);
208*38fd1498Szrj printf ("#define gen_rtx_%s%s(",
209*38fd1498Szrj special_rtx (idx) ? "raw_" : "", defs[idx].enumname);
210*38fd1498Szrj if (has_mode_p)
211*38fd1498Szrj {
212*38fd1498Szrj printf ("MODE");
213*38fd1498Szrj sep = ", ";
214*38fd1498Szrj }
215*38fd1498Szrj
216*38fd1498Szrj for (p = defs[idx].format, i = 0; *p != 0; p++)
217*38fd1498Szrj if (*p != '0')
218*38fd1498Szrj {
219*38fd1498Szrj printf ("%sARG%d", sep, i++);
220*38fd1498Szrj sep = ", ";
221*38fd1498Szrj }
222*38fd1498Szrj
223*38fd1498Szrj printf (") \\\n gen_rtx_fmt_%s (%s, %s",
224*38fd1498Szrj defs[idx].format, defs[idx].enumname,
225*38fd1498Szrj has_mode_p ? "(MODE)" : "VOIDmode");
226*38fd1498Szrj
227*38fd1498Szrj for (p = defs[idx].format, i = 0; *p != 0; p++)
228*38fd1498Szrj if (*p != '0')
229*38fd1498Szrj printf (", (ARG%d)", i++);
230*38fd1498Szrj
231*38fd1498Szrj puts (")");
232*38fd1498Szrj }
233*38fd1498Szrj
234*38fd1498Szrj /* Generate the code for the function to generate RTL whose
235*38fd1498Szrj format is FORMAT. */
236*38fd1498Szrj
237*38fd1498Szrj static void
gendef(const char * format)238*38fd1498Szrj gendef (const char *format)
239*38fd1498Szrj {
240*38fd1498Szrj const char *p;
241*38fd1498Szrj int i, j;
242*38fd1498Szrj
243*38fd1498Szrj /* Start by writing the definition of the function name and the types
244*38fd1498Szrj of the arguments. */
245*38fd1498Szrj
246*38fd1498Szrj printf ("static inline rtx\ngen_rtx_fmt_%s_stat (RTX_CODE code, machine_mode mode", format);
247*38fd1498Szrj for (p = format, i = 0; *p != 0; p++)
248*38fd1498Szrj if (*p != '0')
249*38fd1498Szrj printf (",\n\t%sarg%d", type_from_format (*p), i++);
250*38fd1498Szrj
251*38fd1498Szrj puts (" MEM_STAT_DECL)");
252*38fd1498Szrj
253*38fd1498Szrj /* Now write out the body of the function itself, which allocates
254*38fd1498Szrj the memory and initializes it. */
255*38fd1498Szrj puts ("{");
256*38fd1498Szrj puts (" rtx rt;");
257*38fd1498Szrj puts (" rt = rtx_alloc (code PASS_MEM_STAT);\n");
258*38fd1498Szrj
259*38fd1498Szrj puts (" PUT_MODE_RAW (rt, mode);");
260*38fd1498Szrj
261*38fd1498Szrj for (p = format, i = j = 0; *p ; ++p, ++i)
262*38fd1498Szrj if (*p == '0')
263*38fd1498Szrj printf (" X0EXP (rt, %d) = NULL_RTX;\n", i);
264*38fd1498Szrj else if (*p == 'p')
265*38fd1498Szrj printf (" SUBREG_BYTE (rt) = arg%d;\n", j++);
266*38fd1498Szrj else
267*38fd1498Szrj printf (" %s (rt, %d) = arg%d;\n", accessor_from_format (*p), i, j++);
268*38fd1498Szrj
269*38fd1498Szrj puts ("\n return rt;\n}\n");
270*38fd1498Szrj printf ("#define gen_rtx_fmt_%s(c, m", format);
271*38fd1498Szrj for (p = format, i = 0; *p != 0; p++)
272*38fd1498Szrj if (*p != '0')
273*38fd1498Szrj printf (", p%i",i++);
274*38fd1498Szrj printf (")\\\n gen_rtx_fmt_%s_stat (c, m", format);
275*38fd1498Szrj for (p = format, i = 0; *p != 0; p++)
276*38fd1498Szrj if (*p != '0')
277*38fd1498Szrj printf (", p%i",i++);
278*38fd1498Szrj printf (" MEM_STAT_INFO)\n\n");
279*38fd1498Szrj }
280*38fd1498Szrj
281*38fd1498Szrj /* Generate the documentation header for files we write. */
282*38fd1498Szrj
283*38fd1498Szrj static void
genlegend(void)284*38fd1498Szrj genlegend (void)
285*38fd1498Szrj {
286*38fd1498Szrj puts ("/* Generated automatically by gengenrtl from rtl.def. */\n");
287*38fd1498Szrj }
288*38fd1498Szrj
289*38fd1498Szrj /* Generate the text of the header file we make, genrtl.h. */
290*38fd1498Szrj
291*38fd1498Szrj static void
genheader(void)292*38fd1498Szrj genheader (void)
293*38fd1498Szrj {
294*38fd1498Szrj unsigned int i;
295*38fd1498Szrj const char **fmt;
296*38fd1498Szrj
297*38fd1498Szrj puts ("#ifndef GCC_GENRTL_H");
298*38fd1498Szrj puts ("#define GCC_GENRTL_H\n");
299*38fd1498Szrj puts ("#include \"statistics.h\"\n");
300*38fd1498Szrj
301*38fd1498Szrj for (fmt = formats; *fmt; ++fmt)
302*38fd1498Szrj gendef (*fmt);
303*38fd1498Szrj
304*38fd1498Szrj putchar ('\n');
305*38fd1498Szrj
306*38fd1498Szrj for (i = 0; i < NUM_RTX_CODE; i++)
307*38fd1498Szrj if (! special_format (defs[i].format))
308*38fd1498Szrj genmacro (i);
309*38fd1498Szrj
310*38fd1498Szrj puts ("\n#endif /* GCC_GENRTL_H */");
311*38fd1498Szrj }
312*38fd1498Szrj
313*38fd1498Szrj /* This is the main program. */
314*38fd1498Szrj
315*38fd1498Szrj int
main(void)316*38fd1498Szrj main (void)
317*38fd1498Szrj {
318*38fd1498Szrj find_formats ();
319*38fd1498Szrj genlegend ();
320*38fd1498Szrj
321*38fd1498Szrj genheader ();
322*38fd1498Szrj
323*38fd1498Szrj if (ferror (stdout) || fflush (stdout) || fclose (stdout))
324*38fd1498Szrj return FATAL_EXIT_CODE;
325*38fd1498Szrj
326*38fd1498Szrj return SUCCESS_EXIT_CODE;
327*38fd1498Szrj }
328