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