gengenrtl.c revision 90075
1/* Generate code to allocate RTL structures. 2 Copyright (C) 1997, 1998, 1999, 2000 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 31/* Calculate the format for CONST_DOUBLE. This depends on the relative 32 widths of HOST_WIDE_INT and REAL_VALUE_TYPE. 33 34 We need to go out to e0wwwww, since REAL_ARITHMETIC assumes 16-bits 35 per element in REAL_VALUE_TYPE. 36 37 This is duplicated in rtl.c. 38 39 A number of places assume that there are always at least two 'w' 40 slots in a CONST_DOUBLE, so we provide them even if one would suffice. */ 41 42#ifdef REAL_ARITHMETIC 43# if MAX_LONG_DOUBLE_TYPE_SIZE == 96 44# define REAL_WIDTH \ 45 (11*8 + HOST_BITS_PER_WIDE_INT)/HOST_BITS_PER_WIDE_INT 46# else 47# if MAX_LONG_DOUBLE_TYPE_SIZE == 128 48# define REAL_WIDTH \ 49 (19*8 + HOST_BITS_PER_WIDE_INT)/HOST_BITS_PER_WIDE_INT 50# else 51# if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT 52# define REAL_WIDTH \ 53 (7*8 + HOST_BITS_PER_WIDE_INT)/HOST_BITS_PER_WIDE_INT 54# endif 55# endif 56# endif 57#endif /* REAL_ARITHMETIC */ 58 59#ifndef REAL_WIDTH 60# if HOST_BITS_PER_WIDE_INT*2 >= MAX_LONG_DOUBLE_TYPE_SIZE 61# define REAL_WIDTH 2 62# else 63# if HOST_BITS_PER_WIDE_INT*3 >= MAX_LONG_DOUBLE_TYPE_SIZE 64# define REAL_WIDTH 3 65# else 66# if HOST_BITS_PER_WIDE_INT*4 >= MAX_LONG_DOUBLE_TYPE_SIZE 67# define REAL_WIDTH 4 68# endif 69# endif 70# endif 71#endif /* REAL_WIDTH */ 72 73#if REAL_WIDTH == 1 74# define CONST_DOUBLE_FORMAT "0ww" 75#else 76# if REAL_WIDTH == 2 77# define CONST_DOUBLE_FORMAT "0ww" 78# else 79# if REAL_WIDTH == 3 80# define CONST_DOUBLE_FORMAT "0www" 81# else 82# if REAL_WIDTH == 4 83# define CONST_DOUBLE_FORMAT "0wwww" 84# else 85# if REAL_WIDTH == 5 86# define CONST_DOUBLE_FORMAT "0wwwww" 87# else 88# define CONST_DOUBLE_FORMAT /* nothing - will cause syntax error */ 89# endif 90# endif 91# endif 92# endif 93#endif 94 95 96struct rtx_definition 97{ 98 const char *const enumname, *const name, *const format; 99}; 100 101#define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS) { STRINGX(ENUM), NAME, FORMAT }, 102 103static const struct rtx_definition defs[] = 104{ 105#include "rtl.def" /* rtl expressions are documented here */ 106}; 107 108static const char *formats[NUM_RTX_CODE]; 109 110static const char *type_from_format PARAMS ((int)); 111static const char *accessor_from_format PARAMS ((int)); 112static int special_format PARAMS ((const char *)); 113static int special_rtx PARAMS ((int)); 114static void find_formats PARAMS ((void)); 115static void gendecl PARAMS ((const char *)); 116static void genmacro PARAMS ((int)); 117static void gendef PARAMS ((const char *)); 118static void genlegend PARAMS ((void)); 119static void genheader PARAMS ((void)); 120static void gencode PARAMS ((void)); 121 122/* Decode a format letter into a C type string. */ 123 124static const char * 125type_from_format (c) 126 int c; 127{ 128 switch (c) 129 { 130 case 'i': 131 return "int "; 132 133 case 'w': 134 return "HOST_WIDE_INT "; 135 136 case 's': 137 return "const char *"; 138 139 case 'e': case 'u': 140 return "rtx "; 141 142 case 'E': 143 return "rtvec "; 144 case 'b': 145 return "struct bitmap_head_def *"; /* bitmap - typedef not available */ 146 case 't': 147 return "union tree_node *"; /* tree - typedef not available */ 148 default: 149 abort (); 150 } 151} 152 153/* Decode a format letter into the proper accessor function. */ 154 155static const char * 156accessor_from_format (c) 157 int c; 158{ 159 switch (c) 160 { 161 case 'i': 162 return "XINT"; 163 164 case 'w': 165 return "XWINT"; 166 167 case 's': 168 return "XSTR"; 169 170 case 'e': case 'u': 171 return "XEXP"; 172 173 case 'E': 174 return "XVEC"; 175 176 case 'b': 177 return "XBITMAP"; 178 179 case 't': 180 return "XTREE"; 181 182 default: 183 abort (); 184 } 185} 186 187/* Return nonzero if we should ignore FMT, an RTL format, when making 188 the list of formats we write routines to create. */ 189 190static int 191special_format (fmt) 192 const char *fmt; 193{ 194 return (strchr (fmt, '*') != 0 195 || strchr (fmt, 'V') != 0 196 || strchr (fmt, 'S') != 0 197 || strchr (fmt, 'n') != 0); 198} 199 200/* Return nonzero if the RTL code given by index IDX is one that we should not 201 generate a gen_RTX_FOO function foo (because that function is present 202 elsewhere in the compiler). */ 203 204static int 205special_rtx (idx) 206 int idx; 207{ 208 return (strcmp (defs[idx].enumname, "CONST_INT") == 0 209 || strcmp (defs[idx].enumname, "CONST_DOUBLE") == 0 210 || strcmp (defs[idx].enumname, "REG") == 0 211 || strcmp (defs[idx].enumname, "SUBREG") == 0 212 || strcmp (defs[idx].enumname, "MEM") == 0); 213} 214 215/* Place a list of all format specifiers we use into the array FORMAT. */ 216 217static void 218find_formats () 219{ 220 int i; 221 222 for (i = 0; i < NUM_RTX_CODE; i++) 223 { 224 const char **f; 225 226 if (special_format (defs[i].format)) 227 continue; 228 229 for (f = formats; *f; f++) 230 if (! strcmp (*f, defs[i].format)) 231 break; 232 233 if (*f == 0) 234 *f = defs[i].format; 235 } 236} 237 238/* Write the declarations for the routine to allocate RTL with FORMAT. */ 239 240static void 241gendecl (format) 242 const char *format; 243{ 244 const char *p; 245 int i, pos; 246 247 printf ("extern rtx gen_rtx_fmt_%s\tPARAMS ((RTX_CODE, ", format); 248 printf ("enum machine_mode mode"); 249 250 /* Write each parameter that is needed and start a new line when the line 251 would overflow. */ 252 for (p = format, i = 0, pos = 75; *p != 0; p++) 253 if (*p != '0') 254 { 255 int ourlen = strlen (type_from_format (*p)) + 6 + (i > 9); 256 257 printf (","); 258 if (pos + ourlen > 76) 259 printf ("\n\t\t\t\t "), pos = 39; 260 261 printf (" %sarg%d", type_from_format (*p), i++); 262 pos += ourlen; 263 } 264 265 printf ("));\n"); 266} 267 268/* Generate macros to generate RTL of code IDX using the functions we 269 write. */ 270 271static void 272genmacro (idx) 273 int idx; 274{ 275 const char *p; 276 int i; 277 278 /* We write a macro that defines gen_rtx_RTLCODE to be an equivalent to 279 gen_rtx_fmt_FORMAT where FORMAT is the RTX_FORMAT of RTLCODE. */ 280 281 printf ("#define gen_rtx_%s%s(MODE", 282 special_rtx (idx) ? "raw_" : "", defs[idx].enumname); 283 284 for (p = defs[idx].format, i = 0; *p != 0; p++) 285 if (*p != '0') 286 printf (", ARG%d", i++); 287 288 printf (") \\\n gen_rtx_fmt_%s (%s, (MODE)", 289 defs[idx].format, defs[idx].enumname); 290 291 for (p = defs[idx].format, i = 0; *p != 0; p++) 292 if (*p != '0') 293 printf (", (ARG%d)", i++); 294 295 puts (")"); 296} 297 298/* Generate the code for the function to generate RTL whose 299 format is FORMAT. */ 300 301static void 302gendef (format) 303 const char *format; 304{ 305 const char *p; 306 int i, j; 307 308 /* Start by writing the definition of the function name and the types 309 of the arguments. */ 310 311 printf ("rtx\ngen_rtx_fmt_%s (code, mode", format); 312 for (p = format, i = 0; *p != 0; p++) 313 if (*p != '0') 314 printf (", arg%d", i++); 315 316 puts (")\n RTX_CODE code;\n enum machine_mode mode;"); 317 for (p = format, i = 0; *p != 0; p++) 318 if (*p != '0') 319 printf (" %sarg%d;\n", type_from_format (*p), i++); 320 321 /* Now write out the body of the function itself, which allocates 322 the memory and initializes it. */ 323 puts ("{"); 324 puts (" rtx rt;"); 325 printf (" rt = ggc_alloc_rtx (%d);\n", (int) strlen (format)); 326 327 puts (" memset (rt, 0, sizeof (struct rtx_def) - sizeof (rtunion));\n"); 328 puts (" PUT_CODE (rt, code);"); 329 puts (" PUT_MODE (rt, mode);"); 330 331 for (p = format, i = j = 0; *p ; ++p, ++i) 332 if (*p != '0') 333 printf (" %s (rt, %d) = arg%d;\n", accessor_from_format (*p), i, j++); 334 else 335 printf (" X0EXP (rt, %d) = NULL_RTX;\n", i); 336 337 puts ("\n return rt;\n}\n"); 338} 339 340/* Generate the documentation header for files we write. */ 341 342static void 343genlegend () 344{ 345 puts ("/* Generated automatically by gengenrtl from rtl.def. */\n"); 346} 347 348/* Generate the text of the header file we make, genrtl.h. */ 349 350static void 351genheader () 352{ 353 int i; 354 const char **fmt; 355 356 puts ("#ifndef GCC_GENRTL_H"); 357 puts ("#define GCC_GENRTL_H\n"); 358 359 for (fmt = formats; *fmt; ++fmt) 360 gendecl (*fmt); 361 362 putchar ('\n'); 363 364 for (i = 0; i < NUM_RTX_CODE; i++) 365 if (! special_format (defs[i].format)) 366 genmacro (i); 367 368 puts ("\n#endif /* GCC_GENRTL_H */"); 369} 370 371/* Generate the text of the code file we write, genrtl.c. */ 372 373static void 374gencode () 375{ 376 const char **fmt; 377 378 puts ("#include \"config.h\""); 379 puts ("#include \"system.h\""); 380 puts ("#include \"obstack.h\""); 381 puts ("#include \"rtl.h\""); 382 puts ("#include \"ggc.h\"\n"); 383 puts ("extern struct obstack *rtl_obstack;\n"); 384 puts ("#define obstack_alloc_rtx(n) \\"); 385 puts (" ((rtx) obstack_alloc (rtl_obstack, \\"); 386 puts (" sizeof (struct rtx_def) \\"); 387 puts (" + ((n) - 1) * sizeof (rtunion)))\n"); 388 389 for (fmt = formats; *fmt != 0; fmt++) 390 gendef (*fmt); 391} 392 393/* This is the main program. We accept only one argument, "-h", which 394 says we are writing the genrtl.h file. Otherwise we are writing the 395 genrtl.c file. */ 396extern int main PARAMS ((int, char **)); 397 398int 399main (argc, argv) 400 int argc; 401 char **argv; 402{ 403 find_formats (); 404 genlegend (); 405 406 if (argc == 2 && argv[1][0] == '-' && argv[1][1] == 'h') 407 genheader (); 408 else 409 gencode (); 410 411 if (ferror (stdout) || fflush (stdout) || fclose (stdout)) 412 return FATAL_EXIT_CODE; 413 414 return SUCCESS_EXIT_CODE; 415} 416