gengenrtl.c revision 303975
1234285Sdim/* Generate code to allocate RTL structures. 2234285Sdim Copyright (C) 1997, 1998, 1999, 2000, 2002, 2003, 2004 3234285Sdim Free Software Foundation, Inc. 4234285Sdim 5234285SdimThis file is part of GCC. 6234285Sdim 7234285SdimGCC is free software; you can redistribute it and/or modify it under 8234285Sdimthe terms of the GNU General Public License as published by the Free 9234285SdimSoftware Foundation; either version 2, or (at your option) any later 10234285Sdimversion. 11234285Sdim 12234285SdimGCC is distributed in the hope that it will be useful, but WITHOUT ANY 13234285SdimWARRANTY; without even the implied warranty of MERCHANTABILITY or 14249423SdimFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15234285Sdimfor more details. 16234285Sdim 17234285SdimYou should have received a copy of the GNU General Public License 18234285Sdimalong with GCC; see the file COPYING. If not, write to the Free 19234285SdimSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 20234285Sdim02110-1301, USA. */ 21234285Sdim 22234285Sdim 23234285Sdim#include "bconfig.h" 24234285Sdim#include "system.h" 25234285Sdim 26234285Sdimstruct rtx_definition 27234285Sdim{ 28234285Sdim const char *const enumname, *const name, *const format; 29234285Sdim}; 30234285Sdim 31234285Sdim/* rtl.def needs CONST_DOUBLE_FORMAT, but we don't care what 32234285Sdim CONST_DOUBLE_FORMAT is because we're not going to be generating 33234285Sdim anything for CONST_DOUBLE anyway. */ 34234285Sdim#define CONST_DOUBLE_FORMAT "" 35234285Sdim 36234285Sdim#define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS) { #ENUM, NAME, FORMAT }, 37234285Sdim 38234285Sdimstatic const struct rtx_definition defs[] = 39234285Sdim{ 40234285Sdim#include "rtl.def" /* rtl expressions are documented here */ 41234285Sdim}; 42234285Sdim#define NUM_RTX_CODE ARRAY_SIZE(defs) 43234285Sdim 44234285Sdimstatic const char *formats[NUM_RTX_CODE]; 45 46static const char *type_from_format (int); 47static const char *accessor_from_format (int); 48static int special_format (const char *); 49static int special_rtx (int); 50static int excluded_rtx (int); 51static void find_formats (void); 52static void gendecl (const char *); 53static void genmacro (int); 54static void gendef (const char *); 55static void genlegend (void); 56static void genheader (void); 57static void gencode (void); 58 59/* Decode a format letter into a C type string. */ 60 61static const char * 62type_from_format (int c) 63{ 64 switch (c) 65 { 66 case 'i': 67 return "int "; 68 69 case 'w': 70 return "HOST_WIDE_INT "; 71 72 case 's': 73 return "const char *"; 74 75 case 'e': case 'u': 76 return "rtx "; 77 78 case 'E': 79 return "rtvec "; 80 case 'b': 81 return "struct bitmap_head_def *"; /* bitmap - typedef not available */ 82 case 't': 83 return "union tree_node *"; /* tree - typedef not available */ 84 case 'B': 85 return "struct basic_block_def *"; /* basic block - typedef not available */ 86 default: 87 gcc_unreachable (); 88 } 89} 90 91/* Decode a format letter into the proper accessor function. */ 92 93static const char * 94accessor_from_format (int c) 95{ 96 switch (c) 97 { 98 case 'i': 99 return "XINT"; 100 101 case 'w': 102 return "XWINT"; 103 104 case 's': 105 return "XSTR"; 106 107 case 'e': case 'u': 108 return "XEXP"; 109 110 case 'E': 111 return "XVEC"; 112 113 case 'b': 114 return "XBITMAP"; 115 116 case 't': 117 return "XTREE"; 118 119 case 'B': 120 return "XBBDEF"; 121 122 default: 123 gcc_unreachable (); 124 } 125} 126 127/* Return nonzero if we should ignore FMT, an RTL format, when making 128 the list of formats we write routines to create. */ 129 130static int 131special_format (const char *fmt) 132{ 133 return (strchr (fmt, '*') != 0 134 || strchr (fmt, 'V') != 0 135 || strchr (fmt, 'S') != 0 136 || strchr (fmt, 'n') != 0); 137} 138 139/* Return nonzero if the RTL code given by index IDX is one that we should 140 generate a gen_rtx_raw_FOO macro for, not gen_rtx_FOO (because gen_rtx_FOO 141 is a wrapper in emit-rtl.c). */ 142 143static int 144special_rtx (int idx) 145{ 146 return (strcmp (defs[idx].enumname, "CONST_INT") == 0 147 || strcmp (defs[idx].enumname, "REG") == 0 148 || strcmp (defs[idx].enumname, "SUBREG") == 0 149 || strcmp (defs[idx].enumname, "MEM") == 0 150 || strcmp (defs[idx].enumname, "CONST_VECTOR") == 0); 151} 152 153/* Return nonzero if the RTL code given by index IDX is one that we should 154 generate no macro for at all (because gen_rtx_FOO is never used or 155 cannot have the obvious interface). */ 156 157static int 158excluded_rtx (int idx) 159{ 160 return (strcmp (defs[idx].enumname, "CONST_DOUBLE") == 0); 161} 162 163/* Place a list of all format specifiers we use into the array FORMAT. */ 164 165static void 166find_formats (void) 167{ 168 unsigned int i; 169 170 for (i = 0; i < NUM_RTX_CODE; i++) 171 { 172 const char **f; 173 174 if (special_format (defs[i].format)) 175 continue; 176 177 for (f = formats; *f; f++) 178 if (! strcmp (*f, defs[i].format)) 179 break; 180 181 if (*f == 0) 182 *f = defs[i].format; 183 } 184} 185 186/* Write the declarations for the routine to allocate RTL with FORMAT. */ 187 188static void 189gendecl (const char *format) 190{ 191 const char *p; 192 int i, pos; 193 194 printf ("extern rtx gen_rtx_fmt_%s\t (RTX_CODE, ", format); 195 printf ("enum machine_mode mode"); 196 197 /* Write each parameter that is needed and start a new line when the line 198 would overflow. */ 199 for (p = format, i = 0, pos = 75; *p != 0; p++) 200 if (*p != '0') 201 { 202 int ourlen = strlen (type_from_format (*p)) + 6 + (i > 9); 203 204 printf (","); 205 if (pos + ourlen > 76) 206 printf ("\n\t\t\t\t "), pos = 39; 207 208 printf (" %sarg%d", type_from_format (*p), i++); 209 pos += ourlen; 210 } 211 212 printf (");\n"); 213} 214 215/* Generate macros to generate RTL of code IDX using the functions we 216 write. */ 217 218static void 219genmacro (int idx) 220{ 221 const char *p; 222 int i; 223 224 /* We write a macro that defines gen_rtx_RTLCODE to be an equivalent to 225 gen_rtx_fmt_FORMAT where FORMAT is the RTX_FORMAT of RTLCODE. */ 226 227 if (excluded_rtx (idx)) 228 /* Don't define a macro for this code. */ 229 return; 230 231 printf ("#define gen_rtx_%s%s(MODE", 232 special_rtx (idx) ? "raw_" : "", defs[idx].enumname); 233 234 for (p = defs[idx].format, i = 0; *p != 0; p++) 235 if (*p != '0') 236 printf (", ARG%d", i++); 237 238 printf (") \\\n gen_rtx_fmt_%s (%s, (MODE)", 239 defs[idx].format, defs[idx].enumname); 240 241 for (p = defs[idx].format, i = 0; *p != 0; p++) 242 if (*p != '0') 243 printf (", (ARG%d)", i++); 244 245 puts (")"); 246} 247 248/* Generate the code for the function to generate RTL whose 249 format is FORMAT. */ 250 251static void 252gendef (const char *format) 253{ 254 const char *p; 255 int i, j; 256 257 /* Start by writing the definition of the function name and the types 258 of the arguments. */ 259 260 printf ("rtx\ngen_rtx_fmt_%s (RTX_CODE code, enum machine_mode mode", format); 261 for (p = format, i = 0; *p != 0; p++) 262 if (*p != '0') 263 printf (",\n\t%sarg%d", type_from_format (*p), i++); 264 265 puts (")"); 266 267 /* Now write out the body of the function itself, which allocates 268 the memory and initializes it. */ 269 puts ("{"); 270 puts (" rtx rt;"); 271 puts (" rt = rtx_alloc (code);\n"); 272 273 puts (" PUT_MODE (rt, mode);"); 274 275 for (p = format, i = j = 0; *p ; ++p, ++i) 276 if (*p != '0') 277 printf (" %s (rt, %d) = arg%d;\n", accessor_from_format (*p), i, j++); 278 else 279 printf (" X0EXP (rt, %d) = NULL_RTX;\n", i); 280 281 puts ("\n return rt;\n}\n"); 282} 283 284/* Generate the documentation header for files we write. */ 285 286static void 287genlegend (void) 288{ 289 puts ("/* Generated automatically by gengenrtl from rtl.def. */\n"); 290} 291 292/* Generate the text of the header file we make, genrtl.h. */ 293 294static void 295genheader (void) 296{ 297 unsigned int i; 298 const char **fmt; 299 300 puts ("#ifndef GCC_GENRTL_H"); 301 puts ("#define GCC_GENRTL_H\n"); 302 303 for (fmt = formats; *fmt; ++fmt) 304 gendecl (*fmt); 305 306 putchar ('\n'); 307 308 for (i = 0; i < NUM_RTX_CODE; i++) 309 if (! special_format (defs[i].format)) 310 genmacro (i); 311 312 puts ("\n#endif /* GCC_GENRTL_H */"); 313} 314 315/* Generate the text of the code file we write, genrtl.c. */ 316 317static void 318gencode (void) 319{ 320 const char **fmt; 321 322 puts ("#include \"config.h\""); 323 puts ("#include \"system.h\""); 324 puts ("#include \"coretypes.h\""); 325 puts ("#include \"tm.h\""); 326 puts ("#include \"obstack.h\""); 327 puts ("#include \"rtl.h\""); 328 puts ("#include \"ggc.h\"\n"); 329 330 for (fmt = formats; *fmt != 0; fmt++) 331 gendef (*fmt); 332} 333 334/* This is the main program. We accept only one argument, "-h", which 335 says we are writing the genrtl.h file. Otherwise we are writing the 336 genrtl.c file. */ 337 338int 339main (int argc, char **argv) 340{ 341 find_formats (); 342 genlegend (); 343 344 if (argc == 2 && argv[1][0] == '-' && argv[1][1] == 'h') 345 genheader (); 346 else 347 gencode (); 348 349 if (ferror (stdout) || fflush (stdout) || fclose (stdout)) 350 return FATAL_EXIT_CODE; 351 352 return SUCCESS_EXIT_CODE; 353} 354