1 /* Generate code from machine description to emit insns as rtl. 2 Copyright (C) 1987-2018 Free Software Foundation, Inc. 3 4 This file is part of GCC. 5 6 GCC is free software; you can redistribute it and/or modify it under 7 the terms of the GNU General Public License as published by the Free 8 Software Foundation; either version 3, or (at your option) any later 9 version. 10 11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY 12 WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with GCC; see the file COPYING3. If not see 18 <http://www.gnu.org/licenses/>. */ 19 20 21 #include "bconfig.h" 22 #include "system.h" 23 #include "coretypes.h" 24 #include "tm.h" 25 #include "rtl.h" 26 #include "errors.h" 27 #include "read-md.h" 28 #include "gensupport.h" 29 30 31 /* Data structure for recording the patterns of insns that have CLOBBERs. 32 We use this to output a function that adds these CLOBBERs to a 33 previously-allocated PARALLEL expression. */ 34 35 struct clobber_pat 36 { 37 struct clobber_ent *insns; 38 rtx pattern; 39 int first_clobber; 40 struct clobber_pat *next; 41 int has_hard_reg; 42 } *clobber_list; 43 44 /* Records one insn that uses the clobber list. */ 45 46 struct clobber_ent 47 { 48 int code_number; /* Counts only insns. */ 49 struct clobber_ent *next; 50 }; 51 52 static void output_peephole2_scratches (rtx); 53 54 /* True for <X>_optab if that optab isn't allowed to fail. */ 55 static bool nofail_optabs[NUM_OPTABS]; 56 57 static void 58 print_code (RTX_CODE code) 59 { 60 const char *p1; 61 for (p1 = GET_RTX_NAME (code); *p1; p1++) 62 putchar (TOUPPER (*p1)); 63 } 64 65 static void 66 gen_rtx_scratch (rtx x, enum rtx_code subroutine_type) 67 { 68 if (subroutine_type == DEFINE_PEEPHOLE2) 69 { 70 printf ("operand%d", XINT (x, 0)); 71 } 72 else 73 { 74 printf ("gen_rtx_SCRATCH (%smode)", GET_MODE_NAME (GET_MODE (x))); 75 } 76 } 77 78 /* Print a C expression to construct an RTX just like X, 79 substituting any operand references appearing within. */ 80 81 static void 82 gen_exp (rtx x, enum rtx_code subroutine_type, char *used) 83 { 84 RTX_CODE code; 85 int i; 86 int len; 87 const char *fmt; 88 const char *sep = ""; 89 90 if (x == 0) 91 { 92 printf ("NULL_RTX"); 93 return; 94 } 95 96 code = GET_CODE (x); 97 98 switch (code) 99 { 100 case MATCH_OPERAND: 101 case MATCH_DUP: 102 if (used) 103 { 104 if (used[XINT (x, 0)]) 105 { 106 printf ("copy_rtx (operand%d)", XINT (x, 0)); 107 return; 108 } 109 used[XINT (x, 0)] = 1; 110 } 111 printf ("operand%d", XINT (x, 0)); 112 return; 113 114 case MATCH_OP_DUP: 115 printf ("gen_rtx_fmt_"); 116 for (i = 0; i < XVECLEN (x, 1); i++) 117 printf ("e"); 118 printf (" (GET_CODE (operand%d), ", XINT (x, 0)); 119 if (GET_MODE (x) == VOIDmode) 120 printf ("GET_MODE (operand%d)", XINT (x, 0)); 121 else 122 printf ("%smode", GET_MODE_NAME (GET_MODE (x))); 123 for (i = 0; i < XVECLEN (x, 1); i++) 124 { 125 printf (",\n\t\t"); 126 gen_exp (XVECEXP (x, 1, i), subroutine_type, used); 127 } 128 printf (")"); 129 return; 130 131 case MATCH_OPERATOR: 132 printf ("gen_rtx_fmt_"); 133 for (i = 0; i < XVECLEN (x, 2); i++) 134 printf ("e"); 135 printf (" (GET_CODE (operand%d)", XINT (x, 0)); 136 printf (", %smode", GET_MODE_NAME (GET_MODE (x))); 137 for (i = 0; i < XVECLEN (x, 2); i++) 138 { 139 printf (",\n\t\t"); 140 gen_exp (XVECEXP (x, 2, i), subroutine_type, used); 141 } 142 printf (")"); 143 return; 144 145 case MATCH_PARALLEL: 146 case MATCH_PAR_DUP: 147 printf ("operand%d", XINT (x, 0)); 148 return; 149 150 case MATCH_SCRATCH: 151 gen_rtx_scratch (x, subroutine_type); 152 return; 153 154 case PC: 155 printf ("pc_rtx"); 156 return; 157 case RETURN: 158 printf ("ret_rtx"); 159 return; 160 case SIMPLE_RETURN: 161 printf ("simple_return_rtx"); 162 return; 163 case CLOBBER: 164 if (REG_P (XEXP (x, 0))) 165 { 166 printf ("gen_hard_reg_clobber (%smode, %i)", GET_MODE_NAME (GET_MODE (XEXP (x, 0))), 167 REGNO (XEXP (x, 0))); 168 return; 169 } 170 break; 171 172 case CC0: 173 printf ("cc0_rtx"); 174 return; 175 176 case CONST_INT: 177 if (INTVAL (x) == 0) 178 printf ("const0_rtx"); 179 else if (INTVAL (x) == 1) 180 printf ("const1_rtx"); 181 else if (INTVAL (x) == -1) 182 printf ("constm1_rtx"); 183 else if (-MAX_SAVED_CONST_INT <= INTVAL (x) 184 && INTVAL (x) <= MAX_SAVED_CONST_INT) 185 printf ("const_int_rtx[MAX_SAVED_CONST_INT + (%d)]", 186 (int) INTVAL (x)); 187 else if (INTVAL (x) == STORE_FLAG_VALUE) 188 printf ("const_true_rtx"); 189 else 190 { 191 printf ("GEN_INT ("); 192 printf (HOST_WIDE_INT_PRINT_DEC_C, INTVAL (x)); 193 printf (")"); 194 } 195 return; 196 197 case CONST_DOUBLE: 198 case CONST_FIXED: 199 case CONST_WIDE_INT: 200 /* These shouldn't be written in MD files. Instead, the appropriate 201 routines in varasm.c should be called. */ 202 gcc_unreachable (); 203 204 default: 205 break; 206 } 207 208 printf ("gen_rtx_"); 209 print_code (code); 210 printf (" ("); 211 if (!always_void_p (code)) 212 { 213 printf ("%smode", GET_MODE_NAME (GET_MODE (x))); 214 sep = ",\n\t"; 215 } 216 217 fmt = GET_RTX_FORMAT (code); 218 len = GET_RTX_LENGTH (code); 219 for (i = 0; i < len; i++) 220 { 221 if (fmt[i] == '0') 222 break; 223 fputs (sep, stdout); 224 switch (fmt[i]) 225 { 226 case 'e': case 'u': 227 gen_exp (XEXP (x, i), subroutine_type, used); 228 break; 229 230 case 'i': 231 printf ("%u", XINT (x, i)); 232 break; 233 234 case 'r': 235 printf ("%u", REGNO (x)); 236 break; 237 238 case 'p': 239 /* We don't have a way of parsing polynomial offsets yet, 240 and hopefully never will. */ 241 printf ("%d", SUBREG_BYTE (x).to_constant ()); 242 break; 243 244 case 's': 245 printf ("\"%s\"", XSTR (x, i)); 246 break; 247 248 case 'E': 249 { 250 int j; 251 printf ("gen_rtvec (%d", XVECLEN (x, i)); 252 for (j = 0; j < XVECLEN (x, i); j++) 253 { 254 printf (",\n\t\t"); 255 gen_exp (XVECEXP (x, i, j), subroutine_type, used); 256 } 257 printf (")"); 258 break; 259 } 260 261 default: 262 gcc_unreachable (); 263 } 264 sep = ",\n\t"; 265 } 266 printf (")"); 267 } 268 269 /* Output code to emit the instruction patterns in VEC, with each element 270 becoming a separate instruction. USED is as for gen_exp. */ 271 272 static void 273 gen_emit_seq (rtvec vec, char *used) 274 { 275 for (int i = 0, len = GET_NUM_ELEM (vec); i < len; ++i) 276 { 277 bool last_p = (i == len - 1); 278 rtx next = RTVEC_ELT (vec, i); 279 if (const char *name = get_emit_function (next)) 280 { 281 printf (" %s (", name); 282 gen_exp (next, DEFINE_EXPAND, used); 283 printf (");\n"); 284 if (!last_p && needs_barrier_p (next)) 285 printf (" emit_barrier ();"); 286 } 287 else 288 { 289 printf (" emit ("); 290 gen_exp (next, DEFINE_EXPAND, used); 291 printf (", %s);\n", last_p ? "false" : "true"); 292 } 293 } 294 } 295 296 /* Emit the given C code to the output file. The code is allowed to 297 fail if CAN_FAIL_P. NAME describes what we're generating, 298 for use in error messages. */ 299 300 static void 301 emit_c_code (const char *code, bool can_fail_p, const char *name) 302 { 303 if (can_fail_p) 304 printf ("#define FAIL return (end_sequence (), _val)\n"); 305 else 306 printf ("#define FAIL _Pragma (\"GCC error \\\"%s cannot FAIL\\\"\")" 307 " (void)0\n", name); 308 printf ("#define DONE return (_val = get_insns ()," 309 "end_sequence (), _val)\n"); 310 311 rtx_reader_ptr->print_md_ptr_loc (code); 312 printf ("%s\n", code); 313 314 printf ("#undef DONE\n"); 315 printf ("#undef FAIL\n"); 316 } 317 318 /* Generate the `gen_...' function for a DEFINE_INSN. */ 319 320 static void 321 gen_insn (md_rtx_info *info) 322 { 323 struct pattern_stats stats; 324 int i; 325 326 /* See if the pattern for this insn ends with a group of CLOBBERs of (hard) 327 registers or MATCH_SCRATCHes. If so, store away the information for 328 later. */ 329 330 rtx insn = info->def; 331 if (XVEC (insn, 1)) 332 { 333 int has_hard_reg = 0; 334 335 for (i = XVECLEN (insn, 1) - 1; i > 0; i--) 336 { 337 if (GET_CODE (XVECEXP (insn, 1, i)) != CLOBBER) 338 break; 339 340 if (REG_P (XEXP (XVECEXP (insn, 1, i), 0))) 341 has_hard_reg = 1; 342 else if (GET_CODE (XEXP (XVECEXP (insn, 1, i), 0)) != MATCH_SCRATCH) 343 break; 344 } 345 346 if (i != XVECLEN (insn, 1) - 1) 347 { 348 struct clobber_pat *p; 349 struct clobber_ent *link = XNEW (struct clobber_ent); 350 int j; 351 352 link->code_number = info->index; 353 354 /* See if any previous CLOBBER_LIST entry is the same as this 355 one. */ 356 357 for (p = clobber_list; p; p = p->next) 358 { 359 if (p->first_clobber != i + 1 360 || XVECLEN (p->pattern, 1) != XVECLEN (insn, 1)) 361 continue; 362 363 for (j = i + 1; j < XVECLEN (insn, 1); j++) 364 { 365 rtx old_rtx = XEXP (XVECEXP (p->pattern, 1, j), 0); 366 rtx new_rtx = XEXP (XVECEXP (insn, 1, j), 0); 367 368 /* OLD and NEW_INSN are the same if both are to be a SCRATCH 369 of the same mode, 370 or if both are registers of the same mode and number. */ 371 if (! (GET_MODE (old_rtx) == GET_MODE (new_rtx) 372 && ((GET_CODE (old_rtx) == MATCH_SCRATCH 373 && GET_CODE (new_rtx) == MATCH_SCRATCH) 374 || (REG_P (old_rtx) && REG_P (new_rtx) 375 && REGNO (old_rtx) == REGNO (new_rtx))))) 376 break; 377 } 378 379 if (j == XVECLEN (insn, 1)) 380 break; 381 } 382 383 if (p == 0) 384 { 385 p = XNEW (struct clobber_pat); 386 387 p->insns = 0; 388 p->pattern = insn; 389 p->first_clobber = i + 1; 390 p->next = clobber_list; 391 p->has_hard_reg = has_hard_reg; 392 clobber_list = p; 393 } 394 395 link->next = p->insns; 396 p->insns = link; 397 } 398 } 399 400 /* Don't mention instructions whose names are the null string 401 or begin with '*'. They are in the machine description just 402 to be recognized. */ 403 if (XSTR (insn, 0)[0] == 0 || XSTR (insn, 0)[0] == '*') 404 return; 405 406 printf ("/* %s:%d */\n", info->loc.filename, info->loc.lineno); 407 408 /* Find out how many operands this function has. */ 409 get_pattern_stats (&stats, XVEC (insn, 1)); 410 if (stats.max_dup_opno > stats.max_opno) 411 fatal_at (info->loc, "match_dup operand number has no match_operand"); 412 413 /* Output the function name and argument declarations. */ 414 printf ("rtx\ngen_%s (", XSTR (insn, 0)); 415 if (stats.num_generator_args) 416 for (i = 0; i < stats.num_generator_args; i++) 417 if (i) 418 printf (",\n\trtx operand%d ATTRIBUTE_UNUSED", i); 419 else 420 printf ("rtx operand%d ATTRIBUTE_UNUSED", i); 421 else 422 printf ("void"); 423 printf (")\n"); 424 printf ("{\n"); 425 426 /* Output code to construct and return the rtl for the instruction body. */ 427 428 rtx pattern = add_implicit_parallel (XVEC (insn, 1)); 429 /* ??? This is the traditional behavior, but seems suspect. */ 430 char *used = (XVECLEN (insn, 1) == 1 431 ? NULL 432 : XCNEWVEC (char, stats.num_generator_args)); 433 printf (" return "); 434 gen_exp (pattern, DEFINE_INSN, used); 435 printf (";\n}\n\n"); 436 XDELETEVEC (used); 437 } 438 439 /* Generate the `gen_...' function for a DEFINE_EXPAND. */ 440 441 static void 442 gen_expand (md_rtx_info *info) 443 { 444 struct pattern_stats stats; 445 int i; 446 char *used; 447 448 rtx expand = info->def; 449 if (strlen (XSTR (expand, 0)) == 0) 450 fatal_at (info->loc, "define_expand lacks a name"); 451 if (XVEC (expand, 1) == 0) 452 fatal_at (info->loc, "define_expand for %s lacks a pattern", 453 XSTR (expand, 0)); 454 455 /* Find out how many operands this function has. */ 456 get_pattern_stats (&stats, XVEC (expand, 1)); 457 if (stats.min_scratch_opno != -1 458 && stats.min_scratch_opno <= MAX (stats.max_opno, stats.max_dup_opno)) 459 fatal_at (info->loc, "define_expand for %s needs to have match_scratch " 460 "numbers above all other operands", XSTR (expand, 0)); 461 462 /* Output the function name and argument declarations. */ 463 printf ("rtx\ngen_%s (", XSTR (expand, 0)); 464 if (stats.num_generator_args) 465 for (i = 0; i < stats.num_generator_args; i++) 466 if (i) 467 printf (",\n\trtx operand%d", i); 468 else 469 printf ("rtx operand%d", i); 470 else 471 printf ("void"); 472 printf (")\n"); 473 printf ("{\n"); 474 475 /* If we don't have any C code to write, only one insn is being written, 476 and no MATCH_DUPs are present, we can just return the desired insn 477 like we do for a DEFINE_INSN. This saves memory. */ 478 if ((XSTR (expand, 3) == 0 || *XSTR (expand, 3) == '\0') 479 && stats.max_opno >= stats.max_dup_opno 480 && XVECLEN (expand, 1) == 1) 481 { 482 printf (" return "); 483 gen_exp (XVECEXP (expand, 1, 0), DEFINE_EXPAND, NULL); 484 printf (";\n}\n\n"); 485 return; 486 } 487 488 /* For each operand referred to only with MATCH_DUPs, 489 make a local variable. */ 490 for (i = stats.num_generator_args; i <= stats.max_dup_opno; i++) 491 printf (" rtx operand%d;\n", i); 492 printf (" rtx_insn *_val = 0;\n"); 493 printf (" start_sequence ();\n"); 494 495 /* The fourth operand of DEFINE_EXPAND is some code to be executed 496 before the actual construction. 497 This code expects to refer to `operands' 498 just as the output-code in a DEFINE_INSN does, 499 but here `operands' is an automatic array. 500 So copy the operand values there before executing it. */ 501 if (XSTR (expand, 3) && *XSTR (expand, 3)) 502 { 503 printf (" {\n"); 504 if (stats.num_operand_vars > 0) 505 printf (" rtx operands[%d];\n", stats.num_operand_vars); 506 507 /* Output code to copy the arguments into `operands'. */ 508 for (i = 0; i < stats.num_generator_args; i++) 509 printf (" operands[%d] = operand%d;\n", i, i); 510 511 /* Output the special code to be executed before the sequence 512 is generated. */ 513 optab_pattern p; 514 bool can_fail_p = true; 515 if (find_optab (&p, XSTR (expand, 0))) 516 { 517 gcc_assert (p.op < NUM_OPTABS); 518 if (nofail_optabs[p.op]) 519 can_fail_p = false; 520 } 521 emit_c_code (XSTR (expand, 3), can_fail_p, XSTR (expand, 0)); 522 523 /* Output code to copy the arguments back out of `operands' 524 (unless we aren't going to use them at all). */ 525 if (XVEC (expand, 1) != 0) 526 { 527 for (i = 0; i <= MAX (stats.max_opno, stats.max_dup_opno); i++) 528 { 529 printf (" operand%d = operands[%d];\n", i, i); 530 printf (" (void) operand%d;\n", i); 531 } 532 } 533 printf (" }\n"); 534 } 535 536 used = XCNEWVEC (char, stats.num_operand_vars); 537 gen_emit_seq (XVEC (expand, 1), used); 538 XDELETEVEC (used); 539 540 /* Call `get_insns' to extract the list of all the 541 insns emitted within this gen_... function. */ 542 543 printf (" _val = get_insns ();\n"); 544 printf (" end_sequence ();\n"); 545 printf (" return _val;\n}\n\n"); 546 } 547 548 /* Like gen_expand, but generates insns resulting from splitting SPLIT. */ 549 550 static void 551 gen_split (md_rtx_info *info) 552 { 553 struct pattern_stats stats; 554 int i; 555 rtx split = info->def; 556 const char *const name = 557 ((GET_CODE (split) == DEFINE_PEEPHOLE2) ? "peephole2" : "split"); 558 const char *unused; 559 char *used; 560 561 if (XVEC (split, 0) == 0) 562 fatal_at (info->loc, "%s lacks a pattern", 563 GET_RTX_NAME (GET_CODE (split))); 564 else if (XVEC (split, 2) == 0) 565 fatal_at (info->loc, "%s lacks a replacement pattern", 566 GET_RTX_NAME (GET_CODE (split))); 567 568 /* Find out how many operands this function has. */ 569 570 get_pattern_stats (&stats, XVEC (split, 2)); 571 unused = (stats.num_operand_vars == 0 ? " ATTRIBUTE_UNUSED" : ""); 572 used = XCNEWVEC (char, stats.num_operand_vars); 573 574 /* Output the prototype, function name and argument declarations. */ 575 if (GET_CODE (split) == DEFINE_PEEPHOLE2) 576 { 577 printf ("extern rtx_insn *gen_%s_%d (rtx_insn *, rtx *);\n", 578 name, info->index); 579 printf ("rtx_insn *\ngen_%s_%d (rtx_insn *curr_insn ATTRIBUTE_UNUSED," 580 " rtx *operands%s)\n", 581 name, info->index, unused); 582 } 583 else 584 { 585 printf ("extern rtx_insn *gen_split_%d (rtx_insn *, rtx *);\n", 586 info->index); 587 printf ("rtx_insn *\ngen_split_%d " 588 "(rtx_insn *curr_insn ATTRIBUTE_UNUSED, rtx *operands%s)\n", 589 info->index, unused); 590 } 591 printf ("{\n"); 592 593 /* Declare all local variables. */ 594 for (i = 0; i < stats.num_operand_vars; i++) 595 printf (" rtx operand%d;\n", i); 596 printf (" rtx_insn *_val = NULL;\n"); 597 598 if (GET_CODE (split) == DEFINE_PEEPHOLE2) 599 output_peephole2_scratches (split); 600 601 printf (" if (dump_file)\n"); 602 printf (" fprintf (dump_file, \"Splitting with gen_%s_%d\\n\");\n", 603 name, info->index); 604 605 printf (" start_sequence ();\n"); 606 607 /* The fourth operand of DEFINE_SPLIT is some code to be executed 608 before the actual construction. */ 609 610 if (XSTR (split, 3)) 611 emit_c_code (XSTR (split, 3), true, name); 612 613 /* Output code to copy the arguments back out of `operands' */ 614 for (i = 0; i < stats.num_operand_vars; i++) 615 { 616 printf (" operand%d = operands[%d];\n", i, i); 617 printf (" (void) operand%d;\n", i); 618 } 619 620 gen_emit_seq (XVEC (split, 2), used); 621 622 /* Call `get_insns' to make a list of all the 623 insns emitted within this gen_... function. */ 624 625 printf (" _val = get_insns ();\n"); 626 printf (" end_sequence ();\n"); 627 printf (" return _val;\n}\n\n"); 628 629 free (used); 630 } 631 632 /* Write a function, `add_clobbers', that is given a PARALLEL of sufficient 633 size for the insn and an INSN_CODE, and inserts the required CLOBBERs at 634 the end of the vector. */ 635 636 static void 637 output_add_clobbers (void) 638 { 639 struct clobber_pat *clobber; 640 struct clobber_ent *ent; 641 int i; 642 643 printf ("\n\nvoid\nadd_clobbers (rtx pattern ATTRIBUTE_UNUSED, int insn_code_number)\n"); 644 printf ("{\n"); 645 printf (" switch (insn_code_number)\n"); 646 printf (" {\n"); 647 648 for (clobber = clobber_list; clobber; clobber = clobber->next) 649 { 650 for (ent = clobber->insns; ent; ent = ent->next) 651 printf (" case %d:\n", ent->code_number); 652 653 for (i = clobber->first_clobber; i < XVECLEN (clobber->pattern, 1); i++) 654 { 655 printf (" XVECEXP (pattern, 0, %d) = ", i); 656 gen_exp (XVECEXP (clobber->pattern, 1, i), 657 GET_CODE (clobber->pattern), NULL); 658 printf (";\n"); 659 } 660 661 printf (" break;\n\n"); 662 } 663 664 printf (" default:\n"); 665 printf (" gcc_unreachable ();\n"); 666 printf (" }\n"); 667 printf ("}\n"); 668 } 669 670 /* Write a function, `added_clobbers_hard_reg_p' that is given an insn_code 671 number that will have clobbers added (as indicated by `recog') and returns 672 1 if those include a clobber of a hard reg or 0 if all of them just clobber 673 SCRATCH. */ 674 675 static void 676 output_added_clobbers_hard_reg_p (void) 677 { 678 struct clobber_pat *clobber; 679 struct clobber_ent *ent; 680 int clobber_p, used; 681 682 printf ("\n\nint\nadded_clobbers_hard_reg_p (int insn_code_number)\n"); 683 printf ("{\n"); 684 printf (" switch (insn_code_number)\n"); 685 printf (" {\n"); 686 687 for (clobber_p = 0; clobber_p <= 1; clobber_p++) 688 { 689 used = 0; 690 for (clobber = clobber_list; clobber; clobber = clobber->next) 691 if (clobber->has_hard_reg == clobber_p) 692 for (ent = clobber->insns; ent; ent = ent->next) 693 { 694 printf (" case %d:\n", ent->code_number); 695 used++; 696 } 697 698 if (used) 699 printf (" return %d;\n\n", clobber_p); 700 } 701 702 printf (" default:\n"); 703 printf (" gcc_unreachable ();\n"); 704 printf (" }\n"); 705 printf ("}\n"); 706 } 707 708 /* Generate code to invoke find_free_register () as needed for the 709 scratch registers used by the peephole2 pattern in SPLIT. */ 710 711 static void 712 output_peephole2_scratches (rtx split) 713 { 714 int i; 715 int insn_nr = 0; 716 bool first = true; 717 718 for (i = 0; i < XVECLEN (split, 0); i++) 719 { 720 rtx elt = XVECEXP (split, 0, i); 721 if (GET_CODE (elt) == MATCH_SCRATCH) 722 { 723 int last_insn_nr = insn_nr; 724 int cur_insn_nr = insn_nr; 725 int j; 726 for (j = i + 1; j < XVECLEN (split, 0); j++) 727 if (GET_CODE (XVECEXP (split, 0, j)) == MATCH_DUP) 728 { 729 if (XINT (XVECEXP (split, 0, j), 0) == XINT (elt, 0)) 730 last_insn_nr = cur_insn_nr; 731 } 732 else if (GET_CODE (XVECEXP (split, 0, j)) != MATCH_SCRATCH) 733 cur_insn_nr++; 734 735 if (first) 736 { 737 printf (" HARD_REG_SET _regs_allocated;\n"); 738 printf (" CLEAR_HARD_REG_SET (_regs_allocated);\n"); 739 first = false; 740 } 741 742 printf (" if ((operands[%d] = peep2_find_free_register (%d, %d, \"%s\", %smode, &_regs_allocated)) == NULL_RTX)\n\ 743 return NULL;\n", 744 XINT (elt, 0), 745 insn_nr, last_insn_nr, 746 XSTR (elt, 1), 747 GET_MODE_NAME (GET_MODE (elt))); 748 749 } 750 else if (GET_CODE (elt) != MATCH_DUP) 751 insn_nr++; 752 } 753 } 754 755 int 756 main (int argc, const char **argv) 757 { 758 progname = "genemit"; 759 760 if (!init_rtx_reader_args (argc, argv)) 761 return (FATAL_EXIT_CODE); 762 763 #define DEF_INTERNAL_OPTAB_FN(NAME, FLAGS, OPTAB, TYPE) \ 764 nofail_optabs[OPTAB##_optab] = true; 765 #include "internal-fn.def" 766 767 /* Assign sequential codes to all entries in the machine description 768 in parallel with the tables in insn-output.c. */ 769 770 printf ("/* Generated automatically by the program `genemit'\n\ 771 from the machine description file `md'. */\n\n"); 772 773 printf ("#define IN_TARGET_CODE 1\n"); 774 printf ("#include \"config.h\"\n"); 775 printf ("#include \"system.h\"\n"); 776 printf ("#include \"coretypes.h\"\n"); 777 printf ("#include \"backend.h\"\n"); 778 printf ("#include \"predict.h\"\n"); 779 printf ("#include \"tree.h\"\n"); 780 printf ("#include \"rtl.h\"\n"); 781 printf ("#include \"alias.h\"\n"); 782 printf ("#include \"varasm.h\"\n"); 783 printf ("#include \"stor-layout.h\"\n"); 784 printf ("#include \"calls.h\"\n"); 785 printf ("#include \"memmodel.h\"\n"); 786 printf ("#include \"tm_p.h\"\n"); 787 printf ("#include \"flags.h\"\n"); 788 printf ("#include \"insn-config.h\"\n"); 789 printf ("#include \"expmed.h\"\n"); 790 printf ("#include \"dojump.h\"\n"); 791 printf ("#include \"explow.h\"\n"); 792 printf ("#include \"emit-rtl.h\"\n"); 793 printf ("#include \"stmt.h\"\n"); 794 printf ("#include \"expr.h\"\n"); 795 printf ("#include \"insn-codes.h\"\n"); 796 printf ("#include \"optabs.h\"\n"); 797 printf ("#include \"dfp.h\"\n"); 798 printf ("#include \"output.h\"\n"); 799 printf ("#include \"recog.h\"\n"); 800 printf ("#include \"df.h\"\n"); 801 printf ("#include \"resource.h\"\n"); 802 printf ("#include \"reload.h\"\n"); 803 printf ("#include \"diagnostic-core.h\"\n"); 804 printf ("#include \"regs.h\"\n"); 805 printf ("#include \"tm-constrs.h\"\n"); 806 printf ("#include \"ggc.h\"\n"); 807 printf ("#include \"target.h\"\n\n"); 808 809 /* Read the machine description. */ 810 811 md_rtx_info info; 812 while (read_md_rtx (&info)) 813 switch (GET_CODE (info.def)) 814 { 815 case DEFINE_INSN: 816 gen_insn (&info); 817 break; 818 819 case DEFINE_EXPAND: 820 printf ("/* %s:%d */\n", info.loc.filename, info.loc.lineno); 821 gen_expand (&info); 822 break; 823 824 case DEFINE_SPLIT: 825 printf ("/* %s:%d */\n", info.loc.filename, info.loc.lineno); 826 gen_split (&info); 827 break; 828 829 case DEFINE_PEEPHOLE2: 830 printf ("/* %s:%d */\n", info.loc.filename, info.loc.lineno); 831 gen_split (&info); 832 break; 833 834 default: 835 break; 836 } 837 838 /* Write out the routines to add CLOBBERs to a pattern and say whether they 839 clobber a hard reg. */ 840 output_add_clobbers (); 841 output_added_clobbers_hard_reg_p (); 842 843 fflush (stdout); 844 return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE); 845 } 846