1/* Generate from machine description: 2 3 - some flags HAVE_... saying which simple standard instructions are 4 available for this machine. 5 Copyright (C) 1987, 1991, 1995, 1998, 1999 Free Software Foundation, Inc. 6 7This file is part of GNU CC. 8 9GNU CC is free software; you can redistribute it and/or modify 10it under the terms of the GNU General Public License as published by 11the Free Software Foundation; either version 2, or (at your option) 12any later version. 13 14GNU CC is distributed in the hope that it will be useful, 15but WITHOUT ANY WARRANTY; without even the implied warranty of 16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17GNU General Public License for more details. 18 19You should have received a copy of the GNU General Public License 20along with GNU CC; see the file COPYING. If not, write to 21the Free Software Foundation, 59 Temple Place - Suite 330, 22Boston, MA 02111-1307, USA. */ 23 24 25#include "hconfig.h" 26#include "system.h" 27#include "rtl.h" 28#include "obstack.h" 29 30static struct obstack obstack; 31struct obstack *rtl_obstack = &obstack; 32 33#define obstack_chunk_alloc xmalloc 34#define obstack_chunk_free free 35 36void fatal PVPROTO ((const char *, ...)) 37 ATTRIBUTE_PRINTF_1 ATTRIBUTE_NORETURN; 38void fancy_abort PROTO((void)) ATTRIBUTE_NORETURN; 39 40/* Names for patterns. Need to allow linking with print-rtl. */ 41char **insn_name_ptr; 42 43/* Obstacks to remember normal, and call insns. */ 44static struct obstack call_obstack, normal_obstack; 45 46/* Max size of names encountered. */ 47static int max_id_len; 48 49static int num_operands PROTO((rtx)); 50static void gen_proto PROTO((rtx)); 51static void gen_nonproto PROTO((rtx)); 52static void gen_insn PROTO((rtx)); 53 54 55/* Count the number of match_operand's found. */ 56 57static int 58num_operands (x) 59 rtx x; 60{ 61 int count = 0; 62 int i, j; 63 enum rtx_code code = GET_CODE (x); 64 char *format_ptr = GET_RTX_FORMAT (code); 65 66 if (code == MATCH_OPERAND) 67 return 1; 68 69 if (code == MATCH_OPERATOR || code == MATCH_PARALLEL) 70 count++; 71 72 for (i = 0; i < GET_RTX_LENGTH (code); i++) 73 { 74 switch (*format_ptr++) 75 { 76 case 'u': 77 case 'e': 78 count += num_operands (XEXP (x, i)); 79 break; 80 81 case 'E': 82 if (XVEC (x, i) != NULL) 83 for (j = 0; j < XVECLEN (x, i); j++) 84 count += num_operands (XVECEXP (x, i, j)); 85 86 break; 87 } 88 } 89 90 return count; 91} 92 93/* Print out prototype information for a function. */ 94 95static void 96gen_proto (insn) 97 rtx insn; 98{ 99 int num = num_operands (insn); 100 printf ("extern rtx gen_%-*s PROTO((", max_id_len, XSTR (insn, 0)); 101 102 if (num == 0) 103 printf ("void"); 104 else 105 { 106 while (num-- > 1) 107 printf ("rtx, "); 108 109 printf ("rtx"); 110 } 111 112 printf ("));\n"); 113} 114 115/* Print out a function declaration without a prototype. */ 116 117static void 118gen_nonproto (insn) 119 rtx insn; 120{ 121 printf ("extern rtx gen_%s ();\n", XSTR (insn, 0)); 122} 123 124static void 125gen_insn (insn) 126 rtx insn; 127{ 128 char *name = XSTR (insn, 0); 129 char *p; 130 struct obstack *obstack_ptr; 131 int len; 132 133 /* Don't mention instructions whose names are the null string 134 or begin with '*'. They are in the machine description just 135 to be recognized. */ 136 if (name[0] == 0 || name[0] == '*') 137 return; 138 139 len = strlen (name); 140 141 if (len > max_id_len) 142 max_id_len = len; 143 144 printf ("#define HAVE_%s ", name); 145 if (strlen (XSTR (insn, 2)) == 0) 146 printf ("1\n"); 147 else 148 { 149 /* Write the macro definition, putting \'s at the end of each line, 150 if more than one. */ 151 printf ("("); 152 for (p = XSTR (insn, 2); *p; p++) 153 { 154 if (*p == '\n') 155 printf (" \\\n"); 156 else 157 printf ("%c", *p); 158 } 159 printf (")\n"); 160 } 161 162 /* Save the current insn, so that we can later put out appropriate 163 prototypes. At present, most md files have the wrong number of 164 arguments for the call insns (call, call_value, call_pop, 165 call_value_pop) ignoring the extra arguments that are passed for 166 some machines, so by default, turn off the prototype. */ 167 168 obstack_ptr = (name[0] == 'c' 169 && (!strcmp (name, "call") 170 || !strcmp (name, "call_value") 171 || !strcmp (name, "call_pop") 172 || !strcmp (name, "call_value_pop"))) 173 ? &call_obstack : &normal_obstack; 174 175 obstack_grow (obstack_ptr, &insn, sizeof (rtx)); 176} 177 178PTR 179xmalloc (size) 180 size_t size; 181{ 182 register PTR val = (PTR) malloc (size); 183 184 if (val == 0) 185 fatal ("virtual memory exhausted"); 186 187 return val; 188} 189 190PTR 191xrealloc (old, size) 192 PTR old; 193 size_t size; 194{ 195 register PTR ptr; 196 if (old) 197 ptr = (PTR) realloc (old, size); 198 else 199 ptr = (PTR) malloc (size); 200 if (!ptr) 201 fatal ("virtual memory exhausted"); 202 return ptr; 203} 204 205void 206fatal VPROTO ((const char *format, ...)) 207{ 208#ifndef ANSI_PROTOTYPES 209 const char *format; 210#endif 211 va_list ap; 212 213 VA_START (ap, format); 214 215#ifndef ANSI_PROTOTYPES 216 format = va_arg (ap, const char *); 217#endif 218 219 fprintf (stderr, "genflags: "); 220 vfprintf (stderr, format, ap); 221 va_end (ap); 222 fprintf (stderr, "\n"); 223 exit (FATAL_EXIT_CODE); 224} 225 226/* More 'friendly' abort that prints the line and file. 227 config.h can #define abort fancy_abort if you like that sort of thing. */ 228 229void 230fancy_abort () 231{ 232 fatal ("Internal gcc abort."); 233} 234 235int 236main (argc, argv) 237 int argc; 238 char **argv; 239{ 240 rtx desc; 241 rtx dummy; 242 rtx *call_insns; 243 rtx *normal_insns; 244 rtx *insn_ptr; 245 FILE *infile; 246 register int c; 247 248 obstack_init (rtl_obstack); 249 obstack_init (&call_obstack); 250 obstack_init (&normal_obstack); 251 252 if (argc <= 1) 253 fatal ("No input file name."); 254 255 infile = fopen (argv[1], "r"); 256 if (infile == 0) 257 { 258 perror (argv[1]); 259 exit (FATAL_EXIT_CODE); 260 } 261 262 init_rtl (); 263 264 printf ("/* Generated automatically by the program `genflags'\n\ 265from the machine description file `md'. */\n\n"); 266 267 /* Read the machine description. */ 268 269 while (1) 270 { 271 c = read_skip_spaces (infile); 272 if (c == EOF) 273 break; 274 ungetc (c, infile); 275 276 desc = read_rtx (infile); 277 if (GET_CODE (desc) == DEFINE_INSN || GET_CODE (desc) == DEFINE_EXPAND) 278 gen_insn (desc); 279 } 280 281 /* Print out the prototypes now. */ 282 dummy = (rtx) 0; 283 obstack_grow (&call_obstack, &dummy, sizeof (rtx)); 284 call_insns = (rtx *) obstack_finish (&call_obstack); 285 286 obstack_grow (&normal_obstack, &dummy, sizeof (rtx)); 287 normal_insns = (rtx *) obstack_finish (&normal_obstack); 288 289 printf ("\n#ifndef NO_MD_PROTOTYPES\n"); 290 for (insn_ptr = normal_insns; *insn_ptr; insn_ptr++) 291 gen_proto (*insn_ptr); 292 293 printf ("\n#ifdef MD_CALL_PROTOTYPES\n"); 294 for (insn_ptr = call_insns; *insn_ptr; insn_ptr++) 295 gen_proto (*insn_ptr); 296 297 printf ("\n#else /* !MD_CALL_PROTOTYPES */\n"); 298 for (insn_ptr = call_insns; *insn_ptr; insn_ptr++) 299 gen_nonproto (*insn_ptr); 300 301 printf ("#endif /* !MD_CALL_PROTOTYPES */\n"); 302 printf ("\n#else /* NO_MD_PROTOTYPES */\n"); 303 for (insn_ptr = normal_insns; *insn_ptr; insn_ptr++) 304 gen_nonproto (*insn_ptr); 305 306 for (insn_ptr = call_insns; *insn_ptr; insn_ptr++) 307 gen_nonproto (*insn_ptr); 308 309 printf ("#endif /* NO_MD_PROTOTYPES */\n"); 310 311 fflush (stdout); 312 exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE); 313 /* NOTREACHED */ 314 return 0; 315} 316