1/* Generate from machine description: 2 - prototype declarations for operand predicates (tm-preds.h) 3 - function definitions of operand predicates, if defined new-style 4 (insn-preds.c) 5 Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. 6 7This file is part of GCC. 8 9GCC is free software; you can redistribute it and/or modify 10it under the terms of the GNU General Public License as published by 11the Free Software Foundation; either version 2, or (at your option) 12any later version. 13 14GCC is distributed in the hope that it will be useful, 15but WITHOUT ANY WARRANTY; without even the implied warranty of 16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17GNU General Public License for 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 21the Free Software Foundation, 51 Franklin Street, Fifth Floor, 22Boston, MA 02110-1301, USA. */ 23 24#include "bconfig.h" 25#include "system.h" 26#include "coretypes.h" 27#include "tm.h" 28#include "rtl.h" 29#include "errors.h" 30#include "gensupport.h" 31#include "obstack.h" 32 33/* The new way to declare predicates is with (define_predicate) or 34 (define_special_predicate) expressions in the machine description. 35 This provides a function body as well as a name. */ 36static void 37process_define_predicate (rtx defn) 38{ 39 struct pred_data *pred; 40 if (XEXP (defn, 1) == 0) 41 { 42 error ("%s: must give a predicate expression", XSTR (defn, 0)); 43 return; 44 } 45 46 pred = xcalloc (sizeof (struct pred_data), 1); 47 pred->name = XSTR (defn, 0); 48 pred->exp = XEXP (defn, 1); 49 pred->c_block = XSTR (defn, 2); 50 51 if (GET_CODE (defn) == DEFINE_SPECIAL_PREDICATE) 52 pred->special = true; 53 54 add_predicate (pred); 55} 56 57/* Write tm-preds.h. Unfortunately, it is impossible to forward-declare 58 an enumeration in portable C, so we have to condition all these 59 prototypes on HAVE_MACHINE_MODES. */ 60static void 61write_tm_preds_h (void) 62{ 63 struct pred_data *p; 64 65 printf ("\ 66/* Generated automatically by the program '%s'\n\ 67 from the machine description file '%s'. */\n\n", progname, in_fname); 68 69 puts ("\ 70#ifndef GCC_TM_PREDS_H\n\ 71#define GCC_TM_PREDS_H\n\ 72\n\ 73#ifdef HAVE_MACHINE_MODES"); 74 75 FOR_ALL_PREDICATES (p) 76 printf ("extern int %s (rtx, enum machine_mode);\n", p->name); 77 78 puts ("\ 79#endif /* HAVE_MACHINE_MODES */\n\ 80#endif /* tm-preds.h */"); 81} 82 83/* Given a predicate, if it has an embedded C block, write the block 84 out as a static inline subroutine, and augment the RTL test with a 85 match_test that calls that subroutine. For instance, 86 87 (define_predicate "basereg_operand" 88 (match_operand 0 "register_operand") 89 { 90 if (GET_CODE (op) == SUBREG) 91 op = SUBREG_REG (op); 92 return REG_POINTER (op); 93 }) 94 95 becomes 96 97 static inline int basereg_operand_1(rtx op, enum machine_mode mode) 98 { 99 if (GET_CODE (op) == SUBREG) 100 op = SUBREG_REG (op); 101 return REG_POINTER (op); 102 } 103 104 (define_predicate "basereg_operand" 105 (and (match_operand 0 "register_operand") 106 (match_test "basereg_operand_1 (op, mode)"))) 107 108 The only wart is that there's no way to insist on a { } string in 109 an RTL template, so we have to handle "" strings. */ 110 111 112static void 113write_predicate_subfunction (struct pred_data *p) 114{ 115 const char *match_test_str; 116 rtx match_test_exp, and_exp; 117 118 if (p->c_block[0] == '\0') 119 return; 120 121 /* Construct the function-call expression. */ 122 obstack_grow (rtl_obstack, p->name, strlen (p->name)); 123 obstack_grow (rtl_obstack, "_1 (op, mode)", 124 sizeof "_1 (op, mode)"); 125 match_test_str = XOBFINISH (rtl_obstack, const char *); 126 127 /* Add the function-call expression to the complete expression to be 128 evaluated. */ 129 match_test_exp = rtx_alloc (MATCH_TEST); 130 XSTR (match_test_exp, 0) = match_test_str; 131 132 and_exp = rtx_alloc (AND); 133 XEXP (and_exp, 0) = p->exp; 134 XEXP (and_exp, 1) = match_test_exp; 135 136 p->exp = and_exp; 137 138 printf ("static inline int\n" 139 "%s_1 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)\n", 140 p->name); 141 print_rtx_ptr_loc (p->c_block); 142 if (p->c_block[0] == '{') 143 fputs (p->c_block, stdout); 144 else 145 printf ("{\n %s\n}", p->c_block); 146 fputs ("\n\n", stdout); 147} 148 149/* Given an RTL expression EXP, find all subexpressions which we may 150 assume to perform mode tests. Normal MATCH_OPERAND does; 151 MATCH_CODE does if and only if it accepts CONST_INT or 152 CONST_DOUBLE; and we have to assume that MATCH_TEST does not. 153 These combine in almost-boolean fashion - the only exception is 154 that (not X) must be assumed not to perform a mode test, whether or 155 not X does. 156 157 The mark is the RTL /v flag, which is true for subexpressions which 158 do *not* perform mode tests. 159*/ 160#define NO_MODE_TEST(EXP) RTX_FLAG (EXP, volatil) 161static void 162mark_mode_tests (rtx exp) 163{ 164 switch (GET_CODE (exp)) 165 { 166 case MATCH_OPERAND: 167 { 168 struct pred_data *p = lookup_predicate (XSTR (exp, 1)); 169 if (!p) 170 error ("reference to undefined predicate '%s'", XSTR (exp, 1)); 171 else if (p->special || GET_MODE (exp) != VOIDmode) 172 NO_MODE_TEST (exp) = 1; 173 } 174 break; 175 176 case MATCH_CODE: 177 if (!strstr (XSTR (exp, 0), "const_int") 178 && !strstr (XSTR (exp, 0), "const_double")) 179 NO_MODE_TEST (exp) = 1; 180 break; 181 182 case MATCH_TEST: 183 case NOT: 184 NO_MODE_TEST (exp) = 1; 185 break; 186 187 case AND: 188 mark_mode_tests (XEXP (exp, 0)); 189 mark_mode_tests (XEXP (exp, 1)); 190 191 NO_MODE_TEST (exp) = (NO_MODE_TEST (XEXP (exp, 0)) 192 && NO_MODE_TEST (XEXP (exp, 1))); 193 break; 194 195 case IOR: 196 mark_mode_tests (XEXP (exp, 0)); 197 mark_mode_tests (XEXP (exp, 1)); 198 199 NO_MODE_TEST (exp) = (NO_MODE_TEST (XEXP (exp, 0)) 200 || NO_MODE_TEST (XEXP (exp, 1))); 201 break; 202 203 case IF_THEN_ELSE: 204 /* A ? B : C does a mode test if (one of A and B) does a mode 205 test, and C does too. */ 206 mark_mode_tests (XEXP (exp, 0)); 207 mark_mode_tests (XEXP (exp, 1)); 208 mark_mode_tests (XEXP (exp, 2)); 209 210 NO_MODE_TEST (exp) = ((NO_MODE_TEST (XEXP (exp, 0)) 211 && NO_MODE_TEST (XEXP (exp, 1))) 212 || NO_MODE_TEST (XEXP (exp, 2))); 213 break; 214 215 default: 216 error ("'%s' cannot be used in a define_predicate expression", 217 GET_RTX_NAME (GET_CODE (exp))); 218 } 219} 220 221/* Given a predicate, work out where in its RTL expression to add 222 tests for proper modes. Special predicates do not get any such 223 tests. We try to avoid adding tests when we don't have to; in 224 particular, other normal predicates can be counted on to do it for 225 us. */ 226 227static void 228add_mode_tests (struct pred_data *p) 229{ 230 rtx match_test_exp, and_exp; 231 rtx *pos; 232 233 /* Don't touch special predicates. */ 234 if (p->special) 235 return; 236 237 mark_mode_tests (p->exp); 238 239 /* If the whole expression already tests the mode, we're done. */ 240 if (!NO_MODE_TEST (p->exp)) 241 return; 242 243 match_test_exp = rtx_alloc (MATCH_TEST); 244 XSTR (match_test_exp, 0) = "mode == VOIDmode || GET_MODE (op) == mode"; 245 and_exp = rtx_alloc (AND); 246 XEXP (and_exp, 1) = match_test_exp; 247 248 /* It is always correct to rewrite p->exp as 249 250 (and (...) (match_test "mode == VOIDmode || GET_MODE (op) == mode")) 251 252 but there are a couple forms where we can do better. If the 253 top-level pattern is an IOR, and one of the two branches does test 254 the mode, we can wrap just the branch that doesn't. Likewise, if 255 we have an IF_THEN_ELSE, and one side of it tests the mode, we can 256 wrap just the side that doesn't. And, of course, we can repeat this 257 descent as many times as it works. */ 258 259 pos = &p->exp; 260 for (;;) 261 { 262 rtx subexp = *pos; 263 264 switch (GET_CODE (subexp)) 265 { 266 case IOR: 267 { 268 int test0 = NO_MODE_TEST (XEXP (subexp, 0)); 269 int test1 = NO_MODE_TEST (XEXP (subexp, 1)); 270 271 gcc_assert (test0 || test1); 272 273 if (test0 && test1) 274 goto break_loop; 275 pos = test0 ? &XEXP (subexp, 0) : &XEXP (subexp, 1); 276 } 277 break; 278 279 case IF_THEN_ELSE: 280 { 281 int test0 = NO_MODE_TEST (XEXP (subexp, 0)); 282 int test1 = NO_MODE_TEST (XEXP (subexp, 1)); 283 int test2 = NO_MODE_TEST (XEXP (subexp, 2)); 284 285 gcc_assert ((test0 && test1) || test2); 286 287 if (test0 && test1 && test2) 288 goto break_loop; 289 if (test0 && test1) 290 /* Must put it on the dependent clause, not the 291 controlling expression, or we change the meaning of 292 the test. */ 293 pos = &XEXP (subexp, 1); 294 else 295 pos = &XEXP (subexp, 2); 296 } 297 break; 298 299 default: 300 goto break_loop; 301 } 302 } 303 break_loop: 304 XEXP (and_exp, 0) = *pos; 305 *pos = and_exp; 306} 307 308 309/* CODES is a list of RTX codes. Write out an expression which 310 determines whether the operand has one of those codes. */ 311static void 312write_match_code (const char *codes) 313{ 314 const char *code; 315 316 while ((code = scan_comma_elt (&codes)) != 0) 317 { 318 fputs ("GET_CODE (op) == ", stdout); 319 while (code < codes) 320 { 321 putchar (TOUPPER (*code)); 322 code++; 323 } 324 325 if (*codes == ',') 326 fputs (" || ", stdout); 327 } 328} 329 330/* EXP is an RTL (sub)expression for a predicate. Recursively 331 descend the expression and write out an equivalent C expression. */ 332static void 333write_predicate_expr (const char *name, rtx exp) 334{ 335 switch (GET_CODE (exp)) 336 { 337 case AND: 338 putchar ('('); 339 write_predicate_expr (name, XEXP (exp, 0)); 340 fputs (") && (", stdout); 341 write_predicate_expr (name, XEXP (exp, 1)); 342 putchar (')'); 343 break; 344 345 case IOR: 346 putchar ('('); 347 write_predicate_expr (name, XEXP (exp, 0)); 348 fputs (") || (", stdout); 349 write_predicate_expr (name, XEXP (exp, 1)); 350 putchar (')'); 351 break; 352 353 case NOT: 354 fputs ("!(", stdout); 355 write_predicate_expr (name, XEXP (exp, 0)); 356 putchar (')'); 357 break; 358 359 case IF_THEN_ELSE: 360 putchar ('('); 361 write_predicate_expr (name, XEXP (exp, 0)); 362 fputs (") ? (", stdout); 363 write_predicate_expr (name, XEXP (exp, 1)); 364 fputs (") : (", stdout); 365 write_predicate_expr (name, XEXP (exp, 2)); 366 putchar (')'); 367 break; 368 369 case MATCH_OPERAND: 370 if (GET_MODE (exp) == VOIDmode) 371 printf ("%s (op, mode)", XSTR (exp, 1)); 372 else 373 printf ("%s (op, %smode)", XSTR (exp, 1), mode_name[GET_MODE (exp)]); 374 break; 375 376 case MATCH_CODE: 377 write_match_code (XSTR (exp, 0)); 378 break; 379 380 case MATCH_TEST: 381 print_c_condition (XSTR (exp, 0)); 382 break; 383 384 default: 385 error ("%s: cannot use '%s' in a predicate expression", 386 name, GET_RTX_NAME (GET_CODE (exp))); 387 putchar ('0'); 388 } 389} 390 391/* Given a predicate, write out a complete C function to compute it. */ 392static void 393write_one_predicate_function (struct pred_data *p) 394{ 395 if (!p->exp) 396 return; 397 398 write_predicate_subfunction (p); 399 add_mode_tests (p); 400 401 /* A normal predicate can legitimately not look at enum machine_mode 402 if it accepts only CONST_INTs and/or CONST_DOUBLEs. */ 403 printf ("int\n%s (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)\n" 404 "{\n return ", 405 p->name); 406 write_predicate_expr (p->name, p->exp); 407 fputs (";\n}\n\n", stdout); 408} 409 410/* Write insn-preds.c. 411 N.B. the list of headers to include was copied from genrecog; it 412 may not be ideal. 413 414 FUTURE: Write #line markers referring back to the machine 415 description. (Can't practically do this now since we don't know 416 the line number of the C block - just the line number of the enclosing 417 expression.) */ 418static void 419write_insn_preds_c (void) 420{ 421 struct pred_data *p; 422 423 printf ("\ 424/* Generated automatically by the program '%s'\n\ 425 from the machine description file '%s'. */\n\n", progname, in_fname); 426 427 puts ("\ 428#include \"config.h\"\n\ 429#include \"system.h\"\n\ 430#include \"coretypes.h\"\n\ 431#include \"tm.h\"\n\ 432#include \"rtl.h\"\n\ 433#include \"tree.h\"\n\ 434#include \"tm_p.h\"\n\ 435#include \"function.h\"\n\ 436#include \"insn-config.h\"\n\ 437#include \"recog.h\"\n\ 438#include \"real.h\"\n\ 439#include \"output.h\"\n\ 440#include \"flags.h\"\n\ 441#include \"hard-reg-set.h\"\n\ 442#include \"resource.h\"\n\ 443#include \"toplev.h\"\n\ 444#include \"reload.h\"\n\ 445#include \"regs.h\"\n"); 446 447 FOR_ALL_PREDICATES (p) 448 write_one_predicate_function (p); 449} 450 451/* Argument parsing. */ 452static bool gen_header; 453static bool 454parse_option (const char *opt) 455{ 456 if (!strcmp (opt, "-h")) 457 { 458 gen_header = true; 459 return 1; 460 } 461 else 462 return 0; 463} 464 465/* Master control. */ 466int 467main (int argc, char **argv) 468{ 469 rtx defn; 470 int pattern_lineno, next_insn_code = 0; 471 472 progname = argv[0]; 473 if (argc <= 1) 474 fatal ("no input file name"); 475 if (init_md_reader_args_cb (argc, argv, parse_option) != SUCCESS_EXIT_CODE) 476 return FATAL_EXIT_CODE; 477 478 while ((defn = read_md_rtx (&pattern_lineno, &next_insn_code)) != 0) 479 { 480 if (GET_CODE (defn) == DEFINE_PREDICATE 481 || GET_CODE (defn) == DEFINE_SPECIAL_PREDICATE) 482 process_define_predicate (defn); 483 } 484 485 if (gen_header) 486 write_tm_preds_h (); 487 else 488 write_insn_preds_c (); 489 490 if (have_error || ferror (stdout) || fflush (stdout) || fclose (stdout)) 491 return FATAL_EXIT_CODE; 492 493 return SUCCESS_EXIT_CODE; 494} 495 496/* Dummy for debugging purposes. */ 497const char * 498get_insn_name (int code ATTRIBUTE_UNUSED) 499{ 500 return 0; 501} 502