00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "bconfig.h"
00025 #include "system.h"
00026 #include "coretypes.h"
00027 #include "tm.h"
00028 #include "rtl.h"
00029 #include "errors.h"
00030 #include "obstack.h"
00031 #include "gensupport.h"
00032
00033
00034
00035
00036
00037 static bool
00038 validate_exp (rtx exp, const char *name, int lineno)
00039 {
00040 if (exp == 0)
00041 {
00042 message_with_line (lineno, "%s: must give a predicate expression", name);
00043 return true;
00044 }
00045
00046 switch (GET_CODE (exp))
00047 {
00048
00049 case IF_THEN_ELSE:
00050 if (validate_exp (XEXP (exp, 2), name, lineno))
00051 return true;
00052
00053 case AND:
00054 case IOR:
00055 if (validate_exp (XEXP (exp, 1), name, lineno))
00056 return true;
00057
00058 case NOT:
00059 return validate_exp (XEXP (exp, 0), name, lineno);
00060
00061
00062 case MATCH_CODE:
00063 {
00064 const char *p;
00065 for (p = XSTR (exp, 1); *p; p++)
00066 {
00067 if (!ISDIGIT (*p) && !ISLOWER (*p))
00068 {
00069 message_with_line (lineno, "%s: invalid character in path "
00070 "string '%s'", name, XSTR (exp, 1));
00071 have_error = 1;
00072 return true;
00073 }
00074 }
00075 }
00076
00077
00078
00079 case MATCH_OPERAND:
00080 case MATCH_TEST:
00081 return false;
00082
00083 default:
00084 message_with_line (lineno,
00085 "%s: cannot use '%s' in a predicate expression",
00086 name, GET_RTX_NAME (GET_CODE (exp)));
00087 have_error = 1;
00088 return true;
00089 }
00090 }
00091
00092
00093
00094 static void
00095 process_define_predicate (rtx defn, int lineno)
00096 {
00097 struct pred_data *pred;
00098 const char *p;
00099
00100 if (!ISALPHA (XSTR (defn, 0)[0]) && XSTR (defn, 0)[0] != '_')
00101 goto bad_name;
00102 for (p = XSTR (defn, 0) + 1; *p; p++)
00103 if (!ISALNUM (*p) && *p != '_')
00104 goto bad_name;
00105
00106 if (validate_exp (XEXP (defn, 1), XSTR (defn, 0), lineno))
00107 return;
00108
00109 pred = XCNEW (struct pred_data);
00110 pred->name = XSTR (defn, 0);
00111 pred->exp = XEXP (defn, 1);
00112 pred->c_block = XSTR (defn, 2);
00113
00114 if (GET_CODE (defn) == DEFINE_SPECIAL_PREDICATE)
00115 pred->special = true;
00116
00117 add_predicate (pred);
00118 return;
00119
00120 bad_name:
00121 message_with_line (lineno,
00122 "%s: predicate name must be a valid C function name",
00123 XSTR (defn, 0));
00124 have_error = 1;
00125 return;
00126 }
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157 static void
00158 write_predicate_subfunction (struct pred_data *p)
00159 {
00160 const char *match_test_str;
00161 rtx match_test_exp, and_exp;
00162
00163 if (p->c_block[0] == '\0')
00164 return;
00165
00166
00167 obstack_grow (rtl_obstack, p->name, strlen (p->name));
00168 obstack_grow (rtl_obstack, "_1 (op, mode)",
00169 sizeof "_1 (op, mode)");
00170 match_test_str = XOBFINISH (rtl_obstack, const char *);
00171
00172
00173
00174 match_test_exp = rtx_alloc (MATCH_TEST);
00175 XSTR (match_test_exp, 0) = match_test_str;
00176
00177 and_exp = rtx_alloc (AND);
00178 XEXP (and_exp, 0) = p->exp;
00179 XEXP (and_exp, 1) = match_test_exp;
00180
00181 p->exp = and_exp;
00182
00183 printf ("static inline int\n"
00184 "%s_1 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)\n",
00185 p->name);
00186 print_rtx_ptr_loc (p->c_block);
00187 if (p->c_block[0] == '{')
00188 fputs (p->c_block, stdout);
00189 else
00190 printf ("{\n %s\n}", p->c_block);
00191 fputs ("\n\n", stdout);
00192 }
00193
00194
00195
00196 static bool
00197 needs_variable (rtx exp, const char *var)
00198 {
00199 switch (GET_CODE (exp))
00200 {
00201
00202
00203 case IF_THEN_ELSE:
00204 if (needs_variable (XEXP (exp, 2), var))
00205 return true;
00206
00207 case AND:
00208 case IOR:
00209 if (needs_variable (XEXP (exp, 1), var))
00210 return true;
00211
00212 case NOT:
00213 return needs_variable (XEXP (exp, 0), var);
00214
00215
00216 case MATCH_CODE:
00217 return !strcmp (var, "op");
00218
00219
00220 case MATCH_OPERAND:
00221 if (!strcmp (var, "op"))
00222 return true;
00223 if (!strcmp (var, "mode") && GET_MODE (exp) == VOIDmode)
00224 return true;
00225 return false;
00226
00227
00228 case MATCH_TEST:
00229 {
00230 const char *p = XSTR (exp, 0);
00231 const char *q = strstr (p, var);
00232 if (!q)
00233 return false;
00234 if (q != p && (ISALNUM (q[-1]) || q[-1] == '_'))
00235 return false;
00236 q += strlen (var);
00237 if (ISALNUM (q[0] || q[0] == '_'))
00238 return false;
00239 }
00240 return true;
00241
00242 default:
00243 gcc_unreachable ();
00244 }
00245 }
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258 #define NO_MODE_TEST(EXP) RTX_FLAG (EXP, volatil)
00259 static void
00260 mark_mode_tests (rtx exp)
00261 {
00262 switch (GET_CODE (exp))
00263 {
00264 case MATCH_OPERAND:
00265 {
00266 struct pred_data *p = lookup_predicate (XSTR (exp, 1));
00267 if (!p)
00268 error ("reference to undefined predicate '%s'", XSTR (exp, 1));
00269 else if (p->special || GET_MODE (exp) != VOIDmode)
00270 NO_MODE_TEST (exp) = 1;
00271 }
00272 break;
00273
00274 case MATCH_CODE:
00275 if (XSTR (exp, 1)[0] != '\0'
00276 || (!strstr (XSTR (exp, 0), "const_int")
00277 && !strstr (XSTR (exp, 0), "const_double")))
00278 NO_MODE_TEST (exp) = 1;
00279 break;
00280
00281 case MATCH_TEST:
00282 case NOT:
00283 NO_MODE_TEST (exp) = 1;
00284 break;
00285
00286 case AND:
00287 mark_mode_tests (XEXP (exp, 0));
00288 mark_mode_tests (XEXP (exp, 1));
00289
00290 NO_MODE_TEST (exp) = (NO_MODE_TEST (XEXP (exp, 0))
00291 && NO_MODE_TEST (XEXP (exp, 1)));
00292 break;
00293
00294 case IOR:
00295 mark_mode_tests (XEXP (exp, 0));
00296 mark_mode_tests (XEXP (exp, 1));
00297
00298 NO_MODE_TEST (exp) = (NO_MODE_TEST (XEXP (exp, 0))
00299 || NO_MODE_TEST (XEXP (exp, 1)));
00300 break;
00301
00302 case IF_THEN_ELSE:
00303
00304
00305 mark_mode_tests (XEXP (exp, 0));
00306 mark_mode_tests (XEXP (exp, 1));
00307 mark_mode_tests (XEXP (exp, 2));
00308
00309 NO_MODE_TEST (exp) = ((NO_MODE_TEST (XEXP (exp, 0))
00310 && NO_MODE_TEST (XEXP (exp, 1)))
00311 || NO_MODE_TEST (XEXP (exp, 2)));
00312 break;
00313
00314 default:
00315 gcc_unreachable ();
00316 }
00317 }
00318
00319
00320
00321 static bool
00322 generate_switch_p (rtx exp)
00323 {
00324 return GET_CODE (exp) == MATCH_CODE
00325 && strchr (XSTR (exp, 0), ',');
00326 }
00327
00328
00329
00330
00331
00332
00333
00334 static void
00335 add_mode_tests (struct pred_data *p)
00336 {
00337 rtx match_test_exp, and_exp;
00338 rtx *pos;
00339
00340
00341 if (p->special)
00342 return;
00343
00344 mark_mode_tests (p->exp);
00345
00346
00347 if (!NO_MODE_TEST (p->exp))
00348 return;
00349
00350 match_test_exp = rtx_alloc (MATCH_TEST);
00351 XSTR (match_test_exp, 0) = "mode == VOIDmode || GET_MODE (op) == mode";
00352 and_exp = rtx_alloc (AND);
00353 XEXP (and_exp, 1) = match_test_exp;
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366 pos = &p->exp;
00367 for (;;)
00368 {
00369 rtx subexp = *pos;
00370
00371 switch (GET_CODE (subexp))
00372 {
00373 case AND:
00374
00375
00376
00377
00378 if (generate_switch_p (XEXP (subexp, 0)))
00379 pos = &XEXP (subexp, 1);
00380 goto break_loop;
00381
00382 case IOR:
00383 {
00384 int test0 = NO_MODE_TEST (XEXP (subexp, 0));
00385 int test1 = NO_MODE_TEST (XEXP (subexp, 1));
00386
00387 gcc_assert (test0 || test1);
00388
00389 if (test0 && test1)
00390 goto break_loop;
00391 pos = test0 ? &XEXP (subexp, 0) : &XEXP (subexp, 1);
00392 }
00393 break;
00394
00395 case IF_THEN_ELSE:
00396 {
00397 int test0 = NO_MODE_TEST (XEXP (subexp, 0));
00398 int test1 = NO_MODE_TEST (XEXP (subexp, 1));
00399 int test2 = NO_MODE_TEST (XEXP (subexp, 2));
00400
00401 gcc_assert ((test0 && test1) || test2);
00402
00403 if (test0 && test1 && test2)
00404 goto break_loop;
00405 if (test0 && test1)
00406
00407
00408
00409 pos = &XEXP (subexp, 1);
00410 else
00411 pos = &XEXP (subexp, 2);
00412 }
00413 break;
00414
00415 default:
00416 goto break_loop;
00417 }
00418 }
00419 break_loop:
00420 XEXP (and_exp, 0) = *pos;
00421 *pos = and_exp;
00422 }
00423
00424
00425
00426
00427
00428 static void
00429 write_extract_subexp (const char *path)
00430 {
00431 int len = strlen (path);
00432 int i;
00433
00434
00435
00436 for (i = len - 1; i >= 0; i--)
00437 {
00438 if (ISLOWER (path[i]))
00439 fputs ("XVECEXP (", stdout);
00440 else if (ISDIGIT (path[i]))
00441 fputs ("XEXP (", stdout);
00442 else
00443 gcc_unreachable ();
00444 }
00445
00446 fputs ("op", stdout);
00447
00448 for (i = 0; i < len; i++)
00449 {
00450 if (ISLOWER (path[i]))
00451 printf (", 0, %d)", path[i] - 'a');
00452 else if (ISDIGIT (path[i]))
00453 printf (", %d)", path[i] - '0');
00454 else
00455 gcc_unreachable ();
00456 }
00457 }
00458
00459
00460
00461 static void
00462 write_match_code (const char *path, const char *codes)
00463 {
00464 const char *code;
00465
00466 while ((code = scan_comma_elt (&codes)) != 0)
00467 {
00468 fputs ("GET_CODE (", stdout);
00469 write_extract_subexp (path);
00470 fputs (") == ", stdout);
00471 while (code < codes)
00472 {
00473 putchar (TOUPPER (*code));
00474 code++;
00475 }
00476
00477 if (*codes == ',')
00478 fputs (" || ", stdout);
00479 }
00480 }
00481
00482
00483
00484 static void
00485 write_predicate_expr (rtx exp)
00486 {
00487 switch (GET_CODE (exp))
00488 {
00489 case AND:
00490 putchar ('(');
00491 write_predicate_expr (XEXP (exp, 0));
00492 fputs (") && (", stdout);
00493 write_predicate_expr (XEXP (exp, 1));
00494 putchar (')');
00495 break;
00496
00497 case IOR:
00498 putchar ('(');
00499 write_predicate_expr (XEXP (exp, 0));
00500 fputs (") || (", stdout);
00501 write_predicate_expr (XEXP (exp, 1));
00502 putchar (')');
00503 break;
00504
00505 case NOT:
00506 fputs ("!(", stdout);
00507 write_predicate_expr (XEXP (exp, 0));
00508 putchar (')');
00509 break;
00510
00511 case IF_THEN_ELSE:
00512 putchar ('(');
00513 write_predicate_expr (XEXP (exp, 0));
00514 fputs (") ? (", stdout);
00515 write_predicate_expr (XEXP (exp, 1));
00516 fputs (") : (", stdout);
00517 write_predicate_expr (XEXP (exp, 2));
00518 putchar (')');
00519 break;
00520
00521 case MATCH_OPERAND:
00522 if (GET_MODE (exp) == VOIDmode)
00523 printf ("%s (op, mode)", XSTR (exp, 1));
00524 else
00525 printf ("%s (op, %smode)", XSTR (exp, 1), mode_name[GET_MODE (exp)]);
00526 break;
00527
00528 case MATCH_CODE:
00529 write_match_code (XSTR (exp, 1), XSTR (exp, 0));
00530 break;
00531
00532 case MATCH_TEST:
00533 print_c_condition (XSTR (exp, 0));
00534 break;
00535
00536 default:
00537 gcc_unreachable ();
00538 }
00539 }
00540
00541
00542
00543 static void
00544 write_match_code_switch (rtx exp)
00545 {
00546 const char *codes = XSTR (exp, 0);
00547 const char *path = XSTR (exp, 1);
00548 const char *code;
00549
00550 fputs (" switch (GET_CODE (", stdout);
00551 write_extract_subexp (path);
00552 fputs ("))\n {\n", stdout);
00553
00554 while ((code = scan_comma_elt (&codes)) != 0)
00555 {
00556 fputs (" case ", stdout);
00557 while (code < codes)
00558 {
00559 putchar (TOUPPER (*code));
00560 code++;
00561 }
00562 fputs(":\n", stdout);
00563 }
00564 }
00565
00566
00567
00568
00569
00570 static void
00571 write_predicate_stmts (rtx exp)
00572 {
00573 switch (GET_CODE (exp))
00574 {
00575 case MATCH_CODE:
00576 if (generate_switch_p (exp))
00577 {
00578 write_match_code_switch (exp);
00579 puts (" return true;\n"
00580 " default:\n"
00581 " break;\n"
00582 " }\n"
00583 " return false;");
00584 return;
00585 }
00586 break;
00587
00588 case AND:
00589 if (generate_switch_p (XEXP (exp, 0)))
00590 {
00591 write_match_code_switch (XEXP (exp, 0));
00592 puts (" break;\n"
00593 " default:\n"
00594 " return false;\n"
00595 " }");
00596 exp = XEXP (exp, 1);
00597 }
00598 break;
00599
00600 case IOR:
00601 if (generate_switch_p (XEXP (exp, 0)))
00602 {
00603 write_match_code_switch (XEXP (exp, 0));
00604 puts (" return true;\n"
00605 " default:\n"
00606 " break;\n"
00607 " }");
00608 exp = XEXP (exp, 1);
00609 }
00610 break;
00611
00612 case NOT:
00613 if (generate_switch_p (XEXP (exp, 0)))
00614 {
00615 write_match_code_switch (XEXP (exp, 0));
00616 puts (" return false;\n"
00617 " default:\n"
00618 " break;\n"
00619 " }\n"
00620 " return true;");
00621 return;
00622 }
00623 break;
00624
00625 default:
00626 break;
00627 }
00628
00629 fputs(" return ",stdout);
00630 write_predicate_expr (exp);
00631 fputs(";\n", stdout);
00632 }
00633
00634
00635 static void
00636 write_one_predicate_function (struct pred_data *p)
00637 {
00638 if (!p->exp)
00639 return;
00640
00641 write_predicate_subfunction (p);
00642 add_mode_tests (p);
00643
00644
00645
00646 printf ("int\n%s (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)\n{\n",
00647 p->name);
00648 write_predicate_stmts (p->exp);
00649 fputs ("}\n\n", stdout);
00650 }
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661 struct constraint_data
00662 {
00663 struct constraint_data *next_this_letter;
00664 struct constraint_data *next_textual;
00665 const char *name;
00666 const char *c_name;
00667 size_t namelen;
00668 const char *regclass;
00669 rtx exp;
00670 unsigned int lineno;
00671 unsigned int is_register : 1;
00672 unsigned int is_const_int : 1;
00673 unsigned int is_const_dbl : 1;
00674 unsigned int is_extra : 1;
00675 unsigned int is_memory : 1;
00676 unsigned int is_address : 1;
00677 };
00678
00679
00680
00681 static struct constraint_data *
00682 constraints_by_letter_table[1<<CHAR_BIT];
00683
00684
00685
00686 static struct constraint_data *first_constraint;
00687 static struct constraint_data **last_constraint_ptr = &first_constraint;
00688
00689 #define FOR_ALL_CONSTRAINTS(iter_) \
00690 for (iter_ = first_constraint; iter_; iter_ = iter_->next_textual)
00691
00692
00693
00694 static const char generic_constraint_letters[] = "EFVXgimnoprs";
00695
00696
00697
00698
00699 static const char const_int_constraints[] = "IJKLMNOP";
00700
00701
00702
00703
00704 static const char const_dbl_constraints[] = "GH";
00705
00706
00707
00708 static unsigned int constraint_max_namelen;
00709 static bool have_register_constraints;
00710 static bool have_memory_constraints;
00711 static bool have_address_constraints;
00712 static bool have_extra_constraints;
00713 static bool have_const_int_constraints;
00714 static bool have_const_dbl_constraints;
00715
00716
00717
00718
00719 static const char *
00720 mangle (const char *name)
00721 {
00722 for (; *name; name++)
00723 switch (*name)
00724 {
00725 case '_': obstack_grow (rtl_obstack, "__", 2); break;
00726 case '<': obstack_grow (rtl_obstack, "_l", 2); break;
00727 case '>': obstack_grow (rtl_obstack, "_g", 2); break;
00728 default: obstack_1grow (rtl_obstack, *name); break;
00729 }
00730
00731 obstack_1grow (rtl_obstack, '\0');
00732 return obstack_finish (rtl_obstack);
00733 }
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746 static void
00747 add_constraint (const char *name, const char *regclass,
00748 rtx exp, bool is_memory, bool is_address,
00749 int lineno)
00750 {
00751 struct constraint_data *c, **iter, **slot;
00752 const char *p;
00753 bool need_mangled_name = false;
00754 bool is_const_int;
00755 bool is_const_dbl;
00756 size_t namelen;
00757
00758 if (exp && validate_exp (exp, name, lineno))
00759 return;
00760
00761 if (!ISALPHA (name[0]) && name[0] != '_')
00762 {
00763 if (name[1] == '\0')
00764 message_with_line (lineno, "constraint name '%s' is not "
00765 "a letter or underscore", name);
00766 else
00767 message_with_line (lineno, "constraint name '%s' does not begin "
00768 "with a letter or underscore", name);
00769 have_error = 1;
00770 return;
00771 }
00772 for (p = name; *p; p++)
00773 if (!ISALNUM (*p))
00774 {
00775 if (*p == '<' || *p == '>' || *p == '_')
00776 need_mangled_name = true;
00777 else
00778 {
00779 message_with_line (lineno,
00780 "constraint name '%s' must be composed of "
00781 "letters, digits, underscores, and "
00782 "angle brackets", name);
00783 have_error = 1;
00784 return;
00785 }
00786 }
00787
00788 if (strchr (generic_constraint_letters, name[0]))
00789 {
00790 if (name[1] == '\0')
00791 message_with_line (lineno, "constraint letter '%s' cannot be "
00792 "redefined by the machine description", name);
00793 else
00794 message_with_line (lineno, "constraint name '%s' cannot be defined by "
00795 "the machine description, as it begins with '%c'",
00796 name, name[0]);
00797 have_error = 1;
00798 return;
00799 }
00800
00801
00802 namelen = strlen (name);
00803 slot = &constraints_by_letter_table[(unsigned int)name[0]];
00804 for (iter = slot; *iter; iter = &(*iter)->next_this_letter)
00805 {
00806
00807
00808
00809
00810
00811 if ((*iter)->namelen >= namelen)
00812 slot = iter;
00813
00814 if (!strcmp ((*iter)->name, name))
00815 {
00816 message_with_line (lineno, "redefinition of constraint '%s'", name);
00817 message_with_line ((*iter)->lineno, "previous definition is here");
00818 have_error = 1;
00819 return;
00820 }
00821 else if (!strncmp ((*iter)->name, name, (*iter)->namelen))
00822 {
00823 message_with_line (lineno, "defining constraint '%s' here", name);
00824 message_with_line ((*iter)->lineno, "renders constraint '%s' "
00825 "(defined here) a prefix", (*iter)->name);
00826 have_error = 1;
00827 return;
00828 }
00829 else if (!strncmp ((*iter)->name, name, namelen))
00830 {
00831 message_with_line (lineno, "constraint '%s' is a prefix", name);
00832 message_with_line ((*iter)->lineno, "of constraint '%s' "
00833 "(defined here)", (*iter)->name);
00834 have_error = 1;
00835 return;
00836 }
00837 }
00838
00839 is_const_int = strchr (const_int_constraints, name[0]) != 0;
00840 is_const_dbl = strchr (const_dbl_constraints, name[0]) != 0;
00841
00842 if (is_const_int || is_const_dbl)
00843 {
00844 enum rtx_code appropriate_code
00845 = is_const_int ? CONST_INT : CONST_DOUBLE;
00846
00847
00848 if (regclass
00849 || GET_CODE (exp) != AND
00850 || GET_CODE (XEXP (exp, 0)) != MATCH_CODE
00851 || strcmp (XSTR (XEXP (exp, 0), 0),
00852 GET_RTX_NAME (appropriate_code)))
00853 {
00854 if (name[1] == '\0')
00855 message_with_line (lineno, "constraint letter '%c' is reserved "
00856 "for %s constraints",
00857 name[0], GET_RTX_NAME (appropriate_code));
00858 else
00859 message_with_line (lineno, "constraint names beginning with '%c' "
00860 "(%s) are reserved for %s constraints",
00861 name[0], name,
00862 GET_RTX_NAME (appropriate_code));
00863
00864 have_error = 1;
00865 return;
00866 }
00867
00868 if (is_memory)
00869 {
00870 if (name[1] == '\0')
00871 message_with_line (lineno, "constraint letter '%c' cannot be a "
00872 "memory constraint", name[0]);
00873 else
00874 message_with_line (lineno, "constraint name '%s' begins with '%c', "
00875 "and therefore cannot be a memory constraint",
00876 name, name[0]);
00877
00878 have_error = 1;
00879 return;
00880 }
00881 else if (is_address)
00882 {
00883 if (name[1] == '\0')
00884 message_with_line (lineno, "constraint letter '%c' cannot be a "
00885 "memory constraint", name[0]);
00886 else
00887 message_with_line (lineno, "constraint name '%s' begins with '%c', "
00888 "and therefore cannot be a memory constraint",
00889 name, name[0]);
00890
00891 have_error = 1;
00892 return;
00893 }
00894 }
00895
00896
00897 c = obstack_alloc (rtl_obstack, sizeof (struct constraint_data));
00898 c->name = name;
00899 c->c_name = need_mangled_name ? mangle (name) : name;
00900 c->lineno = lineno;
00901 c->namelen = namelen;
00902 c->regclass = regclass;
00903 c->exp = exp;
00904 c->is_register = regclass != 0;
00905 c->is_const_int = is_const_int;
00906 c->is_const_dbl = is_const_dbl;
00907 c->is_extra = !(regclass || is_const_int || is_const_dbl);
00908 c->is_memory = is_memory;
00909 c->is_address = is_address;
00910
00911 c->next_this_letter = *slot;
00912 *slot = c;
00913
00914
00915
00916 c->next_textual = 0;
00917 *last_constraint_ptr = c;
00918 last_constraint_ptr = &c->next_textual;
00919
00920 constraint_max_namelen = MAX (constraint_max_namelen, strlen (name));
00921 have_register_constraints |= c->is_register;
00922 have_const_int_constraints |= c->is_const_int;
00923 have_const_dbl_constraints |= c->is_const_dbl;
00924 have_extra_constraints |= c->is_extra;
00925 have_memory_constraints |= c->is_memory;
00926 have_address_constraints |= c->is_address;
00927 }
00928
00929
00930
00931 static void
00932 process_define_constraint (rtx c, int lineno)
00933 {
00934 add_constraint (XSTR (c, 0), 0, XEXP (c, 2),
00935 GET_CODE (c) == DEFINE_MEMORY_CONSTRAINT,
00936 GET_CODE (c) == DEFINE_ADDRESS_CONSTRAINT,
00937 lineno);
00938 }
00939
00940
00941 static void
00942 process_define_register_constraint (rtx c, int lineno)
00943 {
00944 add_constraint (XSTR (c, 0), XSTR (c, 1), 0, false, false, lineno);
00945 }
00946
00947
00948
00949 static void
00950 write_enum_constraint_num (void)
00951 {
00952 struct constraint_data *c;
00953
00954 fputs ("enum constraint_num\n"
00955 "{\n"
00956 " CONSTRAINT__UNKNOWN = 0", stdout);
00957 FOR_ALL_CONSTRAINTS (c)
00958 printf (",\n CONSTRAINT_%s", c->c_name);
00959 puts ("\n};\n");
00960 }
00961
00962
00963
00964 static void
00965 write_lookup_constraint (void)
00966 {
00967 unsigned int i;
00968 puts ("enum constraint_num\n"
00969 "lookup_constraint (const char *str)\n"
00970 "{\n"
00971 " switch (str[0])\n"
00972 " {");
00973
00974 for (i = 0; i < ARRAY_SIZE(constraints_by_letter_table); i++)
00975 {
00976 struct constraint_data *c = constraints_by_letter_table[i];
00977 if (!c)
00978 continue;
00979
00980 printf (" case '%c':\n", i);
00981 if (c->namelen == 1)
00982 printf (" return CONSTRAINT_%s;\n", c->c_name);
00983 else
00984 {
00985 do
00986 {
00987 printf (" if (!strncmp (str, \"%s\", %lu))\n"
00988 " return CONSTRAINT_%s;\n",
00989 c->name, (unsigned long int) c->namelen, c->c_name);
00990 c = c->next_this_letter;
00991 }
00992 while (c);
00993 puts (" break;");
00994 }
00995 }
00996
00997 puts (" default: break;\n"
00998 " }\n"
00999 " return CONSTRAINT__UNKNOWN;\n"
01000 "}\n");
01001 }
01002
01003
01004
01005 static void
01006 write_insn_constraint_len (void)
01007 {
01008 struct constraint_data *c;
01009
01010 if (constraint_max_namelen == 1)
01011 return;
01012
01013 puts ("size_t\n"
01014 "insn_constraint_len (enum constraint_num c)\n"
01015 "{\n"
01016 " switch (c)\n"
01017 " {");
01018
01019 FOR_ALL_CONSTRAINTS (c)
01020 if (c->namelen > 1)
01021 printf (" case CONSTRAINT_%s: return %lu;\n", c->c_name,
01022 (unsigned long int) c->namelen);
01023
01024 puts (" default: break;\n"
01025 " }\n"
01026 " return 1;\n"
01027 "}\n");
01028 }
01029
01030
01031
01032 static void
01033 write_regclass_for_constraint (void)
01034 {
01035 struct constraint_data *c;
01036
01037 puts ("enum reg_class\n"
01038 "regclass_for_constraint (enum constraint_num c)\n"
01039 "{\n"
01040 " switch (c)\n"
01041 " {");
01042
01043 FOR_ALL_CONSTRAINTS (c)
01044 if (c->is_register)
01045 printf (" case CONSTRAINT_%s: return %s;\n", c->c_name, c->regclass);
01046
01047 puts (" default: break;\n"
01048 " }\n"
01049 " return NO_REGS;\n"
01050 "}\n");
01051 }
01052
01053
01054
01055 static void
01056 write_tm_constrs_h (void)
01057 {
01058 struct constraint_data *c;
01059
01060 printf ("\
01061 /* Generated automatically by the program '%s'\n\
01062 from the machine description file '%s'. */\n\n", progname, in_fname);
01063
01064 puts ("\
01065 #ifndef GCC_TM_CONSTRS_H\n\
01066 #define GCC_TM_CONSTRS_H\n");
01067
01068 FOR_ALL_CONSTRAINTS (c)
01069 if (!c->is_register)
01070 {
01071 bool needs_ival = needs_variable (c->exp, "ival");
01072 bool needs_hval = needs_variable (c->exp, "hval");
01073 bool needs_lval = needs_variable (c->exp, "lval");
01074 bool needs_rval = needs_variable (c->exp, "rval");
01075 bool needs_mode = (needs_variable (c->exp, "mode")
01076 || needs_hval || needs_lval || needs_rval);
01077 bool needs_op = (needs_variable (c->exp, "op")
01078 || needs_ival || needs_mode);
01079
01080 printf ("static inline bool\n"
01081 "satisfies_constraint_%s (rtx %s)\n"
01082 "{\n", c->c_name,
01083 needs_op ? "op" : "ARG_UNUSED (op)");
01084 if (needs_mode)
01085 puts ("enum machine_mode mode = GET_MODE (op);");
01086 if (needs_ival)
01087 puts (" HOST_WIDE_INT ival = 0;");
01088 if (needs_hval)
01089 puts (" HOST_WIDE_INT hval = 0;");
01090 if (needs_lval)
01091 puts (" unsigned HOST_WIDE_INT lval = 0;");
01092 if (needs_rval)
01093 puts (" const REAL_VALUE_TYPE *rval = 0;");
01094
01095 if (needs_ival)
01096 puts (" if (GET_CODE (op) == CONST_INT)\n"
01097 " ival = INTVAL (op);");
01098 if (needs_hval)
01099 puts (" if (GET_CODE (op) == CONST_DOUBLE && mode == VOIDmode)"
01100 " hval = CONST_DOUBLE_HIGH (op);");
01101 if (needs_lval)
01102 puts (" if (GET_CODE (op) == CONST_DOUBLE && mode == VOIDmode)"
01103 " lval = CONST_DOUBLE_LOW (op);");
01104 if (needs_rval)
01105 puts (" if (GET_CODE (op) == CONST_DOUBLE && mode != VOIDmode)"
01106 " rval = CONST_DOUBLE_REAL_VALUE (op);");
01107
01108 write_predicate_stmts (c->exp);
01109 fputs ("}\n", stdout);
01110 }
01111 puts ("#endif /* tm-constrs.h */");
01112 }
01113
01114
01115
01116
01117 static void
01118 write_constraint_satisfied_p (void)
01119 {
01120 struct constraint_data *c;
01121
01122 puts ("bool\n"
01123 "constraint_satisfied_p (rtx op, enum constraint_num c)\n"
01124 "{\n"
01125 " switch (c)\n"
01126 " {");
01127
01128 FOR_ALL_CONSTRAINTS (c)
01129 if (!c->is_register)
01130 printf (" case CONSTRAINT_%s: "
01131 "return satisfies_constraint_%s (op);\n",
01132 c->c_name, c->c_name);
01133
01134 puts (" default: break;\n"
01135 " }\n"
01136 " return false;\n"
01137 "}\n");
01138 }
01139
01140
01141
01142
01143 static void
01144 write_insn_const_int_ok_for_constraint (void)
01145 {
01146 struct constraint_data *c;
01147
01148 puts ("bool\n"
01149 "insn_const_int_ok_for_constraint (HOST_WIDE_INT ival, "
01150 "enum constraint_num c)\n"
01151 "{\n"
01152 " switch (c)\n"
01153 " {");
01154
01155 FOR_ALL_CONSTRAINTS (c)
01156 if (c->is_const_int)
01157 {
01158 printf (" case CONSTRAINT_%s:\n return ", c->c_name);
01159
01160
01161
01162 write_predicate_expr (XEXP (c->exp, 1));
01163 fputs (";\n\n", stdout);
01164 }
01165
01166 puts (" default: break;\n"
01167 " }\n"
01168 " return false;\n"
01169 "}\n");
01170 }
01171
01172
01173
01174
01175 static void
01176 write_insn_extra_memory_constraint (void)
01177 {
01178 struct constraint_data *c;
01179
01180 puts ("bool\n"
01181 "insn_extra_memory_constraint (enum constraint_num c)\n"
01182 "{\n"
01183 " switch (c)\n"
01184 " {");
01185
01186 FOR_ALL_CONSTRAINTS (c)
01187 if (c->is_memory)
01188 printf (" case CONSTRAINT_%s:\n return true;\n\n", c->c_name);
01189
01190 puts (" default: break;\n"
01191 " }\n"
01192 " return false;\n"
01193 "}\n");
01194 }
01195
01196
01197
01198 static void
01199 write_insn_extra_address_constraint (void)
01200 {
01201 struct constraint_data *c;
01202
01203 puts ("bool\n"
01204 "insn_extra_address_constraint (enum constraint_num c)\n"
01205 "{\n"
01206 " switch (c)\n"
01207 " {");
01208
01209 FOR_ALL_CONSTRAINTS (c)
01210 if (c->is_address)
01211 printf (" case CONSTRAINT_%s:\n return true;\n\n", c->c_name);
01212
01213 puts (" default: break;\n"
01214 " }\n"
01215 " return false;\n"
01216 "}\n");
01217 }
01218
01219
01220
01221
01222
01223 static void
01224 write_tm_preds_h (void)
01225 {
01226 struct pred_data *p;
01227
01228 printf ("\
01229 /* Generated automatically by the program '%s'\n\
01230 from the machine description file '%s'. */\n\n", progname, in_fname);
01231
01232 puts ("\
01233 #ifndef GCC_TM_PREDS_H\n\
01234 #define GCC_TM_PREDS_H\n\
01235 \n\
01236 #ifdef HAVE_MACHINE_MODES");
01237
01238 FOR_ALL_PREDICATES (p)
01239 printf ("extern int %s (rtx, enum machine_mode);\n", p->name);
01240
01241 puts ("#endif /* HAVE_MACHINE_MODES */\n");
01242
01243 if (constraint_max_namelen > 0)
01244 {
01245 write_enum_constraint_num ();
01246 puts ("extern enum constraint_num lookup_constraint (const char *);\n"
01247 "extern bool constraint_satisfied_p (rtx, enum constraint_num);\n");
01248
01249 if (constraint_max_namelen > 1)
01250 puts ("extern size_t insn_constraint_len (enum constraint_num);\n"
01251 "#define CONSTRAINT_LEN(c_,s_) "
01252 "insn_constraint_len (lookup_constraint (s_))\n");
01253 else
01254 puts ("#define CONSTRAINT_LEN(c_,s_) 1\n");
01255 if (have_register_constraints)
01256 puts ("extern enum reg_class regclass_for_constraint "
01257 "(enum constraint_num);\n"
01258 "#define REG_CLASS_FROM_CONSTRAINT(c_,s_) \\\n"
01259 " regclass_for_constraint (lookup_constraint (s_))\n");
01260 else
01261 puts ("#define REG_CLASS_FROM_CONSTRAINT(c_,s_) NO_REGS");
01262 if (have_const_int_constraints)
01263 puts ("extern bool insn_const_int_ok_for_constraint "
01264 "(HOST_WIDE_INT, enum constraint_num);\n"
01265 "#define CONST_OK_FOR_CONSTRAINT_P(v_,c_,s_) \\\n"
01266 " insn_const_int_ok_for_constraint (v_, "
01267 "lookup_constraint (s_))\n");
01268 if (have_const_dbl_constraints)
01269 puts ("#define CONST_DOUBLE_OK_FOR_CONSTRAINT_P(v_,c_,s_) \\\n"
01270 " constraint_satisfied_p (v_, lookup_constraint (s_))\n");
01271 else
01272 puts ("#define CONST_DOUBLE_OK_FOR_CONSTRAINT_P(v_,c_,s_) 0\n");
01273 if (have_extra_constraints)
01274 puts ("#define EXTRA_CONSTRAINT_STR(v_,c_,s_) \\\n"
01275 " constraint_satisfied_p (v_, lookup_constraint (s_))\n");
01276 if (have_memory_constraints)
01277 puts ("extern bool "
01278 "insn_extra_memory_constraint (enum constraint_num);\n"
01279 "#define EXTRA_MEMORY_CONSTRAINT(c_,s_) "
01280 "insn_extra_memory_constraint (lookup_constraint (s_))\n");
01281 else
01282 puts ("#define EXTRA_MEMORY_CONSTRAINT(c_,s_) false\n");
01283 if (have_address_constraints)
01284 puts ("extern bool "
01285 "insn_extra_address_constraint (enum constraint_num);\n"
01286 "#define EXTRA_ADDRESS_CONSTRAINT(c_,s_) "
01287 "insn_extra_address_constraint (lookup_constraint (s_))\n");
01288 else
01289 puts ("#define EXTRA_ADDRESS_CONSTRAINT(c_,s_) false\n");
01290 }
01291
01292 puts ("#endif /* tm-preds.h */");
01293 }
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303 static void
01304 write_insn_preds_c (void)
01305 {
01306 struct pred_data *p;
01307
01308 printf ("\
01309 /* Generated automatically by the program '%s'\n\
01310 from the machine description file '%s'. */\n\n", progname, in_fname);
01311
01312 puts ("\
01313 #include \"config.h\"\n\
01314 #include \"system.h\"\n\
01315 #include \"coretypes.h\"\n\
01316 #include \"tm.h\"\n\
01317 #include \"rtl.h\"\n\
01318 #include \"tree.h\"\n\
01319 #include \"tm_p.h\"\n\
01320 #include \"function.h\"\n\
01321 #include \"insn-config.h\"\n\
01322 #include \"recog.h\"\n\
01323 #include \"real.h\"\n\
01324 #include \"output.h\"\n\
01325 #include \"flags.h\"\n\
01326 #include \"hard-reg-set.h\"\n\
01327 #include \"resource.h\"\n\
01328 #include \"toplev.h\"\n\
01329 #include \"reload.h\"\n\
01330 #include \"regs.h\"\n\
01331 #include \"tm-constrs.h\"\n");
01332
01333 FOR_ALL_PREDICATES (p)
01334 write_one_predicate_function (p);
01335
01336 if (constraint_max_namelen > 0)
01337 {
01338 write_lookup_constraint ();
01339 write_regclass_for_constraint ();
01340 write_constraint_satisfied_p ();
01341
01342 if (constraint_max_namelen > 1)
01343 write_insn_constraint_len ();
01344
01345 if (have_const_int_constraints)
01346 write_insn_const_int_ok_for_constraint ();
01347
01348 if (have_memory_constraints)
01349 write_insn_extra_memory_constraint ();
01350 if (have_address_constraints)
01351 write_insn_extra_address_constraint ();
01352 }
01353 }
01354
01355
01356 static bool gen_header;
01357 static bool gen_constrs;
01358
01359 static bool
01360 parse_option (const char *opt)
01361 {
01362 if (!strcmp (opt, "-h"))
01363 {
01364 gen_header = true;
01365 return 1;
01366 }
01367 else if (!strcmp (opt, "-c"))
01368 {
01369 gen_constrs = true;
01370 return 1;
01371 }
01372 else
01373 return 0;
01374 }
01375
01376
01377 int
01378 main (int argc, char **argv)
01379 {
01380 rtx defn;
01381 int pattern_lineno, next_insn_code = 0;
01382
01383 progname = argv[0];
01384 if (argc <= 1)
01385 fatal ("no input file name");
01386 if (init_md_reader_args_cb (argc, argv, parse_option) != SUCCESS_EXIT_CODE)
01387 return FATAL_EXIT_CODE;
01388
01389 while ((defn = read_md_rtx (&pattern_lineno, &next_insn_code)) != 0)
01390 switch (GET_CODE (defn))
01391 {
01392 case DEFINE_PREDICATE:
01393 case DEFINE_SPECIAL_PREDICATE:
01394 process_define_predicate (defn, pattern_lineno);
01395 break;
01396
01397 case DEFINE_CONSTRAINT:
01398 case DEFINE_MEMORY_CONSTRAINT:
01399 case DEFINE_ADDRESS_CONSTRAINT:
01400 process_define_constraint (defn, pattern_lineno);
01401 break;
01402
01403 case DEFINE_REGISTER_CONSTRAINT:
01404 process_define_register_constraint (defn, pattern_lineno);
01405 break;
01406
01407 default:
01408 break;
01409 }
01410
01411 if (gen_header)
01412 write_tm_preds_h ();
01413 else if (gen_constrs)
01414 write_tm_constrs_h ();
01415 else
01416 write_insn_preds_c ();
01417
01418 if (have_error || ferror (stdout) || fflush (stdout) || fclose (stdout))
01419 return FATAL_EXIT_CODE;
01420
01421 return SUCCESS_EXIT_CODE;
01422 }