150397Sobrien/* Generate code to allocate RTL structures.
2169689Skan   Copyright (C) 1997, 1998, 1999, 2000, 2002, 2003, 2004
3132718Skan   Free Software Foundation, Inc.
450397Sobrien
590075SobrienThis file is part of GCC.
650397Sobrien
790075SobrienGCC is free software; you can redistribute it and/or modify it under
890075Sobrienthe terms of the GNU General Public License as published by the Free
990075SobrienSoftware Foundation; either version 2, or (at your option) any later
1090075Sobrienversion.
1150397Sobrien
1290075SobrienGCC is distributed in the hope that it will be useful, but WITHOUT ANY
1390075SobrienWARRANTY; without even the implied warranty of MERCHANTABILITY or
1490075SobrienFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1590075Sobrienfor more details.
1650397Sobrien
1750397SobrienYou should have received a copy of the GNU General Public License
1890075Sobrienalong with GCC; see the file COPYING.  If not, write to the Free
19169689SkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
20169689Skan02110-1301, USA.  */
2150397Sobrien
2250397Sobrien
23132718Skan#include "bconfig.h"
2450397Sobrien#include "system.h"
2550397Sobrien
26117395Skanstruct rtx_definition
2750397Sobrien{
2890075Sobrien  const char *const enumname, *const name, *const format;
2950397Sobrien};
3050397Sobrien
31132718Skan/* rtl.def needs CONST_DOUBLE_FORMAT, but we don't care what
32132718Skan   CONST_DOUBLE_FORMAT is because we're not going to be generating
33132718Skan   anything for CONST_DOUBLE anyway.  */
34132718Skan#define CONST_DOUBLE_FORMAT ""
3550397Sobrien
36132718Skan#define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS) { #ENUM, NAME, FORMAT },
37132718Skan
38117395Skanstatic const struct rtx_definition defs[] =
39117395Skan{
4050397Sobrien#include "rtl.def"		/* rtl expressions are documented here */
4150397Sobrien};
42132718Skan#define NUM_RTX_CODE ARRAY_SIZE(defs)
4350397Sobrien
4490075Sobrienstatic const char *formats[NUM_RTX_CODE];
4550397Sobrien
46132718Skanstatic const char *type_from_format	(int);
47132718Skanstatic const char *accessor_from_format	(int);
48132718Skanstatic int special_format		(const char *);
49132718Skanstatic int special_rtx			(int);
50132718Skanstatic int excluded_rtx			(int);
51132718Skanstatic void find_formats		(void);
52132718Skanstatic void gendecl			(const char *);
53132718Skanstatic void genmacro			(int);
54132718Skanstatic void gendef			(const char *);
55132718Skanstatic void genlegend			(void);
56132718Skanstatic void genheader			(void);
57132718Skanstatic void gencode			(void);
5890075Sobrien
5952284Sobrien/* Decode a format letter into a C type string.  */
6052284Sobrien
6150397Sobrienstatic const char *
62132718Skantype_from_format (int c)
6350397Sobrien{
6450397Sobrien  switch (c)
6550397Sobrien    {
6650397Sobrien    case 'i':
6790075Sobrien      return "int ";
6890075Sobrien
6950397Sobrien    case 'w':
7090075Sobrien      return "HOST_WIDE_INT ";
7190075Sobrien
7250397Sobrien    case 's':
7390075Sobrien      return "const char *";
7490075Sobrien
7590075Sobrien    case 'e':  case 'u':
7690075Sobrien      return "rtx ";
7790075Sobrien
7850397Sobrien    case 'E':
7990075Sobrien      return "rtvec ";
8050397Sobrien    case 'b':
8190075Sobrien      return "struct bitmap_head_def *";  /* bitmap - typedef not available */
8250397Sobrien    case 't':
8390075Sobrien      return "union tree_node *";  /* tree - typedef not available */
84117395Skan    case 'B':
85117395Skan      return "struct basic_block_def *";  /* basic block - typedef not available */
8650397Sobrien    default:
87169689Skan      gcc_unreachable ();
8850397Sobrien    }
8950397Sobrien}
9050397Sobrien
9152284Sobrien/* Decode a format letter into the proper accessor function.  */
9252284Sobrien
9350397Sobrienstatic const char *
94132718Skanaccessor_from_format (int c)
9550397Sobrien{
9650397Sobrien  switch (c)
9750397Sobrien    {
9850397Sobrien    case 'i':
9950397Sobrien      return "XINT";
10090075Sobrien
10150397Sobrien    case 'w':
10250397Sobrien      return "XWINT";
10390075Sobrien
10450397Sobrien    case 's':
10550397Sobrien      return "XSTR";
10690075Sobrien
10790075Sobrien    case 'e':  case 'u':
10850397Sobrien      return "XEXP";
10990075Sobrien
11050397Sobrien    case 'E':
11150397Sobrien      return "XVEC";
11290075Sobrien
11350397Sobrien    case 'b':
11450397Sobrien      return "XBITMAP";
11590075Sobrien
11650397Sobrien    case 't':
11750397Sobrien      return "XTREE";
11890075Sobrien
119117395Skan    case 'B':
120117395Skan      return "XBBDEF";
121117395Skan
12250397Sobrien    default:
123169689Skan      gcc_unreachable ();
12450397Sobrien    }
12550397Sobrien}
12650397Sobrien
12790075Sobrien/* Return nonzero if we should ignore FMT, an RTL format, when making
12890075Sobrien   the list of formats we write routines to create.  */
12952284Sobrien
13050397Sobrienstatic int
131132718Skanspecial_format (const char *fmt)
13250397Sobrien{
13350397Sobrien  return (strchr (fmt, '*') != 0
13450397Sobrien	  || strchr (fmt, 'V') != 0
13550397Sobrien	  || strchr (fmt, 'S') != 0
13650397Sobrien	  || strchr (fmt, 'n') != 0);
13750397Sobrien}
13850397Sobrien
139117395Skan/* Return nonzero if the RTL code given by index IDX is one that we should
140117395Skan   generate a gen_rtx_raw_FOO macro for, not gen_rtx_FOO (because gen_rtx_FOO
141117395Skan   is a wrapper in emit-rtl.c).  */
14252284Sobrien
14350397Sobrienstatic int
144132718Skanspecial_rtx (int idx)
14550397Sobrien{
14650397Sobrien  return (strcmp (defs[idx].enumname, "CONST_INT") == 0
14750397Sobrien	  || strcmp (defs[idx].enumname, "REG") == 0
14890075Sobrien	  || strcmp (defs[idx].enumname, "SUBREG") == 0
149117395Skan	  || strcmp (defs[idx].enumname, "MEM") == 0
150117395Skan	  || strcmp (defs[idx].enumname, "CONST_VECTOR") == 0);
15150397Sobrien}
15250397Sobrien
153117395Skan/* Return nonzero if the RTL code given by index IDX is one that we should
154117395Skan   generate no macro for at all (because gen_rtx_FOO is never used or
155117395Skan   cannot have the obvious interface).  */
156117395Skan
157117395Skanstatic int
158132718Skanexcluded_rtx (int idx)
159117395Skan{
160117395Skan  return (strcmp (defs[idx].enumname, "CONST_DOUBLE") == 0);
161117395Skan}
162117395Skan
16390075Sobrien/* Place a list of all format specifiers we use into the array FORMAT.  */
16452284Sobrien
16550397Sobrienstatic void
166132718Skanfind_formats (void)
16750397Sobrien{
168132718Skan  unsigned int i;
16950397Sobrien
17090075Sobrien  for (i = 0; i < NUM_RTX_CODE; i++)
17150397Sobrien    {
17250397Sobrien      const char **f;
17350397Sobrien
17450397Sobrien      if (special_format (defs[i].format))
17550397Sobrien	continue;
17650397Sobrien
17790075Sobrien      for (f = formats; *f; f++)
17852284Sobrien	if (! strcmp (*f, defs[i].format))
17950397Sobrien	  break;
18050397Sobrien
18190075Sobrien      if (*f == 0)
18250397Sobrien	*f = defs[i].format;
18350397Sobrien    }
18450397Sobrien}
18550397Sobrien
18690075Sobrien/* Write the declarations for the routine to allocate RTL with FORMAT.  */
18752284Sobrien
18850397Sobrienstatic void
189132718Skangendecl (const char *format)
19050397Sobrien{
19150397Sobrien  const char *p;
19290075Sobrien  int i, pos;
193117395Skan
194132718Skan  printf ("extern rtx gen_rtx_fmt_%s\t (RTX_CODE, ", format);
19590075Sobrien  printf ("enum machine_mode mode");
19690075Sobrien
19790075Sobrien  /* Write each parameter that is needed and start a new line when the line
19890075Sobrien     would overflow.  */
19990075Sobrien  for (p = format, i = 0, pos = 75; *p != 0; p++)
20050397Sobrien    if (*p != '0')
20190075Sobrien      {
20290075Sobrien	int ourlen = strlen (type_from_format (*p)) + 6 + (i > 9);
20390075Sobrien
20490075Sobrien	printf (",");
20590075Sobrien	if (pos + ourlen > 76)
20690075Sobrien	  printf ("\n\t\t\t\t      "), pos = 39;
20790075Sobrien
20890075Sobrien	printf (" %sarg%d", type_from_format (*p), i++);
20990075Sobrien	pos += ourlen;
21090075Sobrien      }
21190075Sobrien
212132718Skan  printf (");\n");
21350397Sobrien}
21450397Sobrien
21590075Sobrien/* Generate macros to generate RTL of code IDX using the functions we
21690075Sobrien   write.  */
21752284Sobrien
218117395Skanstatic void
219132718Skangenmacro (int idx)
22050397Sobrien{
22150397Sobrien  const char *p;
22250397Sobrien  int i;
22350397Sobrien
22490075Sobrien  /* We write a macro that defines gen_rtx_RTLCODE to be an equivalent to
22590075Sobrien     gen_rtx_fmt_FORMAT where FORMAT is the RTX_FORMAT of RTLCODE.  */
22650397Sobrien
227117395Skan  if (excluded_rtx (idx))
228117395Skan    /* Don't define a macro for this code.  */
229117395Skan    return;
230117395Skan
23190075Sobrien  printf ("#define gen_rtx_%s%s(MODE",
23290075Sobrien	   special_rtx (idx) ? "raw_" : "", defs[idx].enumname);
23390075Sobrien
23490075Sobrien  for (p = defs[idx].format, i = 0; *p != 0; p++)
23550397Sobrien    if (*p != '0')
23690075Sobrien      printf (", ARG%d", i++);
23750397Sobrien
23890075Sobrien  printf (") \\\n  gen_rtx_fmt_%s (%s, (MODE)",
23990075Sobrien	  defs[idx].format, defs[idx].enumname);
24090075Sobrien
24190075Sobrien  for (p = defs[idx].format, i = 0; *p != 0; p++)
24250397Sobrien    if (*p != '0')
24390075Sobrien      printf (", (ARG%d)", i++);
24490075Sobrien
24590075Sobrien  puts (")");
24650397Sobrien}
24750397Sobrien
24890075Sobrien/* Generate the code for the function to generate RTL whose
24990075Sobrien   format is FORMAT.  */
25052284Sobrien
25150397Sobrienstatic void
252132718Skangendef (const char *format)
25350397Sobrien{
25450397Sobrien  const char *p;
25550397Sobrien  int i, j;
256117395Skan
25790075Sobrien  /* Start by writing the definition of the function name and the types
25890075Sobrien     of the arguments.  */
25990075Sobrien
260132718Skan  printf ("rtx\ngen_rtx_fmt_%s (RTX_CODE code, enum machine_mode mode", format);
26190075Sobrien  for (p = format, i = 0; *p != 0; p++)
26250397Sobrien    if (*p != '0')
263132718Skan      printf (",\n\t%sarg%d", type_from_format (*p), i++);
26450397Sobrien
265132718Skan  puts (")");
26650397Sobrien
26790075Sobrien  /* Now write out the body of the function itself, which allocates
26890075Sobrien     the memory and initializes it.  */
26990075Sobrien  puts ("{");
27090075Sobrien  puts ("  rtx rt;");
271169689Skan  puts ("  rt = rtx_alloc (code);\n");
27250397Sobrien
27390075Sobrien  puts ("  PUT_MODE (rt, mode);");
27450397Sobrien
27550397Sobrien  for (p = format, i = j = 0; *p ; ++p, ++i)
27650397Sobrien    if (*p != '0')
27790075Sobrien      printf ("  %s (rt, %d) = arg%d;\n", accessor_from_format (*p), i, j++);
27890075Sobrien    else
27990075Sobrien      printf ("  X0EXP (rt, %d) = NULL_RTX;\n", i);
28050397Sobrien
28190075Sobrien  puts ("\n  return rt;\n}\n");
28250397Sobrien}
28350397Sobrien
28490075Sobrien/* Generate the documentation header for files we write.  */
28552284Sobrien
28650397Sobrienstatic void
287132718Skangenlegend (void)
28850397Sobrien{
28990075Sobrien  puts ("/* Generated automatically by gengenrtl from rtl.def.  */\n");
29050397Sobrien}
29150397Sobrien
29290075Sobrien/* Generate the text of the header file we make, genrtl.h.  */
29352284Sobrien
29450397Sobrienstatic void
295132718Skangenheader (void)
29650397Sobrien{
297132718Skan  unsigned int i;
29850397Sobrien  const char **fmt;
29950397Sobrien
30090075Sobrien  puts ("#ifndef GCC_GENRTL_H");
30190075Sobrien  puts ("#define GCC_GENRTL_H\n");
30290075Sobrien
30350397Sobrien  for (fmt = formats; *fmt; ++fmt)
30490075Sobrien    gendecl (*fmt);
30550397Sobrien
30690075Sobrien  putchar ('\n');
30750397Sobrien
30850397Sobrien  for (i = 0; i < NUM_RTX_CODE; i++)
30990075Sobrien    if (! special_format (defs[i].format))
31090075Sobrien      genmacro (i);
31190075Sobrien
31290075Sobrien  puts ("\n#endif /* GCC_GENRTL_H */");
31350397Sobrien}
31450397Sobrien
31590075Sobrien/* Generate the text of the code file we write, genrtl.c.  */
31652284Sobrien
31750397Sobrienstatic void
318132718Skangencode (void)
31950397Sobrien{
32050397Sobrien  const char **fmt;
32150397Sobrien
32290075Sobrien  puts ("#include \"config.h\"");
32390075Sobrien  puts ("#include \"system.h\"");
324132718Skan  puts ("#include \"coretypes.h\"");
325132718Skan  puts ("#include \"tm.h\"");
32690075Sobrien  puts ("#include \"obstack.h\"");
32790075Sobrien  puts ("#include \"rtl.h\"");
32890075Sobrien  puts ("#include \"ggc.h\"\n");
32950397Sobrien
33090075Sobrien  for (fmt = formats; *fmt != 0; fmt++)
33190075Sobrien    gendef (*fmt);
33250397Sobrien}
33350397Sobrien
33490075Sobrien/* This is the main program.  We accept only one argument, "-h", which
33590075Sobrien   says we are writing the genrtl.h file.  Otherwise we are writing the
33690075Sobrien   genrtl.c file.  */
33750397Sobrien
33850397Sobrienint
339132718Skanmain (int argc, char **argv)
34050397Sobrien{
34150397Sobrien  find_formats ();
34290075Sobrien  genlegend ();
34350397Sobrien
34490075Sobrien  if (argc == 2 && argv[1][0] == '-' && argv[1][1] == 'h')
34590075Sobrien    genheader ();
34690075Sobrien  else
34790075Sobrien    gencode ();
34850397Sobrien
34990075Sobrien  if (ferror (stdout) || fflush (stdout) || fclose (stdout))
35090075Sobrien    return FATAL_EXIT_CODE;
35150397Sobrien
35290075Sobrien  return SUCCESS_EXIT_CODE;
35350397Sobrien}
354