genflags.c revision 132718
118334Speter/* Generate from machine description: 218334Speter - some flags HAVE_... saying which simple standard instructions are 318334Speter available for this machine. 490075Sobrien Copyright (C) 1987, 1991, 1995, 1998, 5132718Skan 1999, 2000, 2003, 2004 Free Software Foundation, Inc. 618334Speter 790075SobrienThis file is part of GCC. 818334Speter 990075SobrienGCC is free software; you can redistribute it and/or modify it under 1090075Sobrienthe terms of the GNU General Public License as published by the Free 1190075SobrienSoftware Foundation; either version 2, or (at your option) any later 1290075Sobrienversion. 1318334Speter 1490075SobrienGCC is distributed in the hope that it will be useful, but WITHOUT ANY 1590075SobrienWARRANTY; without even the implied warranty of MERCHANTABILITY or 1690075SobrienFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1790075Sobrienfor more details. 1818334Speter 1918334SpeterYou should have received a copy of the GNU General Public License 2090075Sobrienalong with GCC; see the file COPYING. If not, write to the Free 2190075SobrienSoftware Foundation, 59 Temple Place - Suite 330, Boston, MA 2290075Sobrien02111-1307, USA. */ 2318334Speter 2418334Speter 25132718Skan#include "bconfig.h" 2650397Sobrien#include "system.h" 27132718Skan#include "coretypes.h" 28132718Skan#include "tm.h" 2918334Speter#include "rtl.h" 3018334Speter#include "obstack.h" 3190075Sobrien#include "errors.h" 3290075Sobrien#include "gensupport.h" 3318334Speter 3490075Sobrien/* Obstack to remember insns with. */ 3590075Sobrienstatic struct obstack obstack; 3618334Speter 3718334Speter/* Max size of names encountered. */ 3818334Speterstatic int max_id_len; 3918334Speter 4090075Sobrien/* Max operand encountered in a scan over some insn. */ 4190075Sobrienstatic int max_opno; 4250397Sobrien 43132718Skanstatic void max_operand_1 (rtx); 44132718Skanstatic int num_operands (rtx); 45132718Skanstatic void gen_proto (rtx); 46132718Skanstatic void gen_macro (const char *, int, int); 47132718Skanstatic void gen_insn (rtx); 4850397Sobrien 4918334Speter/* Count the number of match_operand's found. */ 5050397Sobrien 5190075Sobrienstatic void 52132718Skanmax_operand_1 (rtx x) 5318334Speter{ 5490075Sobrien RTX_CODE code; 5590075Sobrien int i; 5690075Sobrien int len; 5790075Sobrien const char *fmt; 5818334Speter 5990075Sobrien if (x == 0) 6090075Sobrien return; 6118334Speter 6290075Sobrien code = GET_CODE (x); 6318334Speter 6490075Sobrien if (code == MATCH_OPERAND || code == MATCH_OPERATOR 6590075Sobrien || code == MATCH_PARALLEL) 6690075Sobrien max_opno = MAX (max_opno, XINT (x, 0)); 6790075Sobrien 6890075Sobrien fmt = GET_RTX_FORMAT (code); 6990075Sobrien len = GET_RTX_LENGTH (code); 7090075Sobrien for (i = 0; i < len; i++) 7118334Speter { 7290075Sobrien if (fmt[i] == 'e' || fmt[i] == 'u') 7390075Sobrien max_operand_1 (XEXP (x, i)); 7490075Sobrien else if (fmt[i] == 'E') 7518334Speter { 7690075Sobrien int j; 7790075Sobrien for (j = 0; j < XVECLEN (x, i); j++) 7890075Sobrien max_operand_1 (XVECEXP (x, i, j)); 7918334Speter } 8018334Speter } 8190075Sobrien} 8218334Speter 8390075Sobrienstatic int 84132718Skannum_operands (rtx insn) 8590075Sobrien{ 8690075Sobrien int len = XVECLEN (insn, 1); 8790075Sobrien int i; 8890075Sobrien 8990075Sobrien max_opno = -1; 9090075Sobrien 9190075Sobrien for (i = 0; i < len; i++) 9290075Sobrien max_operand_1 (XVECEXP (insn, 1, i)); 9390075Sobrien 9490075Sobrien return max_opno + 1; 9518334Speter} 9618334Speter 9790075Sobrien/* Print out a wrapper macro for a function which corrects the number 9890075Sobrien of arguments it takes. Any missing arguments are assumed to be at 9990075Sobrien the end. */ 10090075Sobrienstatic void 101132718Skangen_macro (const char *name, int real, int expect) 10290075Sobrien{ 10390075Sobrien int i; 10490075Sobrien 10590075Sobrien if (real > expect) 10690075Sobrien abort (); 10790075Sobrien if (real == 0) 10890075Sobrien abort (); 10990075Sobrien 11090075Sobrien /* #define GEN_CALL(A, B, C, D) gen_call((A), (B)) */ 11190075Sobrien fputs ("#define GEN_", stdout); 11290075Sobrien for (i = 0; name[i]; i++) 11390075Sobrien putchar (TOUPPER (name[i])); 11490075Sobrien 11590075Sobrien putchar('('); 11690075Sobrien for (i = 0; i < expect - 1; i++) 11790075Sobrien printf ("%c, ", i + 'A'); 11890075Sobrien printf ("%c) gen_%s (", i + 'A', name); 11990075Sobrien 12090075Sobrien for (i = 0; i < real - 1; i++) 12190075Sobrien printf ("(%c), ", i + 'A'); 12290075Sobrien printf ("(%c))\n", i + 'A'); 12390075Sobrien} 12490075Sobrien 125117395Skan/* Print out prototype information for a generator function. If the 126117395Skan insn pattern has been elided, print out a dummy generator that 127117395Skan does nothing. */ 12850397Sobrien 12918334Speterstatic void 130132718Skangen_proto (rtx insn) 13118334Speter{ 13218334Speter int num = num_operands (insn); 133117395Skan int i; 13490075Sobrien const char *name = XSTR (insn, 0); 135117395Skan int truth = maybe_eval_c_test (XSTR (insn, 2)); 13618334Speter 13790075Sobrien /* Many md files don't refer to the last two operands passed to the 13890075Sobrien call patterns. This means their generator functions will be two 13990075Sobrien arguments too short. Instead of changing every md file to touch 14090075Sobrien those operands, we wrap the prototypes in macros that take the 14190075Sobrien correct number of arguments. */ 14290075Sobrien if (name[0] == 'c' || name[0] == 's') 14390075Sobrien { 14490075Sobrien if (!strcmp (name, "call") 14590075Sobrien || !strcmp (name, "call_pop") 14690075Sobrien || !strcmp (name, "sibcall") 14790075Sobrien || !strcmp (name, "sibcall_pop")) 14890075Sobrien gen_macro (name, num, 4); 14990075Sobrien else if (!strcmp (name, "call_value") 15090075Sobrien || !strcmp (name, "call_value_pop") 15190075Sobrien || !strcmp (name, "sibcall_value") 15290075Sobrien || !strcmp (name, "sibcall_value_pop")) 15390075Sobrien gen_macro (name, num, 5); 15490075Sobrien } 15590075Sobrien 156117395Skan if (truth != 0) 157132718Skan printf ("extern rtx gen_%-*s (", max_id_len, name); 158117395Skan else 159132718Skan printf ("static inline rtx gen_%-*s (", max_id_len, name); 16090075Sobrien 16118334Speter if (num == 0) 162117395Skan fputs ("void", stdout); 16318334Speter else 16418334Speter { 165117395Skan for (i = 1; i < num; i++) 166117395Skan fputs ("rtx, ", stdout); 167132718Skan 168117395Skan fputs ("rtx", stdout); 169117395Skan } 17018334Speter 171132718Skan puts (");"); 172117395Skan 173117395Skan /* Some back ends want to take the address of generator functions, 174117395Skan so we cannot simply use #define for these dummy definitions. */ 175117395Skan if (truth == 0) 176117395Skan { 177117395Skan printf ("static inline rtx\ngen_%s", name); 178117395Skan if (num > 0) 179117395Skan { 180117395Skan putchar ('('); 181117395Skan for (i = 0; i < num-1; i++) 182132718Skan printf ("rtx %c ATTRIBUTE_UNUSED, ", 'a' + i); 183132718Skan printf ("rtx %c ATTRIBUTE_UNUSED)\n", 'a' + i); 184117395Skan } 185117395Skan else 186132718Skan puts ("(void)"); 187117395Skan puts ("{\n return 0;\n}"); 18818334Speter } 18918334Speter 19018334Speter} 19118334Speter 19218334Speterstatic void 193132718Skangen_insn (rtx insn) 19418334Speter{ 19590075Sobrien const char *name = XSTR (insn, 0); 19690075Sobrien const char *p; 19718334Speter int len; 198117395Skan int truth = maybe_eval_c_test (XSTR (insn, 2)); 19918334Speter 20018334Speter /* Don't mention instructions whose names are the null string 20118334Speter or begin with '*'. They are in the machine description just 20218334Speter to be recognized. */ 20318334Speter if (name[0] == 0 || name[0] == '*') 20418334Speter return; 20518334Speter 20618334Speter len = strlen (name); 20718334Speter 20818334Speter if (len > max_id_len) 20918334Speter max_id_len = len; 21018334Speter 211117395Skan if (truth == 0) 212132718Skan /* Emit nothing. */; 213117395Skan else if (truth == 1) 214117395Skan printf ("#define HAVE_%s 1\n", name); 21518334Speter else 21618334Speter { 21718334Speter /* Write the macro definition, putting \'s at the end of each line, 21818334Speter if more than one. */ 219117395Skan printf ("#define HAVE_%s (", name); 22018334Speter for (p = XSTR (insn, 2); *p; p++) 22118334Speter { 22296263Sobrien if (IS_VSPACE (*p)) 223117395Skan fputs (" \\\n", stdout); 22418334Speter else 225117395Skan putchar (*p); 22618334Speter } 227117395Skan fputs (")\n", stdout); 22818334Speter } 22918334Speter 23090075Sobrien obstack_grow (&obstack, &insn, sizeof (rtx)); 23118334Speter} 23218334Speter 23318334Speterint 234132718Skanmain (int argc, char **argv) 23518334Speter{ 23618334Speter rtx desc; 23718334Speter rtx dummy; 23890075Sobrien rtx *insns; 23918334Speter rtx *insn_ptr; 24018334Speter 24190075Sobrien progname = "genflags"; 24290075Sobrien obstack_init (&obstack); 24318334Speter 244117395Skan /* We need to see all the possibilities. Elided insns may have 245117395Skan direct calls to their generators in C code. */ 246117395Skan insn_elision = 0; 247117395Skan 24818334Speter if (argc <= 1) 24990075Sobrien fatal ("no input file name"); 25018334Speter 25190075Sobrien if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE) 25290075Sobrien return (FATAL_EXIT_CODE); 253132718Skan 25490075Sobrien puts ("/* Generated automatically by the program `genflags'"); 25590075Sobrien puts (" from the machine description file `md'. */\n"); 25690075Sobrien puts ("#ifndef GCC_INSN_FLAGS_H"); 25790075Sobrien puts ("#define GCC_INSN_FLAGS_H\n"); 25818334Speter 25918334Speter /* Read the machine description. */ 26018334Speter 26118334Speter while (1) 26218334Speter { 26390075Sobrien int line_no, insn_code_number = 0; 26490075Sobrien 26590075Sobrien desc = read_md_rtx (&line_no, &insn_code_number); 26690075Sobrien if (desc == NULL) 26718334Speter break; 26818334Speter if (GET_CODE (desc) == DEFINE_INSN || GET_CODE (desc) == DEFINE_EXPAND) 26918334Speter gen_insn (desc); 27018334Speter } 27118334Speter 27218334Speter /* Print out the prototypes now. */ 27350397Sobrien dummy = (rtx) 0; 27490075Sobrien obstack_grow (&obstack, &dummy, sizeof (rtx)); 27590075Sobrien insns = (rtx *) obstack_finish (&obstack); 27618334Speter 27790075Sobrien for (insn_ptr = insns; *insn_ptr; insn_ptr++) 27818334Speter gen_proto (*insn_ptr); 27918334Speter 28090075Sobrien puts("\n#endif /* GCC_INSN_FLAGS_H */"); 28118334Speter 28290075Sobrien if (ferror (stdout) || fflush (stdout) || fclose (stdout)) 28390075Sobrien return FATAL_EXIT_CODE; 28418334Speter 28590075Sobrien return SUCCESS_EXIT_CODE; 28690075Sobrien} 28718334Speter 28890075Sobrien/* Define this so we can link with print-rtl.o to get debug_rtx function. */ 28990075Sobrienconst char * 290132718Skanget_insn_name (int code ATTRIBUTE_UNUSED) 29190075Sobrien{ 29290075Sobrien return NULL; 29318334Speter} 294