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