|
|
1.1 ! root 1: /* Generate code from machine description to extract operands from insn as rtl. ! 2: Copyright (C) 1987, 1991, 1992, 1993 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: #include <stdio.h> ! 22: #include "hconfig.h" ! 23: #include "rtl.h" ! 24: #include "obstack.h" ! 25: #include "insn-config.h" ! 26: ! 27: static struct obstack obstack; ! 28: struct obstack *rtl_obstack = &obstack; ! 29: ! 30: #define obstack_chunk_alloc xmalloc ! 31: #define obstack_chunk_free free ! 32: ! 33: extern void free (); ! 34: extern rtx read_rtx (); ! 35: ! 36: /* Names for patterns. Need to allow linking with print-rtl. */ ! 37: char **insn_name_ptr; ! 38: ! 39: /* This structure contains all the information needed to describe one ! 40: set of extractions methods. Each method may be used by more than ! 41: one pattern if the operands are in the same place. ! 42: ! 43: The string for each operand describes that path to the operand and ! 44: contains `0' through `9' when going into an expression and `a' through ! 45: `z' when going into a vector. We assume here that only the first operand ! 46: of an rtl expression is a vector. genrecog.c makes the same assumption ! 47: (and uses the same representation) and it is currently true. */ ! 48: ! 49: struct extraction ! 50: { ! 51: int op_count; ! 52: char *oplocs[MAX_RECOG_OPERANDS]; ! 53: int dup_count; ! 54: char *duplocs[MAX_DUP_OPERANDS]; ! 55: int dupnums[MAX_DUP_OPERANDS]; ! 56: struct code_ptr *insns; ! 57: struct extraction *next; ! 58: }; ! 59: ! 60: /* Holds a single insn code that use an extraction method. */ ! 61: ! 62: struct code_ptr ! 63: { ! 64: int insn_code; ! 65: struct code_ptr *next; ! 66: }; ! 67: ! 68: static struct extraction *extractions; ! 69: ! 70: /* Number instruction patterns handled, starting at 0 for first one. */ ! 71: ! 72: static int insn_code_number; ! 73: ! 74: /* Records the large operand number in this insn. */ ! 75: ! 76: static int op_count; ! 77: ! 78: /* Records the location of any operands using the string format described ! 79: above. */ ! 80: ! 81: static char *oplocs[MAX_RECOG_OPERANDS]; ! 82: ! 83: /* Number the occurrences of MATCH_DUP in each instruction, ! 84: starting at 0 for the first occurrence. */ ! 85: ! 86: static int dup_count; ! 87: ! 88: /* Records the location of any MATCH_DUP operands. */ ! 89: ! 90: static char *duplocs[MAX_DUP_OPERANDS]; ! 91: ! 92: /* Record the operand number of any MATCH_DUPs. */ ! 93: ! 94: static int dupnums[MAX_DUP_OPERANDS]; ! 95: ! 96: /* Record the list of insn_codes for peepholes. */ ! 97: ! 98: static struct code_ptr *peepholes; ! 99: ! 100: static void walk_rtx (); ! 101: static void print_path (); ! 102: char *xmalloc (); ! 103: char *xrealloc (); ! 104: static void fatal (); ! 105: static char *copystr (); ! 106: static void mybzero (); ! 107: void fancy_abort (); ! 108: ! 109: static void ! 110: gen_insn (insn) ! 111: rtx insn; ! 112: { ! 113: register int i; ! 114: register struct extraction *p; ! 115: register struct code_ptr *link; ! 116: ! 117: op_count = 0; ! 118: dup_count = 0; ! 119: ! 120: /* No operands seen so far in this pattern. */ ! 121: mybzero (oplocs, sizeof oplocs); ! 122: ! 123: /* Walk the insn's pattern, remembering at all times the path ! 124: down to the walking point. */ ! 125: ! 126: if (XVECLEN (insn, 1) == 1) ! 127: walk_rtx (XVECEXP (insn, 1, 0), ""); ! 128: else ! 129: for (i = XVECLEN (insn, 1) - 1; i >= 0; i--) ! 130: { ! 131: char *path = (char *) alloca (2); ! 132: ! 133: path[0] = 'a' + i; ! 134: path[1] = 0; ! 135: ! 136: walk_rtx (XVECEXP (insn, 1, i), path); ! 137: } ! 138: ! 139: link = (struct code_ptr *) xmalloc (sizeof (struct code_ptr)); ! 140: link->insn_code = insn_code_number; ! 141: ! 142: /* See if we find something that already had this extraction method. */ ! 143: ! 144: for (p = extractions; p; p = p->next) ! 145: { ! 146: if (p->op_count != op_count || p->dup_count != dup_count) ! 147: continue; ! 148: ! 149: for (i = 0; i < op_count; i++) ! 150: if (p->oplocs[i] != oplocs[i] ! 151: && ! (p->oplocs[i] != 0 && oplocs[i] != 0 ! 152: && ! strcmp (p->oplocs[i], oplocs[i]))) ! 153: break; ! 154: ! 155: if (i != op_count) ! 156: continue; ! 157: ! 158: for (i = 0; i < dup_count; i++) ! 159: if (p->dupnums[i] != dupnums[i] ! 160: || strcmp (p->duplocs[i], duplocs[i])) ! 161: break; ! 162: ! 163: if (i != dup_count) ! 164: continue; ! 165: ! 166: /* This extraction is the same as ours. Just link us in. */ ! 167: link->next = p->insns; ! 168: p->insns = link; ! 169: return; ! 170: } ! 171: ! 172: /* Otherwise, make a new extraction method. */ ! 173: ! 174: p = (struct extraction *) xmalloc (sizeof (struct extraction)); ! 175: p->op_count = op_count; ! 176: p->dup_count = dup_count; ! 177: p->next = extractions; ! 178: extractions = p; ! 179: p->insns = link; ! 180: link->next = 0; ! 181: ! 182: for (i = 0; i < op_count; i++) ! 183: p->oplocs[i] = oplocs[i]; ! 184: ! 185: for (i = 0; i < dup_count; i++) ! 186: p->dupnums[i] = dupnums[i], p->duplocs[i] = duplocs[i]; ! 187: } ! 188: ! 189: static void ! 190: walk_rtx (x, path) ! 191: rtx x; ! 192: char *path; ! 193: { ! 194: register RTX_CODE code; ! 195: register int i; ! 196: register int len; ! 197: register char *fmt; ! 198: register struct code_ptr *link; ! 199: int depth = strlen (path); ! 200: char *newpath; ! 201: ! 202: if (x == 0) ! 203: return; ! 204: ! 205: code = GET_CODE (x); ! 206: ! 207: switch (code) ! 208: { ! 209: case PC: ! 210: case CC0: ! 211: case CONST_INT: ! 212: case SYMBOL_REF: ! 213: return; ! 214: ! 215: case MATCH_OPERAND: ! 216: case MATCH_SCRATCH: ! 217: oplocs[XINT (x, 0)] = copystr (path); ! 218: op_count = MAX (op_count, XINT (x, 0) + 1); ! 219: break; ! 220: ! 221: case MATCH_DUP: ! 222: case MATCH_PAR_DUP: ! 223: duplocs[dup_count] = copystr (path); ! 224: dupnums[dup_count] = XINT (x, 0); ! 225: dup_count++; ! 226: break; ! 227: ! 228: case MATCH_OP_DUP: ! 229: duplocs[dup_count] = copystr (path); ! 230: dupnums[dup_count] = XINT (x, 0); ! 231: dup_count++; ! 232: ! 233: newpath = (char *) alloca (depth + 2); ! 234: strcpy (newpath, path); ! 235: newpath[depth + 1] = 0; ! 236: ! 237: for (i = XVECLEN (x, 1) - 1; i >= 0; i--) ! 238: { ! 239: newpath[depth] = '0' + i; ! 240: walk_rtx (XVECEXP (x, 1, i), newpath); ! 241: } ! 242: return; ! 243: ! 244: case MATCH_OPERATOR: ! 245: oplocs[XINT (x, 0)] = copystr (path); ! 246: op_count = MAX (op_count, XINT (x, 0) + 1); ! 247: ! 248: newpath = (char *) alloca (depth + 2); ! 249: strcpy (newpath, path); ! 250: newpath[depth + 1] = 0; ! 251: ! 252: for (i = XVECLEN (x, 2) - 1; i >= 0; i--) ! 253: { ! 254: newpath[depth] = '0' + i; ! 255: walk_rtx (XVECEXP (x, 2, i), newpath); ! 256: } ! 257: return; ! 258: ! 259: case MATCH_PARALLEL: ! 260: oplocs[XINT (x, 0)] = copystr (path); ! 261: op_count = MAX (op_count, XINT (x, 0) + 1); ! 262: ! 263: newpath = (char *) alloca (depth + 2); ! 264: strcpy (newpath, path); ! 265: newpath[depth + 1] = 0; ! 266: ! 267: for (i = XVECLEN (x, 2) - 1; i >= 0; i--) ! 268: { ! 269: newpath[depth] = 'a' + i; ! 270: walk_rtx (XVECEXP (x, 2, i), newpath); ! 271: } ! 272: return; ! 273: ! 274: case ADDRESS: ! 275: walk_rtx (XEXP (x, 0), path); ! 276: return; ! 277: } ! 278: ! 279: newpath = (char *) alloca (depth + 2); ! 280: strcpy (newpath, path); ! 281: newpath[depth + 1] = 0; ! 282: ! 283: fmt = GET_RTX_FORMAT (code); ! 284: len = GET_RTX_LENGTH (code); ! 285: for (i = 0; i < len; i++) ! 286: { ! 287: if (fmt[i] == 'e' || fmt[i] == 'u') ! 288: { ! 289: newpath[depth] = '0' + i; ! 290: walk_rtx (XEXP (x, i), newpath); ! 291: } ! 292: else if (fmt[i] == 'E') ! 293: { ! 294: int j; ! 295: for (j = XVECLEN (x, i) - 1; j >= 0; j--) ! 296: { ! 297: newpath[depth] = 'a' + j; ! 298: walk_rtx (XVECEXP (x, i, j), newpath); ! 299: } ! 300: } ! 301: } ! 302: } ! 303: ! 304: /* Given a PATH, representing a path down the instruction's ! 305: pattern from the root to a certain point, output code to ! 306: evaluate to the rtx at that point. */ ! 307: ! 308: static void ! 309: print_path (path) ! 310: char *path; ! 311: { ! 312: register int len = strlen (path); ! 313: register int i; ! 314: ! 315: /* We first write out the operations (XEXP or XVECEXP) in reverse ! 316: order, then write "insn", then the indices in forward order. */ ! 317: ! 318: for (i = len - 1; i >=0 ; i--) ! 319: { ! 320: if (path[i] >= 'a' && path[i] <= 'z') ! 321: printf ("XVECEXP ("); ! 322: else if (path[i] >= '0' && path[i] <= '9') ! 323: printf ("XEXP ("); ! 324: else ! 325: abort (); ! 326: } ! 327: ! 328: printf ("pat"); ! 329: ! 330: for (i = 0; i < len; i++) ! 331: { ! 332: if (path[i] >= 'a' && path[i] <= 'z') ! 333: printf (", 0, %d)", path[i] - 'a'); ! 334: else if (path[i] >= '0' && path[i] <= '9') ! 335: printf (", %d)", path[i] - '0'); ! 336: else ! 337: abort (); ! 338: } ! 339: } ! 340: ! 341: char * ! 342: xmalloc (size) ! 343: unsigned size; ! 344: { ! 345: register char *val = (char *) malloc (size); ! 346: ! 347: if (val == 0) ! 348: fatal ("virtual memory exhausted"); ! 349: return val; ! 350: } ! 351: ! 352: char * ! 353: xrealloc (ptr, size) ! 354: char *ptr; ! 355: unsigned size; ! 356: { ! 357: char *result = (char *) realloc (ptr, size); ! 358: if (!result) ! 359: fatal ("virtual memory exhausted"); ! 360: return result; ! 361: } ! 362: ! 363: static void ! 364: fatal (s, a1, a2) ! 365: char *s; ! 366: { ! 367: fprintf (stderr, "genextract: "); ! 368: fprintf (stderr, s, a1, a2); ! 369: fprintf (stderr, "\n"); ! 370: exit (FATAL_EXIT_CODE); ! 371: } ! 372: ! 373: /* More 'friendly' abort that prints the line and file. ! 374: config.h can #define abort fancy_abort if you like that sort of thing. */ ! 375: ! 376: void ! 377: fancy_abort () ! 378: { ! 379: fatal ("Internal gcc abort."); ! 380: } ! 381: ! 382: static char * ! 383: copystr (s1) ! 384: char *s1; ! 385: { ! 386: register char *tem; ! 387: ! 388: if (s1 == 0) ! 389: return 0; ! 390: ! 391: tem = (char *) xmalloc (strlen (s1) + 1); ! 392: strcpy (tem, s1); ! 393: ! 394: return tem; ! 395: } ! 396: ! 397: static void ! 398: mybzero (b, length) ! 399: register char *b; ! 400: register unsigned length; ! 401: { ! 402: while (length-- > 0) ! 403: *b++ = 0; ! 404: } ! 405: ! 406: int ! 407: main (argc, argv) ! 408: int argc; ! 409: char **argv; ! 410: { ! 411: rtx desc; ! 412: FILE *infile; ! 413: register int c, i; ! 414: struct extraction *p; ! 415: struct code_ptr *link; ! 416: ! 417: obstack_init (rtl_obstack); ! 418: ! 419: if (argc <= 1) ! 420: fatal ("No input file name."); ! 421: ! 422: infile = fopen (argv[1], "r"); ! 423: if (infile == 0) ! 424: { ! 425: perror (argv[1]); ! 426: exit (FATAL_EXIT_CODE); ! 427: } ! 428: ! 429: init_rtl (); ! 430: ! 431: /* Assign sequential codes to all entries in the machine description ! 432: in parallel with the tables in insn-output.c. */ ! 433: ! 434: insn_code_number = 0; ! 435: ! 436: printf ("/* Generated automatically by the program `genextract'\n\ ! 437: from the machine description file `md'. */\n\n"); ! 438: ! 439: printf ("#include \"config.h\"\n"); ! 440: printf ("#include \"rtl.h\"\n\n"); ! 441: ! 442: /* This variable exists only so it can be the "location" ! 443: of any missing operand whose numbers are skipped by a given pattern. */ ! 444: printf ("static rtx junk;\n"); ! 445: ! 446: printf ("extern rtx recog_operand[];\n"); ! 447: printf ("extern rtx *recog_operand_loc[];\n"); ! 448: printf ("extern rtx *recog_dup_loc[];\n"); ! 449: printf ("extern char recog_dup_num[];\n"); ! 450: printf ("extern\n#ifdef __GNUC__\n__volatile__\n#endif\n"); ! 451: printf ("void fatal_insn_not_found ();\n\n"); ! 452: ! 453: printf ("void\ninsn_extract (insn)\n"); ! 454: printf (" rtx insn;\n"); ! 455: printf ("{\n"); ! 456: printf (" register rtx *ro = recog_operand;\n"); ! 457: printf (" register rtx **ro_loc = recog_operand_loc;\n"); ! 458: printf (" rtx pat = PATTERN (insn);\n"); ! 459: printf (" switch (INSN_CODE (insn))\n"); ! 460: printf (" {\n"); ! 461: printf (" case -1:\n"); ! 462: printf (" fatal_insn_not_found (insn);\n\n"); ! 463: ! 464: /* Read the machine description. */ ! 465: ! 466: while (1) ! 467: { ! 468: c = read_skip_spaces (infile); ! 469: if (c == EOF) ! 470: break; ! 471: ungetc (c, infile); ! 472: ! 473: desc = read_rtx (infile); ! 474: if (GET_CODE (desc) == DEFINE_INSN) ! 475: { ! 476: gen_insn (desc); ! 477: ++insn_code_number; ! 478: } ! 479: ! 480: else if (GET_CODE (desc) == DEFINE_PEEPHOLE) ! 481: { ! 482: struct code_ptr *link ! 483: = (struct code_ptr *) xmalloc (sizeof (struct code_ptr)); ! 484: ! 485: link->insn_code = insn_code_number; ! 486: link->next = peepholes; ! 487: peepholes = link; ! 488: ++insn_code_number; ! 489: } ! 490: ! 491: else if (GET_CODE (desc) == DEFINE_EXPAND ! 492: || GET_CODE (desc) == DEFINE_SPLIT) ! 493: ++insn_code_number; ! 494: } ! 495: ! 496: /* Write out code to handle peepholes and the insn_codes that it should ! 497: be called for. */ ! 498: if (peepholes) ! 499: { ! 500: for (link = peepholes; link; link = link->next) ! 501: printf (" case %d:\n", link->insn_code); ! 502: ! 503: /* The vector in the insn says how many operands it has. ! 504: And all it contains are operands. In fact, the vector was ! 505: created just for the sake of this function. */ ! 506: printf ("#if __GNUC__ > 1 && !defined (bcopy)\n"); ! 507: printf ("#define bcopy(FROM,TO,COUNT) __builtin_memcpy(TO,FROM,COUNT)\n"); ! 508: printf ("#endif\n"); ! 509: printf (" bcopy (&XVECEXP (pat, 0, 0), ro,\n"); ! 510: printf (" sizeof (rtx) * XVECLEN (pat, 0));\n"); ! 511: printf (" break;\n\n"); ! 512: } ! 513: ! 514: /* Write out all the ways to extract insn operands. */ ! 515: for (p = extractions; p; p = p->next) ! 516: { ! 517: for (link = p->insns; link; link = link->next) ! 518: printf (" case %d:\n", link->insn_code); ! 519: ! 520: for (i = 0; i < p->op_count; i++) ! 521: { ! 522: if (p->oplocs[i] == 0) ! 523: { ! 524: printf (" ro[%d] = const0_rtx;\n", i); ! 525: printf (" ro_loc[%d] = &junk;\n", i); ! 526: } ! 527: else ! 528: { ! 529: printf (" ro[%d] = *(ro_loc[%d] = &", i, i); ! 530: print_path (p->oplocs[i]); ! 531: printf (");\n"); ! 532: } ! 533: } ! 534: ! 535: for (i = 0; i < p->dup_count; i++) ! 536: { ! 537: printf (" recog_dup_loc[%d] = &", i); ! 538: print_path (p->duplocs[i]); ! 539: printf (";\n"); ! 540: printf (" recog_dup_num[%d] = %d;\n", i, p->dupnums[i]); ! 541: } ! 542: ! 543: printf (" break;\n\n"); ! 544: } ! 545: ! 546: /* This should never be reached. Note that we would also reach this abort ! 547: if we tried to extract something whose INSN_CODE was a DEFINE_EXPAND or ! 548: DEFINE_SPLIT, but that is correct. */ ! 549: printf (" default:\n abort ();\n"); ! 550: ! 551: printf (" }\n}\n"); ! 552: ! 553: fflush (stdout); ! 554: exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE); ! 555: /* NOTREACHED */ ! 556: return 0; ! 557: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.