1/* Generate code to allocate RTL structures. 2 Copyright (C) 1997, 1998, 1999, 2000, 2002, 2003, 2004 3 Free Software Foundation, Inc. 4 5This file is part of GCC. 6 7GCC is free software; you can redistribute it and/or modify it under 8the terms of the GNU General Public License as published by the Free 9Software Foundation; either version 2, or (at your option) any later 10version. 11 12GCC is distributed in the hope that it will be useful, but WITHOUT ANY 13WARRANTY; without even the implied warranty of MERCHANTABILITY or 14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15for more details. 16 17You should have received a copy of the GNU General Public License 18along with GCC; see the file COPYING. If not, write to the Free 19Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 2002110-1301, USA. */ 21 22 23#include "bconfig.h" 24#include "system.h" 25 26struct rtx_definition 27{ 28 const char *const enumname, *const name, *const format; 29}; 30 31/* rtl.def needs CONST_DOUBLE_FORMAT, but we don't care what 32 CONST_DOUBLE_FORMAT is because we're not going to be generating 33 anything for CONST_DOUBLE anyway. */ 34#define CONST_DOUBLE_FORMAT "" 35 36#define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS) { #ENUM, NAME, FORMAT }, 37 38static const struct rtx_definition defs[] = 39{ 40#include "rtl.def" /* rtl expressions are documented here */ 41}; 42#define NUM_RTX_CODE ARRAY_SIZE(defs) 43 44static 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