190075Sobrien/* Generate from machine description: 2169689Skan - prototype declarations for operand predicates (tm-preds.h) 3169689Skan - function definitions of operand predicates, if defined new-style 4169689Skan (insn-preds.c) 5169689Skan Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. 690075Sobrien 790075SobrienThis file is part of GCC. 890075Sobrien 990075SobrienGCC is free software; you can redistribute it and/or modify 1090075Sobrienit under the terms of the GNU General Public License as published by 1190075Sobrienthe Free Software Foundation; either version 2, or (at your option) 1290075Sobrienany later version. 1390075Sobrien 1490075SobrienGCC is distributed in the hope that it will be useful, 1590075Sobrienbut WITHOUT ANY WARRANTY; without even the implied warranty of 1690075SobrienMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1790075SobrienGNU General Public License for more details. 1890075Sobrien 1990075SobrienYou should have received a copy of the GNU General Public License 2090075Sobrienalong with GCC; see the file COPYING. If not, write to 21169689Skanthe Free Software Foundation, 51 Franklin Street, Fifth Floor, 22169689SkanBoston, MA 02110-1301, USA. */ 2390075Sobrien 24132718Skan#include "bconfig.h" 2590075Sobrien#include "system.h" 26132718Skan#include "coretypes.h" 27132718Skan#include "tm.h" 2890075Sobrien#include "rtl.h" 29169689Skan#include "errors.h" 30169689Skan#include "obstack.h" 31169689Skan#include "gensupport.h" 3290075Sobrien 33169689Skan/* Given a predicate expression EXP, from form NAME at line LINENO, 34169689Skan verify that it does not contain any RTL constructs which are not 35169689Skan valid in predicate definitions. Returns true if EXP is 36169689Skan INvalid; issues error messages, caller need not. */ 37169689Skanstatic bool 38169689Skanvalidate_exp (rtx exp, const char *name, int lineno) 39169689Skan{ 40169689Skan if (exp == 0) 41169689Skan { 42169689Skan message_with_line (lineno, "%s: must give a predicate expression", name); 43169689Skan return true; 44169689Skan } 4590075Sobrien 46169689Skan switch (GET_CODE (exp)) 47169689Skan { 48169689Skan /* Ternary, binary, unary expressions: recurse into subexpressions. */ 49169689Skan case IF_THEN_ELSE: 50169689Skan if (validate_exp (XEXP (exp, 2), name, lineno)) 51169689Skan return true; 52169689Skan /* else fall through */ 53169689Skan case AND: 54169689Skan case IOR: 55169689Skan if (validate_exp (XEXP (exp, 1), name, lineno)) 56169689Skan return true; 57169689Skan /* else fall through */ 58169689Skan case NOT: 59169689Skan return validate_exp (XEXP (exp, 0), name, lineno); 60169689Skan 61169689Skan /* MATCH_CODE might have a syntax error in its path expression. */ 62169689Skan case MATCH_CODE: 63169689Skan { 64169689Skan const char *p; 65169689Skan for (p = XSTR (exp, 1); *p; p++) 66169689Skan { 67169689Skan if (!ISDIGIT (*p) && !ISLOWER (*p)) 68169689Skan { 69169689Skan message_with_line (lineno, "%s: invalid character in path " 70169689Skan "string '%s'", name, XSTR (exp, 1)); 71169689Skan have_error = 1; 72169689Skan return true; 73169689Skan } 74169689Skan } 75169689Skan } 76169689Skan /* fall through */ 77169689Skan 78169689Skan /* These need no special checking. */ 79169689Skan case MATCH_OPERAND: 80169689Skan case MATCH_TEST: 81169689Skan return false; 82169689Skan 83169689Skan default: 84169689Skan message_with_line (lineno, 85169689Skan "%s: cannot use '%s' in a predicate expression", 86169689Skan name, GET_RTX_NAME (GET_CODE (exp))); 87169689Skan have_error = 1; 88169689Skan return true; 89169689Skan } 90169689Skan} 91169689Skan 92169689Skan/* Predicates are defined with (define_predicate) or 93169689Skan (define_special_predicate) expressions in the machine description. */ 9490075Sobrienstatic void 95169689Skanprocess_define_predicate (rtx defn, int lineno) 9690075Sobrien{ 97169689Skan struct pred_data *pred; 98169689Skan const char *p; 9990075Sobrien 100169689Skan if (!ISALPHA (XSTR (defn, 0)[0]) && XSTR (defn, 0)[0] != '_') 101169689Skan goto bad_name; 102169689Skan for (p = XSTR (defn, 0) + 1; *p; p++) 103169689Skan if (!ISALNUM (*p) && *p != '_') 104169689Skan goto bad_name; 105169689Skan 106169689Skan if (validate_exp (XEXP (defn, 1), XSTR (defn, 0), lineno)) 107169689Skan return; 108169689Skan 109169689Skan pred = XCNEW (struct pred_data); 110169689Skan pred->name = XSTR (defn, 0); 111169689Skan pred->exp = XEXP (defn, 1); 112169689Skan pred->c_block = XSTR (defn, 2); 113169689Skan 114169689Skan if (GET_CODE (defn) == DEFINE_SPECIAL_PREDICATE) 115169689Skan pred->special = true; 116169689Skan 117169689Skan add_predicate (pred); 118169689Skan return; 119169689Skan 120169689Skan bad_name: 121169689Skan message_with_line (lineno, 122169689Skan "%s: predicate name must be a valid C function name", 123169689Skan XSTR (defn, 0)); 124169689Skan have_error = 1; 125169689Skan return; 12690075Sobrien} 12790075Sobrien 128169689Skan/* Given a predicate, if it has an embedded C block, write the block 129169689Skan out as a static inline subroutine, and augment the RTL test with a 130169689Skan match_test that calls that subroutine. For instance, 131169689Skan 132169689Skan (define_predicate "basereg_operand" 133169689Skan (match_operand 0 "register_operand") 134169689Skan { 135169689Skan if (GET_CODE (op) == SUBREG) 136169689Skan op = SUBREG_REG (op); 137169689Skan return REG_POINTER (op); 138169689Skan }) 139169689Skan 140169689Skan becomes 141169689Skan 142169689Skan static inline int basereg_operand_1(rtx op, enum machine_mode mode) 143169689Skan { 144169689Skan if (GET_CODE (op) == SUBREG) 145169689Skan op = SUBREG_REG (op); 146169689Skan return REG_POINTER (op); 147169689Skan } 148169689Skan 149169689Skan (define_predicate "basereg_operand" 150169689Skan (and (match_operand 0 "register_operand") 151169689Skan (match_test "basereg_operand_1 (op, mode)"))) 152169689Skan 153169689Skan The only wart is that there's no way to insist on a { } string in 154169689Skan an RTL template, so we have to handle "" strings. */ 155169689Skan 156169689Skan 157169689Skanstatic void 158169689Skanwrite_predicate_subfunction (struct pred_data *p) 159169689Skan{ 160169689Skan const char *match_test_str; 161169689Skan rtx match_test_exp, and_exp; 162169689Skan 163169689Skan if (p->c_block[0] == '\0') 164169689Skan return; 165169689Skan 166169689Skan /* Construct the function-call expression. */ 167169689Skan obstack_grow (rtl_obstack, p->name, strlen (p->name)); 168169689Skan obstack_grow (rtl_obstack, "_1 (op, mode)", 169169689Skan sizeof "_1 (op, mode)"); 170169689Skan match_test_str = XOBFINISH (rtl_obstack, const char *); 171169689Skan 172169689Skan /* Add the function-call expression to the complete expression to be 173169689Skan evaluated. */ 174169689Skan match_test_exp = rtx_alloc (MATCH_TEST); 175169689Skan XSTR (match_test_exp, 0) = match_test_str; 176169689Skan 177169689Skan and_exp = rtx_alloc (AND); 178169689Skan XEXP (and_exp, 0) = p->exp; 179169689Skan XEXP (and_exp, 1) = match_test_exp; 180169689Skan 181169689Skan p->exp = and_exp; 182169689Skan 183169689Skan printf ("static inline int\n" 184169689Skan "%s_1 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)\n", 185169689Skan p->name); 186169689Skan print_rtx_ptr_loc (p->c_block); 187169689Skan if (p->c_block[0] == '{') 188169689Skan fputs (p->c_block, stdout); 189169689Skan else 190169689Skan printf ("{\n %s\n}", p->c_block); 191169689Skan fputs ("\n\n", stdout); 192169689Skan} 193169689Skan 194169689Skan/* Given a predicate expression EXP, from form NAME, determine whether 195169689Skan it refers to the variable given as VAR. */ 196169689Skanstatic bool 197169689Skanneeds_variable (rtx exp, const char *var) 198169689Skan{ 199169689Skan switch (GET_CODE (exp)) 200169689Skan { 201169689Skan /* Ternary, binary, unary expressions need a variable if 202169689Skan any of their subexpressions do. */ 203169689Skan case IF_THEN_ELSE: 204169689Skan if (needs_variable (XEXP (exp, 2), var)) 205169689Skan return true; 206169689Skan /* else fall through */ 207169689Skan case AND: 208169689Skan case IOR: 209169689Skan if (needs_variable (XEXP (exp, 1), var)) 210169689Skan return true; 211169689Skan /* else fall through */ 212169689Skan case NOT: 213169689Skan return needs_variable (XEXP (exp, 0), var); 214169689Skan 215169689Skan /* MATCH_CODE uses "op", but nothing else. */ 216169689Skan case MATCH_CODE: 217169689Skan return !strcmp (var, "op"); 218169689Skan 219169689Skan /* MATCH_OPERAND uses "op" and may use "mode". */ 220169689Skan case MATCH_OPERAND: 221169689Skan if (!strcmp (var, "op")) 222169689Skan return true; 223169689Skan if (!strcmp (var, "mode") && GET_MODE (exp) == VOIDmode) 224169689Skan return true; 225169689Skan return false; 226169689Skan 227169689Skan /* MATCH_TEST uses var if XSTR (exp, 0) =~ /\b${var}\b/o; */ 228169689Skan case MATCH_TEST: 229169689Skan { 230169689Skan const char *p = XSTR (exp, 0); 231169689Skan const char *q = strstr (p, var); 232169689Skan if (!q) 233169689Skan return false; 234169689Skan if (q != p && (ISALNUM (q[-1]) || q[-1] == '_')) 235169689Skan return false; 236169689Skan q += strlen (var); 237169689Skan if (ISALNUM (q[0] || q[0] == '_')) 238169689Skan return false; 239169689Skan } 240169689Skan return true; 241169689Skan 242169689Skan default: 243169689Skan gcc_unreachable (); 244169689Skan } 245169689Skan} 246169689Skan 247169689Skan/* Given an RTL expression EXP, find all subexpressions which we may 248169689Skan assume to perform mode tests. Normal MATCH_OPERAND does; 249169689Skan MATCH_CODE does if it applies to the whole expression and accepts 250169689Skan CONST_INT or CONST_DOUBLE; and we have to assume that MATCH_TEST 251169689Skan does not. These combine in almost-boolean fashion - the only 252169689Skan exception is that (not X) must be assumed not to perform a mode 253169689Skan test, whether or not X does. 254169689Skan 255169689Skan The mark is the RTL /v flag, which is true for subexpressions which 256169689Skan do *not* perform mode tests. 257169689Skan*/ 258169689Skan#define NO_MODE_TEST(EXP) RTX_FLAG (EXP, volatil) 259169689Skanstatic void 260169689Skanmark_mode_tests (rtx exp) 261169689Skan{ 262169689Skan switch (GET_CODE (exp)) 263169689Skan { 264169689Skan case MATCH_OPERAND: 265169689Skan { 266169689Skan struct pred_data *p = lookup_predicate (XSTR (exp, 1)); 267169689Skan if (!p) 268169689Skan error ("reference to undefined predicate '%s'", XSTR (exp, 1)); 269169689Skan else if (p->special || GET_MODE (exp) != VOIDmode) 270169689Skan NO_MODE_TEST (exp) = 1; 271169689Skan } 272169689Skan break; 273169689Skan 274169689Skan case MATCH_CODE: 275169689Skan if (XSTR (exp, 1)[0] != '\0' 276169689Skan || (!strstr (XSTR (exp, 0), "const_int") 277169689Skan && !strstr (XSTR (exp, 0), "const_double"))) 278169689Skan NO_MODE_TEST (exp) = 1; 279169689Skan break; 280169689Skan 281169689Skan case MATCH_TEST: 282169689Skan case NOT: 283169689Skan NO_MODE_TEST (exp) = 1; 284169689Skan break; 285169689Skan 286169689Skan case AND: 287169689Skan mark_mode_tests (XEXP (exp, 0)); 288169689Skan mark_mode_tests (XEXP (exp, 1)); 289169689Skan 290169689Skan NO_MODE_TEST (exp) = (NO_MODE_TEST (XEXP (exp, 0)) 291169689Skan && NO_MODE_TEST (XEXP (exp, 1))); 292169689Skan break; 293169689Skan 294169689Skan case IOR: 295169689Skan mark_mode_tests (XEXP (exp, 0)); 296169689Skan mark_mode_tests (XEXP (exp, 1)); 297169689Skan 298169689Skan NO_MODE_TEST (exp) = (NO_MODE_TEST (XEXP (exp, 0)) 299169689Skan || NO_MODE_TEST (XEXP (exp, 1))); 300169689Skan break; 301169689Skan 302169689Skan case IF_THEN_ELSE: 303169689Skan /* A ? B : C does a mode test if (one of A and B) does a mode 304169689Skan test, and C does too. */ 305169689Skan mark_mode_tests (XEXP (exp, 0)); 306169689Skan mark_mode_tests (XEXP (exp, 1)); 307169689Skan mark_mode_tests (XEXP (exp, 2)); 308169689Skan 309169689Skan NO_MODE_TEST (exp) = ((NO_MODE_TEST (XEXP (exp, 0)) 310169689Skan && NO_MODE_TEST (XEXP (exp, 1))) 311169689Skan || NO_MODE_TEST (XEXP (exp, 2))); 312169689Skan break; 313169689Skan 314169689Skan default: 315169689Skan gcc_unreachable (); 316169689Skan } 317169689Skan} 318169689Skan 319169689Skan/* Determine whether the expression EXP is a MATCH_CODE that should 320169689Skan be written as a switch statement. */ 321169689Skanstatic bool 322169689Skangenerate_switch_p (rtx exp) 323169689Skan{ 324169689Skan return GET_CODE (exp) == MATCH_CODE 325169689Skan && strchr (XSTR (exp, 0), ','); 326169689Skan} 327169689Skan 328169689Skan/* Given a predicate, work out where in its RTL expression to add 329169689Skan tests for proper modes. Special predicates do not get any such 330169689Skan tests. We try to avoid adding tests when we don't have to; in 331169689Skan particular, other normal predicates can be counted on to do it for 332169689Skan us. */ 333169689Skan 334169689Skanstatic void 335169689Skanadd_mode_tests (struct pred_data *p) 336169689Skan{ 337169689Skan rtx match_test_exp, and_exp; 338169689Skan rtx *pos; 339169689Skan 340169689Skan /* Don't touch special predicates. */ 341169689Skan if (p->special) 342169689Skan return; 343169689Skan 344169689Skan mark_mode_tests (p->exp); 345169689Skan 346169689Skan /* If the whole expression already tests the mode, we're done. */ 347169689Skan if (!NO_MODE_TEST (p->exp)) 348169689Skan return; 349169689Skan 350169689Skan match_test_exp = rtx_alloc (MATCH_TEST); 351169689Skan XSTR (match_test_exp, 0) = "mode == VOIDmode || GET_MODE (op) == mode"; 352169689Skan and_exp = rtx_alloc (AND); 353169689Skan XEXP (and_exp, 1) = match_test_exp; 354169689Skan 355169689Skan /* It is always correct to rewrite p->exp as 356169689Skan 357169689Skan (and (...) (match_test "mode == VOIDmode || GET_MODE (op) == mode")) 358169689Skan 359169689Skan but there are a couple forms where we can do better. If the 360169689Skan top-level pattern is an IOR, and one of the two branches does test 361169689Skan the mode, we can wrap just the branch that doesn't. Likewise, if 362169689Skan we have an IF_THEN_ELSE, and one side of it tests the mode, we can 363169689Skan wrap just the side that doesn't. And, of course, we can repeat this 364169689Skan descent as many times as it works. */ 365169689Skan 366169689Skan pos = &p->exp; 367169689Skan for (;;) 368169689Skan { 369169689Skan rtx subexp = *pos; 370169689Skan 371169689Skan switch (GET_CODE (subexp)) 372169689Skan { 373169689Skan case AND: 374169689Skan /* The switch code generation in write_predicate_stmts prefers 375169689Skan rtx code tests to be at the top of the expression tree. So 376169689Skan push this AND down into the second operand of an existing 377169689Skan AND expression. */ 378169689Skan if (generate_switch_p (XEXP (subexp, 0))) 379169689Skan pos = &XEXP (subexp, 1); 380169689Skan goto break_loop; 381169689Skan 382169689Skan case IOR: 383169689Skan { 384169689Skan int test0 = NO_MODE_TEST (XEXP (subexp, 0)); 385169689Skan int test1 = NO_MODE_TEST (XEXP (subexp, 1)); 386169689Skan 387169689Skan gcc_assert (test0 || test1); 388169689Skan 389169689Skan if (test0 && test1) 390169689Skan goto break_loop; 391169689Skan pos = test0 ? &XEXP (subexp, 0) : &XEXP (subexp, 1); 392169689Skan } 393169689Skan break; 394169689Skan 395169689Skan case IF_THEN_ELSE: 396169689Skan { 397169689Skan int test0 = NO_MODE_TEST (XEXP (subexp, 0)); 398169689Skan int test1 = NO_MODE_TEST (XEXP (subexp, 1)); 399169689Skan int test2 = NO_MODE_TEST (XEXP (subexp, 2)); 400169689Skan 401169689Skan gcc_assert ((test0 && test1) || test2); 402169689Skan 403169689Skan if (test0 && test1 && test2) 404169689Skan goto break_loop; 405169689Skan if (test0 && test1) 406169689Skan /* Must put it on the dependent clause, not the 407169689Skan controlling expression, or we change the meaning of 408169689Skan the test. */ 409169689Skan pos = &XEXP (subexp, 1); 410169689Skan else 411169689Skan pos = &XEXP (subexp, 2); 412169689Skan } 413169689Skan break; 414169689Skan 415169689Skan default: 416169689Skan goto break_loop; 417169689Skan } 418169689Skan } 419169689Skan break_loop: 420169689Skan XEXP (and_exp, 0) = *pos; 421169689Skan *pos = and_exp; 422169689Skan} 423169689Skan 424169689Skan/* PATH is a string describing a path from the root of an RTL 425169689Skan expression to an inner subexpression to be tested. Output 426169689Skan code which computes the subexpression from the variable 427169689Skan holding the root of the expression. */ 428169689Skanstatic void 429169689Skanwrite_extract_subexp (const char *path) 430169689Skan{ 431169689Skan int len = strlen (path); 432169689Skan int i; 433169689Skan 434169689Skan /* We first write out the operations (XEXP or XVECEXP) in reverse 435169689Skan order, then write "op", then the indices in forward order. */ 436169689Skan for (i = len - 1; i >= 0; i--) 437169689Skan { 438169689Skan if (ISLOWER (path[i])) 439169689Skan fputs ("XVECEXP (", stdout); 440169689Skan else if (ISDIGIT (path[i])) 441169689Skan fputs ("XEXP (", stdout); 442169689Skan else 443169689Skan gcc_unreachable (); 444169689Skan } 445169689Skan 446169689Skan fputs ("op", stdout); 447169689Skan 448169689Skan for (i = 0; i < len; i++) 449169689Skan { 450169689Skan if (ISLOWER (path[i])) 451169689Skan printf (", 0, %d)", path[i] - 'a'); 452169689Skan else if (ISDIGIT (path[i])) 453169689Skan printf (", %d)", path[i] - '0'); 454169689Skan else 455169689Skan gcc_unreachable (); 456169689Skan } 457169689Skan} 458169689Skan 459169689Skan/* CODES is a list of RTX codes. Write out an expression which 460169689Skan determines whether the operand has one of those codes. */ 461169689Skanstatic void 462169689Skanwrite_match_code (const char *path, const char *codes) 463169689Skan{ 464169689Skan const char *code; 465169689Skan 466169689Skan while ((code = scan_comma_elt (&codes)) != 0) 467169689Skan { 468169689Skan fputs ("GET_CODE (", stdout); 469169689Skan write_extract_subexp (path); 470169689Skan fputs (") == ", stdout); 471169689Skan while (code < codes) 472169689Skan { 473169689Skan putchar (TOUPPER (*code)); 474169689Skan code++; 475169689Skan } 476169689Skan 477169689Skan if (*codes == ',') 478169689Skan fputs (" || ", stdout); 479169689Skan } 480169689Skan} 481169689Skan 482169689Skan/* EXP is an RTL (sub)expression for a predicate. Recursively 483169689Skan descend the expression and write out an equivalent C expression. */ 484169689Skanstatic void 485169689Skanwrite_predicate_expr (rtx exp) 486169689Skan{ 487169689Skan switch (GET_CODE (exp)) 488169689Skan { 489169689Skan case AND: 490169689Skan putchar ('('); 491169689Skan write_predicate_expr (XEXP (exp, 0)); 492169689Skan fputs (") && (", stdout); 493169689Skan write_predicate_expr (XEXP (exp, 1)); 494169689Skan putchar (')'); 495169689Skan break; 496169689Skan 497169689Skan case IOR: 498169689Skan putchar ('('); 499169689Skan write_predicate_expr (XEXP (exp, 0)); 500169689Skan fputs (") || (", stdout); 501169689Skan write_predicate_expr (XEXP (exp, 1)); 502169689Skan putchar (')'); 503169689Skan break; 504169689Skan 505169689Skan case NOT: 506169689Skan fputs ("!(", stdout); 507169689Skan write_predicate_expr (XEXP (exp, 0)); 508169689Skan putchar (')'); 509169689Skan break; 510169689Skan 511169689Skan case IF_THEN_ELSE: 512169689Skan putchar ('('); 513169689Skan write_predicate_expr (XEXP (exp, 0)); 514169689Skan fputs (") ? (", stdout); 515169689Skan write_predicate_expr (XEXP (exp, 1)); 516169689Skan fputs (") : (", stdout); 517169689Skan write_predicate_expr (XEXP (exp, 2)); 518169689Skan putchar (')'); 519169689Skan break; 520169689Skan 521169689Skan case MATCH_OPERAND: 522169689Skan if (GET_MODE (exp) == VOIDmode) 523169689Skan printf ("%s (op, mode)", XSTR (exp, 1)); 524169689Skan else 525169689Skan printf ("%s (op, %smode)", XSTR (exp, 1), mode_name[GET_MODE (exp)]); 526169689Skan break; 527169689Skan 528169689Skan case MATCH_CODE: 529169689Skan write_match_code (XSTR (exp, 1), XSTR (exp, 0)); 530169689Skan break; 531169689Skan 532169689Skan case MATCH_TEST: 533169689Skan print_c_condition (XSTR (exp, 0)); 534169689Skan break; 535169689Skan 536169689Skan default: 537169689Skan gcc_unreachable (); 538169689Skan } 539169689Skan} 540169689Skan 541169689Skan/* Write the MATCH_CODE expression EXP as a switch statement. */ 542169689Skan 543169689Skanstatic void 544169689Skanwrite_match_code_switch (rtx exp) 545169689Skan{ 546169689Skan const char *codes = XSTR (exp, 0); 547169689Skan const char *path = XSTR (exp, 1); 548169689Skan const char *code; 549169689Skan 550169689Skan fputs (" switch (GET_CODE (", stdout); 551169689Skan write_extract_subexp (path); 552169689Skan fputs ("))\n {\n", stdout); 553169689Skan 554169689Skan while ((code = scan_comma_elt (&codes)) != 0) 555169689Skan { 556169689Skan fputs (" case ", stdout); 557169689Skan while (code < codes) 558169689Skan { 559169689Skan putchar (TOUPPER (*code)); 560169689Skan code++; 561169689Skan } 562169689Skan fputs(":\n", stdout); 563169689Skan } 564169689Skan} 565169689Skan 566169689Skan/* Given a predicate expression EXP, write out a sequence of stmts 567169689Skan to evaluate it. This is similar to write_predicate_expr but can 568169689Skan generate efficient switch statements. */ 569169689Skan 570169689Skanstatic void 571169689Skanwrite_predicate_stmts (rtx exp) 572169689Skan{ 573169689Skan switch (GET_CODE (exp)) 574169689Skan { 575169689Skan case MATCH_CODE: 576169689Skan if (generate_switch_p (exp)) 577169689Skan { 578169689Skan write_match_code_switch (exp); 579169689Skan puts (" return true;\n" 580169689Skan " default:\n" 581169689Skan " break;\n" 582169689Skan " }\n" 583169689Skan " return false;"); 584169689Skan return; 585169689Skan } 586169689Skan break; 587169689Skan 588169689Skan case AND: 589169689Skan if (generate_switch_p (XEXP (exp, 0))) 590169689Skan { 591169689Skan write_match_code_switch (XEXP (exp, 0)); 592169689Skan puts (" break;\n" 593169689Skan " default:\n" 594169689Skan " return false;\n" 595169689Skan " }"); 596169689Skan exp = XEXP (exp, 1); 597169689Skan } 598169689Skan break; 599169689Skan 600169689Skan case IOR: 601169689Skan if (generate_switch_p (XEXP (exp, 0))) 602169689Skan { 603169689Skan write_match_code_switch (XEXP (exp, 0)); 604169689Skan puts (" return true;\n" 605169689Skan " default:\n" 606169689Skan " break;\n" 607169689Skan " }"); 608169689Skan exp = XEXP (exp, 1); 609169689Skan } 610169689Skan break; 611169689Skan 612169689Skan case NOT: 613169689Skan if (generate_switch_p (XEXP (exp, 0))) 614169689Skan { 615169689Skan write_match_code_switch (XEXP (exp, 0)); 616169689Skan puts (" return false;\n" 617169689Skan " default:\n" 618169689Skan " break;\n" 619169689Skan " }\n" 620169689Skan " return true;"); 621169689Skan return; 622169689Skan } 623169689Skan break; 624169689Skan 625169689Skan default: 626169689Skan break; 627169689Skan } 628169689Skan 629169689Skan fputs(" return ",stdout); 630169689Skan write_predicate_expr (exp); 631169689Skan fputs(";\n", stdout); 632169689Skan} 633169689Skan 634169689Skan/* Given a predicate, write out a complete C function to compute it. */ 635169689Skanstatic void 636169689Skanwrite_one_predicate_function (struct pred_data *p) 637169689Skan{ 638169689Skan if (!p->exp) 639169689Skan return; 640169689Skan 641169689Skan write_predicate_subfunction (p); 642169689Skan add_mode_tests (p); 643169689Skan 644169689Skan /* A normal predicate can legitimately not look at enum machine_mode 645169689Skan if it accepts only CONST_INTs and/or CONST_DOUBLEs. */ 646169689Skan printf ("int\n%s (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)\n{\n", 647169689Skan p->name); 648169689Skan write_predicate_stmts (p->exp); 649169689Skan fputs ("}\n\n", stdout); 650169689Skan} 651169689Skan 652169689Skan/* Constraints fall into two categories: register constraints 653169689Skan (define_register_constraint), and others (define_constraint, 654169689Skan define_memory_constraint, define_address_constraint). We 655169689Skan work out automatically which of the various old-style macros 656169689Skan they correspond to, and produce appropriate code. They all 657169689Skan go in the same hash table so we can verify that there are no 658169689Skan duplicate names. */ 659169689Skan 660169689Skan/* All data from one constraint definition. */ 661169689Skanstruct constraint_data 662169689Skan{ 663169689Skan struct constraint_data *next_this_letter; 664169689Skan struct constraint_data *next_textual; 665169689Skan const char *name; 666169689Skan const char *c_name; /* same as .name unless mangling is necessary */ 667169689Skan size_t namelen; 668169689Skan const char *regclass; /* for register constraints */ 669169689Skan rtx exp; /* for other constraints */ 670169689Skan unsigned int lineno; /* line of definition */ 671169689Skan unsigned int is_register : 1; 672169689Skan unsigned int is_const_int : 1; 673169689Skan unsigned int is_const_dbl : 1; 674169689Skan unsigned int is_extra : 1; 675169689Skan unsigned int is_memory : 1; 676169689Skan unsigned int is_address : 1; 677169689Skan}; 678169689Skan 679169689Skan/* Overview of all constraints beginning with a given letter. */ 680169689Skan 681169689Skanstatic struct constraint_data * 682169689Skanconstraints_by_letter_table[1<<CHAR_BIT]; 683169689Skan 684169689Skan/* For looking up all the constraints in the order that they appeared 685169689Skan in the machine description. */ 686169689Skanstatic struct constraint_data *first_constraint; 687169689Skanstatic struct constraint_data **last_constraint_ptr = &first_constraint; 688169689Skan 689169689Skan#define FOR_ALL_CONSTRAINTS(iter_) \ 690169689Skan for (iter_ = first_constraint; iter_; iter_ = iter_->next_textual) 691169689Skan 692169689Skan/* These letters, and all names beginning with them, are reserved for 693169689Skan generic constraints. */ 694169689Skanstatic const char generic_constraint_letters[] = "EFVXgimnoprs"; 695169689Skan 696169689Skan/* Machine-independent code expects that constraints with these 697169689Skan (initial) letters will allow only (a subset of all) CONST_INTs. */ 698169689Skan 699169689Skanstatic const char const_int_constraints[] = "IJKLMNOP"; 700169689Skan 701169689Skan/* Machine-independent code expects that constraints with these 702169689Skan (initial) letters will allow only (a subset of all) CONST_DOUBLEs. */ 703169689Skan 704169689Skanstatic const char const_dbl_constraints[] = "GH"; 705169689Skan 706169689Skan/* Summary data used to decide whether to output various functions and 707169689Skan macro definitions. */ 708169689Skanstatic unsigned int constraint_max_namelen; 709169689Skanstatic bool have_register_constraints; 710169689Skanstatic bool have_memory_constraints; 711169689Skanstatic bool have_address_constraints; 712169689Skanstatic bool have_extra_constraints; 713169689Skanstatic bool have_const_int_constraints; 714169689Skanstatic bool have_const_dbl_constraints; 715169689Skan 716169689Skan/* Convert NAME, which contains angle brackets and/or underscores, to 717169689Skan a string that can be used as part of a C identifier. The string 718169689Skan comes from the rtl_obstack. */ 719169689Skanstatic const char * 720169689Skanmangle (const char *name) 721169689Skan{ 722169689Skan for (; *name; name++) 723169689Skan switch (*name) 724169689Skan { 725169689Skan case '_': obstack_grow (rtl_obstack, "__", 2); break; 726169689Skan case '<': obstack_grow (rtl_obstack, "_l", 2); break; 727169689Skan case '>': obstack_grow (rtl_obstack, "_g", 2); break; 728169689Skan default: obstack_1grow (rtl_obstack, *name); break; 729169689Skan } 730169689Skan 731169689Skan obstack_1grow (rtl_obstack, '\0'); 732169689Skan return obstack_finish (rtl_obstack); 733169689Skan} 734169689Skan 735169689Skan/* Add one constraint, of any sort, to the tables. NAME is its name; 736169689Skan REGCLASS is the register class, if any; EXP is the expression to 737169689Skan test, if any; IS_MEMORY and IS_ADDRESS indicate memory and address 738169689Skan constraints, respectively; LINENO is the line number from the MD reader. 739169689Skan Not all combinations of arguments are valid; most importantly, REGCLASS 740169689Skan is mutually exclusive with EXP, and IS_MEMORY/IS_ADDRESS are only 741169689Skan meaningful for constraints with EXP. 742169689Skan 743169689Skan This function enforces all syntactic and semantic rules about what 744169689Skan constraints can be defined. */ 745169689Skan 746169689Skanstatic void 747169689Skanadd_constraint (const char *name, const char *regclass, 748169689Skan rtx exp, bool is_memory, bool is_address, 749169689Skan int lineno) 750169689Skan{ 751169689Skan struct constraint_data *c, **iter, **slot; 752169689Skan const char *p; 753169689Skan bool need_mangled_name = false; 754169689Skan bool is_const_int; 755169689Skan bool is_const_dbl; 756169689Skan size_t namelen; 757169689Skan 758169689Skan if (exp && validate_exp (exp, name, lineno)) 759169689Skan return; 760169689Skan 761169689Skan if (!ISALPHA (name[0]) && name[0] != '_') 762169689Skan { 763169689Skan if (name[1] == '\0') 764169689Skan message_with_line (lineno, "constraint name '%s' is not " 765169689Skan "a letter or underscore", name); 766169689Skan else 767169689Skan message_with_line (lineno, "constraint name '%s' does not begin " 768169689Skan "with a letter or underscore", name); 769169689Skan have_error = 1; 770169689Skan return; 771169689Skan } 772169689Skan for (p = name; *p; p++) 773169689Skan if (!ISALNUM (*p)) 774169689Skan { 775169689Skan if (*p == '<' || *p == '>' || *p == '_') 776169689Skan need_mangled_name = true; 777169689Skan else 778169689Skan { 779169689Skan message_with_line (lineno, 780169689Skan "constraint name '%s' must be composed of " 781169689Skan "letters, digits, underscores, and " 782169689Skan "angle brackets", name); 783169689Skan have_error = 1; 784169689Skan return; 785169689Skan } 786169689Skan } 787169689Skan 788169689Skan if (strchr (generic_constraint_letters, name[0])) 789169689Skan { 790169689Skan if (name[1] == '\0') 791169689Skan message_with_line (lineno, "constraint letter '%s' cannot be " 792169689Skan "redefined by the machine description", name); 793169689Skan else 794169689Skan message_with_line (lineno, "constraint name '%s' cannot be defined by " 795169689Skan "the machine description, as it begins with '%c'", 796169689Skan name, name[0]); 797169689Skan have_error = 1; 798169689Skan return; 799169689Skan } 800169689Skan 801169689Skan 802169689Skan namelen = strlen (name); 803169689Skan slot = &constraints_by_letter_table[(unsigned int)name[0]]; 804169689Skan for (iter = slot; *iter; iter = &(*iter)->next_this_letter) 805169689Skan { 806169689Skan /* This causes slot to end up pointing to the 807169689Skan next_this_letter field of the last constraint with a name 808169689Skan of equal or greater length than the new constraint; hence 809169689Skan the new constraint will be inserted after all previous 810169689Skan constraints with names of the same length. */ 811169689Skan if ((*iter)->namelen >= namelen) 812169689Skan slot = iter; 813169689Skan 814169689Skan if (!strcmp ((*iter)->name, name)) 815169689Skan { 816169689Skan message_with_line (lineno, "redefinition of constraint '%s'", name); 817169689Skan message_with_line ((*iter)->lineno, "previous definition is here"); 818169689Skan have_error = 1; 819169689Skan return; 820169689Skan } 821169689Skan else if (!strncmp ((*iter)->name, name, (*iter)->namelen)) 822169689Skan { 823169689Skan message_with_line (lineno, "defining constraint '%s' here", name); 824169689Skan message_with_line ((*iter)->lineno, "renders constraint '%s' " 825169689Skan "(defined here) a prefix", (*iter)->name); 826169689Skan have_error = 1; 827169689Skan return; 828169689Skan } 829169689Skan else if (!strncmp ((*iter)->name, name, namelen)) 830169689Skan { 831169689Skan message_with_line (lineno, "constraint '%s' is a prefix", name); 832169689Skan message_with_line ((*iter)->lineno, "of constraint '%s' " 833169689Skan "(defined here)", (*iter)->name); 834169689Skan have_error = 1; 835169689Skan return; 836169689Skan } 837169689Skan } 838169689Skan 839169689Skan is_const_int = strchr (const_int_constraints, name[0]) != 0; 840169689Skan is_const_dbl = strchr (const_dbl_constraints, name[0]) != 0; 841169689Skan 842169689Skan if (is_const_int || is_const_dbl) 843169689Skan { 844169689Skan enum rtx_code appropriate_code 845169689Skan = is_const_int ? CONST_INT : CONST_DOUBLE; 846169689Skan 847169689Skan /* Consider relaxing this requirement in the future. */ 848169689Skan if (regclass 849169689Skan || GET_CODE (exp) != AND 850169689Skan || GET_CODE (XEXP (exp, 0)) != MATCH_CODE 851169689Skan || strcmp (XSTR (XEXP (exp, 0), 0), 852169689Skan GET_RTX_NAME (appropriate_code))) 853169689Skan { 854169689Skan if (name[1] == '\0') 855169689Skan message_with_line (lineno, "constraint letter '%c' is reserved " 856169689Skan "for %s constraints", 857169689Skan name[0], GET_RTX_NAME (appropriate_code)); 858169689Skan else 859169689Skan message_with_line (lineno, "constraint names beginning with '%c' " 860169689Skan "(%s) are reserved for %s constraints", 861169689Skan name[0], name, 862169689Skan GET_RTX_NAME (appropriate_code)); 863169689Skan 864169689Skan have_error = 1; 865169689Skan return; 866169689Skan } 867169689Skan 868169689Skan if (is_memory) 869169689Skan { 870169689Skan if (name[1] == '\0') 871169689Skan message_with_line (lineno, "constraint letter '%c' cannot be a " 872169689Skan "memory constraint", name[0]); 873169689Skan else 874169689Skan message_with_line (lineno, "constraint name '%s' begins with '%c', " 875169689Skan "and therefore cannot be a memory constraint", 876169689Skan name, name[0]); 877169689Skan 878169689Skan have_error = 1; 879169689Skan return; 880169689Skan } 881169689Skan else if (is_address) 882169689Skan { 883169689Skan if (name[1] == '\0') 884169689Skan message_with_line (lineno, "constraint letter '%c' cannot be a " 885169689Skan "memory constraint", name[0]); 886169689Skan else 887169689Skan message_with_line (lineno, "constraint name '%s' begins with '%c', " 888169689Skan "and therefore cannot be a memory constraint", 889169689Skan name, name[0]); 890169689Skan 891169689Skan have_error = 1; 892169689Skan return; 893169689Skan } 894169689Skan } 895169689Skan 896169689Skan 897169689Skan c = obstack_alloc (rtl_obstack, sizeof (struct constraint_data)); 898169689Skan c->name = name; 899169689Skan c->c_name = need_mangled_name ? mangle (name) : name; 900169689Skan c->lineno = lineno; 901169689Skan c->namelen = namelen; 902169689Skan c->regclass = regclass; 903169689Skan c->exp = exp; 904169689Skan c->is_register = regclass != 0; 905169689Skan c->is_const_int = is_const_int; 906169689Skan c->is_const_dbl = is_const_dbl; 907169689Skan c->is_extra = !(regclass || is_const_int || is_const_dbl); 908169689Skan c->is_memory = is_memory; 909169689Skan c->is_address = is_address; 910169689Skan 911169689Skan c->next_this_letter = *slot; 912169689Skan *slot = c; 913169689Skan 914169689Skan /* Insert this constraint in the list of all constraints in textual 915169689Skan order. */ 916169689Skan c->next_textual = 0; 917169689Skan *last_constraint_ptr = c; 918169689Skan last_constraint_ptr = &c->next_textual; 919169689Skan 920169689Skan constraint_max_namelen = MAX (constraint_max_namelen, strlen (name)); 921169689Skan have_register_constraints |= c->is_register; 922169689Skan have_const_int_constraints |= c->is_const_int; 923169689Skan have_const_dbl_constraints |= c->is_const_dbl; 924169689Skan have_extra_constraints |= c->is_extra; 925169689Skan have_memory_constraints |= c->is_memory; 926169689Skan have_address_constraints |= c->is_address; 927169689Skan} 928169689Skan 929169689Skan/* Process a DEFINE_CONSTRAINT, DEFINE_MEMORY_CONSTRAINT, or 930169689Skan DEFINE_ADDRESS_CONSTRAINT expression, C. */ 931169689Skanstatic void 932169689Skanprocess_define_constraint (rtx c, int lineno) 933169689Skan{ 934169689Skan add_constraint (XSTR (c, 0), 0, XEXP (c, 2), 935169689Skan GET_CODE (c) == DEFINE_MEMORY_CONSTRAINT, 936169689Skan GET_CODE (c) == DEFINE_ADDRESS_CONSTRAINT, 937169689Skan lineno); 938169689Skan} 939169689Skan 940169689Skan/* Process a DEFINE_REGISTER_CONSTRAINT expression, C. */ 941169689Skanstatic void 942169689Skanprocess_define_register_constraint (rtx c, int lineno) 943169689Skan{ 944169689Skan add_constraint (XSTR (c, 0), XSTR (c, 1), 0, false, false, lineno); 945169689Skan} 946169689Skan 947169689Skan/* Write out an enumeration with one entry per machine-specific 948169689Skan constraint. */ 949169689Skanstatic void 950169689Skanwrite_enum_constraint_num (void) 951169689Skan{ 952169689Skan struct constraint_data *c; 953169689Skan 954169689Skan fputs ("enum constraint_num\n" 955169689Skan "{\n" 956169689Skan " CONSTRAINT__UNKNOWN = 0", stdout); 957169689Skan FOR_ALL_CONSTRAINTS (c) 958169689Skan printf (",\n CONSTRAINT_%s", c->c_name); 959169689Skan puts ("\n};\n"); 960169689Skan} 961169689Skan 962169689Skan/* Write out a function which looks at a string and determines what 963169689Skan constraint name, if any, it begins with. */ 964169689Skanstatic void 965169689Skanwrite_lookup_constraint (void) 966169689Skan{ 967169689Skan unsigned int i; 968169689Skan puts ("enum constraint_num\n" 969169689Skan "lookup_constraint (const char *str)\n" 970169689Skan "{\n" 971169689Skan " switch (str[0])\n" 972169689Skan " {"); 973169689Skan 974169689Skan for (i = 0; i < ARRAY_SIZE(constraints_by_letter_table); i++) 975169689Skan { 976169689Skan struct constraint_data *c = constraints_by_letter_table[i]; 977169689Skan if (!c) 978169689Skan continue; 979169689Skan 980169689Skan printf (" case '%c':\n", i); 981169689Skan if (c->namelen == 1) 982169689Skan printf (" return CONSTRAINT_%s;\n", c->c_name); 983169689Skan else 984169689Skan { 985169689Skan do 986169689Skan { 987169689Skan printf (" if (!strncmp (str, \"%s\", %lu))\n" 988169689Skan " return CONSTRAINT_%s;\n", 989169689Skan c->name, (unsigned long int) c->namelen, c->c_name); 990169689Skan c = c->next_this_letter; 991169689Skan } 992169689Skan while (c); 993169689Skan puts (" break;"); 994169689Skan } 995169689Skan } 996169689Skan 997169689Skan puts (" default: break;\n" 998169689Skan " }\n" 999169689Skan " return CONSTRAINT__UNKNOWN;\n" 1000169689Skan "}\n"); 1001169689Skan} 1002169689Skan 1003169689Skan/* Write out the function which computes constraint name lengths from 1004169689Skan their enumerators. */ 1005169689Skanstatic void 1006169689Skanwrite_insn_constraint_len (void) 1007169689Skan{ 1008169689Skan struct constraint_data *c; 1009169689Skan 1010169689Skan if (constraint_max_namelen == 1) 1011169689Skan return; 1012169689Skan 1013169689Skan puts ("size_t\n" 1014169689Skan "insn_constraint_len (enum constraint_num c)\n" 1015169689Skan "{\n" 1016169689Skan " switch (c)\n" 1017169689Skan " {"); 1018169689Skan 1019169689Skan FOR_ALL_CONSTRAINTS (c) 1020169689Skan if (c->namelen > 1) 1021169689Skan printf (" case CONSTRAINT_%s: return %lu;\n", c->c_name, 1022169689Skan (unsigned long int) c->namelen); 1023169689Skan 1024169689Skan puts (" default: break;\n" 1025169689Skan " }\n" 1026169689Skan " return 1;\n" 1027169689Skan "}\n"); 1028169689Skan} 1029169689Skan 1030169689Skan/* Write out the function which computes the register class corresponding 1031169689Skan to a register constraint. */ 1032169689Skanstatic void 1033169689Skanwrite_regclass_for_constraint (void) 1034169689Skan{ 1035169689Skan struct constraint_data *c; 1036169689Skan 1037169689Skan puts ("enum reg_class\n" 1038169689Skan "regclass_for_constraint (enum constraint_num c)\n" 1039169689Skan "{\n" 1040169689Skan " switch (c)\n" 1041169689Skan " {"); 1042169689Skan 1043169689Skan FOR_ALL_CONSTRAINTS (c) 1044169689Skan if (c->is_register) 1045169689Skan printf (" case CONSTRAINT_%s: return %s;\n", c->c_name, c->regclass); 1046169689Skan 1047169689Skan puts (" default: break;\n" 1048169689Skan " }\n" 1049169689Skan " return NO_REGS;\n" 1050169689Skan "}\n"); 1051169689Skan} 1052169689Skan 1053169689Skan/* Write out the functions which compute whether a given value matches 1054169689Skan a given non-register constraint. */ 1055169689Skanstatic void 1056169689Skanwrite_tm_constrs_h (void) 1057169689Skan{ 1058169689Skan struct constraint_data *c; 1059169689Skan 1060169689Skan printf ("\ 1061169689Skan/* Generated automatically by the program '%s'\n\ 1062169689Skan from the machine description file '%s'. */\n\n", progname, in_fname); 1063169689Skan 1064169689Skan puts ("\ 1065169689Skan#ifndef GCC_TM_CONSTRS_H\n\ 1066169689Skan#define GCC_TM_CONSTRS_H\n"); 1067169689Skan 1068169689Skan FOR_ALL_CONSTRAINTS (c) 1069169689Skan if (!c->is_register) 1070169689Skan { 1071169689Skan bool needs_ival = needs_variable (c->exp, "ival"); 1072169689Skan bool needs_hval = needs_variable (c->exp, "hval"); 1073169689Skan bool needs_lval = needs_variable (c->exp, "lval"); 1074169689Skan bool needs_rval = needs_variable (c->exp, "rval"); 1075169689Skan bool needs_mode = (needs_variable (c->exp, "mode") 1076169689Skan || needs_hval || needs_lval || needs_rval); 1077169689Skan bool needs_op = (needs_variable (c->exp, "op") 1078169689Skan || needs_ival || needs_mode); 1079169689Skan 1080169689Skan printf ("static inline bool\n" 1081169689Skan "satisfies_constraint_%s (rtx %s)\n" 1082169689Skan "{\n", c->c_name, 1083169689Skan needs_op ? "op" : "ARG_UNUSED (op)"); 1084169689Skan if (needs_mode) 1085169689Skan puts ("enum machine_mode mode = GET_MODE (op);"); 1086169689Skan if (needs_ival) 1087169689Skan puts (" HOST_WIDE_INT ival = 0;"); 1088169689Skan if (needs_hval) 1089169689Skan puts (" HOST_WIDE_INT hval = 0;"); 1090169689Skan if (needs_lval) 1091169689Skan puts (" unsigned HOST_WIDE_INT lval = 0;"); 1092169689Skan if (needs_rval) 1093169689Skan puts (" const REAL_VALUE_TYPE *rval = 0;"); 1094169689Skan 1095169689Skan if (needs_ival) 1096169689Skan puts (" if (GET_CODE (op) == CONST_INT)\n" 1097169689Skan " ival = INTVAL (op);"); 1098169689Skan if (needs_hval) 1099169689Skan puts (" if (GET_CODE (op) == CONST_DOUBLE && mode == VOIDmode)" 1100169689Skan " hval = CONST_DOUBLE_HIGH (op);"); 1101169689Skan if (needs_lval) 1102169689Skan puts (" if (GET_CODE (op) == CONST_DOUBLE && mode == VOIDmode)" 1103169689Skan " lval = CONST_DOUBLE_LOW (op);"); 1104169689Skan if (needs_rval) 1105169689Skan puts (" if (GET_CODE (op) == CONST_DOUBLE && mode != VOIDmode)" 1106169689Skan " rval = CONST_DOUBLE_REAL_VALUE (op);"); 1107169689Skan 1108169689Skan write_predicate_stmts (c->exp); 1109169689Skan fputs ("}\n", stdout); 1110169689Skan } 1111169689Skan puts ("#endif /* tm-constrs.h */"); 1112169689Skan} 1113169689Skan 1114169689Skan/* Write out the wrapper function, constraint_satisfied_p, that maps 1115169689Skan a CONSTRAINT_xxx constant to one of the predicate functions generated 1116169689Skan above. */ 1117169689Skanstatic void 1118169689Skanwrite_constraint_satisfied_p (void) 1119169689Skan{ 1120169689Skan struct constraint_data *c; 1121169689Skan 1122169689Skan puts ("bool\n" 1123169689Skan "constraint_satisfied_p (rtx op, enum constraint_num c)\n" 1124169689Skan "{\n" 1125169689Skan " switch (c)\n" 1126169689Skan " {"); 1127169689Skan 1128169689Skan FOR_ALL_CONSTRAINTS (c) 1129169689Skan if (!c->is_register) 1130169689Skan printf (" case CONSTRAINT_%s: " 1131169689Skan "return satisfies_constraint_%s (op);\n", 1132169689Skan c->c_name, c->c_name); 1133169689Skan 1134169689Skan puts (" default: break;\n" 1135169689Skan " }\n" 1136169689Skan " return false;\n" 1137169689Skan "}\n"); 1138169689Skan} 1139169689Skan 1140169689Skan/* Write out the function which computes whether a given value matches 1141169689Skan a given CONST_INT constraint. This doesn't just forward to 1142169689Skan constraint_satisfied_p because caller passes the INTVAL, not the RTX. */ 1143169689Skanstatic void 1144169689Skanwrite_insn_const_int_ok_for_constraint (void) 1145169689Skan{ 1146169689Skan struct constraint_data *c; 1147169689Skan 1148169689Skan puts ("bool\n" 1149169689Skan "insn_const_int_ok_for_constraint (HOST_WIDE_INT ival, " 1150169689Skan "enum constraint_num c)\n" 1151169689Skan "{\n" 1152169689Skan " switch (c)\n" 1153169689Skan " {"); 1154169689Skan 1155169689Skan FOR_ALL_CONSTRAINTS (c) 1156169689Skan if (c->is_const_int) 1157169689Skan { 1158169689Skan printf (" case CONSTRAINT_%s:\n return ", c->c_name); 1159169689Skan /* c->exp is guaranteed to be (and (match_code "const_int") (...)); 1160169689Skan we know at this point that we have a const_int, so we need not 1161169689Skan bother with that part of the test. */ 1162169689Skan write_predicate_expr (XEXP (c->exp, 1)); 1163169689Skan fputs (";\n\n", stdout); 1164169689Skan } 1165169689Skan 1166169689Skan puts (" default: break;\n" 1167169689Skan " }\n" 1168169689Skan " return false;\n" 1169169689Skan "}\n"); 1170169689Skan} 1171169689Skan 1172169689Skan 1173169689Skan/* Write out the function which computes whether a given constraint is 1174169689Skan a memory constraint. */ 1175169689Skanstatic void 1176169689Skanwrite_insn_extra_memory_constraint (void) 1177169689Skan{ 1178169689Skan struct constraint_data *c; 1179169689Skan 1180169689Skan puts ("bool\n" 1181169689Skan "insn_extra_memory_constraint (enum constraint_num c)\n" 1182169689Skan "{\n" 1183169689Skan " switch (c)\n" 1184169689Skan " {"); 1185169689Skan 1186169689Skan FOR_ALL_CONSTRAINTS (c) 1187169689Skan if (c->is_memory) 1188169689Skan printf (" case CONSTRAINT_%s:\n return true;\n\n", c->c_name); 1189169689Skan 1190169689Skan puts (" default: break;\n" 1191169689Skan " }\n" 1192169689Skan " return false;\n" 1193169689Skan "}\n"); 1194169689Skan} 1195169689Skan 1196169689Skan/* Write out the function which computes whether a given constraint is 1197169689Skan an address constraint. */ 1198169689Skanstatic void 1199169689Skanwrite_insn_extra_address_constraint (void) 1200169689Skan{ 1201169689Skan struct constraint_data *c; 1202169689Skan 1203169689Skan puts ("bool\n" 1204169689Skan "insn_extra_address_constraint (enum constraint_num c)\n" 1205169689Skan "{\n" 1206169689Skan " switch (c)\n" 1207169689Skan " {"); 1208169689Skan 1209169689Skan FOR_ALL_CONSTRAINTS (c) 1210169689Skan if (c->is_address) 1211169689Skan printf (" case CONSTRAINT_%s:\n return true;\n\n", c->c_name); 1212169689Skan 1213169689Skan puts (" default: break;\n" 1214169689Skan " }\n" 1215169689Skan " return false;\n" 1216169689Skan "}\n"); 1217169689Skan} 1218169689Skan 1219169689Skan 1220169689Skan/* Write tm-preds.h. Unfortunately, it is impossible to forward-declare 1221169689Skan an enumeration in portable C, so we have to condition all these 1222169689Skan prototypes on HAVE_MACHINE_MODES. */ 1223169689Skanstatic void 1224169689Skanwrite_tm_preds_h (void) 1225169689Skan{ 1226169689Skan struct pred_data *p; 1227169689Skan 1228169689Skan printf ("\ 1229169689Skan/* Generated automatically by the program '%s'\n\ 1230169689Skan from the machine description file '%s'. */\n\n", progname, in_fname); 1231169689Skan 1232169689Skan puts ("\ 1233169689Skan#ifndef GCC_TM_PREDS_H\n\ 1234169689Skan#define GCC_TM_PREDS_H\n\ 1235169689Skan\n\ 1236169689Skan#ifdef HAVE_MACHINE_MODES"); 1237169689Skan 1238169689Skan FOR_ALL_PREDICATES (p) 1239169689Skan printf ("extern int %s (rtx, enum machine_mode);\n", p->name); 1240169689Skan 1241169689Skan puts ("#endif /* HAVE_MACHINE_MODES */\n"); 1242169689Skan 1243169689Skan if (constraint_max_namelen > 0) 1244169689Skan { 1245169689Skan write_enum_constraint_num (); 1246169689Skan puts ("extern enum constraint_num lookup_constraint (const char *);\n" 1247169689Skan "extern bool constraint_satisfied_p (rtx, enum constraint_num);\n"); 1248169689Skan 1249169689Skan if (constraint_max_namelen > 1) 1250169689Skan puts ("extern size_t insn_constraint_len (enum constraint_num);\n" 1251169689Skan "#define CONSTRAINT_LEN(c_,s_) " 1252169689Skan "insn_constraint_len (lookup_constraint (s_))\n"); 1253169689Skan else 1254169689Skan puts ("#define CONSTRAINT_LEN(c_,s_) 1\n"); 1255169689Skan if (have_register_constraints) 1256169689Skan puts ("extern enum reg_class regclass_for_constraint " 1257169689Skan "(enum constraint_num);\n" 1258169689Skan "#define REG_CLASS_FROM_CONSTRAINT(c_,s_) \\\n" 1259169689Skan " regclass_for_constraint (lookup_constraint (s_))\n"); 1260169689Skan else 1261169689Skan puts ("#define REG_CLASS_FROM_CONSTRAINT(c_,s_) NO_REGS"); 1262169689Skan if (have_const_int_constraints) 1263169689Skan puts ("extern bool insn_const_int_ok_for_constraint " 1264169689Skan "(HOST_WIDE_INT, enum constraint_num);\n" 1265169689Skan "#define CONST_OK_FOR_CONSTRAINT_P(v_,c_,s_) \\\n" 1266169689Skan " insn_const_int_ok_for_constraint (v_, " 1267169689Skan "lookup_constraint (s_))\n"); 1268169689Skan if (have_const_dbl_constraints) 1269169689Skan puts ("#define CONST_DOUBLE_OK_FOR_CONSTRAINT_P(v_,c_,s_) \\\n" 1270169689Skan " constraint_satisfied_p (v_, lookup_constraint (s_))\n"); 1271169689Skan else 1272169689Skan puts ("#define CONST_DOUBLE_OK_FOR_CONSTRAINT_P(v_,c_,s_) 0\n"); 1273169689Skan if (have_extra_constraints) 1274169689Skan puts ("#define EXTRA_CONSTRAINT_STR(v_,c_,s_) \\\n" 1275169689Skan " constraint_satisfied_p (v_, lookup_constraint (s_))\n"); 1276169689Skan if (have_memory_constraints) 1277169689Skan puts ("extern bool " 1278169689Skan "insn_extra_memory_constraint (enum constraint_num);\n" 1279169689Skan "#define EXTRA_MEMORY_CONSTRAINT(c_,s_) " 1280169689Skan "insn_extra_memory_constraint (lookup_constraint (s_))\n"); 1281169689Skan else 1282169689Skan puts ("#define EXTRA_MEMORY_CONSTRAINT(c_,s_) false\n"); 1283169689Skan if (have_address_constraints) 1284169689Skan puts ("extern bool " 1285169689Skan "insn_extra_address_constraint (enum constraint_num);\n" 1286169689Skan "#define EXTRA_ADDRESS_CONSTRAINT(c_,s_) " 1287169689Skan "insn_extra_address_constraint (lookup_constraint (s_))\n"); 1288169689Skan else 1289169689Skan puts ("#define EXTRA_ADDRESS_CONSTRAINT(c_,s_) false\n"); 1290169689Skan } 1291169689Skan 1292169689Skan puts ("#endif /* tm-preds.h */"); 1293169689Skan} 1294169689Skan 1295169689Skan/* Write insn-preds.c. 1296169689Skan N.B. the list of headers to include was copied from genrecog; it 1297169689Skan may not be ideal. 1298169689Skan 1299169689Skan FUTURE: Write #line markers referring back to the machine 1300169689Skan description. (Can't practically do this now since we don't know 1301169689Skan the line number of the C block - just the line number of the enclosing 1302169689Skan expression.) */ 1303169689Skanstatic void 1304169689Skanwrite_insn_preds_c (void) 1305169689Skan{ 1306169689Skan struct pred_data *p; 1307169689Skan 1308169689Skan printf ("\ 1309169689Skan/* Generated automatically by the program '%s'\n\ 1310169689Skan from the machine description file '%s'. */\n\n", progname, in_fname); 1311169689Skan 1312169689Skan puts ("\ 1313169689Skan#include \"config.h\"\n\ 1314169689Skan#include \"system.h\"\n\ 1315169689Skan#include \"coretypes.h\"\n\ 1316169689Skan#include \"tm.h\"\n\ 1317169689Skan#include \"rtl.h\"\n\ 1318169689Skan#include \"tree.h\"\n\ 1319169689Skan#include \"tm_p.h\"\n\ 1320169689Skan#include \"function.h\"\n\ 1321169689Skan#include \"insn-config.h\"\n\ 1322169689Skan#include \"recog.h\"\n\ 1323169689Skan#include \"real.h\"\n\ 1324169689Skan#include \"output.h\"\n\ 1325169689Skan#include \"flags.h\"\n\ 1326169689Skan#include \"hard-reg-set.h\"\n\ 1327169689Skan#include \"resource.h\"\n\ 1328169689Skan#include \"toplev.h\"\n\ 1329169689Skan#include \"reload.h\"\n\ 1330169689Skan#include \"regs.h\"\n\ 1331169689Skan#include \"tm-constrs.h\"\n"); 1332169689Skan 1333169689Skan FOR_ALL_PREDICATES (p) 1334169689Skan write_one_predicate_function (p); 1335169689Skan 1336169689Skan if (constraint_max_namelen > 0) 1337169689Skan { 1338169689Skan write_lookup_constraint (); 1339169689Skan write_regclass_for_constraint (); 1340169689Skan write_constraint_satisfied_p (); 1341169689Skan 1342169689Skan if (constraint_max_namelen > 1) 1343169689Skan write_insn_constraint_len (); 1344169689Skan 1345169689Skan if (have_const_int_constraints) 1346169689Skan write_insn_const_int_ok_for_constraint (); 1347169689Skan 1348169689Skan if (have_memory_constraints) 1349169689Skan write_insn_extra_memory_constraint (); 1350169689Skan if (have_address_constraints) 1351169689Skan write_insn_extra_address_constraint (); 1352169689Skan } 1353169689Skan} 1354169689Skan 1355169689Skan/* Argument parsing. */ 1356169689Skanstatic bool gen_header; 1357169689Skanstatic bool gen_constrs; 1358169689Skan 1359169689Skanstatic bool 1360169689Skanparse_option (const char *opt) 1361169689Skan{ 1362169689Skan if (!strcmp (opt, "-h")) 1363169689Skan { 1364169689Skan gen_header = true; 1365169689Skan return 1; 1366169689Skan } 1367169689Skan else if (!strcmp (opt, "-c")) 1368169689Skan { 1369169689Skan gen_constrs = true; 1370169689Skan return 1; 1371169689Skan } 1372169689Skan else 1373169689Skan return 0; 1374169689Skan} 1375169689Skan 1376169689Skan/* Master control. */ 137790075Sobrienint 1378169689Skanmain (int argc, char **argv) 137990075Sobrien{ 1380169689Skan rtx defn; 1381169689Skan int pattern_lineno, next_insn_code = 0; 138290075Sobrien 1383169689Skan progname = argv[0]; 1384169689Skan if (argc <= 1) 1385169689Skan fatal ("no input file name"); 1386169689Skan if (init_md_reader_args_cb (argc, argv, parse_option) != SUCCESS_EXIT_CODE) 1387169689Skan return FATAL_EXIT_CODE; 138890075Sobrien 1389169689Skan while ((defn = read_md_rtx (&pattern_lineno, &next_insn_code)) != 0) 1390169689Skan switch (GET_CODE (defn)) 1391169689Skan { 1392169689Skan case DEFINE_PREDICATE: 1393169689Skan case DEFINE_SPECIAL_PREDICATE: 1394169689Skan process_define_predicate (defn, pattern_lineno); 1395169689Skan break; 139690075Sobrien 1397169689Skan case DEFINE_CONSTRAINT: 1398169689Skan case DEFINE_MEMORY_CONSTRAINT: 1399169689Skan case DEFINE_ADDRESS_CONSTRAINT: 1400169689Skan process_define_constraint (defn, pattern_lineno); 1401169689Skan break; 1402169689Skan 1403169689Skan case DEFINE_REGISTER_CONSTRAINT: 1404169689Skan process_define_register_constraint (defn, pattern_lineno); 1405169689Skan break; 1406169689Skan 1407169689Skan default: 1408169689Skan break; 1409169689Skan } 1410169689Skan 1411169689Skan if (gen_header) 1412169689Skan write_tm_preds_h (); 1413169689Skan else if (gen_constrs) 1414169689Skan write_tm_constrs_h (); 1415169689Skan else 1416169689Skan write_insn_preds_c (); 1417169689Skan 1418169689Skan if (have_error || ferror (stdout) || fflush (stdout) || fclose (stdout)) 141990075Sobrien return FATAL_EXIT_CODE; 142090075Sobrien 142190075Sobrien return SUCCESS_EXIT_CODE; 142290075Sobrien} 1423