1/* Generate code to allocate RTL structures. 2 Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc. 3 4This file is part of GNU CC. 5 6GNU CC is free software; you can redistribute it and/or modify 7it under the terms of the GNU General Public License as published by 8the Free Software Foundation; either version 2, or (at your option) 9any later version. 10 11GNU CC is distributed in the hope that it will be useful, 12but WITHOUT ANY WARRANTY; without even the implied warranty of 13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14GNU General Public License for more details. 15 16You should have received a copy of the GNU General Public License 17along with GNU CC; see the file COPYING. If not, write to 18the Free Software Foundation, 59 Temple Place - Suite 330, 19Boston, MA 02111-1307, USA. */ 20 21 22#include "hconfig.h" 23#include "system.h" 24#undef abort 25 26#define NO_GENRTL_H 27#include "rtl.h" 28 29 30struct rtx_definition 31{ 32 const char *enumname, *name, *format; 33}; 34 35#define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS) { STRINGIFY(ENUM), NAME, FORMAT }, 36 37struct rtx_definition defs[] = 38{ 39#include "rtl.def" /* rtl expressions are documented here */ 40}; 41 42const char *formats[NUM_RTX_CODE]; 43 44static const char *type_from_format PROTO((int)); 45static const char *accessor_from_format PROTO((int)); 46static int special_format PROTO((const char *)); 47static int special_rtx PROTO((int)); 48static void find_formats PROTO((void)); 49static void gendecl PROTO((FILE *, const char *)); 50static void genmacro PROTO((FILE *, int)); 51static void gendef PROTO((FILE *, const char *)); 52static void genlegend PROTO((FILE *)); 53static void genheader PROTO((FILE *)); 54static void gencode PROTO((FILE *)); 55 56/* Decode a format letter into a C type string. */ 57 58static const char * 59type_from_format (c) 60 int c; 61{ 62 switch (c) 63 { 64 case 'i': 65 return "int"; 66 case 'w': 67 return "HOST_WIDE_INT"; 68 case 's': 69 return "char *"; 70 case 'e': 71 case 'u': 72 return "rtx"; 73 case 'E': 74 return "rtvec"; 75 /* ?!? These should be bitmap and tree respectively, but those types 76 are not available in many of the files which include the output 77 of gengenrtl. 78 79 These are only used in prototypes, so I think we can assume that 80 void * is useable. */ 81 case 'b': 82 return "void *"; 83 case 't': 84 return "void *"; 85 default: 86 abort (); 87 } 88} 89 90/* Decode a format letter into the proper accessor function. */ 91 92static const char * 93accessor_from_format (c) 94 int c; 95{ 96 switch (c) 97 { 98 case 'i': 99 return "XINT"; 100 case 'w': 101 return "XWINT"; 102 case 's': 103 return "XSTR"; 104 case 'e': 105 case 'u': 106 return "XEXP"; 107 case 'E': 108 return "XVEC"; 109 case 'b': 110 return "XBITMAP"; 111 case 't': 112 return "XTREE"; 113 default: 114 abort (); 115 } 116} 117 118/* Return true if a format character doesn't need normal processing. */ 119 120static int 121special_format (fmt) 122 const char *fmt; 123{ 124 return (strchr (fmt, '*') != 0 125 || strchr (fmt, 'V') != 0 126 || strchr (fmt, 'S') != 0 127 || strchr (fmt, 'n') != 0); 128} 129 130/* Return true if an rtx requires special processing. */ 131 132static int 133special_rtx (idx) 134 int idx; 135{ 136 return (strcmp (defs[idx].enumname, "CONST_INT") == 0 137 || strcmp (defs[idx].enumname, "CONST_DOUBLE") == 0 138 || strcmp (defs[idx].enumname, "REG") == 0 139 || strcmp (defs[idx].enumname, "MEM") == 0); 140} 141 142/* Fill `formats' with all unique format strings. */ 143 144static void 145find_formats () 146{ 147 int i; 148 149 for (i = 0; i < NUM_RTX_CODE; ++i) 150 { 151 const char **f; 152 153 if (special_format (defs[i].format)) 154 continue; 155 156 for (f = formats; *f ; ++f) 157 if (! strcmp (*f, defs[i].format)) 158 break; 159 160 if (!*f) 161 *f = defs[i].format; 162 } 163} 164 165/* Emit a prototype for the rtx generator for a format. */ 166 167static void 168gendecl (f, format) 169 FILE *f; 170 const char *format; 171{ 172 const char *p; 173 int i; 174 175 fprintf (f, "extern rtx gen_rtx_fmt_%s PROTO((RTX_CODE, enum machine_mode mode", 176 format); 177 for (p = format, i = 0; *p ; ++p) 178 if (*p != '0') 179 fprintf (f, ", %s arg%d", type_from_format (*p), i++); 180 fprintf (f, "));\n"); 181} 182 183/* Emit a define mapping an rtx code to the generator for its format. */ 184 185static void 186genmacro (f, idx) 187 FILE *f; 188 int idx; 189{ 190 const char *p; 191 int i; 192 193 fprintf (f, "#define gen_rtx_%s%s(mode", 194 (special_rtx (idx) ? "raw_" : ""), defs[idx].enumname); 195 196 for (p = defs[idx].format, i = 0; *p ; ++p) 197 if (*p != '0') 198 fprintf (f, ", arg%d", i++); 199 fprintf (f, ") "); 200 201 fprintf (f, "gen_rtx_fmt_%s(%s,(mode)", defs[idx].format, defs[idx].enumname); 202 for (p = defs[idx].format, i = 0; *p ; ++p) 203 if (*p != '0') 204 fprintf (f, ",(arg%d)", i++); 205 fprintf (f, ")\n"); 206} 207 208/* Emit the implementation for the rtx generator for a format. */ 209 210static void 211gendef (f, format) 212 FILE *f; 213 const char *format; 214{ 215 const char *p; 216 int i, j; 217 218 fprintf (f, "rtx\ngen_rtx_fmt_%s (code, mode", format); 219 for (p = format, i = 0; *p ; ++p) 220 if (*p != '0') 221 fprintf (f, ", arg%d", i++); 222 223 fprintf (f, ")\n RTX_CODE code;\n enum machine_mode mode;\n"); 224 for (p = format, i = 0; *p ; ++p) 225 if (*p != '0') 226 fprintf (f, " %s arg%d;\n", type_from_format (*p), i++); 227 228 /* See rtx_alloc in rtl.c for comments. */ 229 fprintf (f, "{\n"); 230 fprintf (f, " rtx rt = obstack_alloc_rtx (sizeof (struct rtx_def) + %d * sizeof (rtunion));\n", 231 (int) strlen (format) - 1); 232 233 fprintf (f, " PUT_CODE (rt, code);\n"); 234 fprintf (f, " PUT_MODE (rt, mode);\n"); 235 236 for (p = format, i = j = 0; *p ; ++p, ++i) 237 if (*p != '0') 238 { 239 fprintf (f, " %s (rt, %d) = arg%d;\n", 240 accessor_from_format (*p), i, j++); 241 } 242 243 fprintf (f, "\n return rt;\n}\n\n"); 244} 245 246/* Emit the `do not edit' banner. */ 247 248static void 249genlegend (f) 250 FILE *f; 251{ 252 fputs ("/* Generated automaticaly by the program `gengenrtl'\n", f); 253 fputs (" from the RTL description file `rtl.def' */\n\n", f); 254} 255 256/* Emit "genrtl.h". */ 257 258static void 259genheader (f) 260 FILE *f; 261{ 262 int i; 263 const char **fmt; 264 265 for (fmt = formats; *fmt; ++fmt) 266 gendecl (f, *fmt); 267 268 fprintf (f, "\n"); 269 270 for (i = 0; i < NUM_RTX_CODE; i++) 271 { 272 if (special_format (defs[i].format)) 273 continue; 274 genmacro (f, i); 275 } 276} 277 278/* Emit "genrtl.c". */ 279 280static void 281gencode (f) 282 FILE *f; 283{ 284 const char **fmt; 285 286 fputs ("#include \"config.h\"\n", f); 287 fputs ("#include \"system.h\"\n", f); 288 fputs ("#include \"obstack.h\"\n", f); 289 fputs ("#include \"rtl.h\"\n\n", f); 290 fputs ("extern struct obstack *rtl_obstack;\n\n", f); 291 fputs ("static rtx obstack_alloc_rtx PROTO((int length));\n", f); 292 fputs ("static rtx obstack_alloc_rtx (length)\n", f); 293 fputs (" register int length;\n{\n", f); 294 fputs (" rtx rt = (rtx) obstack_alloc (rtl_obstack, length);\n\n", f); 295 fputs (" memset(rt, 0, sizeof(struct rtx_def) - sizeof(rtunion));\n\n", f); 296 fputs (" return rt;\n}\n\n", f); 297 298 for (fmt = formats; *fmt; ++fmt) 299 gendef (f, *fmt); 300} 301 302#if defined(USE_C_ALLOCA) 303PTR 304xmalloc (nbytes) 305 size_t nbytes; 306{ 307 register PTR tmp = (PTR) malloc (nbytes); 308 309 if (!tmp) 310 { 311 fprintf (stderr, "can't allocate %d bytes (out of virtual memory)\n", 312 nbytes); 313 exit (FATAL_EXIT_CODE); 314 } 315 316 return tmp; 317} 318#endif /* USE_C_ALLOCA */ 319 320int 321main(argc, argv) 322 int argc; 323 char **argv; 324{ 325 FILE *f; 326 327 if (argc != 3) 328 exit (1); 329 330 find_formats (); 331 332 f = fopen (argv[1], "w"); 333 if (f == NULL) 334 { 335 perror (argv[1]); 336 exit (1); 337 } 338 genlegend (f); 339 genheader (f); 340 fclose (f); 341 342 f = fopen (argv[2], "w"); 343 if (f == NULL) 344 { 345 perror (argv[2]); 346 exit (1); 347 } 348 genlegend (f); 349 gencode (f); 350 fclose (f); 351 352 exit (0); 353} 354