genflags.c revision 50397
1214501Srpaulo/* Generate from machine description: 2214501Srpaulo 3214501Srpaulo - some flags HAVE_... saying which simple standard instructions are 4214501Srpaulo available for this machine. 5214501Srpaulo Copyright (C) 1987, 1991, 1995, 1998 Free Software Foundation, Inc. 6252190Srpaulo 7252190SrpauloThis file is part of GNU CC. 8214501Srpaulo 9214501SrpauloGNU CC is free software; you can redistribute it and/or modify 10214501Srpauloit under the terms of the GNU General Public License as published by 11214501Srpaulothe Free Software Foundation; either version 2, or (at your option) 12214501Srpauloany later version. 13214501Srpaulo 14214501SrpauloGNU CC is distributed in the hope that it will be useful, 15214501Srpaulobut WITHOUT ANY WARRANTY; without even the implied warranty of 16214501SrpauloMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17214501SrpauloGNU General Public License for more details. 18214501Srpaulo 19214501SrpauloYou should have received a copy of the GNU General Public License 20214501Srpauloalong with GNU CC; see the file COPYING. If not, write to 21214501Srpaulothe Free Software Foundation, 59 Temple Place - Suite 330, 22214501SrpauloBoston, MA 02111-1307, USA. */ 23252190Srpaulo 24252190Srpaulo 25252190Srpaulo#include "hconfig.h" 26252190Srpaulo#ifdef __STDC__ 27214501Srpaulo#include <stdarg.h> 28252190Srpaulo#else 29252190Srpaulo#include <varargs.h> 30252190Srpaulo#endif 31214501Srpaulo#include "system.h" 32252190Srpaulo#include "rtl.h" 33252190Srpaulo#include "obstack.h" 34252190Srpaulo 35252190Srpaulostatic struct obstack obstack; 36252190Srpaulostruct obstack *rtl_obstack = &obstack; 37214501Srpaulo 38252190Srpaulo#define obstack_chunk_alloc xmalloc 39252190Srpaulo#define obstack_chunk_free free 40252190Srpaulo 41252190Srpaulochar *xmalloc PROTO((unsigned)); 42252190Srpaulostatic void fatal PVPROTO ((char *, ...)) ATTRIBUTE_PRINTF_1; 43252190Srpaulovoid fancy_abort PROTO((void)); 44214501Srpaulo 45214501Srpaulo/* Names for patterns. Need to allow linking with print-rtl. */ 46214501Srpaulochar **insn_name_ptr; 47214501Srpaulo 48214501Srpaulo/* Obstacks to remember normal, and call insns. */ 49214501Srpaulostatic struct obstack call_obstack, normal_obstack; 50214501Srpaulo 51214501Srpaulo/* Max size of names encountered. */ 52214501Srpaulostatic int max_id_len; 53252190Srpaulo 54252190Srpaulostatic int num_operands PROTO((rtx)); 55252190Srpaulostatic void gen_proto PROTO((rtx)); 56214501Srpaulostatic void gen_nonproto PROTO((rtx)); 57252190Srpaulostatic void gen_insn PROTO((rtx)); 58281806Srpaulo 59281806Srpaulo 60214501Srpaulo/* Count the number of match_operand's found. */ 61252190Srpaulo 62252190Srpaulostatic int 63252190Srpaulonum_operands (x) 64214501Srpaulo rtx x; 65252190Srpaulo{ 66252190Srpaulo int count = 0; 67214501Srpaulo int i, j; 68252190Srpaulo enum rtx_code code = GET_CODE (x); 69252190Srpaulo char *format_ptr = GET_RTX_FORMAT (code); 70252190Srpaulo 71214501Srpaulo if (code == MATCH_OPERAND) 72252190Srpaulo return 1; 73252190Srpaulo 74252190Srpaulo if (code == MATCH_OPERATOR || code == MATCH_PARALLEL) 75214501Srpaulo count++; 76252190Srpaulo 77252190Srpaulo for (i = 0; i < GET_RTX_LENGTH (code); i++) 78252190Srpaulo { 79214501Srpaulo switch (*format_ptr++) 80252190Srpaulo { 81252190Srpaulo case 'u': 82214501Srpaulo case 'e': 83252190Srpaulo count += num_operands (XEXP (x, i)); 84252190Srpaulo break; 85252190Srpaulo 86252190Srpaulo case 'E': 87214501Srpaulo if (XVEC (x, i) != NULL) 88214501Srpaulo for (j = 0; j < XVECLEN (x, i); j++) 89214501Srpaulo count += num_operands (XVECEXP (x, i, j)); 90281806Srpaulo 91281806Srpaulo break; 92281806Srpaulo } 93214501Srpaulo } 94214501Srpaulo 95214501Srpaulo return count; 96252190Srpaulo} 97252190Srpaulo 98252190Srpaulo/* Print out prototype information for a function. */ 99252190Srpaulo 100252190Srpaulostatic void 101214501Srpaulogen_proto (insn) 102214501Srpaulo rtx insn; 103214501Srpaulo{ 104252190Srpaulo int num = num_operands (insn); 105252190Srpaulo printf ("extern rtx gen_%-*s PROTO((", max_id_len, XSTR (insn, 0)); 106252190Srpaulo 107281806Srpaulo if (num == 0) 108281806Srpaulo printf ("void"); 109281806Srpaulo else 110214501Srpaulo { 111214501Srpaulo while (num-- > 1) 112214501Srpaulo printf ("rtx, "); 113252190Srpaulo 114252190Srpaulo printf ("rtx"); 115252190Srpaulo } 116214501Srpaulo 117214501Srpaulo printf ("));\n"); 118214501Srpaulo} 119252190Srpaulo 120252190Srpaulo/* Print out a function declaration without a prototype. */ 121252190Srpaulo 122214501Srpaulostatic void 123214501Srpaulogen_nonproto (insn) 124214501Srpaulo rtx insn; 125214501Srpaulo{ 126214501Srpaulo printf ("extern rtx gen_%s ();\n", XSTR (insn, 0)); 127214501Srpaulo} 128214501Srpaulo 129214501Srpaulostatic void 130214501Srpaulogen_insn (insn) 131281806Srpaulo rtx insn; 132281806Srpaulo{ 133281806Srpaulo char *name = XSTR (insn, 0); 134252190Srpaulo char *p; 135252190Srpaulo struct obstack *obstack_ptr; 136214501Srpaulo int len; 137252190Srpaulo 138252190Srpaulo /* Don't mention instructions whose names are the null string 139214501Srpaulo or begin with '*'. They are in the machine description just 140281806Srpaulo to be recognized. */ 141281806Srpaulo if (name[0] == 0 || name[0] == '*') 142281806Srpaulo return; 143281806Srpaulo 144281806Srpaulo len = strlen (name); 145281806Srpaulo 146252190Srpaulo if (len > max_id_len) 147252190Srpaulo max_id_len = len; 148214501Srpaulo 149252190Srpaulo printf ("#define HAVE_%s ", name); 150252190Srpaulo if (strlen (XSTR (insn, 2)) == 0) 151214501Srpaulo printf ("1\n"); 152252190Srpaulo else 153252190Srpaulo { 154214501Srpaulo /* Write the macro definition, putting \'s at the end of each line, 155252190Srpaulo if more than one. */ 156252190Srpaulo printf ("("); 157214501Srpaulo for (p = XSTR (insn, 2); *p; p++) 158252190Srpaulo { 159252190Srpaulo if (*p == '\n') 160214501Srpaulo printf (" \\\n"); 161252190Srpaulo else 162252190Srpaulo printf ("%c", *p); 163252190Srpaulo } 164214501Srpaulo printf (")\n"); 165252190Srpaulo } 166252190Srpaulo 167252190Srpaulo /* Save the current insn, so that we can later put out appropriate 168214501Srpaulo prototypes. At present, most md files have the wrong number of 169252190Srpaulo arguments for the call insns (call, call_value, call_pop, 170252190Srpaulo call_value_pop) ignoring the extra arguments that are passed for 171252190Srpaulo some machines, so by default, turn off the prototype. */ 172214501Srpaulo 173252190Srpaulo obstack_ptr = (name[0] == 'c' 174252190Srpaulo && (!strcmp (name, "call") 175214501Srpaulo || !strcmp (name, "call_value") 176252190Srpaulo || !strcmp (name, "call_pop") 177252190Srpaulo || !strcmp (name, "call_value_pop"))) 178252190Srpaulo ? &call_obstack : &normal_obstack; 179214501Srpaulo 180252190Srpaulo obstack_grow (obstack_ptr, &insn, sizeof (rtx)); 181252190Srpaulo} 182252190Srpaulo 183214501Srpaulochar * 184252190Srpauloxmalloc (size) 185252190Srpaulo unsigned size; 186252190Srpaulo{ 187214501Srpaulo register char *val = (char *) malloc (size); 188252190Srpaulo 189252190Srpaulo if (val == 0) 190214501Srpaulo fatal ("virtual memory exhausted"); 191252190Srpaulo 192252190Srpaulo return val; 193214501Srpaulo} 194252190Srpaulo 195252190Srpaulochar * 196252190Srpauloxrealloc (ptr, size) 197214501Srpaulo char *ptr; 198252190Srpaulo unsigned size; 199252190Srpaulo{ 200252190Srpaulo char *result = (char *) realloc (ptr, size); 201214501Srpaulo if (!result) 202252190Srpaulo fatal ("virtual memory exhausted"); 203252190Srpaulo return result; 204214501Srpaulo} 205252190Srpaulo 206252190Srpaulostatic void 207214501Srpaulofatal VPROTO ((char *format, ...)) 208252190Srpaulo{ 209252190Srpaulo#ifndef __STDC__ 210252190Srpaulo char *format; 211214501Srpaulo#endif 212252190Srpaulo va_list ap; 213252190Srpaulo 214252190Srpaulo VA_START (ap, format); 215214501Srpaulo 216252190Srpaulo#ifndef __STDC__ 217252190Srpaulo format = va_arg (ap, char *); 218252190Srpaulo#endif 219214501Srpaulo 220252190Srpaulo fprintf (stderr, "genflags: "); 221252190Srpaulo vfprintf (stderr, format, ap); 222252190Srpaulo va_end (ap); 223214501Srpaulo fprintf (stderr, "\n"); 224252190Srpaulo exit (FATAL_EXIT_CODE); 225252190Srpaulo} 226214501Srpaulo 227252190Srpaulo/* More 'friendly' abort that prints the line and file. 228252190Srpaulo config.h can #define abort fancy_abort if you like that sort of thing. */ 229214501Srpaulo 230281806Srpaulovoid 231281806Srpaulofancy_abort () 232281806Srpaulo{ 233281806Srpaulo fatal ("Internal gcc abort."); 234281806Srpaulo} 235281806Srpaulo 236281806Srpauloint 237281806Srpaulomain (argc, argv) 238252190Srpaulo int argc; 239252190Srpaulo char **argv; 240214501Srpaulo{ 241252190Srpaulo rtx desc; 242252190Srpaulo rtx dummy; 243252190Srpaulo rtx *call_insns; 244252190Srpaulo rtx *normal_insns; 245252190Srpaulo rtx *insn_ptr; 246252190Srpaulo FILE *infile; 247252190Srpaulo register int c; 248252190Srpaulo 249252190Srpaulo obstack_init (rtl_obstack); 250252190Srpaulo obstack_init (&call_obstack); 251252190Srpaulo obstack_init (&normal_obstack); 252252190Srpaulo 253252190Srpaulo if (argc <= 1) 254252190Srpaulo fatal ("No input file name."); 255252190Srpaulo 256252190Srpaulo infile = fopen (argv[1], "r"); 257252190Srpaulo if (infile == 0) 258252190Srpaulo { 259252190Srpaulo perror (argv[1]); 260252190Srpaulo exit (FATAL_EXIT_CODE); 261252190Srpaulo } 262252190Srpaulo 263252190Srpaulo init_rtl (); 264252190Srpaulo 265252190Srpaulo printf ("/* Generated automatically by the program `genflags'\n\ 266252190Srpaulofrom the machine description file `md'. */\n\n"); 267252190Srpaulo 268252190Srpaulo /* Read the machine description. */ 269252190Srpaulo 270252190Srpaulo while (1) 271252190Srpaulo { 272252190Srpaulo c = read_skip_spaces (infile); 273252190Srpaulo if (c == EOF) 274281806Srpaulo break; 275281806Srpaulo ungetc (c, infile); 276281806Srpaulo 277252190Srpaulo desc = read_rtx (infile); 278252190Srpaulo if (GET_CODE (desc) == DEFINE_INSN || GET_CODE (desc) == DEFINE_EXPAND) 279252190Srpaulo gen_insn (desc); 280252190Srpaulo } 281252190Srpaulo 282252190Srpaulo /* Print out the prototypes now. */ 283252190Srpaulo dummy = (rtx) 0; 284252190Srpaulo obstack_grow (&call_obstack, &dummy, sizeof (rtx)); 285252190Srpaulo call_insns = (rtx *) obstack_finish (&call_obstack); 286252190Srpaulo 287252190Srpaulo obstack_grow (&normal_obstack, &dummy, sizeof (rtx)); 288252190Srpaulo normal_insns = (rtx *) obstack_finish (&normal_obstack); 289252190Srpaulo 290252190Srpaulo printf ("\n#ifndef NO_MD_PROTOTYPES\n"); 291214501Srpaulo for (insn_ptr = normal_insns; *insn_ptr; insn_ptr++) 292214501Srpaulo gen_proto (*insn_ptr); 293214501Srpaulo 294252190Srpaulo printf ("\n#ifdef MD_CALL_PROTOTYPES\n"); 295252190Srpaulo for (insn_ptr = call_insns; *insn_ptr; insn_ptr++) 296214501Srpaulo gen_proto (*insn_ptr); 297252190Srpaulo 298252190Srpaulo printf ("\n#else /* !MD_CALL_PROTOTYPES */\n"); 299252190Srpaulo for (insn_ptr = call_insns; *insn_ptr; insn_ptr++) 300214501Srpaulo gen_nonproto (*insn_ptr); 301281806Srpaulo 302281806Srpaulo printf ("#endif /* !MD_CALL_PROTOTYPES */\n"); 303281806Srpaulo printf ("\n#else /* NO_MD_PROTOTYPES */\n"); 304281806Srpaulo for (insn_ptr = normal_insns; *insn_ptr; insn_ptr++) 305281806Srpaulo gen_nonproto (*insn_ptr); 306281806Srpaulo 307281806Srpaulo for (insn_ptr = call_insns; *insn_ptr; insn_ptr++) 308281806Srpaulo gen_nonproto (*insn_ptr); 309281806Srpaulo 310281806Srpaulo printf ("#endif /* NO_MD_PROTOTYPES */\n"); 311281806Srpaulo 312281806Srpaulo fflush (stdout); 313281806Srpaulo exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE); 314281806Srpaulo /* NOTREACHED */ 315281806Srpaulo return 0; 316281806Srpaulo} 317281806Srpaulo