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