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