genflags.c revision 18334
12061Sjkh/* Generate from machine description: 250479Speter 32061Sjkh - some flags HAVE_... saying which simple standard instructions are 438666Sjb available for this machine. 532427Sjb Copyright (C) 1987, 1991, 1995 Free Software Foundation, Inc. 638666Sjb 738666SjbThis file is part of GNU CC. 838666Sjb 938666SjbGNU CC is free software; you can redistribute it and/or modify 1064049Salexit under the terms of the GNU General Public License as published by 1164049Salexthe Free Software Foundation; either version 2, or (at your option) 1266071Smarkmany later version. 1373504Sobrien 1438666SjbGNU CC is distributed in the hope that it will be useful, 1544918Sjkhbut WITHOUT ANY WARRANTY; without even the implied warranty of 1638666SjbMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1738666SjbGNU General Public License for more details. 1838666Sjb 1938666SjbYou should have received a copy of the GNU General Public License 2038666Sjbalong with GNU CC; see the file COPYING. If not, write to 2138666Sjbthe Free Software Foundation, 59 Temple Place - Suite 330, 2238666SjbBoston, MA 02111-1307, USA. */ 2338978Sjb 2438978Sjb 2532427Sjb#include <stdio.h> 2638666Sjb#include "hconfig.h" 2738666Sjb#include "rtl.h" 2838666Sjb#include "obstack.h" 2938666Sjb 3038666Sjbstatic struct obstack obstack; 3138666Sjbstruct obstack *rtl_obstack = &obstack; 3217308Speter 3338666Sjb#define obstack_chunk_alloc xmalloc 3438666Sjb#define obstack_chunk_free free 3538666Sjb 3619175Sbdeextern void free (); 3738666Sjbextern rtx read_rtx (); 3838666Sjb 3938042Sbdechar *xmalloc (); 4039726Sjbstatic void fatal (); 4138666Sjbvoid fancy_abort (); 4238666Sjb 4338042Sbde/* Names for patterns. Need to allow linking with print-rtl. */ 4438666Sjbchar **insn_name_ptr; 4549315Shoek 4617308Speter/* Obstacks to remember normal, and call insns. */ 4738666Sjbstatic struct obstack call_obstack, normal_obstack; 4838666Sjb 4938666Sjb/* Max size of names encountered. */ 5038666Sjbstatic int max_id_len; 5117308Speter 5245108Sobrien/* Count the number of match_operand's found. */ 5342128Speterstatic int 5442128Speternum_operands (x) 5538666Sjb rtx x; 5651361Sjb{ 5738666Sjb int count = 0; 5817308Speter int i, j; 5938666Sjb enum rtx_code code = GET_CODE (x); 6017308Speter char *format_ptr = GET_RTX_FORMAT (code); 6138666Sjb 6217308Speter if (code == MATCH_OPERAND) 6327910Sasami return 1; 6443226Sjkh 6543226Sjkh if (code == MATCH_OPERATOR || code == MATCH_PARALLEL) 6643226Sjkh count++; 6738666Sjb 6827910Sasami for (i = 0; i < GET_RTX_LENGTH (code); i++) 6938666Sjb { 7038666Sjb switch (*format_ptr++) 7138666Sjb { 7227910Sasami case 'u': 7338666Sjb case 'e': 7438666Sjb count += num_operands (XEXP (x, i)); 7543226Sjkh break; 7643226Sjkh 7727910Sasami case 'E': 7838666Sjb if (XVEC (x, i) != NULL) 7938666Sjb for (j = 0; j < XVECLEN (x, i); j++) 8027910Sasami count += num_operands (XVECEXP (x, i, j)); 8138666Sjb 8227910Sasami break; 8317308Speter } 8438666Sjb } 8538666Sjb 8617308Speter return count; 8774842Sru} 8868987Smarcel 8969496Sjkh/* Print out prototype information for a function. */ 9069496Sjkhstatic void 9169496Sjkhgen_proto (insn) 922061Sjkh rtx insn; 9355026Smarcel{ 9455026Smarcel int num = num_operands (insn); 9554324Smarcel printf ("extern rtx gen_%-*s PROTO((", max_id_len, XSTR (insn, 0)); 9617308Speter 9738666Sjb if (num == 0) 9817308Speter printf ("void"); 9955678Smarcel else 10038666Sjb { 10154324Smarcel while (num-- > 1) 1022302Spaul printf ("rtx, "); 10339206Sjkh 10439206Sjkh printf ("rtx"); 10539206Sjkh } 10673349Sru 10717308Speter printf ("));\n"); 10854324Smarcel} 10954324Smarcel 11054324Smarcel/* Print out a function declaration without a prototype. */ 11154324Smarcelstatic void 11254324Smarcelgen_nonproto (insn) 11354324Smarcel rtx insn; 11454324Smarcel{ 11569659Sobrien printf ("extern rtx gen_%s ();\n", XSTR (insn, 0)); 11654324Smarcel} 11754324Smarcel 11854324Smarcelstatic void 11954324Smarcelgen_insn (insn) 12054324Smarcel rtx insn; 12154324Smarcel{ 12254324Smarcel char *name = XSTR (insn, 0); 12354324Smarcel char *p; 12454324Smarcel struct obstack *obstack_ptr; 12554324Smarcel int len; 12654324Smarcel 12754324Smarcel /* Don't mention instructions whose names are the null string 12854324Smarcel or begin with '*'. They are in the machine description just 12954324Smarcel to be recognized. */ 13054324Smarcel if (name[0] == 0 || name[0] == '*') 13154324Smarcel return; 13254324Smarcel 13354324Smarcel len = strlen (name); 13454324Smarcel 13573504Sobrien if (len > max_id_len) 13654324Smarcel max_id_len = len; 13754324Smarcel 13854324Smarcel printf ("#define HAVE_%s ", name); 13938666Sjb if (strlen (XSTR (insn, 2)) == 0) 14038666Sjb printf ("1\n"); 14117308Speter else 14238666Sjb { 14338666Sjb /* Write the macro definition, putting \'s at the end of each line, 14438666Sjb if more than one. */ 14517308Speter printf ("("); 14655678Smarcel for (p = XSTR (insn, 2); *p; p++) 14755678Smarcel { 14855678Smarcel if (*p == '\n') 14955678Smarcel printf (" \\\n"); 15055678Smarcel else 1512061Sjkh printf ("%c", *p); 15217308Speter } 15338666Sjb printf (")\n"); 15438666Sjb } 15517308Speter 15655678Smarcel /* Save the current insn, so that we can later put out appropriate 1573626Swollman prototypes. At present, most md files have the wrong number of 15817308Speter arguments for the call insns (call, call_value, call_pop, 15955678Smarcel call_value_pop) ignoring the extra arguments that are passed for 16055678Smarcel some machines, so by default, turn off the prototype. */ 16155678Smarcel 16255678Smarcel obstack_ptr = (name[0] == 'c' 16355678Smarcel && (!strcmp (name, "call") 16455678Smarcel || !strcmp (name, "call_value") 16555678Smarcel || !strcmp (name, "call_pop") 16655678Smarcel || !strcmp (name, "call_value_pop"))) 16755678Smarcel ? &call_obstack : &normal_obstack; 16855678Smarcel 16955678Smarcel obstack_grow (obstack_ptr, &insn, sizeof (rtx)); 17055678Smarcel} 17155678Smarcel 17238666Sjbchar * 17338666Sjbxmalloc (size) 17417308Speter unsigned size; 17555678Smarcel{ 17638978Sjb register char *val = (char *) malloc (size); 1773626Swollman 17817308Speter if (val == 0) 17938666Sjb fatal ("virtual memory exhausted"); 18017308Speter 18143226Sjkh return val; 18243226Sjkh} 18343226Sjkh 18438666Sjbchar * 18538666Sjbxrealloc (ptr, size) 18644103Smsmith char *ptr; 187 unsigned size; 188{ 189 char *result = (char *) realloc (ptr, size); 190 if (!result) 191 fatal ("virtual memory exhausted"); 192 return result; 193} 194 195static void 196fatal (s, a1, a2) 197 char *s; 198{ 199 fprintf (stderr, "genflags: "); 200 fprintf (stderr, s, a1, a2); 201 fprintf (stderr, "\n"); 202 exit (FATAL_EXIT_CODE); 203} 204 205/* More 'friendly' abort that prints the line and file. 206 config.h can #define abort fancy_abort if you like that sort of thing. */ 207 208void 209fancy_abort () 210{ 211 fatal ("Internal gcc abort."); 212} 213 214int 215main (argc, argv) 216 int argc; 217 char **argv; 218{ 219 rtx desc; 220 rtx dummy; 221 rtx *call_insns; 222 rtx *normal_insns; 223 rtx *insn_ptr; 224 FILE *infile; 225 register int c; 226 227 obstack_init (rtl_obstack); 228 obstack_init (&call_obstack); 229 obstack_init (&normal_obstack); 230 231 if (argc <= 1) 232 fatal ("No input file name."); 233 234 infile = fopen (argv[1], "r"); 235 if (infile == 0) 236 { 237 perror (argv[1]); 238 exit (FATAL_EXIT_CODE); 239 } 240 241 init_rtl (); 242 243 printf ("/* Generated automatically by the program `genflags'\n\ 244from the machine description file `md'. */\n\n"); 245 246 /* Read the machine description. */ 247 248 while (1) 249 { 250 c = read_skip_spaces (infile); 251 if (c == EOF) 252 break; 253 ungetc (c, infile); 254 255 desc = read_rtx (infile); 256 if (GET_CODE (desc) == DEFINE_INSN || GET_CODE (desc) == DEFINE_EXPAND) 257 gen_insn (desc); 258 } 259 260 /* Print out the prototypes now. */ 261 dummy = (rtx)0; 262 obstack_grow (&call_obstack, &dummy, sizeof (rtx)); 263 call_insns = (rtx *) obstack_finish (&call_obstack); 264 265 obstack_grow (&normal_obstack, &dummy, sizeof (rtx)); 266 normal_insns = (rtx *) obstack_finish (&normal_obstack); 267 268 printf ("\n#ifndef NO_MD_PROTOTYPES\n"); 269 for (insn_ptr = normal_insns; *insn_ptr; insn_ptr++) 270 gen_proto (*insn_ptr); 271 272 printf ("\n#ifdef MD_CALL_PROTOTYPES\n"); 273 for (insn_ptr = call_insns; *insn_ptr; insn_ptr++) 274 gen_proto (*insn_ptr); 275 276 printf ("\n#else /* !MD_CALL_PROTOTYPES */\n"); 277 for (insn_ptr = call_insns; *insn_ptr; insn_ptr++) 278 gen_nonproto (*insn_ptr); 279 280 printf ("#endif /* !MD_CALL_PROTOTYPES */\n"); 281 printf ("\n#else /* NO_MD_PROTOTYPES */\n"); 282 for (insn_ptr = normal_insns; *insn_ptr; insn_ptr++) 283 gen_nonproto (*insn_ptr); 284 285 for (insn_ptr = call_insns; *insn_ptr; insn_ptr++) 286 gen_nonproto (*insn_ptr); 287 288 printf ("#endif /* NO_MD_PROTOTYPES */\n"); 289 290 fflush (stdout); 291 exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE); 292 /* NOTREACHED */ 293 return 0; 294} 295