genflags.c revision 18334
117680Spst/* Generate from machine description: 217680Spst 317680Spst - some flags HAVE_... saying which simple standard instructions are 417680Spst available for this machine. 517680Spst Copyright (C) 1987, 1991, 1995 Free Software Foundation, Inc. 617680Spst 717680SpstThis file is part of GNU CC. 817680Spst 917680SpstGNU CC is free software; you can redistribute it and/or modify 1017680Spstit under the terms of the GNU General Public License as published by 1117680Spstthe Free Software Foundation; either version 2, or (at your option) 1217680Spstany later version. 1317680Spst 1417680SpstGNU CC is distributed in the hope that it will be useful, 1517680Spstbut WITHOUT ANY WARRANTY; without even the implied warranty of 1617680SpstMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1717680SpstGNU General Public License for more details. 1817680Spst 1917680SpstYou should have received a copy of the GNU General Public License 2017680Spstalong with GNU CC; see the file COPYING. If not, write to 2117680Spstthe Free Software Foundation, 59 Temple Place - Suite 330, 2217680SpstBoston, MA 02111-1307, USA. */ 2317680Spst 2417680Spst 2517680Spst#include <stdio.h> 2617680Spst#include "hconfig.h" 2717680Spst#include "rtl.h" 2817680Spst#include "obstack.h" 2917680Spst 3017680Spststatic struct obstack obstack; 3117680Spststruct obstack *rtl_obstack = &obstack; 3217680Spst 3317680Spst#define obstack_chunk_alloc xmalloc 3417680Spst#define obstack_chunk_free free 3517680Spst 3617680Spstextern void free (); 3717680Spstextern rtx read_rtx (); 3821262Swollman 3917680Spstchar *xmalloc (); 4017680Spststatic void fatal (); 4117680Spstvoid fancy_abort (); 4217680Spst 4317680Spst/* Names for patterns. Need to allow linking with print-rtl. */ 4417680Spstchar **insn_name_ptr; 4517680Spst 4617680Spst/* Obstacks to remember normal, and call insns. */ 4717680Spststatic struct obstack call_obstack, normal_obstack; 4817680Spst 4917680Spst/* Max size of names encountered. */ 5017680Spststatic int max_id_len; 5117680Spst 5217680Spst/* Count the number of match_operand's found. */ 5317680Spststatic int 5417680Spstnum_operands (x) 5517680Spst rtx x; 5617680Spst{ 5717680Spst int count = 0; 5817680Spst int i, j; 5917680Spst enum rtx_code code = GET_CODE (x); 6017680Spst char *format_ptr = GET_RTX_FORMAT (code); 6117680Spst 6217680Spst if (code == MATCH_OPERAND) 6317680Spst return 1; 6417680Spst 6517680Spst if (code == MATCH_OPERATOR || code == MATCH_PARALLEL) 6617680Spst count++; 6717680Spst 6817680Spst for (i = 0; i < GET_RTX_LENGTH (code); i++) 6917680Spst { 7017680Spst switch (*format_ptr++) 7117680Spst { 7217680Spst case 'u': 7317680Spst case 'e': 7417680Spst count += num_operands (XEXP (x, i)); 7517680Spst break; 7617680Spst 7717680Spst case 'E': 7817680Spst if (XVEC (x, i) != NULL) 7917680Spst for (j = 0; j < XVECLEN (x, i); j++) 8017680Spst count += num_operands (XVECEXP (x, i, j)); 8117680Spst 8217680Spst break; 8317680Spst } 8417680Spst } 8517680Spst 8617680Spst return count; 8717680Spst} 8817680Spst 8917680Spst/* Print out prototype information for a function. */ 9017680Spststatic void 9117680Spstgen_proto (insn) 9217680Spst rtx insn; 9317680Spst{ 9417680Spst int num = num_operands (insn); 9517680Spst printf ("extern rtx gen_%-*s PROTO((", max_id_len, XSTR (insn, 0)); 9617680Spst 9717680Spst if (num == 0) 9817680Spst printf ("void"); 9917680Spst else 10017680Spst { 10117680Spst while (num-- > 1) 10217680Spst printf ("rtx, "); 10317680Spst 10417680Spst printf ("rtx"); 10517680Spst } 10617680Spst 10717680Spst printf ("));\n"); 10817680Spst} 10917680Spst 11017680Spst/* Print out a function declaration without a prototype. */ 11117680Spststatic void 11217680Spstgen_nonproto (insn) 11317680Spst rtx insn; 11417680Spst{ 11517680Spst printf ("extern rtx gen_%s ();\n", XSTR (insn, 0)); 11617680Spst} 11717680Spst 11817680Spststatic void 11917680Spstgen_insn (insn) 12017680Spst rtx insn; 12117680Spst{ 12217680Spst char *name = XSTR (insn, 0); 12317680Spst char *p; 12417680Spst struct obstack *obstack_ptr; 12517680Spst int len; 12617680Spst 12717680Spst /* Don't mention instructions whose names are the null string 12817680Spst or begin with '*'. They are in the machine description just 12917680Spst to be recognized. */ 13017680Spst if (name[0] == 0 || name[0] == '*') 13117680Spst return; 13217680Spst 13317680Spst len = strlen (name); 13417680Spst 13517680Spst if (len > max_id_len) 13617680Spst max_id_len = len; 13717680Spst 13817680Spst printf ("#define HAVE_%s ", name); 13917680Spst if (strlen (XSTR (insn, 2)) == 0) 14017680Spst printf ("1\n"); 14117680Spst else 14217680Spst { 14317680Spst /* Write the macro definition, putting \'s at the end of each line, 14417680Spst if more than one. */ 14517680Spst printf ("("); 14617680Spst for (p = XSTR (insn, 2); *p; p++) 14717680Spst { 14817680Spst if (*p == '\n') 14917680Spst printf (" \\\n"); 15017680Spst else 15117680Spst printf ("%c", *p); 15217680Spst } 15317680Spst printf (")\n"); 15417680Spst } 15517680Spst 15617680Spst /* Save the current insn, so that we can later put out appropriate 15717680Spst prototypes. At present, most md files have the wrong number of 15817680Spst arguments for the call insns (call, call_value, call_pop, 15917680Spst call_value_pop) ignoring the extra arguments that are passed for 16017680Spst some machines, so by default, turn off the prototype. */ 16117680Spst 16217680Spst obstack_ptr = (name[0] == 'c' 16317680Spst && (!strcmp (name, "call") 16417680Spst || !strcmp (name, "call_value") 16517680Spst || !strcmp (name, "call_pop") 16617680Spst || !strcmp (name, "call_value_pop"))) 16717680Spst ? &call_obstack : &normal_obstack; 16817680Spst 16917680Spst obstack_grow (obstack_ptr, &insn, sizeof (rtx)); 17017680Spst} 17117680Spst 17217680Spstchar * 17317680Spstxmalloc (size) 17417680Spst unsigned size; 17517680Spst{ 17617680Spst register char *val = (char *) malloc (size); 17717680Spst 17817680Spst if (val == 0) 17917680Spst fatal ("virtual memory exhausted"); 18017680Spst 18117680Spst return val; 18217680Spst} 18317680Spst 18417680Spstchar * 18517680Spstxrealloc (ptr, size) 18617680Spst char *ptr; 18717680Spst unsigned size; 18817680Spst{ 18917680Spst char *result = (char *) realloc (ptr, size); 19017680Spst if (!result) 19117680Spst fatal ("virtual memory exhausted"); 19217680Spst return result; 19317680Spst} 19417680Spst 19517680Spststatic void 19617680Spstfatal (s, a1, a2) 19717680Spst char *s; 19817680Spst{ 19917680Spst fprintf (stderr, "genflags: "); 20017680Spst fprintf (stderr, s, a1, a2); 20117680Spst fprintf (stderr, "\n"); 20217680Spst exit (FATAL_EXIT_CODE); 20317680Spst} 20417680Spst 20517680Spst/* More 'friendly' abort that prints the line and file. 20617680Spst config.h can #define abort fancy_abort if you like that sort of thing. */ 20717680Spst 20817680Spstvoid 20917680Spstfancy_abort () 21017680Spst{ 21117680Spst fatal ("Internal gcc abort."); 21217680Spst} 21317680Spst 21417680Spstint 21517680Spstmain (argc, argv) 21617680Spst int argc; 21717680Spst char **argv; 21817680Spst{ 21917680Spst rtx desc; 22017680Spst rtx dummy; 22117680Spst rtx *call_insns; 22217680Spst rtx *normal_insns; 22317680Spst rtx *insn_ptr; 22417680Spst FILE *infile; 22517680Spst register int c; 22617680Spst 22717680Spst obstack_init (rtl_obstack); 22817680Spst obstack_init (&call_obstack); 22917680Spst obstack_init (&normal_obstack); 23017680Spst 23117680Spst if (argc <= 1) 23217680Spst fatal ("No input file name."); 23317680Spst 23417680Spst infile = fopen (argv[1], "r"); 23517680Spst if (infile == 0) 23617680Spst { 23717680Spst perror (argv[1]); 23817680Spst exit (FATAL_EXIT_CODE); 23917680Spst } 24017680Spst 24117680Spst init_rtl (); 24217680Spst 24317680Spst printf ("/* Generated automatically by the program `genflags'\n\ 24417680Spstfrom the machine description file `md'. */\n\n"); 24517680Spst 24617680Spst /* Read the machine description. */ 24717680Spst 24817680Spst while (1) 24917680Spst { 25017680Spst c = read_skip_spaces (infile); 25117680Spst if (c == EOF) 25217680Spst break; 25317680Spst ungetc (c, infile); 25417680Spst 25517680Spst desc = read_rtx (infile); 25617680Spst if (GET_CODE (desc) == DEFINE_INSN || GET_CODE (desc) == DEFINE_EXPAND) 25717680Spst gen_insn (desc); 25817680Spst } 25917680Spst 26017680Spst /* Print out the prototypes now. */ 26117680Spst dummy = (rtx)0; 26217680Spst obstack_grow (&call_obstack, &dummy, sizeof (rtx)); 26317680Spst call_insns = (rtx *) obstack_finish (&call_obstack); 26417680Spst 26517680Spst obstack_grow (&normal_obstack, &dummy, sizeof (rtx)); 26617680Spst normal_insns = (rtx *) obstack_finish (&normal_obstack); 26717680Spst 26817680Spst printf ("\n#ifndef NO_MD_PROTOTYPES\n"); 26917680Spst for (insn_ptr = normal_insns; *insn_ptr; insn_ptr++) 27017680Spst gen_proto (*insn_ptr); 27117680Spst 27217680Spst printf ("\n#ifdef MD_CALL_PROTOTYPES\n"); 27317680Spst for (insn_ptr = call_insns; *insn_ptr; insn_ptr++) 27417680Spst gen_proto (*insn_ptr); 27517680Spst 27617680Spst printf ("\n#else /* !MD_CALL_PROTOTYPES */\n"); 27717680Spst for (insn_ptr = call_insns; *insn_ptr; insn_ptr++) 27817680Spst gen_nonproto (*insn_ptr); 27917680Spst 28017680Spst printf ("#endif /* !MD_CALL_PROTOTYPES */\n"); 28117680Spst printf ("\n#else /* NO_MD_PROTOTYPES */\n"); 28217680Spst for (insn_ptr = normal_insns; *insn_ptr; insn_ptr++) 28317680Spst gen_nonproto (*insn_ptr); 28417680Spst 28517680Spst for (insn_ptr = call_insns; *insn_ptr; insn_ptr++) 28617680Spst gen_nonproto (*insn_ptr); 28717680Spst 28817680Spst printf ("#endif /* NO_MD_PROTOTYPES */\n"); 28917680Spst 29017680Spst fflush (stdout); 29117680Spst exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE); 29217680Spst /* NOTREACHED */ 29317680Spst return 0; 29417680Spst} 29517680Spst