11debfc3dSmrg /* Generate code to allocate RTL structures.
2*8feb0f0bSmrg Copyright (C) 1997-2020 Free Software Foundation, Inc.
31debfc3dSmrg
41debfc3dSmrg This file is part of GCC.
51debfc3dSmrg
61debfc3dSmrg GCC is free software; you can redistribute it and/or modify it under
71debfc3dSmrg the terms of the GNU General Public License as published by the Free
81debfc3dSmrg Software Foundation; either version 3, or (at your option) any later
91debfc3dSmrg version.
101debfc3dSmrg
111debfc3dSmrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
121debfc3dSmrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
131debfc3dSmrg FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
141debfc3dSmrg for more details.
151debfc3dSmrg
161debfc3dSmrg You should have received a copy of the GNU General Public License
171debfc3dSmrg along with GCC; see the file COPYING3. If not see
181debfc3dSmrg <http://www.gnu.org/licenses/>. */
191debfc3dSmrg
201debfc3dSmrg
211debfc3dSmrg #include "bconfig.h"
221debfc3dSmrg #include "system.h"
231debfc3dSmrg
241debfc3dSmrg struct rtx_definition
251debfc3dSmrg {
261debfc3dSmrg const char *const enumname, *const name, *const format;
271debfc3dSmrg };
281debfc3dSmrg
291debfc3dSmrg /* rtl.def needs CONST_DOUBLE_FORMAT, but we don't care what
301debfc3dSmrg CONST_DOUBLE_FORMAT is because we're not going to be generating
311debfc3dSmrg anything for CONST_DOUBLE anyway. */
321debfc3dSmrg #define CONST_DOUBLE_FORMAT ""
331debfc3dSmrg
341debfc3dSmrg #define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS) { #ENUM, NAME, FORMAT },
351debfc3dSmrg
361debfc3dSmrg static const struct rtx_definition defs[] =
371debfc3dSmrg {
381debfc3dSmrg #include "rtl.def" /* rtl expressions are documented here */
391debfc3dSmrg };
401debfc3dSmrg #define NUM_RTX_CODE ARRAY_SIZE (defs)
411debfc3dSmrg
421debfc3dSmrg static const char *formats[NUM_RTX_CODE];
431debfc3dSmrg
441debfc3dSmrg /* Decode a format letter into a C type string. */
451debfc3dSmrg
461debfc3dSmrg static const char *
type_from_format(int c)471debfc3dSmrg type_from_format (int c)
481debfc3dSmrg {
491debfc3dSmrg switch (c)
501debfc3dSmrg {
511debfc3dSmrg case 'i':
521debfc3dSmrg return "int ";
531debfc3dSmrg
541debfc3dSmrg case 'w':
551debfc3dSmrg return "HOST_WIDE_INT ";
561debfc3dSmrg
57a2dc1f3fSmrg case 'p':
58a2dc1f3fSmrg return "poly_uint16 ";
59a2dc1f3fSmrg
601debfc3dSmrg case 's':
611debfc3dSmrg return "const char *";
621debfc3dSmrg
631debfc3dSmrg case 'e': case 'u':
641debfc3dSmrg return "rtx ";
651debfc3dSmrg
661debfc3dSmrg case 'E':
671debfc3dSmrg return "rtvec ";
681debfc3dSmrg case 't':
691debfc3dSmrg return "tree ";
701debfc3dSmrg case 'B':
711debfc3dSmrg return "basic_block ";
721debfc3dSmrg default:
731debfc3dSmrg gcc_unreachable ();
741debfc3dSmrg }
751debfc3dSmrg }
761debfc3dSmrg
771debfc3dSmrg /* Decode a format letter into the proper accessor function. */
781debfc3dSmrg
791debfc3dSmrg static const char *
accessor_from_format(int c)801debfc3dSmrg accessor_from_format (int c)
811debfc3dSmrg {
821debfc3dSmrg switch (c)
831debfc3dSmrg {
841debfc3dSmrg case 'i':
851debfc3dSmrg return "XINT";
861debfc3dSmrg
871debfc3dSmrg case 'w':
881debfc3dSmrg return "XWINT";
891debfc3dSmrg
901debfc3dSmrg case 's':
911debfc3dSmrg return "XSTR";
921debfc3dSmrg
931debfc3dSmrg case 'e': case 'u':
941debfc3dSmrg return "XEXP";
951debfc3dSmrg
961debfc3dSmrg case 'E':
971debfc3dSmrg return "XVEC";
981debfc3dSmrg
991debfc3dSmrg case 't':
1001debfc3dSmrg return "XTREE";
1011debfc3dSmrg
1021debfc3dSmrg case 'B':
1031debfc3dSmrg return "XBBDEF";
1041debfc3dSmrg
1051debfc3dSmrg default:
1061debfc3dSmrg gcc_unreachable ();
1071debfc3dSmrg }
1081debfc3dSmrg }
1091debfc3dSmrg
1101debfc3dSmrg /* Return nonzero if we should ignore FMT, an RTL format, when making
1111debfc3dSmrg the list of formats we write routines to create. */
1121debfc3dSmrg
1131debfc3dSmrg static int
special_format(const char * fmt)1141debfc3dSmrg special_format (const char *fmt)
1151debfc3dSmrg {
1161debfc3dSmrg return (strchr (fmt, '*') != 0
1171debfc3dSmrg || strchr (fmt, 'V') != 0
1181debfc3dSmrg || strchr (fmt, 'S') != 0
1191debfc3dSmrg || strchr (fmt, 'n') != 0
1201debfc3dSmrg || strchr (fmt, 'r') != 0);
1211debfc3dSmrg }
1221debfc3dSmrg
1231debfc3dSmrg /* Return true if CODE always has VOIDmode. */
1241debfc3dSmrg
1251debfc3dSmrg static inline bool
always_void_p(int idx)1261debfc3dSmrg always_void_p (int idx)
1271debfc3dSmrg {
1281debfc3dSmrg return strcmp (defs[idx].enumname, "SET") == 0;
1291debfc3dSmrg }
1301debfc3dSmrg
1311debfc3dSmrg /* Return nonzero if the RTL code given by index IDX is one that we should
1321debfc3dSmrg generate a gen_rtx_raw_FOO macro for, not gen_rtx_FOO (because gen_rtx_FOO
1331debfc3dSmrg is a wrapper in emit-rtl.c). */
1341debfc3dSmrg
1351debfc3dSmrg static int
special_rtx(int idx)1361debfc3dSmrg special_rtx (int idx)
1371debfc3dSmrg {
1381debfc3dSmrg return (strcmp (defs[idx].enumname, "EXPR_LIST") == 0
1391debfc3dSmrg || strcmp (defs[idx].enumname, "INSN_LIST") == 0
1401debfc3dSmrg || strcmp (defs[idx].enumname, "INSN") == 0
1411debfc3dSmrg || strcmp (defs[idx].enumname, "CONST_INT") == 0
1421debfc3dSmrg || strcmp (defs[idx].enumname, "REG") == 0
1431debfc3dSmrg || strcmp (defs[idx].enumname, "SUBREG") == 0
1441debfc3dSmrg || strcmp (defs[idx].enumname, "MEM") == 0
1451debfc3dSmrg || strcmp (defs[idx].enumname, "PC") == 0
1461debfc3dSmrg || strcmp (defs[idx].enumname, "CC0") == 0
1471debfc3dSmrg || strcmp (defs[idx].enumname, "RETURN") == 0
1481debfc3dSmrg || strcmp (defs[idx].enumname, "SIMPLE_RETURN") == 0
1491debfc3dSmrg || strcmp (defs[idx].enumname, "CONST_VECTOR") == 0);
1501debfc3dSmrg }
1511debfc3dSmrg
1521debfc3dSmrg /* Return nonzero if the RTL code given by index IDX is one that we should
1531debfc3dSmrg generate no macro for at all (because gen_rtx_FOO is never used or
1541debfc3dSmrg cannot have the obvious interface). */
1551debfc3dSmrg
1561debfc3dSmrg static int
excluded_rtx(int idx)1571debfc3dSmrg excluded_rtx (int idx)
1581debfc3dSmrg {
1591debfc3dSmrg return (strcmp (defs[idx].enumname, "VAR_LOCATION") == 0
1601debfc3dSmrg || strcmp (defs[idx].enumname, "CONST_DOUBLE") == 0
1611debfc3dSmrg || strcmp (defs[idx].enumname, "CONST_WIDE_INT") == 0
162a2dc1f3fSmrg || strcmp (defs[idx].enumname, "CONST_POLY_INT") == 0
1631debfc3dSmrg || strcmp (defs[idx].enumname, "CONST_FIXED") == 0);
1641debfc3dSmrg }
1651debfc3dSmrg
1661debfc3dSmrg /* Place a list of all format specifiers we use into the array FORMAT. */
1671debfc3dSmrg
1681debfc3dSmrg static void
find_formats(void)1691debfc3dSmrg find_formats (void)
1701debfc3dSmrg {
1711debfc3dSmrg unsigned int i;
1721debfc3dSmrg
1731debfc3dSmrg for (i = 0; i < NUM_RTX_CODE; i++)
1741debfc3dSmrg {
1751debfc3dSmrg const char **f;
1761debfc3dSmrg
1771debfc3dSmrg if (special_format (defs[i].format))
1781debfc3dSmrg continue;
1791debfc3dSmrg
1801debfc3dSmrg for (f = formats; *f; f++)
1811debfc3dSmrg if (! strcmp (*f, defs[i].format))
1821debfc3dSmrg break;
1831debfc3dSmrg
1841debfc3dSmrg if (*f == 0)
1851debfc3dSmrg *f = defs[i].format;
1861debfc3dSmrg }
1871debfc3dSmrg }
1881debfc3dSmrg
1891debfc3dSmrg
1901debfc3dSmrg /* Generate macros to generate RTL of code IDX using the functions we
1911debfc3dSmrg write. */
1921debfc3dSmrg
1931debfc3dSmrg static void
genmacro(int idx)1941debfc3dSmrg genmacro (int idx)
1951debfc3dSmrg {
1961debfc3dSmrg const char *p;
1971debfc3dSmrg const char *sep = "";
1981debfc3dSmrg int i;
1991debfc3dSmrg
2001debfc3dSmrg /* We write a macro that defines gen_rtx_RTLCODE to be an equivalent to
2011debfc3dSmrg gen_rtx_fmt_FORMAT where FORMAT is the RTX_FORMAT of RTLCODE. */
2021debfc3dSmrg
2031debfc3dSmrg if (excluded_rtx (idx))
2041debfc3dSmrg /* Don't define a macro for this code. */
2051debfc3dSmrg return;
2061debfc3dSmrg
2071debfc3dSmrg bool has_mode_p = !always_void_p (idx);
2081debfc3dSmrg printf ("#define gen_rtx_%s%s(",
2091debfc3dSmrg special_rtx (idx) ? "raw_" : "", defs[idx].enumname);
2101debfc3dSmrg if (has_mode_p)
2111debfc3dSmrg {
2121debfc3dSmrg printf ("MODE");
2131debfc3dSmrg sep = ", ";
2141debfc3dSmrg }
2151debfc3dSmrg
2161debfc3dSmrg for (p = defs[idx].format, i = 0; *p != 0; p++)
2171debfc3dSmrg if (*p != '0')
2181debfc3dSmrg {
2191debfc3dSmrg printf ("%sARG%d", sep, i++);
2201debfc3dSmrg sep = ", ";
2211debfc3dSmrg }
2221debfc3dSmrg
2231debfc3dSmrg printf (") \\\n gen_rtx_fmt_%s (%s, %s",
2241debfc3dSmrg defs[idx].format, defs[idx].enumname,
2251debfc3dSmrg has_mode_p ? "(MODE)" : "VOIDmode");
2261debfc3dSmrg
2271debfc3dSmrg for (p = defs[idx].format, i = 0; *p != 0; p++)
2281debfc3dSmrg if (*p != '0')
2291debfc3dSmrg printf (", (ARG%d)", i++);
2301debfc3dSmrg
2311debfc3dSmrg puts (")");
2321debfc3dSmrg }
2331debfc3dSmrg
234*8feb0f0bSmrg /* Generate the code for functions to generate RTL whose format is FORMAT. */
2351debfc3dSmrg
2361debfc3dSmrg static void
gendef(const char * format)2371debfc3dSmrg gendef (const char *format)
2381debfc3dSmrg {
2391debfc3dSmrg const char *p;
2401debfc3dSmrg int i, j;
2411debfc3dSmrg
242*8feb0f0bSmrg /* Write the definition of the init function name and the types
2431debfc3dSmrg of the arguments. */
2441debfc3dSmrg
245*8feb0f0bSmrg puts ("static inline rtx");
246*8feb0f0bSmrg printf ("init_rtx_fmt_%s (rtx rt, machine_mode mode", format);
2471debfc3dSmrg for (p = format, i = 0; *p != 0; p++)
2481debfc3dSmrg if (*p != '0')
2491debfc3dSmrg printf (",\n\t%sarg%d", type_from_format (*p), i++);
250*8feb0f0bSmrg puts (")");
2511debfc3dSmrg
252*8feb0f0bSmrg /* Now write out the body of the init function itself. */
2531debfc3dSmrg puts ("{");
2541debfc3dSmrg puts (" PUT_MODE_RAW (rt, mode);");
2551debfc3dSmrg
2561debfc3dSmrg for (p = format, i = j = 0; *p ; ++p, ++i)
257a2dc1f3fSmrg if (*p == '0')
2581debfc3dSmrg printf (" X0EXP (rt, %d) = NULL_RTX;\n", i);
259a2dc1f3fSmrg else if (*p == 'p')
260a2dc1f3fSmrg printf (" SUBREG_BYTE (rt) = arg%d;\n", j++);
261a2dc1f3fSmrg else
262a2dc1f3fSmrg printf (" %s (rt, %d) = arg%d;\n", accessor_from_format (*p), i, j++);
2631debfc3dSmrg
264*8feb0f0bSmrg puts (" return rt;\n}\n");
265*8feb0f0bSmrg
266*8feb0f0bSmrg /* Write the definition of the gen function name and the types
267*8feb0f0bSmrg of the arguments. */
268*8feb0f0bSmrg
269*8feb0f0bSmrg puts ("static inline rtx");
270*8feb0f0bSmrg printf ("gen_rtx_fmt_%s_stat (RTX_CODE code, machine_mode mode", format);
271*8feb0f0bSmrg for (p = format, i = 0; *p != 0; p++)
272*8feb0f0bSmrg if (*p != '0')
273*8feb0f0bSmrg printf (",\n\t%sarg%d", type_from_format (*p), i++);
274*8feb0f0bSmrg puts (" MEM_STAT_DECL)");
275*8feb0f0bSmrg
276*8feb0f0bSmrg /* Now write out the body of the function itself, which allocates
277*8feb0f0bSmrg the memory and initializes it. */
278*8feb0f0bSmrg puts ("{");
279*8feb0f0bSmrg puts (" rtx rt;\n");
280*8feb0f0bSmrg
281*8feb0f0bSmrg puts (" rt = rtx_alloc (code PASS_MEM_STAT);");
282*8feb0f0bSmrg printf (" return init_rtx_fmt_%s (rt, mode", format);
283*8feb0f0bSmrg for (p = format, i = 0; *p != 0; p++)
284*8feb0f0bSmrg if (*p != '0')
285*8feb0f0bSmrg printf (", arg%d", i++);
286*8feb0f0bSmrg puts (");\n}\n");
287*8feb0f0bSmrg
288*8feb0f0bSmrg /* Write the definition of gen macro. */
289*8feb0f0bSmrg
2901debfc3dSmrg printf ("#define gen_rtx_fmt_%s(c, m", format);
2911debfc3dSmrg for (p = format, i = 0; *p != 0; p++)
2921debfc3dSmrg if (*p != '0')
293*8feb0f0bSmrg printf (", arg%d", i++);
294*8feb0f0bSmrg printf (") \\\n gen_rtx_fmt_%s_stat ((c), (m)", format);
2951debfc3dSmrg for (p = format, i = 0; *p != 0; p++)
2961debfc3dSmrg if (*p != '0')
297*8feb0f0bSmrg printf (", (arg%d)", i++);
2981debfc3dSmrg printf (" MEM_STAT_INFO)\n\n");
299*8feb0f0bSmrg
300*8feb0f0bSmrg /* Write the definition of alloca macro. */
301*8feb0f0bSmrg
302*8feb0f0bSmrg printf ("#define alloca_rtx_fmt_%s(c, m", format);
303*8feb0f0bSmrg for (p = format, i = 0; *p != 0; p++)
304*8feb0f0bSmrg if (*p != '0')
305*8feb0f0bSmrg printf (", arg%d", i++);
306*8feb0f0bSmrg printf (") \\\n init_rtx_fmt_%s (rtx_alloca ((c)), (m)", format);
307*8feb0f0bSmrg for (p = format, i = 0; *p != 0; p++)
308*8feb0f0bSmrg if (*p != '0')
309*8feb0f0bSmrg printf (", (arg%d)", i++);
310*8feb0f0bSmrg printf (")\n\n");
3111debfc3dSmrg }
3121debfc3dSmrg
3131debfc3dSmrg /* Generate the documentation header for files we write. */
3141debfc3dSmrg
3151debfc3dSmrg static void
genlegend(void)3161debfc3dSmrg genlegend (void)
3171debfc3dSmrg {
3181debfc3dSmrg puts ("/* Generated automatically by gengenrtl from rtl.def. */\n");
3191debfc3dSmrg }
3201debfc3dSmrg
3211debfc3dSmrg /* Generate the text of the header file we make, genrtl.h. */
3221debfc3dSmrg
3231debfc3dSmrg static void
genheader(void)3241debfc3dSmrg genheader (void)
3251debfc3dSmrg {
3261debfc3dSmrg unsigned int i;
3271debfc3dSmrg const char **fmt;
3281debfc3dSmrg
3291debfc3dSmrg puts ("#ifndef GCC_GENRTL_H");
3301debfc3dSmrg puts ("#define GCC_GENRTL_H\n");
3311debfc3dSmrg puts ("#include \"statistics.h\"\n");
3321debfc3dSmrg
3331debfc3dSmrg for (fmt = formats; *fmt; ++fmt)
3341debfc3dSmrg gendef (*fmt);
3351debfc3dSmrg
3361debfc3dSmrg putchar ('\n');
3371debfc3dSmrg
3381debfc3dSmrg for (i = 0; i < NUM_RTX_CODE; i++)
3391debfc3dSmrg if (! special_format (defs[i].format))
3401debfc3dSmrg genmacro (i);
3411debfc3dSmrg
3421debfc3dSmrg puts ("\n#endif /* GCC_GENRTL_H */");
3431debfc3dSmrg }
3441debfc3dSmrg
3451debfc3dSmrg /* This is the main program. */
3461debfc3dSmrg
3471debfc3dSmrg int
main(void)3481debfc3dSmrg main (void)
3491debfc3dSmrg {
3501debfc3dSmrg find_formats ();
3511debfc3dSmrg genlegend ();
3521debfc3dSmrg
3531debfc3dSmrg genheader ();
3541debfc3dSmrg
3551debfc3dSmrg if (ferror (stdout) || fflush (stdout) || fclose (stdout))
3561debfc3dSmrg return FATAL_EXIT_CODE;
3571debfc3dSmrg
3581debfc3dSmrg return SUCCESS_EXIT_CODE;
3591debfc3dSmrg }
360