|
|
1.1 ! root 1: /* Generate code from machine description to extract operands from insn as rtl. ! 2: Copyright (C) 1987, 1991 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 "config.h" ! 23: #include "rtl.h" ! 24: #include "obstack.h" ! 25: ! 26: static struct obstack obstack; ! 27: struct obstack *rtl_obstack = &obstack; ! 28: ! 29: #define obstack_chunk_alloc xmalloc ! 30: #define obstack_chunk_free free ! 31: ! 32: extern void free (); ! 33: ! 34: /* Number instruction patterns handled, starting at 0 for first one. */ ! 35: ! 36: static int insn_code_number; ! 37: ! 38: /* Number the occurrences of MATCH_DUP in each instruction, ! 39: starting at 0 for the first occurrence. */ ! 40: ! 41: static int dup_count; ! 42: ! 43: /* Record which operand numbers have been seen in the current pattern. ! 44: This table is made longer as needed. */ ! 45: ! 46: static char *operand_seen; ! 47: ! 48: /* Current allocated length of operand_seen. */ ! 49: ! 50: static int operand_seen_length; ! 51: ! 52: /* Have we got any peephole patterns yet? */ ! 53: ! 54: static int peephole_seen; ! 55: ! 56: /* While tree-walking an instruction pattern, we keep a chain ! 57: of these `struct link's to record how to get down to the ! 58: current position. In each one, POS is the operand number, ! 59: and if the operand is a vector VEC is the element number. ! 60: VEC is -1 if the operand is not a vector. */ ! 61: ! 62: struct link ! 63: { ! 64: struct link *next; ! 65: int pos; ! 66: int vecelt; ! 67: }; ! 68: ! 69: static void walk_rtx (); ! 70: static void print_path (); ! 71: char *xmalloc (); ! 72: char *xrealloc (); ! 73: static void fatal (); ! 74: void fancy_abort (); ! 75: ! 76: static void ! 77: gen_insn (insn) ! 78: rtx insn; ! 79: { ! 80: register int i; ! 81: ! 82: dup_count = 0; ! 83: ! 84: /* No operands seen so far in this pattern. */ ! 85: bzero (operand_seen, operand_seen_length); ! 86: ! 87: printf (" case %d:\n", insn_code_number); ! 88: ! 89: /* Walk the insn's pattern, remembering at all times the path ! 90: down to the walking point. */ ! 91: ! 92: if (XVECLEN (insn, 1) == 1) ! 93: walk_rtx (XVECEXP (insn, 1, 0), 0); ! 94: else ! 95: for (i = XVECLEN (insn, 1) - 1; i >= 0; i--) ! 96: { ! 97: struct link link; ! 98: link.next = 0; ! 99: link.pos = 0; ! 100: link.vecelt = i; ! 101: walk_rtx (XVECEXP (insn, 1, i), &link); ! 102: } ! 103: ! 104: /* If the operand numbers used in the pattern are not consecutive, ! 105: don't leave an operand uninitialized. */ ! 106: for (i = operand_seen_length - 1; i >= 0; i--) ! 107: if (operand_seen[i]) ! 108: break; ! 109: for (; i >= 0; i--) ! 110: if (!operand_seen[i]) ! 111: { ! 112: printf (" recog_operand[%d] = const0_rtx;\n", i); ! 113: printf (" recog_operand_loc[%d] = &junk;\n", i); ! 114: } ! 115: printf (" break;\n"); ! 116: } ! 117: ! 118: /* Record that we have seen an operand with number OPNO in this pattern. */ ! 119: ! 120: static void ! 121: mark_operand_seen (opno) ! 122: int opno; ! 123: { ! 124: if (opno >= operand_seen_length) ! 125: { ! 126: operand_seen_length *= 2; ! 127: operand_seen = (char *) xrealloc (operand_seen_length); ! 128: } ! 129: ! 130: operand_seen[opno] = 1; ! 131: } ! 132: ! 133: static void ! 134: walk_rtx (x, path) ! 135: rtx x; ! 136: struct link *path; ! 137: { ! 138: register RTX_CODE code; ! 139: register int i; ! 140: register int len; ! 141: register char *fmt; ! 142: struct link link; ! 143: ! 144: if (x == 0) ! 145: return; ! 146: ! 147: code = GET_CODE (x); ! 148: ! 149: switch (code) ! 150: { ! 151: case PC: ! 152: case CC0: ! 153: case CONST_INT: ! 154: case SYMBOL_REF: ! 155: return; ! 156: ! 157: case MATCH_OPERAND: ! 158: case MATCH_SCRATCH: ! 159: mark_operand_seen (XINT (x, 0)); ! 160: printf (" recog_operand[%d] = *(recog_operand_loc[%d]\n = &", ! 161: XINT (x, 0), XINT (x, 0)); ! 162: print_path (path); ! 163: printf (");\n"); ! 164: break; ! 165: ! 166: case MATCH_DUP: ! 167: case MATCH_OP_DUP: ! 168: printf (" recog_dup_loc[%d] = &", dup_count); ! 169: print_path (path); ! 170: printf (";\n"); ! 171: printf (" recog_dup_num[%d] = %d;\n", dup_count, XINT (x, 0)); ! 172: dup_count++; ! 173: break; ! 174: ! 175: case MATCH_OPERATOR: ! 176: mark_operand_seen (XINT (x, 0)); ! 177: printf (" recog_operand[%d] = *(recog_operand_loc[%d]\n = &", ! 178: XINT (x, 0), XINT (x, 0)); ! 179: print_path (path); ! 180: printf (");\n"); ! 181: link.next = path; ! 182: link.vecelt = -1; ! 183: for (i = XVECLEN (x, 2) - 1; i >= 0; i--) ! 184: { ! 185: link.pos = i; ! 186: walk_rtx (XVECEXP (x, 2, i), &link); ! 187: } ! 188: return; ! 189: ! 190: case MATCH_PARALLEL: ! 191: mark_operand_seen (XINT (x, 0)); ! 192: printf (" recog_operand[%d] = *(recog_operand_loc[%d]\n = &", ! 193: XINT (x, 0), XINT (x, 0)); ! 194: print_path (path); ! 195: printf (");\n"); ! 196: link.next = path; ! 197: link.pos = 0; ! 198: for (i = XVECLEN (x, 2) - 1; i >= 0; i--) ! 199: { ! 200: link.vecelt = i; ! 201: walk_rtx (XVECEXP (x, 2, i), &link); ! 202: } ! 203: return; ! 204: ! 205: case ADDRESS: ! 206: walk_rtx (XEXP (x, 0), path); ! 207: return; ! 208: } ! 209: ! 210: link.next = path; ! 211: link.vecelt = -1; ! 212: fmt = GET_RTX_FORMAT (code); ! 213: len = GET_RTX_LENGTH (code); ! 214: for (i = 0; i < len; i++) ! 215: { ! 216: link.pos = i; ! 217: if (fmt[i] == 'e' || fmt[i] == 'u') ! 218: { ! 219: walk_rtx (XEXP (x, i), &link); ! 220: } ! 221: else if (fmt[i] == 'E') ! 222: { ! 223: int j; ! 224: for (j = XVECLEN (x, i) - 1; j >= 0; j--) ! 225: { ! 226: link.vecelt = j; ! 227: walk_rtx (XVECEXP (x, i, j), &link); ! 228: } ! 229: } ! 230: } ! 231: } ! 232: ! 233: /* Given a PATH, representing a path down the instruction's ! 234: pattern from the root to a certain point, output code to ! 235: evaluate to the rtx at that point. */ ! 236: ! 237: static void ! 238: print_path (path) ! 239: struct link *path; ! 240: { ! 241: if (path == 0) ! 242: printf ("insn"); ! 243: else if (path->vecelt >= 0) ! 244: { ! 245: printf ("XVECEXP ("); ! 246: print_path (path->next); ! 247: printf (", %d, %d)", path->pos, path->vecelt); ! 248: } ! 249: else ! 250: { ! 251: printf ("XEXP ("); ! 252: print_path (path->next); ! 253: printf (", %d)", path->pos); ! 254: } ! 255: } ! 256: ! 257: char * ! 258: xmalloc (size) ! 259: unsigned size; ! 260: { ! 261: register char *val = (char *) malloc (size); ! 262: ! 263: if (val == 0) ! 264: fatal ("virtual memory exhausted"); ! 265: return val; ! 266: } ! 267: ! 268: char * ! 269: xrealloc (ptr, size) ! 270: char *ptr; ! 271: unsigned size; ! 272: { ! 273: char *result = (char *) realloc (ptr, size); ! 274: if (!result) ! 275: fatal ("virtual memory exhausted"); ! 276: return result; ! 277: } ! 278: ! 279: static void ! 280: fatal (s, a1, a2) ! 281: char *s; ! 282: { ! 283: fprintf (stderr, "genextract: "); ! 284: fprintf (stderr, s, a1, a2); ! 285: fprintf (stderr, "\n"); ! 286: exit (FATAL_EXIT_CODE); ! 287: } ! 288: ! 289: /* More 'friendly' abort that prints the line and file. ! 290: config.h can #define abort fancy_abort if you like that sort of thing. */ ! 291: ! 292: void ! 293: fancy_abort () ! 294: { ! 295: fatal ("Internal gcc abort."); ! 296: } ! 297: ! 298: int ! 299: main (argc, argv) ! 300: int argc; ! 301: char **argv; ! 302: { ! 303: rtx desc; ! 304: FILE *infile; ! 305: extern rtx read_rtx (); ! 306: register int c, i; ! 307: ! 308: obstack_init (rtl_obstack); ! 309: ! 310: if (argc <= 1) ! 311: fatal ("No input file name."); ! 312: ! 313: infile = fopen (argv[1], "r"); ! 314: if (infile == 0) ! 315: { ! 316: perror (argv[1]); ! 317: exit (FATAL_EXIT_CODE); ! 318: } ! 319: ! 320: init_rtl (); ! 321: ! 322: /* Assign sequential codes to all entries in the machine description ! 323: in parallel with the tables in insn-output.c. */ ! 324: ! 325: insn_code_number = 0; ! 326: ! 327: operand_seen_length = 40; ! 328: operand_seen = (char *) xmalloc (40); ! 329: ! 330: printf ("/* Generated automatically by the program `genextract'\n\ ! 331: from the machine description file `md'. */\n\n"); ! 332: ! 333: printf ("#include \"config.h\"\n"); ! 334: printf ("#include \"rtl.h\"\n\n"); ! 335: ! 336: /* This variable exists only so it can be the "location" ! 337: of any missing operand whose numbers are skipped by a given pattern. */ ! 338: printf ("static rtx junk;\n"); ! 339: printf ("extern rtx recog_operand[];\n"); ! 340: printf ("extern rtx *recog_operand_loc[];\n"); ! 341: printf ("extern rtx *recog_dup_loc[];\n"); ! 342: printf ("extern char recog_dup_num[];\n"); ! 343: printf ("extern void fatal_insn_not_found ();\n\n"); ! 344: ! 345: printf ("void\ninsn_extract (insn)\n"); ! 346: printf (" rtx insn;\n"); ! 347: printf ("{\n"); ! 348: printf (" int insn_code = INSN_CODE (insn);\n"); ! 349: printf (" if (insn_code == -1) fatal_insn_not_found (insn);\n"); ! 350: printf (" insn = PATTERN (insn);\n"); ! 351: printf (" switch (insn_code)\n"); ! 352: printf (" {\n"); ! 353: ! 354: /* Read the machine description. */ ! 355: ! 356: while (1) ! 357: { ! 358: c = read_skip_spaces (infile); ! 359: if (c == EOF) ! 360: break; ! 361: ungetc (c, infile); ! 362: ! 363: desc = read_rtx (infile); ! 364: if (GET_CODE (desc) == DEFINE_INSN) ! 365: { ! 366: gen_insn (desc); ! 367: ++insn_code_number; ! 368: } ! 369: if (GET_CODE (desc) == DEFINE_PEEPHOLE) ! 370: { ! 371: printf (" case %d: goto peephole;\n", insn_code_number); ! 372: ++insn_code_number; ! 373: ++peephole_seen; ! 374: } ! 375: if (GET_CODE (desc) == DEFINE_EXPAND || GET_CODE (desc) == DEFINE_SPLIT) ! 376: { ! 377: printf (" case %d: break;\n", insn_code_number); ! 378: ++insn_code_number; ! 379: } ! 380: } ! 381: ! 382: /* This should never be reached. */ ! 383: printf ("\n default:\n abort ();\n"); ! 384: ! 385: if (peephole_seen) ! 386: { ! 387: /* The vector in the insn says how many operands it has. ! 388: And all it contains are operands. In fact, the vector was ! 389: created just for the sake of this function. */ ! 390: printf (" peephole:\n"); ! 391: printf ("#if __GNUC__ > 1 && !defined (bcopy)\n"); ! 392: printf ("#define bcopy(FROM,TO,COUNT) __builtin_memcpy(TO,FROM,COUNT)\n"); ! 393: printf ("#endif\n"); ! 394: printf (" bcopy (&XVECEXP (insn, 0, 0), recog_operand,\n"); ! 395: printf (" sizeof (rtx) * XVECLEN (insn, 0));\n"); ! 396: printf (" break;\n"); ! 397: } ! 398: ! 399: printf (" }\n}\n"); ! 400: ! 401: fflush (stdout); ! 402: exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE); ! 403: /* NOTREACHED */ ! 404: return 0; ! 405: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.