1/* Generate code to allocate RTL structures. 2 Copyright (C) 1997, 1998, 1999, 2000, 2002 Free Software Foundation, Inc. 3 4This file is part of GCC. 5 6GCC is free software; you can redistribute it and/or modify it under 7the terms of the GNU General Public License as published by the Free 8Software Foundation; either version 2, or (at your option) any later 9version. 10 11GCC is distributed in the hope that it will be useful, but WITHOUT ANY 12WARRANTY; without even the implied warranty of MERCHANTABILITY or 13FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14for more details. 15 16You should have received a copy of the GNU General Public License 17along with GCC; see the file COPYING. If not, write to the Free 18Software Foundation, 59 Temple Place - Suite 330, Boston, MA 1902111-1307, USA. */ 20 21 22#include "hconfig.h" 23#include "system.h" 24 25#define NO_GENRTL_H 26#include "rtl.h" 27#undef abort 28 29#include "real.h" 30 31struct rtx_definition 32{ 33 const char *const enumname, *const name, *const format; 34}; 35 36#define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS) { STRINGX(ENUM), NAME, FORMAT }, 37 38static const struct rtx_definition defs[] = 39{ 40#include "rtl.def" /* rtl expressions are documented here */ 41}; 42 43static const char *formats[NUM_RTX_CODE]; 44 45static const char *type_from_format PARAMS ((int)); 46static const char *accessor_from_format PARAMS ((int)); 47static int special_format PARAMS ((const char *)); 48static int special_rtx PARAMS ((int)); 49static int excluded_rtx PARAMS ((int)); 50static void find_formats PARAMS ((void)); 51static void gendecl PARAMS ((const char *)); 52static void genmacro PARAMS ((int)); 53static void gendef PARAMS ((const char *)); 54static void genlegend PARAMS ((void)); 55static void genheader PARAMS ((void)); 56static void gencode PARAMS ((void)); 57 58/* Decode a format letter into a C type string. */ 59 60static const char * 61type_from_format (c) 62 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 abort (); 88 } 89} 90 91/* Decode a format letter into the proper accessor function. */ 92 93static const char * 94accessor_from_format (c) 95 int c; 96{ 97 switch (c) 98 { 99 case 'i': 100 return "XINT"; 101 102 case 'w': 103 return "XWINT"; 104 105 case 's': 106 return "XSTR"; 107 108 case 'e': case 'u': 109 return "XEXP"; 110 111 case 'E': 112 return "XVEC"; 113 114 case 'b': 115 return "XBITMAP"; 116 117 case 't': 118 return "XTREE"; 119 120 case 'B': 121 return "XBBDEF"; 122 123 default: 124 abort (); 125 } 126} 127 128/* Return nonzero if we should ignore FMT, an RTL format, when making 129 the list of formats we write routines to create. */ 130 131static int 132special_format (fmt) 133 const char *fmt; 134{ 135 return (strchr (fmt, '*') != 0 136 || strchr (fmt, 'V') != 0 137 || strchr (fmt, 'S') != 0 138 || strchr (fmt, 'n') != 0); 139} 140 141/* Return nonzero if the RTL code given by index IDX is one that we should 142 generate a gen_rtx_raw_FOO macro for, not gen_rtx_FOO (because gen_rtx_FOO 143 is a wrapper in emit-rtl.c). */ 144 145static int 146special_rtx (idx) 147 int idx; 148{ 149 return (strcmp (defs[idx].enumname, "CONST_INT") == 0 150 || strcmp (defs[idx].enumname, "REG") == 0 151 || strcmp (defs[idx].enumname, "SUBREG") == 0 152 || strcmp (defs[idx].enumname, "MEM") == 0 153 || strcmp (defs[idx].enumname, "CONST_VECTOR") == 0); 154} 155 156/* Return nonzero if the RTL code given by index IDX is one that we should 157 generate no macro for at all (because gen_rtx_FOO is never used or 158 cannot have the obvious interface). */ 159 160static int 161excluded_rtx (idx) 162 int idx; 163{ 164 return (strcmp (defs[idx].enumname, "CONST_DOUBLE") == 0); 165} 166 167/* Place a list of all format specifiers we use into the array FORMAT. */ 168 169static void 170find_formats () 171{ 172 int i; 173 174 for (i = 0; i < NUM_RTX_CODE; i++) 175 { 176 const char **f; 177 178 if (special_format (defs[i].format)) 179 continue; 180 181 for (f = formats; *f; f++) 182 if (! strcmp (*f, defs[i].format)) 183 break; 184 185 if (*f == 0) 186 *f = defs[i].format; 187 } 188} 189 190/* Write the declarations for the routine to allocate RTL with FORMAT. */ 191 192static void 193gendecl (format) 194 const char *format; 195{ 196 const char *p; 197 int i, pos; 198 199 printf ("extern rtx gen_rtx_fmt_%s\tPARAMS ((RTX_CODE, ", format); 200 printf ("enum machine_mode mode"); 201 202 /* Write each parameter that is needed and start a new line when the line 203 would overflow. */ 204 for (p = format, i = 0, pos = 75; *p != 0; p++) 205 if (*p != '0') 206 { 207 int ourlen = strlen (type_from_format (*p)) + 6 + (i > 9); 208 209 printf (","); 210 if (pos + ourlen > 76) 211 printf ("\n\t\t\t\t "), pos = 39; 212 213 printf (" %sarg%d", type_from_format (*p), i++); 214 pos += ourlen; 215 } 216 217 printf ("));\n"); 218} 219 220/* Generate macros to generate RTL of code IDX using the functions we 221 write. */ 222 223static void 224genmacro (idx) 225 int idx; 226{ 227 const char *p; 228 int i; 229 230 /* We write a macro that defines gen_rtx_RTLCODE to be an equivalent to 231 gen_rtx_fmt_FORMAT where FORMAT is the RTX_FORMAT of RTLCODE. */ 232 233 if (excluded_rtx (idx)) 234 /* Don't define a macro for this code. */ 235 return; 236 237 printf ("#define gen_rtx_%s%s(MODE", 238 special_rtx (idx) ? "raw_" : "", defs[idx].enumname); 239 240 for (p = defs[idx].format, i = 0; *p != 0; p++) 241 if (*p != '0') 242 printf (", ARG%d", i++); 243 244 printf (") \\\n gen_rtx_fmt_%s (%s, (MODE)", 245 defs[idx].format, defs[idx].enumname); 246 247 for (p = defs[idx].format, i = 0; *p != 0; p++) 248 if (*p != '0') 249 printf (", (ARG%d)", i++); 250 251 puts (")"); 252} 253 254/* Generate the code for the function to generate RTL whose 255 format is FORMAT. */ 256 257static void 258gendef (format) 259 const char *format; 260{ 261 const char *p; 262 int i, j; 263 264 /* Start by writing the definition of the function name and the types 265 of the arguments. */ 266 267 printf ("rtx\ngen_rtx_fmt_%s (code, mode", format); 268 for (p = format, i = 0; *p != 0; p++) 269 if (*p != '0') 270 printf (", arg%d", i++); 271 272 puts (")\n RTX_CODE code;\n enum machine_mode mode;"); 273 for (p = format, i = 0; *p != 0; p++) 274 if (*p != '0') 275 printf (" %sarg%d;\n", type_from_format (*p), i++); 276 277 /* Now write out the body of the function itself, which allocates 278 the memory and initializes it. */ 279 puts ("{"); 280 puts (" rtx rt;"); 281 printf (" rt = ggc_alloc_rtx (%d);\n", (int) strlen (format)); 282 283 puts (" memset (rt, 0, sizeof (struct rtx_def) - sizeof (rtunion));\n"); 284 puts (" PUT_CODE (rt, code);"); 285 puts (" PUT_MODE (rt, mode);"); 286 287 for (p = format, i = j = 0; *p ; ++p, ++i) 288 if (*p != '0') 289 printf (" %s (rt, %d) = arg%d;\n", accessor_from_format (*p), i, j++); 290 else 291 printf (" X0EXP (rt, %d) = NULL_RTX;\n", i); 292 293 puts ("\n return rt;\n}\n"); 294} 295 296/* Generate the documentation header for files we write. */ 297 298static void 299genlegend () 300{ 301 puts ("/* Generated automatically by gengenrtl from rtl.def. */\n"); 302} 303 304/* Generate the text of the header file we make, genrtl.h. */ 305 306static void 307genheader () 308{ 309 int i; 310 const char **fmt; 311 312 puts ("#ifndef GCC_GENRTL_H"); 313 puts ("#define GCC_GENRTL_H\n"); 314 315 for (fmt = formats; *fmt; ++fmt) 316 gendecl (*fmt); 317 318 putchar ('\n'); 319 320 for (i = 0; i < NUM_RTX_CODE; i++) 321 if (! special_format (defs[i].format)) 322 genmacro (i); 323 324 puts ("\n#endif /* GCC_GENRTL_H */"); 325} 326 327/* Generate the text of the code file we write, genrtl.c. */ 328 329static void 330gencode () 331{ 332 const char **fmt; 333 334 puts ("#include \"config.h\""); 335 puts ("#include \"system.h\""); 336 puts ("#include \"obstack.h\""); 337 puts ("#include \"rtl.h\""); 338 puts ("#include \"ggc.h\"\n"); 339 puts ("extern struct obstack *rtl_obstack;\n"); 340 341 for (fmt = formats; *fmt != 0; fmt++) 342 gendef (*fmt); 343} 344 345/* This is the main program. We accept only one argument, "-h", which 346 says we are writing the genrtl.h file. Otherwise we are writing the 347 genrtl.c file. */ 348extern int main PARAMS ((int, char **)); 349 350int 351main (argc, argv) 352 int argc; 353 char **argv; 354{ 355 find_formats (); 356 genlegend (); 357 358 if (argc == 2 && argv[1][0] == '-' && argv[1][1] == 'h') 359 genheader (); 360 else 361 gencode (); 362 363 if (ferror (stdout) || fflush (stdout) || fclose (stdout)) 364 return FATAL_EXIT_CODE; 365 366 return SUCCESS_EXIT_CODE; 367} 368