|
|
1.1 root 1: /* Generate code from machine description to extract operands from insn as rtl. 1.1.1.6 ! root 2: Copyright (C) 1987, 1991, 1992, 1993 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> 1.1.1.4 root 22: #include "hconfig.h" 1.1 root 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: 1.1.1.6 ! root 36: /* Names for patterns. Need to allow linking with print-rtl. */ ! 37: char **insn_name_ptr; ! 38: 1.1.1.3 root 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; 1.1 root 69: 70: /* Number instruction patterns handled, starting at 0 for first one. */ 71: 72: static int insn_code_number; 73: 1.1.1.3 root 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: 1.1 root 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: 1.1.1.3 root 88: /* Records the location of any MATCH_DUP operands. */ 1.1 root 89: 1.1.1.3 root 90: static char *duplocs[MAX_DUP_OPERANDS]; 1.1 root 91: 1.1.1.3 root 92: /* Record the operand number of any MATCH_DUPs. */ 1.1 root 93: 1.1.1.3 root 94: static int dupnums[MAX_DUP_OPERANDS]; 1.1 root 95: 1.1.1.3 root 96: /* Record the list of insn_codes for peepholes. */ 1.1 root 97: 1.1.1.3 root 98: static struct code_ptr *peepholes; 1.1 root 99: 100: static void walk_rtx (); 101: static void print_path (); 102: char *xmalloc (); 103: char *xrealloc (); 104: static void fatal (); 1.1.1.3 root 105: static char *copystr (); 1.1.1.2 root 106: static void mybzero (); 1.1 root 107: void fancy_abort (); 108: 109: static void 110: gen_insn (insn) 111: rtx insn; 112: { 113: register int i; 1.1.1.3 root 114: register struct extraction *p; 115: register struct code_ptr *link; 1.1 root 116: 1.1.1.3 root 117: op_count = 0; 1.1 root 118: dup_count = 0; 119: 120: /* No operands seen so far in this pattern. */ 1.1.1.3 root 121: mybzero (oplocs, sizeof oplocs); 1.1 root 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) 1.1.1.3 root 127: walk_rtx (XVECEXP (insn, 1, 0), ""); 1.1 root 128: else 129: for (i = XVECLEN (insn, 1) - 1; i >= 0; i--) 130: { 1.1.1.3 root 131: char *path = (char *) alloca (2); 1.1 root 132: 1.1.1.3 root 133: path[0] = 'a' + i; 134: path[1] = 0; 135: 136: walk_rtx (XVECEXP (insn, 1, i), path); 1.1 root 137: } 138: 1.1.1.3 root 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) 1.1 root 145: { 1.1.1.3 root 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; 1.1 root 170: } 171: 1.1.1.3 root 172: /* Otherwise, make a new extraction method. */ 1.1 root 173: 1.1.1.3 root 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: 1.1 root 189: static void 190: walk_rtx (x, path) 191: rtx x; 1.1.1.3 root 192: char *path; 1.1 root 193: { 194: register RTX_CODE code; 195: register int i; 196: register int len; 197: register char *fmt; 1.1.1.3 root 198: register struct code_ptr *link; 199: int depth = strlen (path); 200: char *newpath; 1.1 root 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: 1.1.1.3 root 217: oplocs[XINT (x, 0)] = copystr (path); 218: op_count = MAX (op_count, XINT (x, 0) + 1); 1.1 root 219: break; 220: 221: case MATCH_DUP: 1.1.1.4 root 222: case MATCH_PAR_DUP: 1.1.1.3 root 223: duplocs[dup_count] = copystr (path); 224: dupnums[dup_count] = XINT (x, 0); 1.1 root 225: dup_count++; 226: break; 227: 1.1.1.6 ! root 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: 1.1 root 244: case MATCH_OPERATOR: 1.1.1.3 root 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: 1.1 root 252: for (i = XVECLEN (x, 2) - 1; i >= 0; i--) 253: { 1.1.1.3 root 254: newpath[depth] = '0' + i; 255: walk_rtx (XVECEXP (x, 2, i), newpath); 1.1 root 256: } 257: return; 258: 259: case MATCH_PARALLEL: 1.1.1.3 root 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: 1.1 root 267: for (i = XVECLEN (x, 2) - 1; i >= 0; i--) 268: { 1.1.1.3 root 269: newpath[depth] = 'a' + i; 270: walk_rtx (XVECEXP (x, 2, i), newpath); 1.1 root 271: } 272: return; 273: 274: case ADDRESS: 275: walk_rtx (XEXP (x, 0), path); 276: return; 277: } 278: 1.1.1.3 root 279: newpath = (char *) alloca (depth + 2); 280: strcpy (newpath, path); 281: newpath[depth + 1] = 0; 282: 1.1 root 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: { 1.1.1.3 root 289: newpath[depth] = '0' + i; 290: walk_rtx (XEXP (x, i), newpath); 1.1 root 291: } 292: else if (fmt[i] == 'E') 293: { 294: int j; 295: for (j = XVECLEN (x, i) - 1; j >= 0; j--) 296: { 1.1.1.3 root 297: newpath[depth] = 'a' + j; 298: walk_rtx (XVECEXP (x, i, j), newpath); 1.1 root 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) 1.1.1.3 root 310: char *path; 1.1 root 311: { 1.1.1.3 root 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--) 1.1 root 319: { 1.1.1.3 root 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 (); 1.1 root 326: } 1.1.1.3 root 327: 328: printf ("pat"); 329: 330: for (i = 0; i < len; i++) 1.1 root 331: { 1.1.1.3 root 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 (); 1.1 root 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: } 1.1.1.2 root 381: 1.1.1.3 root 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: 1.1.1.2 root 397: static void 398: mybzero (b, length) 399: register char *b; 400: register unsigned length; 401: { 402: while (length-- > 0) 403: *b++ = 0; 404: } 1.1 root 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; 1.1.1.3 root 414: struct extraction *p; 415: struct code_ptr *link; 1.1 root 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"); 1.1.1.3 root 445: 1.1 root 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"); 1.1.1.5 root 450: printf ("extern\n#ifdef __GNUC__\n__volatile__\n#endif\n"); 1.1.1.3 root 451: printf ("void fatal_insn_not_found ();\n\n"); 1.1 root 452: 453: printf ("void\ninsn_extract (insn)\n"); 454: printf (" rtx insn;\n"); 455: printf ("{\n"); 1.1.1.3 root 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"); 1.1 root 460: printf (" {\n"); 1.1.1.3 root 461: printf (" case -1:\n"); 462: printf (" fatal_insn_not_found (insn);\n\n"); 1.1 root 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: } 1.1.1.3 root 479: 480: else if (GET_CODE (desc) == DEFINE_PEEPHOLE) 1.1 root 481: { 1.1.1.3 root 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; 1.1 root 488: ++insn_code_number; 489: } 490: 1.1.1.3 root 491: else if (GET_CODE (desc) == DEFINE_EXPAND 492: || GET_CODE (desc) == DEFINE_SPLIT) 493: ++insn_code_number; 494: } 1.1 root 495: 1.1.1.3 root 496: /* Write out code to handle peepholes and the insn_codes that it should 497: be called for. */ 498: if (peepholes) 1.1 root 499: { 1.1.1.3 root 500: for (link = peepholes; link; link = link->next) 501: printf (" case %d:\n", link->insn_code); 502: 1.1 root 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"); 1.1.1.3 root 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); 1.1.1.5 root 525: printf (" ro_loc[%d] = &junk;\n", i); 1.1.1.3 root 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"); 1.1 root 544: } 545: 1.1.1.3 root 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: 1.1 root 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.