xref: /dflybsd-src/contrib/gcc-8.0/gcc/gengenrtl.c (revision 38fd149817dfbff97799f62fcb70be98c4e32523)
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