genflags.c revision 96263
1112758Ssam/* Generate from machine description: 2112758Ssam - some flags HAVE_... saying which simple standard instructions are 3112758Ssam available for this machine. 4112758Ssam Copyright (C) 1987, 1991, 1995, 1998, 5112758Ssam 1999, 2000 Free Software Foundation, Inc. 6112758Ssam 7112758SsamThis file is part of GCC. 8112758Ssam 9112758SsamGCC is free software; you can redistribute it and/or modify it under 10112758Ssamthe terms of the GNU General Public License as published by the Free 11112758SsamSoftware Foundation; either version 2, or (at your option) any later 12112758Ssamversion. 13112758Ssam 14112758SsamGCC is distributed in the hope that it will be useful, but WITHOUT ANY 15112758SsamWARRANTY; without even the implied warranty of MERCHANTABILITY or 16112758SsamFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 17112758Ssamfor more details. 18112758Ssam 19112758SsamYou should have received a copy of the GNU General Public License 20112758Ssamalong with GCC; see the file COPYING. If not, write to the Free 21112758SsamSoftware Foundation, 59 Temple Place - Suite 330, Boston, MA 22112758Ssam02111-1307, USA. */ 23112758Ssam 24112758Ssam 25112758Ssam#include "hconfig.h" 26112758Ssam#include "system.h" 27112758Ssam#include "rtl.h" 28105197Ssam#include "obstack.h" 29105197Ssam#include "errors.h" 30105197Ssam#include "gensupport.h" 31105197Ssam 32105197Ssam 33105197Ssam#define obstack_chunk_alloc xmalloc 34105197Ssam#define obstack_chunk_free free 35159965Sthompsa 36105197Ssam/* Obstack to remember insns with. */ 37105197Ssamstatic struct obstack obstack; 38105197Ssam 39105197Ssam/* Max size of names encountered. */ 40105197Ssamstatic int max_id_len; 41105197Ssam 42105197Ssam/* Max operand encountered in a scan over some insn. */ 43105197Ssamstatic int max_opno; 44105197Ssam 45181803Sbzstatic void max_operand_1 PARAMS ((rtx)); 46105197Ssamstatic int num_operands PARAMS ((rtx)); 47105197Ssamstatic void gen_proto PARAMS ((rtx)); 48171497Sbzstatic void gen_macro PARAMS ((const char *, int, int)); 49105197Ssamstatic void gen_insn PARAMS ((rtx)); 50105197Ssam 51105197Ssam/* Count the number of match_operand's found. */ 52105197Ssam 53105197Ssamstatic void 54105197Ssammax_operand_1 (x) 55105197Ssam rtx x; 56105197Ssam{ 57105197Ssam RTX_CODE code; 58105197Ssam int i; 59105197Ssam int len; 60105197Ssam const char *fmt; 61105197Ssam 62105197Ssam if (x == 0) 63105197Ssam return; 64105197Ssam 65105197Ssam code = GET_CODE (x); 66105197Ssam 67105197Ssam if (code == MATCH_OPERAND || code == MATCH_OPERATOR 68185571Sbz || code == MATCH_PARALLEL) 69105197Ssam max_opno = MAX (max_opno, XINT (x, 0)); 70105197Ssam 71105197Ssam fmt = GET_RTX_FORMAT (code); 72105197Ssam len = GET_RTX_LENGTH (code); 73105197Ssam for (i = 0; i < len; i++) 74105197Ssam { 75105197Ssam if (fmt[i] == 'e' || fmt[i] == 'u') 76105197Ssam max_operand_1 (XEXP (x, i)); 77105197Ssam else if (fmt[i] == 'E') 78105197Ssam { 79105197Ssam int j; 80105197Ssam for (j = 0; j < XVECLEN (x, i); j++) 81105197Ssam max_operand_1 (XVECEXP (x, i, j)); 82105197Ssam } 83105197Ssam } 84105197Ssam} 85105197Ssam 86105197Ssamstatic int 87194062Svanhunum_operands (insn) 88194062Svanhu rtx insn; 89194062Svanhu{ 90194062Svanhu int len = XVECLEN (insn, 1); 91181627Svanhu int i; 92181627Svanhu 93181627Svanhu max_opno = -1; 94181627Svanhu 95181627Svanhu for (i = 0; i < len; i++) 96105197Ssam max_operand_1 (XVECEXP (insn, 1, i)); 97105197Ssam 98105197Ssam return max_opno + 1; 99183550Szec} 100105197Ssam 101105197Ssam/* Print out a wrapper macro for a function which corrects the number 102105197Ssam of arguments it takes. Any missing arguments are assumed to be at 103105197Ssam the end. */ 104105197Ssamstatic void 105105197Ssamgen_macro (name, real, expect) 106120585Ssam const char *name; 107120585Ssam int real, expect; 108105197Ssam{ 109120585Ssam int i; 110120585Ssam 111105197Ssam if (real > expect) 112105197Ssam abort (); 113105197Ssam if (real == 0) 114105197Ssam abort (); 115105197Ssam 116105197Ssam /* #define GEN_CALL(A, B, C, D) gen_call((A), (B)) */ 117105197Ssam fputs ("#define GEN_", stdout); 118105197Ssam for (i = 0; name[i]; i++) 119105197Ssam putchar (TOUPPER (name[i])); 120105197Ssam 121105197Ssam putchar('('); 122105197Ssam for (i = 0; i < expect - 1; i++) 123105197Ssam printf ("%c, ", i + 'A'); 124105197Ssam printf ("%c) gen_%s (", i + 'A', name); 125105197Ssam 126105197Ssam for (i = 0; i < real - 1; i++) 127105197Ssam printf ("(%c), ", i + 'A'); 128105197Ssam printf ("(%c))\n", i + 'A'); 129105197Ssam} 130105197Ssam 131105197Ssam/* Print out prototype information for a function. */ 132105197Ssam 133105197Ssamstatic void 134105197Ssamgen_proto (insn) 135105197Ssam rtx insn; 136105197Ssam{ 137120585Ssam int num = num_operands (insn); 138105197Ssam const char *name = XSTR (insn, 0); 139105197Ssam 140105197Ssam /* Many md files don't refer to the last two operands passed to the 141105197Ssam call patterns. This means their generator functions will be two 142105197Ssam arguments too short. Instead of changing every md file to touch 143105197Ssam those operands, we wrap the prototypes in macros that take the 144105197Ssam correct number of arguments. */ 145105197Ssam if (name[0] == 'c' || name[0] == 's') 146105197Ssam { 147105197Ssam if (!strcmp (name, "call") 148105197Ssam || !strcmp (name, "call_pop") 149105197Ssam || !strcmp (name, "sibcall") 150120585Ssam || !strcmp (name, "sibcall_pop")) 151105197Ssam gen_macro (name, num, 4); 152105197Ssam else if (!strcmp (name, "call_value") 153105197Ssam || !strcmp (name, "call_value_pop") 154105197Ssam || !strcmp (name, "sibcall_value") 155105197Ssam || !strcmp (name, "sibcall_value_pop")) 156105197Ssam gen_macro (name, num, 5); 157105197Ssam } 158105197Ssam 159105197Ssam printf ("extern struct rtx_def *gen_%-*s PARAMS ((", max_id_len, name); 160105197Ssam 161105197Ssam if (num == 0) 162105197Ssam printf ("void"); 163105197Ssam else 164105197Ssam { 165105197Ssam while (num-- > 1) 166105197Ssam printf ("struct rtx_def *, "); 167105197Ssam 168105197Ssam printf ("struct rtx_def *"); 169181803Sbz } 170105197Ssam 171105197Ssam printf ("));\n"); 172117056Ssam 173105197Ssam} 174105197Ssam 175105197Ssamstatic void 176105197Ssamgen_insn (insn) 177105197Ssam rtx insn; 178105197Ssam{ 179105197Ssam const char *name = XSTR (insn, 0); 180105197Ssam const char *p; 181105197Ssam int len; 182105197Ssam 183105197Ssam /* Don't mention instructions whose names are the null string 184105197Ssam or begin with '*'. They are in the machine description just 185105197Ssam to be recognized. */ 186105197Ssam if (name[0] == 0 || name[0] == '*') 187194062Svanhu return; 188194062Svanhu 189194062Svanhu len = strlen (name); 190194062Svanhu 191194062Svanhu if (len > max_id_len) 192194062Svanhu max_id_len = len; 193194062Svanhu 194194062Svanhu printf ("#define HAVE_%s ", name); 195194062Svanhu if (strlen (XSTR (insn, 2)) == 0) 196194062Svanhu printf ("1\n"); 197194062Svanhu else 198194062Svanhu { 199194062Svanhu /* Write the macro definition, putting \'s at the end of each line, 200194062Svanhu if more than one. */ 201194062Svanhu printf ("("); 202194062Svanhu for (p = XSTR (insn, 2); *p; p++) 203194062Svanhu { 204194062Svanhu if (IS_VSPACE (*p)) 205194062Svanhu printf (" \\\n"); 206194062Svanhu else 207194062Svanhu printf ("%c", *p); 208194062Svanhu } 209194062Svanhu printf (")\n"); 210194062Svanhu } 211194062Svanhu 212194062Svanhu obstack_grow (&obstack, &insn, sizeof (rtx)); 213194062Svanhu} 214194062Svanhu 215194062Svanhuextern int main PARAMS ((int, char **)); 216194062Svanhu 217194062Svanhuint 218194062Svanhumain (argc, argv) 219194062Svanhu int argc; 220194062Svanhu char **argv; 221194062Svanhu{ 222194062Svanhu rtx desc; 223194062Svanhu rtx dummy; 224194062Svanhu rtx *insns; 225194062Svanhu rtx *insn_ptr; 226194062Svanhu 227194062Svanhu progname = "genflags"; 228194062Svanhu obstack_init (&obstack); 229194062Svanhu 230194062Svanhu if (argc <= 1) 231194062Svanhu fatal ("no input file name"); 232194062Svanhu 233194062Svanhu if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE) 234194062Svanhu return (FATAL_EXIT_CODE); 235194062Svanhu 236194062Svanhu puts ("/* Generated automatically by the program `genflags'"); 237194062Svanhu puts (" from the machine description file `md'. */\n"); 238105197Ssam puts ("#ifndef GCC_INSN_FLAGS_H"); 239105197Ssam puts ("#define GCC_INSN_FLAGS_H\n"); 240105197Ssam 241105197Ssam /* Read the machine description. */ 242105197Ssam 243105197Ssam while (1) 244105197Ssam { 245105197Ssam int line_no, insn_code_number = 0; 246105197Ssam 247105197Ssam desc = read_md_rtx (&line_no, &insn_code_number); 248105197Ssam if (desc == NULL) 249105197Ssam break; 250105197Ssam if (GET_CODE (desc) == DEFINE_INSN || GET_CODE (desc) == DEFINE_EXPAND) 251105197Ssam gen_insn (desc); 252105197Ssam } 253105197Ssam 254105197Ssam /* Print out the prototypes now. */ 255105197Ssam dummy = (rtx) 0; 256105197Ssam obstack_grow (&obstack, &dummy, sizeof (rtx)); 257105197Ssam insns = (rtx *) obstack_finish (&obstack); 258105197Ssam 259105197Ssam printf ("struct rtx_def;\n"); 260105197Ssam for (insn_ptr = insns; *insn_ptr; insn_ptr++) 261105197Ssam gen_proto (*insn_ptr); 262105197Ssam 263105197Ssam puts("\n#endif /* GCC_INSN_FLAGS_H */"); 264105197Ssam 265105197Ssam if (ferror (stdout) || fflush (stdout) || fclose (stdout)) 266105197Ssam return FATAL_EXIT_CODE; 267183550Szec 268105197Ssam return SUCCESS_EXIT_CODE; 269105197Ssam} 270120585Ssam 271120585Ssam/* Define this so we can link with print-rtl.o to get debug_rtx function. */ 272120585Ssamconst char * 273120585Ssamget_insn_name (code) 274105197Ssam int code ATTRIBUTE_UNUSED; 275105197Ssam{ 276105197Ssam return NULL; 277105197Ssam} 278105197Ssam