xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/gengenrtl.c (revision 8feb0f0b7eaff0608f8350bbfa3098827b4bb91b)
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