1/* Generate code from machine description to emit insns as rtl. 2 Copyright (C) 1987-2020 Free Software Foundation, Inc. 3 4This file is part of GCC. 5 6GCC is free software; you can redistribute it and/or modify it under 7the terms of the GNU General Public License as published by the Free 8Software Foundation; either version 3, or (at your option) any later 9version. 10 11GCC is distributed in the hope that it will be useful, but WITHOUT ANY 12WARRANTY; without even the implied warranty of MERCHANTABILITY or 13FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14for more details. 15 16You should have received a copy of the GNU General Public License 17along 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 35struct 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 46struct clobber_ent 47{ 48 int code_number; /* Counts only insns. */ 49 struct clobber_ent *next; 50}; 51 52static void output_peephole2_scratches (rtx); 53 54/* True for <X>_optab if that optab isn't allowed to fail. */ 55static bool nofail_optabs[NUM_OPTABS]; 56 57static void 58print_code (RTX_CODE code) 59{ 60 const char *p1; 61 for (p1 = GET_RTX_NAME (code); *p1; p1++) 62 putchar (TOUPPER (*p1)); 63} 64 65static void 66gen_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 81static void 82gen_exp (rtx x, enum rtx_code subroutine_type, char *used, md_rtx_info *info) 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, info); 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, info); 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)", 167 GET_MODE_NAME (GET_MODE (XEXP (x, 0))), 168 REGNO (XEXP (x, 0))); 169 return; 170 } 171 break; 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_C ("); 193 printf (HOST_WIDE_INT_PRINT_DEC, INTVAL (x)); 194 printf (")"); 195 printf (")"); 196 } 197 return; 198 199 case CONST_DOUBLE: 200 case CONST_FIXED: 201 case CONST_WIDE_INT: 202 /* These shouldn't be written in MD files. Instead, the appropriate 203 routines in varasm.c should be called. */ 204 gcc_unreachable (); 205 206 default: 207 break; 208 } 209 210 printf ("gen_rtx_"); 211 print_code (code); 212 printf (" ("); 213 if (!always_void_p (code)) 214 { 215 printf ("%smode", GET_MODE_NAME (GET_MODE (x))); 216 sep = ",\n\t"; 217 } 218 219 fmt = GET_RTX_FORMAT (code); 220 len = GET_RTX_LENGTH (code); 221 for (i = 0; i < len; i++) 222 { 223 if (fmt[i] == '0') 224 break; 225 fputs (sep, stdout); 226 switch (fmt[i]) 227 { 228 case 'e': case 'u': 229 gen_exp (XEXP (x, i), subroutine_type, used, info); 230 break; 231 232 case 'i': 233 printf ("%u", XINT (x, i)); 234 break; 235 236 case 'r': 237 printf ("%u", REGNO (x)); 238 break; 239 240 case 'p': 241 /* We don't have a way of parsing polynomial offsets yet, 242 and hopefully never will. */ 243 printf ("%d", SUBREG_BYTE (x).to_constant ()); 244 break; 245 246 case 's': 247 printf ("\"%s\"", XSTR (x, i)); 248 break; 249 250 case 'E': 251 { 252 int j; 253 printf ("gen_rtvec (%d", XVECLEN (x, i)); 254 for (j = 0; j < XVECLEN (x, i); j++) 255 { 256 printf (",\n\t\t"); 257 gen_exp (XVECEXP (x, i, j), subroutine_type, used, info); 258 } 259 printf (")"); 260 break; 261 } 262 263 default: 264 gcc_unreachable (); 265 } 266 sep = ",\n\t"; 267 } 268 printf (")"); 269} 270 271/* Output code to emit the instruction patterns in VEC, with each element 272 becoming a separate instruction. USED is as for gen_exp. */ 273 274static void 275gen_emit_seq (rtvec vec, char *used, md_rtx_info *info) 276{ 277 for (int i = 0, len = GET_NUM_ELEM (vec); i < len; ++i) 278 { 279 bool last_p = (i == len - 1); 280 rtx next = RTVEC_ELT (vec, i); 281 if (const char *name = get_emit_function (next)) 282 { 283 printf (" %s (", name); 284 gen_exp (next, DEFINE_EXPAND, used, info); 285 printf (");\n"); 286 if (!last_p && needs_barrier_p (next)) 287 printf (" emit_barrier ();"); 288 } 289 else 290 { 291 printf (" emit ("); 292 gen_exp (next, DEFINE_EXPAND, used, info); 293 printf (", %s);\n", last_p ? "false" : "true"); 294 } 295 } 296} 297 298/* Emit the given C code to the output file. The code is allowed to 299 fail if CAN_FAIL_P. NAME describes what we're generating, 300 for use in error messages. */ 301 302static void 303emit_c_code (const char *code, bool can_fail_p, const char *name) 304{ 305 if (can_fail_p) 306 printf ("#define FAIL return (end_sequence (), _val)\n"); 307 else 308 printf ("#define FAIL _Pragma (\"GCC error \\\"%s cannot FAIL\\\"\")" 309 " (void)0\n", name); 310 printf ("#define DONE return (_val = get_insns (), " 311 "end_sequence (), _val)\n"); 312 313 rtx_reader_ptr->print_md_ptr_loc (code); 314 printf ("%s\n", code); 315 316 printf ("#undef DONE\n"); 317 printf ("#undef FAIL\n"); 318} 319 320/* Generate the `gen_...' function for a DEFINE_INSN. */ 321 322static void 323gen_insn (md_rtx_info *info) 324{ 325 struct pattern_stats stats; 326 int i; 327 328 /* See if the pattern for this insn ends with a group of CLOBBERs of (hard) 329 registers or MATCH_SCRATCHes. If so, store away the information for 330 later. */ 331 332 rtx insn = info->def; 333 if (XVEC (insn, 1)) 334 { 335 int has_hard_reg = 0; 336 337 for (i = XVECLEN (insn, 1) - 1; i > 0; i--) 338 { 339 if (GET_CODE (XVECEXP (insn, 1, i)) != CLOBBER) 340 break; 341 342 if (REG_P (XEXP (XVECEXP (insn, 1, i), 0))) 343 has_hard_reg = 1; 344 else if (GET_CODE (XEXP (XVECEXP (insn, 1, i), 0)) != MATCH_SCRATCH) 345 break; 346 } 347 348 if (i != XVECLEN (insn, 1) - 1) 349 { 350 struct clobber_pat *p; 351 struct clobber_ent *link = XNEW (struct clobber_ent); 352 int j; 353 354 link->code_number = info->index; 355 356 /* See if any previous CLOBBER_LIST entry is the same as this 357 one. */ 358 359 for (p = clobber_list; p; p = p->next) 360 { 361 if (p->first_clobber != i + 1 362 || XVECLEN (p->pattern, 1) != XVECLEN (insn, 1)) 363 continue; 364 365 for (j = i + 1; j < XVECLEN (insn, 1); j++) 366 { 367 rtx old_rtx = XEXP (XVECEXP (p->pattern, 1, j), 0); 368 rtx new_rtx = XEXP (XVECEXP (insn, 1, j), 0); 369 370 /* OLD and NEW_INSN are the same if both are to be a SCRATCH 371 of the same mode, 372 or if both are registers of the same mode and number. */ 373 if (! (GET_CODE (old_rtx) == GET_CODE (new_rtx) 374 && GET_MODE (old_rtx) == GET_MODE (new_rtx) 375 && ((GET_CODE (old_rtx) == MATCH_SCRATCH 376 && GET_CODE (new_rtx) == MATCH_SCRATCH) 377 || (REG_P (old_rtx) && REG_P (new_rtx) 378 && REGNO (old_rtx) == REGNO (new_rtx))))) 379 break; 380 } 381 382 if (j == XVECLEN (insn, 1)) 383 break; 384 } 385 386 if (p == 0) 387 { 388 p = XNEW (struct clobber_pat); 389 390 p->insns = 0; 391 p->pattern = insn; 392 p->first_clobber = i + 1; 393 p->next = clobber_list; 394 p->has_hard_reg = has_hard_reg; 395 clobber_list = p; 396 } 397 398 link->next = p->insns; 399 p->insns = link; 400 } 401 } 402 403 /* Don't mention instructions whose names are the null string 404 or begin with '*'. They are in the machine description just 405 to be recognized. */ 406 if (XSTR (insn, 0)[0] == 0 || XSTR (insn, 0)[0] == '*') 407 return; 408 409 printf ("/* %s:%d */\n", info->loc.filename, info->loc.lineno); 410 411 /* Find out how many operands this function has. */ 412 get_pattern_stats (&stats, XVEC (insn, 1)); 413 if (stats.max_dup_opno > stats.max_opno) 414 fatal_at (info->loc, "match_dup operand number has no match_operand"); 415 416 /* Output the function name and argument declarations. */ 417 printf ("rtx\ngen_%s (", XSTR (insn, 0)); 418 if (stats.num_generator_args) 419 for (i = 0; i < stats.num_generator_args; i++) 420 if (i) 421 printf (",\n\trtx operand%d ATTRIBUTE_UNUSED", i); 422 else 423 printf ("rtx operand%d ATTRIBUTE_UNUSED", i); 424 else 425 printf ("void"); 426 printf (")\n"); 427 printf ("{\n"); 428 429 /* Output code to construct and return the rtl for the instruction body. */ 430 431 rtx pattern = add_implicit_parallel (XVEC (insn, 1)); 432 /* ??? This is the traditional behavior, but seems suspect. */ 433 char *used = (XVECLEN (insn, 1) == 1 434 ? NULL 435 : XCNEWVEC (char, stats.num_generator_args)); 436 printf (" return "); 437 gen_exp (pattern, DEFINE_INSN, used, info); 438 printf (";\n}\n\n"); 439 XDELETEVEC (used); 440} 441 442/* Generate the `gen_...' function for a DEFINE_EXPAND. */ 443 444static void 445gen_expand (md_rtx_info *info) 446{ 447 struct pattern_stats stats; 448 int i; 449 char *used; 450 451 rtx expand = info->def; 452 if (strlen (XSTR (expand, 0)) == 0) 453 fatal_at (info->loc, "define_expand lacks a name"); 454 if (XVEC (expand, 1) == 0) 455 fatal_at (info->loc, "define_expand for %s lacks a pattern", 456 XSTR (expand, 0)); 457 458 /* Find out how many operands this function has. */ 459 get_pattern_stats (&stats, XVEC (expand, 1)); 460 if (stats.min_scratch_opno != -1 461 && stats.min_scratch_opno <= MAX (stats.max_opno, stats.max_dup_opno)) 462 fatal_at (info->loc, "define_expand for %s needs to have match_scratch " 463 "numbers above all other operands", XSTR (expand, 0)); 464 465 /* Output the function name and argument declarations. */ 466 printf ("rtx\ngen_%s (", XSTR (expand, 0)); 467 if (stats.num_generator_args) 468 for (i = 0; i < stats.num_generator_args; i++) 469 if (i) 470 printf (",\n\trtx operand%d", i); 471 else 472 printf ("rtx operand%d", i); 473 else 474 printf ("void"); 475 printf (")\n"); 476 printf ("{\n"); 477 478 /* If we don't have any C code to write, only one insn is being written, 479 and no MATCH_DUPs are present, we can just return the desired insn 480 like we do for a DEFINE_INSN. This saves memory. */ 481 if ((XSTR (expand, 3) == 0 || *XSTR (expand, 3) == '\0') 482 && stats.max_opno >= stats.max_dup_opno 483 && XVECLEN (expand, 1) == 1) 484 { 485 printf (" return "); 486 gen_exp (XVECEXP (expand, 1, 0), DEFINE_EXPAND, NULL, info); 487 printf (";\n}\n\n"); 488 return; 489 } 490 491 /* For each operand referred to only with MATCH_DUPs, 492 make a local variable. */ 493 for (i = stats.num_generator_args; i <= stats.max_dup_opno; i++) 494 printf (" rtx operand%d;\n", i); 495 printf (" rtx_insn *_val = 0;\n"); 496 printf (" start_sequence ();\n"); 497 498 /* The fourth operand of DEFINE_EXPAND is some code to be executed 499 before the actual construction. 500 This code expects to refer to `operands' 501 just as the output-code in a DEFINE_INSN does, 502 but here `operands' is an automatic array. 503 So copy the operand values there before executing it. */ 504 if (XSTR (expand, 3) && *XSTR (expand, 3)) 505 { 506 printf (" {\n"); 507 if (stats.num_operand_vars > 0) 508 printf (" rtx operands[%d];\n", stats.num_operand_vars); 509 510 /* Output code to copy the arguments into `operands'. */ 511 for (i = 0; i < stats.num_generator_args; i++) 512 printf (" operands[%d] = operand%d;\n", i, i); 513 514 /* Output the special code to be executed before the sequence 515 is generated. */ 516 optab_pattern p; 517 bool can_fail_p = true; 518 if (find_optab (&p, XSTR (expand, 0))) 519 { 520 gcc_assert (p.op < NUM_OPTABS); 521 if (nofail_optabs[p.op]) 522 can_fail_p = false; 523 } 524 emit_c_code (XSTR (expand, 3), can_fail_p, XSTR (expand, 0)); 525 526 /* Output code to copy the arguments back out of `operands' 527 (unless we aren't going to use them at all). */ 528 if (XVEC (expand, 1) != 0) 529 { 530 for (i = 0; i <= MAX (stats.max_opno, stats.max_dup_opno); i++) 531 { 532 printf (" operand%d = operands[%d];\n", i, i); 533 printf (" (void) operand%d;\n", i); 534 } 535 } 536 printf (" }\n"); 537 } 538 539 used = XCNEWVEC (char, stats.num_operand_vars); 540 gen_emit_seq (XVEC (expand, 1), used, info); 541 XDELETEVEC (used); 542 543 /* Call `get_insns' to extract the list of all the 544 insns emitted within this gen_... function. */ 545 546 printf (" _val = get_insns ();\n"); 547 printf (" end_sequence ();\n"); 548 printf (" return _val;\n}\n\n"); 549} 550 551/* Like gen_expand, but generates insns resulting from splitting SPLIT. */ 552 553static void 554gen_split (md_rtx_info *info) 555{ 556 struct pattern_stats stats; 557 int i; 558 rtx split = info->def; 559 const char *const name = 560 ((GET_CODE (split) == DEFINE_PEEPHOLE2) ? "peephole2" : "split"); 561 const char *unused; 562 char *used; 563 564 if (XVEC (split, 0) == 0) 565 fatal_at (info->loc, "%s lacks a pattern", 566 GET_RTX_NAME (GET_CODE (split))); 567 else if (XVEC (split, 2) == 0) 568 fatal_at (info->loc, "%s lacks a replacement pattern", 569 GET_RTX_NAME (GET_CODE (split))); 570 571 /* Find out how many operands this function has. */ 572 573 get_pattern_stats (&stats, XVEC (split, 2)); 574 unused = (stats.num_operand_vars == 0 ? " ATTRIBUTE_UNUSED" : ""); 575 used = XCNEWVEC (char, stats.num_operand_vars); 576 577 /* Output the prototype, function name and argument declarations. */ 578 if (GET_CODE (split) == DEFINE_PEEPHOLE2) 579 { 580 printf ("extern rtx_insn *gen_%s_%d (rtx_insn *, rtx *);\n", 581 name, info->index); 582 printf ("rtx_insn *\ngen_%s_%d (rtx_insn *curr_insn ATTRIBUTE_UNUSED," 583 " rtx *operands%s)\n", 584 name, info->index, unused); 585 } 586 else 587 { 588 printf ("extern rtx_insn *gen_split_%d (rtx_insn *, rtx *);\n", 589 info->index); 590 printf ("rtx_insn *\ngen_split_%d " 591 "(rtx_insn *curr_insn ATTRIBUTE_UNUSED, rtx *operands%s)\n", 592 info->index, unused); 593 } 594 printf ("{\n"); 595 596 /* Declare all local variables. */ 597 for (i = 0; i < stats.num_operand_vars; i++) 598 printf (" rtx operand%d;\n", i); 599 printf (" rtx_insn *_val = NULL;\n"); 600 601 if (GET_CODE (split) == DEFINE_PEEPHOLE2) 602 output_peephole2_scratches (split); 603 604 const char *fn = info->loc.filename; 605 for (const char *p = fn; *p; p++) 606 if (*p == '/') 607 fn = p + 1; 608 609 printf (" if (dump_file)\n"); 610 printf (" fprintf (dump_file, \"Splitting with gen_%s_%d (%s:%d)\\n\");\n", 611 name, info->index, fn, info->loc.lineno); 612 613 printf (" start_sequence ();\n"); 614 615 /* The fourth operand of DEFINE_SPLIT is some code to be executed 616 before the actual construction. */ 617 618 if (XSTR (split, 3)) 619 emit_c_code (XSTR (split, 3), true, name); 620 621 /* Output code to copy the arguments back out of `operands' */ 622 for (i = 0; i < stats.num_operand_vars; i++) 623 { 624 printf (" operand%d = operands[%d];\n", i, i); 625 printf (" (void) operand%d;\n", i); 626 } 627 628 gen_emit_seq (XVEC (split, 2), used, info); 629 630 /* Call `get_insns' to make a list of all the 631 insns emitted within this gen_... function. */ 632 633 printf (" _val = get_insns ();\n"); 634 printf (" end_sequence ();\n"); 635 printf (" return _val;\n}\n\n"); 636 637 free (used); 638} 639 640/* Write a function, `add_clobbers', that is given a PARALLEL of sufficient 641 size for the insn and an INSN_CODE, and inserts the required CLOBBERs at 642 the end of the vector. */ 643 644static void 645output_add_clobbers (md_rtx_info *info) 646{ 647 struct clobber_pat *clobber; 648 struct clobber_ent *ent; 649 int i; 650 651 printf ("\n\nvoid\nadd_clobbers (rtx pattern ATTRIBUTE_UNUSED, int insn_code_number)\n"); 652 printf ("{\n"); 653 printf (" switch (insn_code_number)\n"); 654 printf (" {\n"); 655 656 for (clobber = clobber_list; clobber; clobber = clobber->next) 657 { 658 for (ent = clobber->insns; ent; ent = ent->next) 659 printf (" case %d:\n", ent->code_number); 660 661 for (i = clobber->first_clobber; i < XVECLEN (clobber->pattern, 1); i++) 662 { 663 printf (" XVECEXP (pattern, 0, %d) = ", i); 664 gen_exp (XVECEXP (clobber->pattern, 1, i), 665 GET_CODE (clobber->pattern), NULL, info); 666 printf (";\n"); 667 } 668 669 printf (" break;\n\n"); 670 } 671 672 printf (" default:\n"); 673 printf (" gcc_unreachable ();\n"); 674 printf (" }\n"); 675 printf ("}\n"); 676} 677 678/* Write a function, `added_clobbers_hard_reg_p' that is given an insn_code 679 number that will have clobbers added (as indicated by `recog') and returns 680 1 if those include a clobber of a hard reg or 0 if all of them just clobber 681 SCRATCH. */ 682 683static void 684output_added_clobbers_hard_reg_p (void) 685{ 686 struct clobber_pat *clobber; 687 struct clobber_ent *ent; 688 int clobber_p, used; 689 690 printf ("\n\nint\nadded_clobbers_hard_reg_p (int insn_code_number)\n"); 691 printf ("{\n"); 692 printf (" switch (insn_code_number)\n"); 693 printf (" {\n"); 694 695 for (clobber_p = 0; clobber_p <= 1; clobber_p++) 696 { 697 used = 0; 698 for (clobber = clobber_list; clobber; clobber = clobber->next) 699 if (clobber->has_hard_reg == clobber_p) 700 for (ent = clobber->insns; ent; ent = ent->next) 701 { 702 printf (" case %d:\n", ent->code_number); 703 used++; 704 } 705 706 if (used) 707 printf (" return %d;\n\n", clobber_p); 708 } 709 710 printf (" default:\n"); 711 printf (" gcc_unreachable ();\n"); 712 printf (" }\n"); 713 printf ("}\n"); 714} 715 716/* Generate code to invoke find_free_register () as needed for the 717 scratch registers used by the peephole2 pattern in SPLIT. */ 718 719static void 720output_peephole2_scratches (rtx split) 721{ 722 int i; 723 int insn_nr = 0; 724 bool first = true; 725 726 for (i = 0; i < XVECLEN (split, 0); i++) 727 { 728 rtx elt = XVECEXP (split, 0, i); 729 if (GET_CODE (elt) == MATCH_SCRATCH) 730 { 731 int last_insn_nr = insn_nr; 732 int cur_insn_nr = insn_nr; 733 int j; 734 for (j = i + 1; j < XVECLEN (split, 0); j++) 735 if (GET_CODE (XVECEXP (split, 0, j)) == MATCH_DUP) 736 { 737 if (XINT (XVECEXP (split, 0, j), 0) == XINT (elt, 0)) 738 last_insn_nr = cur_insn_nr; 739 } 740 else if (GET_CODE (XVECEXP (split, 0, j)) != MATCH_SCRATCH) 741 cur_insn_nr++; 742 743 if (first) 744 { 745 printf (" HARD_REG_SET _regs_allocated;\n"); 746 printf (" CLEAR_HARD_REG_SET (_regs_allocated);\n"); 747 first = false; 748 } 749 750 printf (" if ((operands[%d] = peep2_find_free_register (%d, %d, \"%s\", %smode, &_regs_allocated)) == NULL_RTX)\n\ 751 return NULL;\n", 752 XINT (elt, 0), 753 insn_nr, last_insn_nr, 754 XSTR (elt, 1), 755 GET_MODE_NAME (GET_MODE (elt))); 756 757 } 758 else if (GET_CODE (elt) != MATCH_DUP) 759 insn_nr++; 760 } 761} 762 763/* Print "arg<N>" parameter declarations for each argument N of ONAME. */ 764 765static void 766print_overload_arguments (overloaded_name *oname) 767{ 768 for (unsigned int i = 0; i < oname->arg_types.length (); ++i) 769 printf ("%s%s arg%d", i == 0 ? "" : ", ", oname->arg_types[i], i); 770} 771 772/* Print code to test whether INSTANCE should be chosen, given that 773 argument N of the overload is available as "arg<N>". */ 774 775static void 776print_overload_test (overloaded_instance *instance) 777{ 778 for (unsigned int i = 0; i < instance->arg_values.length (); ++i) 779 printf ("%sarg%d == %s", i == 0 ? " if (" : "\n && ", 780 i, instance->arg_values[i]); 781 printf (")\n"); 782} 783 784/* Emit a maybe_code_for_* function for ONAME. */ 785 786static void 787handle_overloaded_code_for (overloaded_name *oname) 788{ 789 /* Print the function prototype. */ 790 printf ("\ninsn_code\nmaybe_code_for_%s (", oname->name); 791 print_overload_arguments (oname); 792 printf (")\n{\n"); 793 794 /* Use a sequence of "if" statements for each instance. */ 795 for (overloaded_instance *instance = oname->first_instance; 796 instance; instance = instance->next) 797 { 798 print_overload_test (instance); 799 printf (" return CODE_FOR_%s;\n", instance->name); 800 } 801 802 /* Return null if no match was found. */ 803 printf (" return CODE_FOR_nothing;\n}\n"); 804} 805 806/* Emit a maybe_gen_* function for ONAME. */ 807 808static void 809handle_overloaded_gen (overloaded_name *oname) 810{ 811 unsigned HOST_WIDE_INT seen = 0; 812 /* All patterns must have the same number of operands. */ 813 for (overloaded_instance *instance = oname->first_instance->next; 814 instance; instance = instance->next) 815 { 816 pattern_stats stats; 817 get_pattern_stats (&stats, XVEC (instance->insn, 1)); 818 unsigned HOST_WIDE_INT mask 819 = HOST_WIDE_INT_1U << stats.num_generator_args; 820 if (seen & mask) 821 continue; 822 823 seen |= mask; 824 825 /* Print the function prototype. */ 826 printf ("\nrtx\nmaybe_gen_%s (", oname->name); 827 print_overload_arguments (oname); 828 for (int i = 0; i < stats.num_generator_args; ++i) 829 printf (", rtx x%d", i); 830 printf (")\n{\n"); 831 832 /* Use maybe_code_for_*, instead of duplicating the selection 833 logic here. */ 834 printf (" insn_code code = maybe_code_for_%s (", oname->name); 835 for (unsigned int i = 0; i < oname->arg_types.length (); ++i) 836 printf ("%sarg%d", i == 0 ? "" : ", ", i); 837 printf (");\n" 838 " if (code != CODE_FOR_nothing)\n" 839 " {\n" 840 " gcc_assert (insn_data[code].n_generator_args == %d);\n" 841 " return GEN_FCN (code) (", stats.num_generator_args); 842 for (int i = 0; i < stats.num_generator_args; ++i) 843 printf ("%sx%d", i == 0 ? "" : ", ", i); 844 printf (");\n" 845 " }\n" 846 " else\n" 847 " return NULL_RTX;\n" 848 "}\n"); 849 } 850} 851 852int 853main (int argc, const char **argv) 854{ 855 progname = "genemit"; 856 857 if (!init_rtx_reader_args (argc, argv)) 858 return (FATAL_EXIT_CODE); 859 860#define DEF_INTERNAL_OPTAB_FN(NAME, FLAGS, OPTAB, TYPE) \ 861 nofail_optabs[OPTAB##_optab] = true; 862#include "internal-fn.def" 863 864 /* Assign sequential codes to all entries in the machine description 865 in parallel with the tables in insn-output.c. */ 866 867 printf ("/* Generated automatically by the program `genemit'\n\ 868from the machine description file `md'. */\n\n"); 869 870 printf ("#define IN_TARGET_CODE 1\n"); 871 printf ("#include \"config.h\"\n"); 872 printf ("#include \"system.h\"\n"); 873 printf ("#include \"coretypes.h\"\n"); 874 printf ("#include \"backend.h\"\n"); 875 printf ("#include \"predict.h\"\n"); 876 printf ("#include \"tree.h\"\n"); 877 printf ("#include \"rtl.h\"\n"); 878 printf ("#include \"alias.h\"\n"); 879 printf ("#include \"varasm.h\"\n"); 880 printf ("#include \"stor-layout.h\"\n"); 881 printf ("#include \"calls.h\"\n"); 882 printf ("#include \"memmodel.h\"\n"); 883 printf ("#include \"tm_p.h\"\n"); 884 printf ("#include \"flags.h\"\n"); 885 printf ("#include \"insn-config.h\"\n"); 886 printf ("#include \"expmed.h\"\n"); 887 printf ("#include \"dojump.h\"\n"); 888 printf ("#include \"explow.h\"\n"); 889 printf ("#include \"emit-rtl.h\"\n"); 890 printf ("#include \"stmt.h\"\n"); 891 printf ("#include \"expr.h\"\n"); 892 printf ("#include \"insn-codes.h\"\n"); 893 printf ("#include \"optabs.h\"\n"); 894 printf ("#include \"dfp.h\"\n"); 895 printf ("#include \"output.h\"\n"); 896 printf ("#include \"recog.h\"\n"); 897 printf ("#include \"df.h\"\n"); 898 printf ("#include \"resource.h\"\n"); 899 printf ("#include \"reload.h\"\n"); 900 printf ("#include \"diagnostic-core.h\"\n"); 901 printf ("#include \"regs.h\"\n"); 902 printf ("#include \"tm-constrs.h\"\n"); 903 printf ("#include \"ggc.h\"\n"); 904 printf ("#include \"target.h\"\n\n"); 905 906 /* Read the machine description. */ 907 908 md_rtx_info info; 909 while (read_md_rtx (&info)) 910 switch (GET_CODE (info.def)) 911 { 912 case DEFINE_INSN: 913 gen_insn (&info); 914 break; 915 916 case DEFINE_EXPAND: 917 printf ("/* %s:%d */\n", info.loc.filename, info.loc.lineno); 918 gen_expand (&info); 919 break; 920 921 case DEFINE_SPLIT: 922 printf ("/* %s:%d */\n", info.loc.filename, info.loc.lineno); 923 gen_split (&info); 924 break; 925 926 case DEFINE_PEEPHOLE2: 927 printf ("/* %s:%d */\n", info.loc.filename, info.loc.lineno); 928 gen_split (&info); 929 break; 930 931 default: 932 break; 933 } 934 935 /* Write out the routines to add CLOBBERs to a pattern and say whether they 936 clobber a hard reg. */ 937 output_add_clobbers (&info); 938 output_added_clobbers_hard_reg_p (); 939 940 for (overloaded_name *oname = rtx_reader_ptr->get_overloads (); 941 oname; oname = oname->next) 942 { 943 handle_overloaded_code_for (oname); 944 handle_overloaded_gen (oname); 945 } 946 947 fflush (stdout); 948 return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE); 949} 950