1 /* Generate from machine description: 2 - some flags HAVE_... saying which simple standard instructions are 3 available for this machine. 4 Copyright (C) 1987-2018 Free Software Foundation, Inc. 5 6 This file is part of GCC. 7 8 GCC is free software; you can redistribute it and/or modify it under 9 the terms of the GNU General Public License as published by the Free 10 Software Foundation; either version 3, or (at your option) any later 11 version. 12 13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY 14 WARRANTY; without even the implied warranty of MERCHANTABILITY or 15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 16 for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with GCC; see the file COPYING3. If not see 20 <http://www.gnu.org/licenses/>. */ 21 22 23 #include "bconfig.h" 24 #include "system.h" 25 #include "coretypes.h" 26 #include "tm.h" 27 #include "rtl.h" 28 #include "obstack.h" 29 #include "errors.h" 30 #include "read-md.h" 31 #include "gensupport.h" 32 33 /* Obstack to remember insns with. */ 34 static struct obstack obstack; 35 36 /* Max size of names encountered. */ 37 static int max_id_len; 38 39 /* Max operand encountered in a scan over some insn. */ 40 static int max_opno; 41 42 static void max_operand_1 (rtx); 43 static int num_operands (rtx); 44 static void gen_proto (rtx); 45 46 /* Count the number of match_operand's found. */ 47 48 static void 49 max_operand_1 (rtx x) 50 { 51 RTX_CODE code; 52 int i; 53 int len; 54 const char *fmt; 55 56 if (x == 0) 57 return; 58 59 code = GET_CODE (x); 60 61 if (code == MATCH_OPERAND || code == MATCH_OPERATOR 62 || code == MATCH_PARALLEL) 63 max_opno = MAX (max_opno, XINT (x, 0)); 64 65 fmt = GET_RTX_FORMAT (code); 66 len = GET_RTX_LENGTH (code); 67 for (i = 0; i < len; i++) 68 { 69 if (fmt[i] == 'e' || fmt[i] == 'u') 70 max_operand_1 (XEXP (x, i)); 71 else if (fmt[i] == 'E') 72 { 73 int j; 74 for (j = 0; j < XVECLEN (x, i); j++) 75 max_operand_1 (XVECEXP (x, i, j)); 76 } 77 } 78 } 79 80 static int 81 num_operands (rtx insn) 82 { 83 int len = XVECLEN (insn, 1); 84 int i; 85 86 max_opno = -1; 87 88 for (i = 0; i < len; i++) 89 max_operand_1 (XVECEXP (insn, 1, i)); 90 91 return max_opno + 1; 92 } 93 94 /* Print out prototype information for a generator function. If the 95 insn pattern has been elided, print out a dummy generator that 96 does nothing. */ 97 98 static void 99 gen_proto (rtx insn) 100 { 101 int num = num_operands (insn); 102 int i; 103 const char *name = XSTR (insn, 0); 104 int truth = maybe_eval_c_test (XSTR (insn, 2)); 105 106 if (truth != 0) 107 printf ("extern rtx gen_%-*s (", max_id_len, name); 108 else 109 printf ("static inline rtx gen_%-*s (", max_id_len, name); 110 111 if (num == 0) 112 fputs ("void", stdout); 113 else 114 { 115 for (i = 1; i < num; i++) 116 fputs ("rtx, ", stdout); 117 118 fputs ("rtx", stdout); 119 } 120 121 puts (");"); 122 123 /* Some back ends want to take the address of generator functions, 124 so we cannot simply use #define for these dummy definitions. */ 125 if (truth == 0) 126 { 127 printf ("static inline rtx\ngen_%s", name); 128 if (num > 0) 129 { 130 putchar ('('); 131 for (i = 0; i < num-1; i++) 132 printf ("rtx ARG_UNUSED (%c), ", 'a' + i); 133 printf ("rtx ARG_UNUSED (%c))\n", 'a' + i); 134 } 135 else 136 puts ("(void)"); 137 puts ("{\n return 0;\n}"); 138 } 139 140 } 141 142 static void 143 gen_insn (md_rtx_info *info) 144 { 145 rtx insn = info->def; 146 const char *name = XSTR (insn, 0); 147 const char *p; 148 const char *lt, *gt; 149 int len; 150 int truth = maybe_eval_c_test (XSTR (insn, 2)); 151 152 lt = strchr (name, '<'); 153 if (lt && strchr (lt + 1, '>')) 154 { 155 error_at (info->loc, "unresolved iterator"); 156 return; 157 } 158 159 gt = strchr (name, '>'); 160 if (lt || gt) 161 { 162 error_at (info->loc, "unmatched angle brackets, likely " 163 "an error in iterator syntax"); 164 return; 165 } 166 167 /* Don't mention instructions whose names are the null string 168 or begin with '*'. They are in the machine description just 169 to be recognized. */ 170 if (name[0] == 0 || name[0] == '*') 171 return; 172 173 len = strlen (name); 174 175 if (len > max_id_len) 176 max_id_len = len; 177 178 if (truth == 0) 179 /* Emit nothing. */; 180 else if (truth == 1) 181 printf ("#define HAVE_%s 1\n", name); 182 else 183 { 184 /* Write the macro definition, putting \'s at the end of each line, 185 if more than one. */ 186 printf ("#define HAVE_%s (", name); 187 for (p = XSTR (insn, 2); *p; p++) 188 { 189 if (IS_VSPACE (*p)) 190 fputs (" \\\n", stdout); 191 else 192 putchar (*p); 193 } 194 fputs (")\n", stdout); 195 } 196 197 obstack_grow (&obstack, &insn, sizeof (rtx)); 198 } 199 200 int 201 main (int argc, const char **argv) 202 { 203 rtx dummy; 204 rtx *insns; 205 rtx *insn_ptr; 206 207 progname = "genflags"; 208 obstack_init (&obstack); 209 210 /* We need to see all the possibilities. Elided insns may have 211 direct calls to their generators in C code. */ 212 insn_elision = 0; 213 214 if (!init_rtx_reader_args (argc, argv)) 215 return (FATAL_EXIT_CODE); 216 217 puts ("/* Generated automatically by the program `genflags'"); 218 puts (" from the machine description file `md'. */\n"); 219 puts ("#ifndef GCC_INSN_FLAGS_H"); 220 puts ("#define GCC_INSN_FLAGS_H\n"); 221 222 /* Read the machine description. */ 223 224 md_rtx_info info; 225 while (read_md_rtx (&info)) 226 switch (GET_CODE (info.def)) 227 { 228 case DEFINE_INSN: 229 case DEFINE_EXPAND: 230 gen_insn (&info); 231 break; 232 233 default: 234 break; 235 } 236 237 /* Print out the prototypes now. */ 238 dummy = (rtx) 0; 239 obstack_grow (&obstack, &dummy, sizeof (rtx)); 240 insns = XOBFINISH (&obstack, rtx *); 241 242 for (insn_ptr = insns; *insn_ptr; insn_ptr++) 243 gen_proto (*insn_ptr); 244 245 puts ("\n#endif /* GCC_INSN_FLAGS_H */"); 246 247 if (have_error || ferror (stdout) || fflush (stdout) || fclose (stdout)) 248 return FATAL_EXIT_CODE; 249 250 return SUCCESS_EXIT_CODE; 251 } 252