|
|
1.1 ! root 1: /* Generate code from to output assembler insns as recognized from rtl. ! 2: Copyright (C) 1987, 1988, 1992 Free Software Foundation, Inc. ! 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> ! 93: #include "hconfig.h" ! 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 (); ! 110: extern rtx read_rtx (); ! 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; ! 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; ! 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: ! 240: for (n = insn_data, next = 0; n; n = n->next, next++) ! 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: ! 505: case MATCH_PAR_DUP: ! 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; ! 855: d->n_alternatives = 0; ! 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"); ! 927: ! 928: have_error = 1; ! 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); ! 983: exit (ferror (stdout) != 0 || have_error ! 984: ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE); ! 985: ! 986: /* NOTREACHED */ ! 987: return 0; ! 988: } ! 989: ! 990: static int ! 991: n_occurrences (c, s) ! 992: char c; ! 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.