1/* Generate code from to output assembler insns as recognized from rtl. 2 Copyright (C) 1987, 1988, 1992, 1994, 1995, 1997, 1998, 1999, 2000 3 Free Software Foundation, Inc. 4 5This file is part of GCC. 6 7GCC is free software; you can redistribute it and/or modify it under 8the terms of the GNU General Public License as published by the Free 9Software Foundation; either version 2, or (at your option) any later 10version. 11 12GCC is distributed in the hope that it will be useful, but WITHOUT ANY 13WARRANTY; without even the implied warranty of MERCHANTABILITY or 14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15for more details. 16 17You should have received a copy of the GNU General Public License 18along with GCC; see the file COPYING. If not, write to the Free 19Software Foundation, 59 Temple Place - Suite 330, Boston, MA 2002111-1307, USA. */ 21 22 23/* This program reads the machine description for the compiler target machine 24 and produces a file containing these things: 25 26 1. An array of `struct insn_data', which is indexed by insn code number, 27 which contains: 28 29 a. `name' is the name for that pattern. Nameless patterns are 30 given a name. 31 32 b. `output' hold either the output template, an array of output 33 templates, or an output function. 34 35 c. `genfun' is the function to generate a body for that pattern, 36 given operands as arguments. 37 38 d. `n_operands' is the number of distinct operands in the pattern 39 for that insn, 40 41 e. `n_dups' is the number of match_dup's that appear in the insn's 42 pattern. This says how many elements of `recog_data.dup_loc' are 43 significant after an insn has been recognized. 44 45 f. `n_alternatives' is the number of alternatives in the constraints 46 of each pattern. 47 48 g. `output_format' tells what type of thing `output' is. 49 50 h. `operand' is the base of an array of operand data for the insn. 51 52 2. An array of `struct insn_operand data', used by `operand' above. 53 54 a. `predicate', an int-valued function, is the match_operand predicate 55 for this operand. 56 57 b. `constraint' is the constraint for this operand. This exists 58 only if register constraints appear in match_operand rtx's. 59 60 c. `address_p' indicates that the operand appears within ADDRESS 61 rtx's. This exists only if there are *no* register constraints 62 in the match_operand rtx's. 63 64 d. `mode' is the machine mode that that operand is supposed to have. 65 66 e. `strict_low', is nonzero for operands contained in a STRICT_LOW_PART. 67 68 f. `eliminable', is nonzero for operands that are matched normally by 69 MATCH_OPERAND; it is zero for operands that should not be changed during 70 register elimination such as MATCH_OPERATORs. 71 72 The code number of an insn is simply its position in the machine 73 description; code numbers are assigned sequentially to entries in 74 the description, starting with code number 0. 75 76 Thus, the following entry in the machine description 77 78 (define_insn "clrdf" 79 [(set (match_operand:DF 0 "general_operand" "") 80 (const_int 0))] 81 "" 82 "clrd %0") 83 84 assuming it is the 25th entry present, would cause 85 insn_data[24].template to be "clrd %0", and 86 insn_data[24].n_operands to be 1. */ 87 88#include "hconfig.h" 89#include "system.h" 90#include "rtl.h" 91#include "errors.h" 92#include "gensupport.h" 93 94/* No instruction can have more operands than this. Sorry for this 95 arbitrary limit, but what machine will have an instruction with 96 this many operands? */ 97 98#define MAX_MAX_OPERANDS 40 99 100static int n_occurrences PARAMS ((int, const char *)); 101static const char *strip_whitespace PARAMS ((const char *)); 102 103/* insns in the machine description are assigned sequential code numbers 104 that are used by insn-recog.c (produced by genrecog) to communicate 105 to insn-output.c (produced by this program). */ 106 107static int next_code_number; 108 109/* This counts all definitions in the md file, 110 for the sake of error messages. */ 111 112static int next_index_number; 113 114/* This counts all operands used in the md file. The first is null. */ 115 116static int next_operand_number = 1; 117 118/* Record in this chain all information about the operands we will output. */ 119 120struct operand_data 121{ 122 struct operand_data *next; 123 int index; 124 const char *predicate; 125 const char *constraint; 126 enum machine_mode mode; 127 unsigned char n_alternatives; 128 char address_p; 129 char strict_low; 130 char eliminable; 131 char seen; 132}; 133 134/* Begin with a null operand at index 0. */ 135 136static struct operand_data null_operand = 137{ 138 0, 0, "", "", VOIDmode, 0, 0, 0, 0, 0 139}; 140 141static struct operand_data *odata = &null_operand; 142static struct operand_data **odata_end = &null_operand.next; 143 144/* Must match the constants in recog.h. */ 145 146#define INSN_OUTPUT_FORMAT_NONE 0 /* abort */ 147#define INSN_OUTPUT_FORMAT_SINGLE 1 /* const char * */ 148#define INSN_OUTPUT_FORMAT_MULTI 2 /* const char * const * */ 149#define INSN_OUTPUT_FORMAT_FUNCTION 3 /* const char * (*)(...) */ 150 151/* Record in this chain all information that we will output, 152 associated with the code number of the insn. */ 153 154struct data 155{ 156 struct data *next; 157 const char *name; 158 const char *template; 159 int code_number; 160 int index_number; 161 int lineno; 162 int n_operands; /* Number of operands this insn recognizes */ 163 int n_dups; /* Number times match_dup appears in pattern */ 164 int n_alternatives; /* Number of alternatives in each constraint */ 165 int operand_number; /* Operand index in the big array. */ 166 int output_format; /* INSN_OUTPUT_FORMAT_*. */ 167 struct operand_data operand[MAX_MAX_OPERANDS]; 168}; 169 170/* This variable points to the first link in the insn chain. */ 171 172static struct data *idata, **idata_end = &idata; 173 174static void output_prologue PARAMS ((void)); 175static void output_predicate_decls PARAMS ((void)); 176static void output_operand_data PARAMS ((void)); 177static void output_insn_data PARAMS ((void)); 178static void output_get_insn_name PARAMS ((void)); 179static void scan_operands PARAMS ((struct data *, rtx, int, int)); 180static int compare_operands PARAMS ((struct operand_data *, 181 struct operand_data *)); 182static void place_operands PARAMS ((struct data *)); 183static void process_template PARAMS ((struct data *, const char *)); 184static void validate_insn_alternatives PARAMS ((struct data *)); 185static void validate_insn_operands PARAMS ((struct data *)); 186static void gen_insn PARAMS ((rtx, int)); 187static void gen_peephole PARAMS ((rtx, int)); 188static void gen_expand PARAMS ((rtx, int)); 189static void gen_split PARAMS ((rtx, int)); 190 191const char * 192get_insn_name (index) 193 int index; 194{ 195 static char buf[100]; 196 197 struct data *i, *last_named = NULL; 198 for (i = idata; i ; i = i->next) 199 { 200 if (i->index_number == index) 201 return i->name; 202 if (i->name) 203 last_named = i; 204 } 205 206 if (last_named) 207 sprintf(buf, "%s+%d", last_named->name, index - last_named->index_number); 208 else 209 sprintf(buf, "insn %d", index); 210 211 return buf; 212} 213 214static void 215output_prologue () 216{ 217 printf ("/* Generated automatically by the program `genoutput'\n\ 218 from the machine description file `md'. */\n\n"); 219 220 printf ("#include \"config.h\"\n"); 221 printf ("#include \"system.h\"\n"); 222 printf ("#include \"flags.h\"\n"); 223 printf ("#include \"ggc.h\"\n"); 224 printf ("#include \"rtl.h\"\n"); 225 printf ("#include \"expr.h\"\n"); 226 printf ("#include \"insn-codes.h\"\n"); 227 printf ("#include \"tm_p.h\"\n"); 228 printf ("#include \"function.h\"\n"); 229 printf ("#include \"regs.h\"\n"); 230 printf ("#include \"hard-reg-set.h\"\n"); 231 printf ("#include \"real.h\"\n"); 232 printf ("#include \"insn-config.h\"\n\n"); 233 printf ("#include \"conditions.h\"\n"); 234 printf ("#include \"insn-attr.h\"\n\n"); 235 printf ("#include \"recog.h\"\n\n"); 236 printf ("#include \"toplev.h\"\n"); 237 printf ("#include \"output.h\"\n"); 238} 239 240 241/* We need to define all predicates used. Keep a list of those we 242 have defined so far. There normally aren't very many predicates 243 used, so a linked list should be fast enough. */ 244struct predicate { const char *name; struct predicate *next; }; 245 246static void 247output_predicate_decls () 248{ 249 struct predicate *predicates = 0; 250 struct operand_data *d; 251 struct predicate *p, *next; 252 253 for (d = odata; d; d = d->next) 254 if (d->predicate && d->predicate[0]) 255 { 256 for (p = predicates; p; p = p->next) 257 if (strcmp (p->name, d->predicate) == 0) 258 break; 259 260 if (p == 0) 261 { 262 printf ("extern int %s PARAMS ((rtx, enum machine_mode));\n", 263 d->predicate); 264 p = (struct predicate *) xmalloc (sizeof (struct predicate)); 265 p->name = d->predicate; 266 p->next = predicates; 267 predicates = p; 268 } 269 } 270 271 printf ("\n\n"); 272 for (p = predicates; p; p = next) 273 { 274 next = p->next; 275 free (p); 276 } 277} 278 279static void 280output_operand_data () 281{ 282 struct operand_data *d; 283 284 printf ("\nstatic const struct insn_operand_data operand_data[] = \n{\n"); 285 286 for (d = odata; d; d = d->next) 287 { 288 printf (" {\n"); 289 290 printf (" %s,\n", 291 d->predicate && d->predicate[0] ? d->predicate : "0"); 292 293 printf (" \"%s\",\n", d->constraint ? d->constraint : ""); 294 295 printf (" %smode,\n", GET_MODE_NAME (d->mode)); 296 297 printf (" %d,\n", d->strict_low); 298 299 printf (" %d\n", d->eliminable); 300 301 printf(" },\n"); 302 } 303 printf("};\n\n\n"); 304} 305 306static void 307output_insn_data () 308{ 309 struct data *d; 310 int name_offset = 0; 311 int next_name_offset; 312 const char * last_name = 0; 313 const char * next_name = 0; 314 struct data *n; 315 316 for (n = idata, next_name_offset = 1; n; n = n->next, next_name_offset++) 317 if (n->name) 318 { 319 next_name = n->name; 320 break; 321 } 322 323 printf ("\nconst struct insn_data insn_data[] = \n{\n"); 324 325 for (d = idata; d; d = d->next) 326 { 327 printf (" {\n"); 328 329 if (d->name) 330 { 331 printf (" \"%s\",\n", d->name); 332 name_offset = 0; 333 last_name = d->name; 334 next_name = 0; 335 for (n = d->next, next_name_offset = 1; n; 336 n = n->next, next_name_offset++) 337 { 338 if (n->name) 339 { 340 next_name = n->name; 341 break; 342 } 343 } 344 } 345 else 346 { 347 name_offset++; 348 if (next_name && (last_name == 0 349 || name_offset > next_name_offset / 2)) 350 printf (" \"%s-%d\",\n", next_name, 351 next_name_offset - name_offset); 352 else 353 printf (" \"%s+%d\",\n", last_name, name_offset); 354 } 355 356 switch (d->output_format) 357 { 358 case INSN_OUTPUT_FORMAT_NONE: 359 printf (" 0,\n"); 360 break; 361 case INSN_OUTPUT_FORMAT_SINGLE: 362 { 363 const char *p = d->template; 364 char prev = 0; 365 366 printf (" \""); 367 while (*p) 368 { 369 if (IS_VSPACE (*p) && prev != '\\') 370 { 371 /* Preserve two consecutive \n's or \r's, but treat \r\n 372 as a single newline. */ 373 if (*p == '\n' && prev != '\r') 374 printf ("\\n\\\n"); 375 } 376 else 377 putchar (*p); 378 prev = *p; 379 ++p; 380 } 381 printf ("\",\n"); 382 } 383 break; 384 case INSN_OUTPUT_FORMAT_MULTI: 385 case INSN_OUTPUT_FORMAT_FUNCTION: 386 printf (" (const PTR) output_%d,\n", d->code_number); 387 break; 388 default: 389 abort (); 390 } 391 392 if (d->name && d->name[0] != '*') 393 printf (" (insn_gen_fn) gen_%s,\n", d->name); 394 else 395 printf (" 0,\n"); 396 397 printf (" &operand_data[%d],\n", d->operand_number); 398 printf (" %d,\n", d->n_operands); 399 printf (" %d,\n", d->n_dups); 400 printf (" %d,\n", d->n_alternatives); 401 printf (" %d\n", d->output_format); 402 403 printf(" },\n"); 404 } 405 printf ("};\n\n\n"); 406} 407 408static void 409output_get_insn_name () 410{ 411 printf ("const char *\n"); 412 printf ("get_insn_name (code)\n"); 413 printf (" int code;\n"); 414 printf ("{\n"); 415 printf (" return insn_data[code].name;\n"); 416 printf ("}\n"); 417} 418 419 420/* Stores in max_opno the largest operand number present in `part', if 421 that is larger than the previous value of max_opno, and the rest of 422 the operand data into `d->operand[i]'. 423 424 THIS_ADDRESS_P is nonzero if the containing rtx was an ADDRESS. 425 THIS_STRICT_LOW is nonzero if the containing rtx was a STRICT_LOW_PART. */ 426 427static int max_opno; 428static int num_dups; 429 430static void 431scan_operands (d, part, this_address_p, this_strict_low) 432 struct data *d; 433 rtx part; 434 int this_address_p; 435 int this_strict_low; 436{ 437 int i, j; 438 const char *format_ptr; 439 int opno; 440 441 if (part == 0) 442 return; 443 444 switch (GET_CODE (part)) 445 { 446 case MATCH_OPERAND: 447 opno = XINT (part, 0); 448 if (opno > max_opno) 449 max_opno = opno; 450 if (max_opno >= MAX_MAX_OPERANDS) 451 { 452 message_with_line (d->lineno, 453 "maximum number of operands exceeded"); 454 have_error = 1; 455 return; 456 } 457 if (d->operand[opno].seen) 458 { 459 message_with_line (d->lineno, 460 "repeated operand number %d\n", opno); 461 have_error = 1; 462 } 463 464 d->operand[opno].seen = 1; 465 d->operand[opno].mode = GET_MODE (part); 466 d->operand[opno].strict_low = this_strict_low; 467 d->operand[opno].predicate = XSTR (part, 1); 468 d->operand[opno].constraint = strip_whitespace (XSTR (part, 2)); 469 d->operand[opno].n_alternatives 470 = n_occurrences (',', d->operand[opno].constraint) + 1; 471 d->operand[opno].address_p = this_address_p; 472 d->operand[opno].eliminable = 1; 473 return; 474 475 case MATCH_SCRATCH: 476 opno = XINT (part, 0); 477 if (opno > max_opno) 478 max_opno = opno; 479 if (max_opno >= MAX_MAX_OPERANDS) 480 { 481 message_with_line (d->lineno, 482 "maximum number of operands exceeded"); 483 have_error = 1; 484 return; 485 } 486 if (d->operand[opno].seen) 487 { 488 message_with_line (d->lineno, 489 "repeated operand number %d\n", opno); 490 have_error = 1; 491 } 492 493 d->operand[opno].seen = 1; 494 d->operand[opno].mode = GET_MODE (part); 495 d->operand[opno].strict_low = 0; 496 d->operand[opno].predicate = "scratch_operand"; 497 d->operand[opno].constraint = strip_whitespace (XSTR (part, 1)); 498 d->operand[opno].n_alternatives 499 = n_occurrences (',', d->operand[opno].constraint) + 1; 500 d->operand[opno].address_p = 0; 501 d->operand[opno].eliminable = 0; 502 return; 503 504 case MATCH_OPERATOR: 505 case MATCH_PARALLEL: 506 opno = XINT (part, 0); 507 if (opno > max_opno) 508 max_opno = opno; 509 if (max_opno >= MAX_MAX_OPERANDS) 510 { 511 message_with_line (d->lineno, 512 "maximum number of operands exceeded"); 513 have_error = 1; 514 return; 515 } 516 if (d->operand[opno].seen) 517 { 518 message_with_line (d->lineno, 519 "repeated operand number %d\n", opno); 520 have_error = 1; 521 } 522 523 d->operand[opno].seen = 1; 524 d->operand[opno].mode = GET_MODE (part); 525 d->operand[opno].strict_low = 0; 526 d->operand[opno].predicate = XSTR (part, 1); 527 d->operand[opno].constraint = 0; 528 d->operand[opno].address_p = 0; 529 d->operand[opno].eliminable = 0; 530 for (i = 0; i < XVECLEN (part, 2); i++) 531 scan_operands (d, XVECEXP (part, 2, i), 0, 0); 532 return; 533 534 case MATCH_DUP: 535 case MATCH_OP_DUP: 536 case MATCH_PAR_DUP: 537 ++num_dups; 538 break; 539 540 case ADDRESS: 541 scan_operands (d, XEXP (part, 0), 1, 0); 542 return; 543 544 case STRICT_LOW_PART: 545 scan_operands (d, XEXP (part, 0), 0, 1); 546 return; 547 548 default: 549 break; 550 } 551 552 format_ptr = GET_RTX_FORMAT (GET_CODE (part)); 553 554 for (i = 0; i < GET_RTX_LENGTH (GET_CODE (part)); i++) 555 switch (*format_ptr++) 556 { 557 case 'e': 558 case 'u': 559 scan_operands (d, XEXP (part, i), 0, 0); 560 break; 561 case 'E': 562 if (XVEC (part, i) != NULL) 563 for (j = 0; j < XVECLEN (part, i); j++) 564 scan_operands (d, XVECEXP (part, i, j), 0, 0); 565 break; 566 } 567} 568 569/* Compare two operands for content equality. */ 570 571static int 572compare_operands (d0, d1) 573 struct operand_data *d0, *d1; 574{ 575 const char *p0, *p1; 576 577 p0 = d0->predicate; 578 if (!p0) 579 p0 = ""; 580 p1 = d1->predicate; 581 if (!p1) 582 p1 = ""; 583 if (strcmp (p0, p1) != 0) 584 return 0; 585 586 p0 = d0->constraint; 587 if (!p0) 588 p0 = ""; 589 p1 = d1->constraint; 590 if (!p1) 591 p1 = ""; 592 if (strcmp (p0, p1) != 0) 593 return 0; 594 595 if (d0->mode != d1->mode) 596 return 0; 597 598 if (d0->strict_low != d1->strict_low) 599 return 0; 600 601 if (d0->eliminable != d1->eliminable) 602 return 0; 603 604 return 1; 605} 606 607/* Scan the list of operands we've already committed to output and either 608 find a subsequence that is the same, or allocate a new one at the end. */ 609 610static void 611place_operands (d) 612 struct data *d; 613{ 614 struct operand_data *od, *od2; 615 int i; 616 617 if (d->n_operands == 0) 618 { 619 d->operand_number = 0; 620 return; 621 } 622 623 /* Brute force substring search. */ 624 for (od = odata, i = 0; od; od = od->next, i = 0) 625 if (compare_operands (od, &d->operand[0])) 626 { 627 od2 = od->next; 628 i = 1; 629 while (1) 630 { 631 if (i == d->n_operands) 632 goto full_match; 633 if (od2 == NULL) 634 goto partial_match; 635 if (! compare_operands (od2, &d->operand[i])) 636 break; 637 ++i, od2 = od2->next; 638 } 639 } 640 641 /* Either partial match at the end of the list, or no match. In either 642 case, we tack on what operands are remaining to the end of the list. */ 643 partial_match: 644 d->operand_number = next_operand_number - i; 645 for (; i < d->n_operands; ++i) 646 { 647 od2 = &d->operand[i]; 648 *odata_end = od2; 649 odata_end = &od2->next; 650 od2->index = next_operand_number++; 651 } 652 *odata_end = NULL; 653 return; 654 655 full_match: 656 d->operand_number = od->index; 657 return; 658} 659 660 661/* Process an assembler template from a define_insn or a define_peephole. 662 It is either the assembler code template, a list of assembler code 663 templates, or C code to generate the assembler code template. */ 664 665static void 666process_template (d, template) 667 struct data *d; 668 const char *template; 669{ 670 const char *cp; 671 int i; 672 673 /* Templates starting with * contain straight code to be run. */ 674 if (template[0] == '*') 675 { 676 d->template = 0; 677 d->output_format = INSN_OUTPUT_FORMAT_FUNCTION; 678 679 printf ("\nstatic const char *output_%d PARAMS ((rtx *, rtx));\n", 680 d->code_number); 681 puts ("\nstatic const char *"); 682 printf ("output_%d (operands, insn)\n", d->code_number); 683 puts (" rtx *operands ATTRIBUTE_UNUSED;"); 684 puts (" rtx insn ATTRIBUTE_UNUSED;"); 685 puts ("{"); 686 687 puts (template + 1); 688 puts ("}"); 689 } 690 691 /* If the assembler code template starts with a @ it is a newline-separated 692 list of assembler code templates, one for each alternative. */ 693 else if (template[0] == '@') 694 { 695 d->template = 0; 696 d->output_format = INSN_OUTPUT_FORMAT_MULTI; 697 698 printf ("\nstatic const char * const output_%d[] = {\n", d->code_number); 699 700 for (i = 0, cp = &template[1]; *cp; ) 701 { 702 while (ISSPACE (*cp)) 703 cp++; 704 705 printf (" \""); 706 while (!IS_VSPACE (*cp) && *cp != '\0') 707 { 708 putchar (*cp); 709 cp++; 710 } 711 712 printf ("\",\n"); 713 i++; 714 } 715 if (i == 1) 716 message_with_line (d->lineno, 717 "'@' is redundant for output template with single alternative"); 718 if (i != d->n_alternatives) 719 { 720 message_with_line (d->lineno, 721 "wrong number of alternatives in the output template"); 722 have_error = 1; 723 } 724 725 printf ("};\n"); 726 } 727 else 728 { 729 d->template = template; 730 d->output_format = INSN_OUTPUT_FORMAT_SINGLE; 731 } 732} 733 734/* Check insn D for consistency in number of constraint alternatives. */ 735 736static void 737validate_insn_alternatives (d) 738 struct data *d; 739{ 740 int n = 0, start; 741 742 /* Make sure all the operands have the same number of alternatives 743 in their constraints. Let N be that number. */ 744 for (start = 0; start < d->n_operands; start++) 745 if (d->operand[start].n_alternatives > 0) 746 { 747 if (n == 0) 748 n = d->operand[start].n_alternatives; 749 else if (n != d->operand[start].n_alternatives) 750 { 751 message_with_line (d->lineno, 752 "wrong number of alternatives in operand %d", 753 start); 754 have_error = 1; 755 } 756 } 757 758 /* Record the insn's overall number of alternatives. */ 759 d->n_alternatives = n; 760} 761 762/* Verify that there are no gaps in operand numbers for INSNs. */ 763 764static void 765validate_insn_operands (d) 766 struct data *d; 767{ 768 int i; 769 770 for (i = 0; i < d->n_operands; ++i) 771 if (d->operand[i].seen == 0) 772 { 773 message_with_line (d->lineno, "missing operand %d", i); 774 have_error = 1; 775 } 776} 777 778/* Look at a define_insn just read. Assign its code number. Record 779 on idata the template and the number of arguments. If the insn has 780 a hairy output action, output a function for now. */ 781 782static void 783gen_insn (insn, lineno) 784 rtx insn; 785 int lineno; 786{ 787 struct data *d = (struct data *) xmalloc (sizeof (struct data)); 788 int i; 789 790 d->code_number = next_code_number; 791 d->index_number = next_index_number; 792 d->lineno = lineno; 793 if (XSTR (insn, 0)[0]) 794 d->name = XSTR (insn, 0); 795 else 796 d->name = 0; 797 798 /* Build up the list in the same order as the insns are seen 799 in the machine description. */ 800 d->next = 0; 801 *idata_end = d; 802 idata_end = &d->next; 803 804 max_opno = -1; 805 num_dups = 0; 806 memset (d->operand, 0, sizeof (d->operand)); 807 808 for (i = 0; i < XVECLEN (insn, 1); i++) 809 scan_operands (d, XVECEXP (insn, 1, i), 0, 0); 810 811 d->n_operands = max_opno + 1; 812 d->n_dups = num_dups; 813 814 validate_insn_operands (d); 815 validate_insn_alternatives (d); 816 place_operands (d); 817 process_template (d, XTMPL (insn, 3)); 818} 819 820/* Look at a define_peephole just read. Assign its code number. 821 Record on idata the template and the number of arguments. 822 If the insn has a hairy output action, output it now. */ 823 824static void 825gen_peephole (peep, lineno) 826 rtx peep; 827 int lineno; 828{ 829 struct data *d = (struct data *) xmalloc (sizeof (struct data)); 830 int i; 831 832 d->code_number = next_code_number; 833 d->index_number = next_index_number; 834 d->lineno = lineno; 835 d->name = 0; 836 837 /* Build up the list in the same order as the insns are seen 838 in the machine description. */ 839 d->next = 0; 840 *idata_end = d; 841 idata_end = &d->next; 842 843 max_opno = -1; 844 num_dups = 0; 845 memset (d->operand, 0, sizeof (d->operand)); 846 847 /* Get the number of operands by scanning all the patterns of the 848 peephole optimizer. But ignore all the rest of the information 849 thus obtained. */ 850 for (i = 0; i < XVECLEN (peep, 0); i++) 851 scan_operands (d, XVECEXP (peep, 0, i), 0, 0); 852 853 d->n_operands = max_opno + 1; 854 d->n_dups = 0; 855 856 validate_insn_alternatives (d); 857 place_operands (d); 858 process_template (d, XTMPL (peep, 2)); 859} 860 861/* Process a define_expand just read. Assign its code number, 862 only for the purposes of `insn_gen_function'. */ 863 864static void 865gen_expand (insn, lineno) 866 rtx insn; 867 int lineno; 868{ 869 struct data *d = (struct data *) xmalloc (sizeof (struct data)); 870 int i; 871 872 d->code_number = next_code_number; 873 d->index_number = next_index_number; 874 d->lineno = lineno; 875 if (XSTR (insn, 0)[0]) 876 d->name = XSTR (insn, 0); 877 else 878 d->name = 0; 879 880 /* Build up the list in the same order as the insns are seen 881 in the machine description. */ 882 d->next = 0; 883 *idata_end = d; 884 idata_end = &d->next; 885 886 max_opno = -1; 887 num_dups = 0; 888 memset (d->operand, 0, sizeof (d->operand)); 889 890 /* Scan the operands to get the specified predicates and modes, 891 since expand_binop needs to know them. */ 892 893 if (XVEC (insn, 1)) 894 for (i = 0; i < XVECLEN (insn, 1); i++) 895 scan_operands (d, XVECEXP (insn, 1, i), 0, 0); 896 897 d->n_operands = max_opno + 1; 898 d->n_dups = num_dups; 899 d->template = 0; 900 d->output_format = INSN_OUTPUT_FORMAT_NONE; 901 902 validate_insn_alternatives (d); 903 place_operands (d); 904} 905 906/* Process a define_split just read. Assign its code number, 907 only for reasons of consistency and to simplify genrecog. */ 908 909static void 910gen_split (split, lineno) 911 rtx split; 912 int lineno; 913{ 914 struct data *d = (struct data *) xmalloc (sizeof (struct data)); 915 int i; 916 917 d->code_number = next_code_number; 918 d->index_number = next_index_number; 919 d->lineno = lineno; 920 d->name = 0; 921 922 /* Build up the list in the same order as the insns are seen 923 in the machine description. */ 924 d->next = 0; 925 *idata_end = d; 926 idata_end = &d->next; 927 928 max_opno = -1; 929 num_dups = 0; 930 memset (d->operand, 0, sizeof (d->operand)); 931 932 /* Get the number of operands by scanning all the patterns of the 933 split patterns. But ignore all the rest of the information thus 934 obtained. */ 935 for (i = 0; i < XVECLEN (split, 0); i++) 936 scan_operands (d, XVECEXP (split, 0, i), 0, 0); 937 938 d->n_operands = max_opno + 1; 939 d->n_dups = 0; 940 d->n_alternatives = 0; 941 d->template = 0; 942 d->output_format = INSN_OUTPUT_FORMAT_NONE; 943 944 place_operands (d); 945} 946 947extern int main PARAMS ((int, char **)); 948 949int 950main (argc, argv) 951 int argc; 952 char **argv; 953{ 954 rtx desc; 955 956 progname = "genoutput"; 957 958 if (argc <= 1) 959 fatal ("no input file name"); 960 961 if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE) 962 return (FATAL_EXIT_CODE); 963 964 output_prologue (); 965 next_code_number = 0; 966 next_index_number = 0; 967 968 /* Read the machine description. */ 969 970 while (1) 971 { 972 int line_no; 973 974 desc = read_md_rtx (&line_no, &next_code_number); 975 if (desc == NULL) 976 break; 977 978 if (GET_CODE (desc) == DEFINE_INSN) 979 gen_insn (desc, line_no); 980 if (GET_CODE (desc) == DEFINE_PEEPHOLE) 981 gen_peephole (desc, line_no); 982 if (GET_CODE (desc) == DEFINE_EXPAND) 983 gen_expand (desc, line_no); 984 if (GET_CODE (desc) == DEFINE_SPLIT 985 || GET_CODE (desc) == DEFINE_PEEPHOLE2) 986 gen_split (desc, line_no); 987 next_index_number++; 988 } 989 990 printf("\n\n"); 991 output_predicate_decls (); 992 output_operand_data (); 993 output_insn_data (); 994 output_get_insn_name (); 995 996 fflush (stdout); 997 return (ferror (stdout) != 0 || have_error 998 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE); 999} 1000 1001/* Return the number of occurrences of character C in string S or 1002 -1 if S is the null string. */ 1003 1004static int 1005n_occurrences (c, s) 1006 int c; 1007 const char *s; 1008{ 1009 int n = 0; 1010 1011 if (s == 0 || *s == '\0') 1012 return -1; 1013 1014 while (*s) 1015 n += (*s++ == c); 1016 1017 return n; 1018} 1019 1020/* Remove whitespace in `s' by moving up characters until the end. 1021 Return a new string. */ 1022 1023static const char * 1024strip_whitespace (s) 1025 const char *s; 1026{ 1027 char *p, *q; 1028 char ch; 1029 1030 if (s == 0) 1031 return 0; 1032 1033 p = q = xmalloc (strlen (s) + 1); 1034 while ((ch = *s++) != '\0') 1035 if (! ISSPACE (ch)) 1036 *p++ = ch; 1037 1038 *p = '\0'; 1039 return q; 1040} 1041