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