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 "gensupport.h"
00031 #include "obstack.h"
00032
00033
00034
00035
00036 static void
00037 process_define_predicate (rtx defn)
00038 {
00039 struct pred_data *pred;
00040 if (XEXP (defn, 1) == 0)
00041 {
00042 error ("%s: must give a predicate expression", XSTR (defn, 0));
00043 return;
00044 }
00045
00046 pred = xcalloc (sizeof (struct pred_data), 1);
00047 pred->name = XSTR (defn, 0);
00048 pred->exp = XEXP (defn, 1);
00049 pred->c_block = XSTR (defn, 2);
00050
00051 if (GET_CODE (defn) == DEFINE_SPECIAL_PREDICATE)
00052 pred->special = true;
00053
00054 add_predicate (pred);
00055 }
00056
00057
00058
00059
00060 static void
00061 write_tm_preds_h (void)
00062 {
00063 struct pred_data *p;
00064
00065 printf ("\
00066 /* Generated automatically by the program '%s'\n\
00067 from the machine description file '%s'. */\n\n", progname, in_fname);
00068
00069 puts ("\
00070 #ifndef GCC_TM_PREDS_H\n\
00071 #define GCC_TM_PREDS_H\n\
00072 \n\
00073 #ifdef HAVE_MACHINE_MODES");
00074
00075 FOR_ALL_PREDICATES (p)
00076 printf ("extern int %s (rtx, enum machine_mode);\n", p->name);
00077
00078 puts ("\
00079 #endif /* HAVE_MACHINE_MODES */\n\
00080 #endif /* tm-preds.h */");
00081 }
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112 static void
00113 write_predicate_subfunction (struct pred_data *p)
00114 {
00115 const char *match_test_str;
00116 rtx match_test_exp, and_exp;
00117
00118 if (p->c_block[0] == '\0')
00119 return;
00120
00121
00122 obstack_grow (rtl_obstack, p->name, strlen (p->name));
00123 obstack_grow (rtl_obstack, "_1 (op, mode)",
00124 sizeof "_1 (op, mode)");
00125 match_test_str = obstack_finish (rtl_obstack);
00126
00127
00128
00129 match_test_exp = rtx_alloc (MATCH_TEST);
00130 XSTR (match_test_exp, 0) = match_test_str;
00131
00132 and_exp = rtx_alloc (AND);
00133 XEXP (and_exp, 0) = p->exp;
00134 XEXP (and_exp, 1) = match_test_exp;
00135
00136 p->exp = and_exp;
00137
00138 printf ("static inline int\n"
00139 "%s_1 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)\n",
00140 p->name);
00141 if (p->c_block[0] == '{')
00142 fputs (p->c_block, stdout);
00143 else
00144 printf ("{\n %s\n}", p->c_block);
00145 fputs ("\n\n", stdout);
00146 }
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159 #define NO_MODE_TEST(EXP) RTX_FLAG (EXP, volatil)
00160 static void
00161 mark_mode_tests (rtx exp)
00162 {
00163 switch (GET_CODE (exp))
00164 {
00165 case MATCH_OPERAND:
00166 {
00167 struct pred_data *p = lookup_predicate (XSTR (exp, 1));
00168 if (!p)
00169 error ("reference to undefined predicate '%s'", XSTR (exp, 1));
00170 else if (p->special || GET_MODE (exp) != VOIDmode)
00171 NO_MODE_TEST (exp) = 1;
00172 }
00173 break;
00174
00175 case MATCH_CODE:
00176 if (!strstr (XSTR (exp, 0), "const_int")
00177 && !strstr (XSTR (exp, 0), "const_double"))
00178 NO_MODE_TEST (exp) = 1;
00179 break;
00180
00181 case MATCH_TEST:
00182 case NOT:
00183 NO_MODE_TEST (exp) = 1;
00184 break;
00185
00186 case AND:
00187 mark_mode_tests (XEXP (exp, 0));
00188 mark_mode_tests (XEXP (exp, 1));
00189
00190 NO_MODE_TEST (exp) = (NO_MODE_TEST (XEXP (exp, 0))
00191 && NO_MODE_TEST (XEXP (exp, 1)));
00192 break;
00193
00194 case IOR:
00195 mark_mode_tests (XEXP (exp, 0));
00196 mark_mode_tests (XEXP (exp, 1));
00197
00198 NO_MODE_TEST (exp) = (NO_MODE_TEST (XEXP (exp, 0))
00199 || NO_MODE_TEST (XEXP (exp, 1)));
00200 break;
00201
00202 case IF_THEN_ELSE:
00203
00204
00205 mark_mode_tests (XEXP (exp, 0));
00206 mark_mode_tests (XEXP (exp, 1));
00207 mark_mode_tests (XEXP (exp, 2));
00208
00209 NO_MODE_TEST (exp) = ((NO_MODE_TEST (XEXP (exp, 0))
00210 && NO_MODE_TEST (XEXP (exp, 1)))
00211 || NO_MODE_TEST (XEXP (exp, 2)));
00212 break;
00213
00214 default:
00215 error ("'%s' cannot be used in a define_predicate expression",
00216 GET_RTX_NAME (GET_CODE (exp)));
00217 }
00218 }
00219
00220
00221
00222
00223
00224
00225
00226 static void
00227 add_mode_tests (struct pred_data *p)
00228 {
00229 rtx match_test_exp, and_exp;
00230 rtx *pos;
00231
00232
00233 if (p->special)
00234 return;
00235
00236 mark_mode_tests (p->exp);
00237
00238
00239 if (!NO_MODE_TEST (p->exp))
00240 return;
00241
00242 match_test_exp = rtx_alloc (MATCH_TEST);
00243 XSTR (match_test_exp, 0) = "mode == VOIDmode || GET_MODE (op) == mode";
00244 and_exp = rtx_alloc (AND);
00245 XEXP (and_exp, 1) = match_test_exp;
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258 pos = &p->exp;
00259 for (;;)
00260 {
00261 rtx subexp = *pos;
00262
00263 switch (GET_CODE (subexp))
00264 {
00265 case IOR:
00266 {
00267 int test0 = NO_MODE_TEST (XEXP (subexp, 0));
00268 int test1 = NO_MODE_TEST (XEXP (subexp, 1));
00269
00270 gcc_assert (test0 || test1);
00271
00272 if (test0 && test1)
00273 goto break_loop;
00274 pos = test0 ? &XEXP (subexp, 0) : &XEXP (subexp, 1);
00275 }
00276 break;
00277
00278 case IF_THEN_ELSE:
00279 {
00280 int test0 = NO_MODE_TEST (XEXP (subexp, 0));
00281 int test1 = NO_MODE_TEST (XEXP (subexp, 1));
00282 int test2 = NO_MODE_TEST (XEXP (subexp, 2));
00283
00284 gcc_assert ((test0 && test1) || test2);
00285
00286 if (test0 && test1 && test2)
00287 goto break_loop;
00288 if (test0 && test1)
00289
00290
00291
00292 pos = &XEXP (subexp, 1);
00293 else
00294 pos = &XEXP (subexp, 2);
00295 }
00296 break;
00297
00298 default:
00299 goto break_loop;
00300 }
00301 }
00302 break_loop:
00303 XEXP (and_exp, 0) = *pos;
00304 *pos = and_exp;
00305 }
00306
00307
00308
00309
00310 static void
00311 write_match_code (const char *codes)
00312 {
00313 const char *code;
00314
00315 while ((code = scan_comma_elt (&codes)) != 0)
00316 {
00317 fputs ("GET_CODE (op) == ", stdout);
00318 while (code < codes)
00319 {
00320 putchar (TOUPPER (*code));
00321 code++;
00322 }
00323
00324 if (*codes == ',')
00325 fputs (" || ", stdout);
00326 }
00327 }
00328
00329
00330
00331 static void
00332 write_predicate_expr (const char *name, rtx exp)
00333 {
00334 switch (GET_CODE (exp))
00335 {
00336 case AND:
00337 putchar ('(');
00338 write_predicate_expr (name, XEXP (exp, 0));
00339 fputs (") && (", stdout);
00340 write_predicate_expr (name, XEXP (exp, 1));
00341 putchar (')');
00342 break;
00343
00344 case IOR:
00345 putchar ('(');
00346 write_predicate_expr (name, XEXP (exp, 0));
00347 fputs (") || (", stdout);
00348 write_predicate_expr (name, XEXP (exp, 1));
00349 putchar (')');
00350 break;
00351
00352 case NOT:
00353 fputs ("!(", stdout);
00354 write_predicate_expr (name, XEXP (exp, 0));
00355 putchar (')');
00356 break;
00357
00358 case IF_THEN_ELSE:
00359 putchar ('(');
00360 write_predicate_expr (name, XEXP (exp, 0));
00361 fputs (") ? (", stdout);
00362 write_predicate_expr (name, XEXP (exp, 1));
00363 fputs (") : (", stdout);
00364 write_predicate_expr (name, XEXP (exp, 2));
00365 putchar (')');
00366 break;
00367
00368 case MATCH_OPERAND:
00369 if (GET_MODE (exp) == VOIDmode)
00370 printf ("%s (op, mode)", XSTR (exp, 1));
00371 else
00372 printf ("%s (op, %smode)", XSTR (exp, 1), mode_name[GET_MODE (exp)]);
00373 break;
00374
00375 case MATCH_CODE:
00376 write_match_code (XSTR (exp, 0));
00377 break;
00378
00379 case MATCH_TEST:
00380 fputs (XSTR (exp, 0), stdout);
00381 break;
00382
00383 default:
00384 error ("%s: cannot use '%s' in a predicate expression",
00385 name, GET_RTX_NAME (GET_CODE (exp)));
00386 putchar ('0');
00387 }
00388 }
00389
00390
00391 static void
00392 write_one_predicate_function (struct pred_data *p)
00393 {
00394 if (!p->exp)
00395 return;
00396
00397 write_predicate_subfunction (p);
00398 add_mode_tests (p);
00399
00400
00401
00402 printf ("int\n%s (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)\n"
00403 "{\n return ",
00404 p->name);
00405 write_predicate_expr (p->name, p->exp);
00406 fputs (";\n}\n\n", stdout);
00407 }
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417 static void
00418 write_insn_preds_c (void)
00419 {
00420 struct pred_data *p;
00421
00422 printf ("\
00423 /* Generated automatically by the program '%s'\n\
00424 from the machine description file '%s'. */\n\n", progname, in_fname);
00425
00426 puts ("\
00427 #include \"config.h\"\n\
00428 #include \"system.h\"\n\
00429 #include \"coretypes.h\"\n\
00430 #include \"tm.h\"\n\
00431 #include \"rtl.h\"\n\
00432 #include \"tree.h\"\n\
00433 #include \"tm_p.h\"\n\
00434 #include \"function.h\"\n\
00435 #include \"insn-config.h\"\n\
00436 #include \"recog.h\"\n\
00437 #include \"real.h\"\n\
00438 #include \"output.h\"\n\
00439 #include \"flags.h\"\n\
00440 #include \"hard-reg-set.h\"\n\
00441 #include \"resource.h\"\n\
00442 #include \"toplev.h\"\n\
00443 #include \"reload.h\"\n\
00444 #include \"regs.h\"\n");
00445
00446 FOR_ALL_PREDICATES (p)
00447 write_one_predicate_function (p);
00448 }
00449
00450
00451 static bool gen_header;
00452 static bool
00453 parse_option (const char *opt)
00454 {
00455 if (!strcmp (opt, "-h"))
00456 {
00457 gen_header = true;
00458 return 1;
00459 }
00460 else
00461 return 0;
00462 }
00463
00464
00465 int
00466 main (int argc, char **argv)
00467 {
00468 rtx defn;
00469 int pattern_lineno, next_insn_code = 0;
00470
00471 progname = argv[0];
00472 if (argc <= 1)
00473 fatal ("no input file name");
00474 if (init_md_reader_args_cb (argc, argv, parse_option) != SUCCESS_EXIT_CODE)
00475 return FATAL_EXIT_CODE;
00476
00477 while ((defn = read_md_rtx (&pattern_lineno, &next_insn_code)) != 0)
00478 {
00479 if (GET_CODE (defn) == DEFINE_PREDICATE
00480 || GET_CODE (defn) == DEFINE_SPECIAL_PREDICATE)
00481 process_define_predicate (defn);
00482 }
00483
00484 if (gen_header)
00485 write_tm_preds_h ();
00486 else
00487 write_insn_preds_c ();
00488
00489 if (have_error || ferror (stdout) || fflush (stdout) || fclose (stdout))
00490 return FATAL_EXIT_CODE;
00491
00492 return SUCCESS_EXIT_CODE;
00493 }
00494
00495
00496 const char *
00497 get_insn_name (int code ATTRIBUTE_UNUSED)
00498 {
00499 return 0;
00500 }