genflags.c revision 90075
1/* Generate from machine description: 2 - some flags HAVE_... saying which simple standard instructions are 3 available for this machine. 4 Copyright (C) 1987, 1991, 1995, 1998, 5 1999, 2000 Free Software Foundation, Inc. 6 7This file is part of GCC. 8 9GCC is free software; you can redistribute it and/or modify it under 10the terms of the GNU General Public License as published by the Free 11Software Foundation; either version 2, or (at your option) any later 12version. 13 14GCC is distributed in the hope that it will be useful, but WITHOUT ANY 15WARRANTY; without even the implied warranty of MERCHANTABILITY or 16FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 17for more details. 18 19You should have received a copy of the GNU General Public License 20along with GCC; see the file COPYING. If not, write to the Free 21Software Foundation, 59 Temple Place - Suite 330, Boston, MA 2202111-1307, USA. */ 23 24 25#include "hconfig.h" 26#include "system.h" 27#include "rtl.h" 28#include "obstack.h" 29#include "errors.h" 30#include "gensupport.h" 31 32 33#define obstack_chunk_alloc xmalloc 34#define obstack_chunk_free free 35 36/* Obstack to remember insns with. */ 37static struct obstack obstack; 38 39/* Max size of names encountered. */ 40static int max_id_len; 41 42/* Max operand encountered in a scan over some insn. */ 43static int max_opno; 44 45static void max_operand_1 PARAMS ((rtx)); 46static int num_operands PARAMS ((rtx)); 47static void gen_proto PARAMS ((rtx)); 48static void gen_macro PARAMS ((const char *, int, int)); 49static void gen_insn PARAMS ((rtx)); 50 51/* Count the number of match_operand's found. */ 52 53static void 54max_operand_1 (x) 55 rtx x; 56{ 57 RTX_CODE code; 58 int i; 59 int len; 60 const char *fmt; 61 62 if (x == 0) 63 return; 64 65 code = GET_CODE (x); 66 67 if (code == MATCH_OPERAND || code == MATCH_OPERATOR 68 || code == MATCH_PARALLEL) 69 max_opno = MAX (max_opno, XINT (x, 0)); 70 71 fmt = GET_RTX_FORMAT (code); 72 len = GET_RTX_LENGTH (code); 73 for (i = 0; i < len; i++) 74 { 75 if (fmt[i] == 'e' || fmt[i] == 'u') 76 max_operand_1 (XEXP (x, i)); 77 else if (fmt[i] == 'E') 78 { 79 int j; 80 for (j = 0; j < XVECLEN (x, i); j++) 81 max_operand_1 (XVECEXP (x, i, j)); 82 } 83 } 84} 85 86static int 87num_operands (insn) 88 rtx insn; 89{ 90 int len = XVECLEN (insn, 1); 91 int i; 92 93 max_opno = -1; 94 95 for (i = 0; i < len; i++) 96 max_operand_1 (XVECEXP (insn, 1, i)); 97 98 return max_opno + 1; 99} 100 101/* Print out a wrapper macro for a function which corrects the number 102 of arguments it takes. Any missing arguments are assumed to be at 103 the end. */ 104static void 105gen_macro (name, real, expect) 106 const char *name; 107 int real, expect; 108{ 109 int i; 110 111 if (real > expect) 112 abort (); 113 if (real == 0) 114 abort (); 115 116 /* #define GEN_CALL(A, B, C, D) gen_call((A), (B)) */ 117 fputs ("#define GEN_", stdout); 118 for (i = 0; name[i]; i++) 119 putchar (TOUPPER (name[i])); 120 121 putchar('('); 122 for (i = 0; i < expect - 1; i++) 123 printf ("%c, ", i + 'A'); 124 printf ("%c) gen_%s (", i + 'A', name); 125 126 for (i = 0; i < real - 1; i++) 127 printf ("(%c), ", i + 'A'); 128 printf ("(%c))\n", i + 'A'); 129} 130 131/* Print out prototype information for a function. */ 132 133static void 134gen_proto (insn) 135 rtx insn; 136{ 137 int num = num_operands (insn); 138 const char *name = XSTR (insn, 0); 139 140 /* Many md files don't refer to the last two operands passed to the 141 call patterns. This means their generator functions will be two 142 arguments too short. Instead of changing every md file to touch 143 those operands, we wrap the prototypes in macros that take the 144 correct number of arguments. */ 145 if (name[0] == 'c' || name[0] == 's') 146 { 147 if (!strcmp (name, "call") 148 || !strcmp (name, "call_pop") 149 || !strcmp (name, "sibcall") 150 || !strcmp (name, "sibcall_pop")) 151 gen_macro (name, num, 4); 152 else if (!strcmp (name, "call_value") 153 || !strcmp (name, "call_value_pop") 154 || !strcmp (name, "sibcall_value") 155 || !strcmp (name, "sibcall_value_pop")) 156 gen_macro (name, num, 5); 157 } 158 159 printf ("extern struct rtx_def *gen_%-*s PARAMS ((", max_id_len, name); 160 161 if (num == 0) 162 printf ("void"); 163 else 164 { 165 while (num-- > 1) 166 printf ("struct rtx_def *, "); 167 168 printf ("struct rtx_def *"); 169 } 170 171 printf ("));\n"); 172 173} 174 175static void 176gen_insn (insn) 177 rtx insn; 178{ 179 const char *name = XSTR (insn, 0); 180 const char *p; 181 int len; 182 183 /* Don't mention instructions whose names are the null string 184 or begin with '*'. They are in the machine description just 185 to be recognized. */ 186 if (name[0] == 0 || name[0] == '*') 187 return; 188 189 len = strlen (name); 190 191 if (len > max_id_len) 192 max_id_len = len; 193 194 printf ("#define HAVE_%s ", name); 195 if (strlen (XSTR (insn, 2)) == 0) 196 printf ("1\n"); 197 else 198 { 199 /* Write the macro definition, putting \'s at the end of each line, 200 if more than one. */ 201 printf ("("); 202 for (p = XSTR (insn, 2); *p; p++) 203 { 204 if (*p == '\n') 205 printf (" \\\n"); 206 else 207 printf ("%c", *p); 208 } 209 printf (")\n"); 210 } 211 212 obstack_grow (&obstack, &insn, sizeof (rtx)); 213} 214 215extern int main PARAMS ((int, char **)); 216 217int 218main (argc, argv) 219 int argc; 220 char **argv; 221{ 222 rtx desc; 223 rtx dummy; 224 rtx *insns; 225 rtx *insn_ptr; 226 227 progname = "genflags"; 228 obstack_init (&obstack); 229 230 if (argc <= 1) 231 fatal ("no input file name"); 232 233 if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE) 234 return (FATAL_EXIT_CODE); 235 236 puts ("/* Generated automatically by the program `genflags'"); 237 puts (" from the machine description file `md'. */\n"); 238 puts ("#ifndef GCC_INSN_FLAGS_H"); 239 puts ("#define GCC_INSN_FLAGS_H\n"); 240 241 /* Read the machine description. */ 242 243 while (1) 244 { 245 int line_no, insn_code_number = 0; 246 247 desc = read_md_rtx (&line_no, &insn_code_number); 248 if (desc == NULL) 249 break; 250 if (GET_CODE (desc) == DEFINE_INSN || GET_CODE (desc) == DEFINE_EXPAND) 251 gen_insn (desc); 252 } 253 254 /* Print out the prototypes now. */ 255 dummy = (rtx) 0; 256 obstack_grow (&obstack, &dummy, sizeof (rtx)); 257 insns = (rtx *) obstack_finish (&obstack); 258 259 printf ("struct rtx_def;\n"); 260 for (insn_ptr = insns; *insn_ptr; insn_ptr++) 261 gen_proto (*insn_ptr); 262 263 puts("\n#endif /* GCC_INSN_FLAGS_H */"); 264 265 if (ferror (stdout) || fflush (stdout) || fclose (stdout)) 266 return FATAL_EXIT_CODE; 267 268 return SUCCESS_EXIT_CODE; 269} 270 271/* Define this so we can link with print-rtl.o to get debug_rtx function. */ 272const char * 273get_insn_name (code) 274 int code ATTRIBUTE_UNUSED; 275{ 276 return NULL; 277} 278