|
|
1.1 ! root 1: /* Generate code from machine description to emit insns as rtl. ! 2: Copyright (C) 1987 Free Software Foundation, Inc. ! 3: ! 4: This file is part of GNU CC. ! 5: ! 6: GNU CC is distributed in the hope that it will be useful, ! 7: but WITHOUT ANY WARRANTY. No author or distributor ! 8: accepts responsibility to anyone for the consequences of using it ! 9: or for whether it serves any particular purpose or works at all, ! 10: unless he says so in writing. Refer to the GNU CC General Public ! 11: License for full details. ! 12: ! 13: Everyone is granted permission to copy, modify and redistribute ! 14: GNU CC, but only under the conditions described in the ! 15: GNU CC General Public License. A copy of this license is ! 16: supposed to have been given to you along with GNU CC so you ! 17: can know your rights and responsibilities. It should be in a ! 18: file named COPYING. Among other things, the copyright notice ! 19: and this notice must be preserved on all copies. */ ! 20: ! 21: ! 22: #include <stdio.h> ! 23: #include "config.h" ! 24: #include "rtl.h" ! 25: #include "obstack.h" ! 26: ! 27: struct obstack obstack; ! 28: struct obstack *rtl_obstack = &obstack; ! 29: ! 30: #define obstack_chunk_alloc xmalloc ! 31: #define obstack_chunk_free free ! 32: extern int xmalloc (); ! 33: extern void free (); ! 34: ! 35: void fatal (); ! 36: ! 37: int max_opno; ! 38: int max_dup_opno; ! 39: int register_constraints; ! 40: int insn_code_number; ! 41: ! 42: #define max(a, b) ((a) > (b) ? (a) : (b)) ! 43: ! 44: void ! 45: max_operand_1 (x) ! 46: rtx x; ! 47: { ! 48: register RTX_CODE code; ! 49: register int i; ! 50: register int len; ! 51: register char *fmt; ! 52: ! 53: if (x == 0) ! 54: return; ! 55: ! 56: code = GET_CODE (x); ! 57: ! 58: if (code == MATCH_OPERAND && XSTR (x, 2) != 0) ! 59: register_constraints = 1; ! 60: if (code == MATCH_OPERAND) ! 61: max_opno = max (max_opno, XINT (x, 0)); ! 62: if (code == MATCH_DUP) ! 63: max_dup_opno = max (max_dup_opno, XINT (x, 0)); ! 64: ! 65: fmt = GET_RTX_FORMAT (code); ! 66: len = GET_RTX_LENGTH (code); ! 67: for (i = 0; i < len; i++) ! 68: { ! 69: if (fmt[i] == 'e' || fmt[i] == 'u') ! 70: max_operand_1 (XEXP (x, i)); ! 71: else if (fmt[i] == 'E') ! 72: { ! 73: int j; ! 74: for (j = 0; j < XVECLEN (x, i); j++) ! 75: max_operand_1 (XVECEXP (x, i, j)); ! 76: } ! 77: } ! 78: } ! 79: ! 80: int ! 81: max_operand_vec (insn, arg) ! 82: rtx insn; ! 83: int arg; ! 84: { ! 85: register int len = XVECLEN (insn, arg); ! 86: register int i; ! 87: ! 88: max_opno = -1; ! 89: max_dup_opno = -1; ! 90: ! 91: for (i = 0; i < len; i++) ! 92: max_operand_1 (XVECEXP (insn, arg, i)); ! 93: ! 94: return max_opno + 1; ! 95: } ! 96: ! 97: void ! 98: print_code (code) ! 99: RTX_CODE code; ! 100: { ! 101: register char *p1; ! 102: for (p1 = GET_RTX_NAME (code); *p1; p1++) ! 103: { ! 104: if (*p1 >= 'a' && *p1 <= 'z') ! 105: putchar (*p1 + 'A' - 'a'); ! 106: else ! 107: putchar (*p1); ! 108: } ! 109: } ! 110: ! 111: /* Print a C expression to construct an RTX just like X, ! 112: substituting any operand references appearing within. */ ! 113: ! 114: void ! 115: gen_exp (x) ! 116: rtx x; ! 117: { ! 118: register RTX_CODE code; ! 119: register int i; ! 120: register int len; ! 121: register char *fmt; ! 122: ! 123: if (x == 0) ! 124: { ! 125: printf ("0"); ! 126: return; ! 127: } ! 128: ! 129: code = GET_CODE (x); ! 130: ! 131: switch (code) ! 132: { ! 133: case MATCH_OPERAND: ! 134: case MATCH_DUP: ! 135: printf ("operand%d", XINT (x, 0)); ! 136: return; ! 137: ! 138: case ADDRESS: ! 139: fatal ("ADDRESS expression code used in named instruction pattern"); ! 140: ! 141: case PC: ! 142: printf ("pc_rtx"); ! 143: return; ! 144: ! 145: case CC0: ! 146: printf ("cc0_rtx"); ! 147: return; ! 148: ! 149: case CONST_INT: ! 150: if (INTVAL (x) == 0) ! 151: { ! 152: printf ("const0_rtx"); ! 153: return; ! 154: } ! 155: if (INTVAL (x) == 1) ! 156: { ! 157: printf ("const1_rtx"); ! 158: return; ! 159: } ! 160: } ! 161: ! 162: printf ("gen_rtx ("); ! 163: print_code (code); ! 164: printf (", %smode", GET_MODE_NAME (GET_MODE (x))); ! 165: ! 166: fmt = GET_RTX_FORMAT (code); ! 167: len = GET_RTX_LENGTH (code); ! 168: for (i = 0; i < len; i++) ! 169: { ! 170: if (fmt[i] == '0') ! 171: break; ! 172: printf (", "); ! 173: if (fmt[i] == 'e' || fmt[i] == 'u') ! 174: gen_exp (XEXP (x, i)); ! 175: else if (fmt[i] == 'i') ! 176: printf ("%d", XINT (x, i)); ! 177: else if (fmt[i] == 's') ! 178: printf ("\"%s\"", XSTR (x, i)); ! 179: else if (fmt[i] == 'E') ! 180: { ! 181: int j; ! 182: printf ("gen_rtvec (%d", XVECLEN (x, i)); ! 183: for (j = 0; j < XVECLEN (x, i); j++) ! 184: { ! 185: printf (", "); ! 186: gen_exp (XVECEXP (x, i, j)); ! 187: } ! 188: printf (")"); ! 189: } ! 190: else ! 191: abort (); ! 192: } ! 193: printf (")"); ! 194: } ! 195: ! 196: /* Generate the `gen_...' function for a DEFINE_INSN. */ ! 197: ! 198: void ! 199: gen_insn (insn) ! 200: rtx insn; ! 201: { ! 202: int operands; ! 203: register int i; ! 204: ! 205: /* Don't mention instructions whose names are the null string. ! 206: They are in the machine description just to be recognized. */ ! 207: if (strlen (XSTR (insn, 0)) == 0) ! 208: return; ! 209: ! 210: /* Find out how many operands this function has, ! 211: and also whether any of them have register constraints. */ ! 212: register_constraints = 0; ! 213: operands = max_operand_vec (insn, 1); ! 214: if (max_dup_opno >= operands) ! 215: fatal ("match_dup operand number has no match_operand"); ! 216: ! 217: /* Output the function name and argument declarations. */ ! 218: printf ("rtx\ngen_%s (", XSTR (insn, 0)); ! 219: for (i = 0; i < operands; i++) ! 220: printf (i ? ", operand%d" : "operand%d", i); ! 221: printf (")\n"); ! 222: for (i = 0; i < operands; i++) ! 223: printf (" rtx operand%d;\n", i); ! 224: printf ("{\n"); ! 225: ! 226: /* Output code to construct and return the rtl for the instruction body */ ! 227: ! 228: if (XVECLEN (insn, 1) == 1) ! 229: { ! 230: printf (" return "); ! 231: gen_exp (XVECEXP (insn, 1, 0)); ! 232: printf (";\n}\n\n"); ! 233: } ! 234: else ! 235: { ! 236: printf (" return gen_rtx (PARALLEL, VOIDmode, gen_rtvec (%d", XVECLEN (insn, 1)); ! 237: for (i = 0; i < XVECLEN (insn, 1); i++) ! 238: { ! 239: printf (",\n\t\t"); ! 240: gen_exp (XVECEXP (insn, 1, i)); ! 241: } ! 242: printf ("));\n}\n\n"); ! 243: } ! 244: } ! 245: ! 246: /* Generate the `gen_...' function for a DEFINE_EXPAND. */ ! 247: ! 248: void ! 249: gen_expand (expand) ! 250: rtx expand; ! 251: { ! 252: int operands; ! 253: register int i; ! 254: ! 255: if (strlen (XSTR (expand, 0)) == 0) ! 256: fatal ("define_expand lacks a name"); ! 257: if (XVEC (expand, 1) == 0) ! 258: fatal ("define_expand for %s lacks a pattern", XSTR (expand, 0)); ! 259: ! 260: /* Find out how many operands this function has, ! 261: and also whether any of them have register constraints. */ ! 262: register_constraints = 0; ! 263: ! 264: operands = max_operand_vec (expand, 1); ! 265: ! 266: /* Output the function name and argument declarations. */ ! 267: printf ("rtx\ngen_%s (", XSTR (expand, 0)); ! 268: for (i = 0; i < operands; i++) ! 269: printf (i ? ", operand%d" : "operand%d", i); ! 270: printf (")\n"); ! 271: for (i = 0; i < operands; i++) ! 272: printf (" rtx operand%d;\n", i); ! 273: printf ("{\n"); ! 274: ! 275: /* For each operand referred to only with MATCH_DUPs, ! 276: make a local variable. */ ! 277: for (i = operands; i <= max_dup_opno; i++) ! 278: printf (" rtx operand%d;\n", i); ! 279: printf (" rtx operands[%d];\n\n", max (operands, max_dup_opno + 1)); ! 280: printf (" extern rtx gen_sequence ();\n"); ! 281: printf (" extern int emit_to_sequence;\n\n"); ! 282: printf (" emit_to_sequence++;\n"); ! 283: ! 284: /* The fourth operand of DEFINE_EXPAND is some code to be executed ! 285: before the actual construction. ! 286: This code expects to refer to `operands' ! 287: just as the output-code in a DEFINE_INSN does, ! 288: but here `operands' is an automatic array. ! 289: So copy the operand values there before executing it. */ ! 290: if (XSTR (expand, 3)) ! 291: { ! 292: /* Output code to copy the arguments into `operands'. */ ! 293: for (i = 0; i < operands; i++) ! 294: printf (" operands[%d] = operand%d;\n", i, i); ! 295: ! 296: /* Output the special code to be executed before the sequence ! 297: is generated. */ ! 298: printf ("%s\n", XSTR (expand, 3)); ! 299: ! 300: /* Output code to copy the arguments back out of `operands' ! 301: (unless we aren't going to use them at all). */ ! 302: if (XVEC (expand, 1) != 0) ! 303: { ! 304: for (i = 0; i < operands; i++) ! 305: printf (" operand%d = operands[%d];\n", i, i); ! 306: for (; i <= max_dup_opno; i++) ! 307: printf (" operand%d = operands[%d];\n", i, i); ! 308: } ! 309: } ! 310: ! 311: /* Output code to construct the rtl for the instruction bodies. ! 312: Use emit_insn to add them to the sequence being accumulated. ! 313: But don't do this if the user's code has set `no_more' nonzero. */ ! 314: ! 315: for (i = 0; i < XVECLEN (expand, 1); i++) ! 316: { ! 317: rtx next = XVECEXP (expand, 1, i); ! 318: if ((GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC) ! 319: || (GET_CODE (next) == PARALLEL ! 320: && GET_CODE (XVECEXP (next, 0, 0)) == SET ! 321: && GET_CODE (SET_DEST (XVECEXP (next, 0, 0))) == PC) ! 322: || GET_CODE (next) == RETURN) ! 323: printf (" emit_jump_insn ("); ! 324: else if ((GET_CODE (next) == SET && GET_CODE (SET_SRC (next)) == CALL) ! 325: || GET_CODE (next) == CALL) ! 326: printf (" emit_call_insn ("); ! 327: else if (GET_CODE (next) == CODE_LABEL) ! 328: printf (" emit_label ("); ! 329: else if (GET_CODE (next) == MATCH_OPERAND ! 330: || GET_CODE (next) == MATCH_DUP) ! 331: printf (" emit ("); ! 332: else ! 333: printf (" emit_insn ("); ! 334: gen_exp (next); ! 335: printf (");\n"); ! 336: if (GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC ! 337: && GET_CODE (SET_SRC (next)) == LABEL_REF) ! 338: printf (" emit_barrier ();"); ! 339: } ! 340: ! 341: printf (" emit_to_sequence--;\n"); ! 342: ! 343: /* Call `gen_sequence' to make a SEQUENCE out of all the ! 344: insns emitted within this gen_... function. */ ! 345: ! 346: printf (" return gen_sequence ();\n}\n\n"); ! 347: } ! 348: ! 349: int ! 350: xmalloc (size) ! 351: { ! 352: register int val = malloc (size); ! 353: ! 354: if (val == 0) ! 355: fatal ("virtual memory exhausted"); ! 356: ! 357: return val; ! 358: } ! 359: ! 360: int ! 361: xrealloc (ptr, size) ! 362: char *ptr; ! 363: int size; ! 364: { ! 365: int result = realloc (ptr, size); ! 366: if (!result) ! 367: fatal ("virtual memory exhausted"); ! 368: return result; ! 369: } ! 370: ! 371: void ! 372: fatal (s, a1, a2) ! 373: { ! 374: fprintf (stderr, "genemit: "); ! 375: fprintf (stderr, s, a1, a2); ! 376: fprintf (stderr, "\n"); ! 377: exit (FATAL_EXIT_CODE); ! 378: } ! 379: ! 380: int ! 381: main (argc, argv) ! 382: int argc; ! 383: char **argv; ! 384: { ! 385: rtx desc; ! 386: FILE *infile; ! 387: extern rtx read_rtx (); ! 388: register int c; ! 389: ! 390: obstack_init (rtl_obstack); ! 391: ! 392: if (argc <= 1) ! 393: fatal ("No input file name."); ! 394: ! 395: infile = fopen (argv[1], "r"); ! 396: if (infile == 0) ! 397: { ! 398: perror (argv[1]); ! 399: exit (FATAL_EXIT_CODE); ! 400: } ! 401: ! 402: init_rtl (); ! 403: ! 404: /* Assign sequential codes to all entries in the machine description ! 405: in parallel with the tables in insn-output.c. */ ! 406: ! 407: insn_code_number = 0; ! 408: ! 409: printf ("/* Generated automatically by the program `genemit'\n\ ! 410: from the machine description file `md'. */\n\n"); ! 411: ! 412: printf ("#include \"config.h\"\n"); ! 413: printf ("#include \"rtl.h\"\n"); ! 414: printf ("#include \"expr.h\"\n"); ! 415: printf ("#include \"insn-config.h\"\n\n"); ! 416: printf ("extern char *insn_operand_constraint[][MAX_RECOG_OPERANDS];\n\n"); ! 417: printf ("extern rtx recog_operand[];\n"); ! 418: printf ("#define operands recog_operand\n\n"); ! 419: printf ("#define FAIL do { emit_to_sequence--; return 0;} while (0)\n\n"); ! 420: printf ("#define DONE do { emit_to_sequence--; return gen_sequence ();} while (0)\n\n"); ! 421: ! 422: /* Read the machine description. */ ! 423: ! 424: while (1) ! 425: { ! 426: c = read_skip_spaces (infile); ! 427: if (c == EOF) ! 428: break; ! 429: ungetc (c, infile); ! 430: ! 431: desc = read_rtx (infile); ! 432: if (GET_CODE (desc) == DEFINE_INSN) ! 433: { ! 434: gen_insn (desc); ! 435: ++insn_code_number; ! 436: } ! 437: if (GET_CODE (desc) == DEFINE_EXPAND) ! 438: { ! 439: gen_expand (desc); ! 440: ++insn_code_number; ! 441: } ! 442: if (GET_CODE (desc) == DEFINE_PEEPHOLE) ! 443: { ! 444: ++insn_code_number; ! 445: } ! 446: } ! 447: ! 448: fflush (stdout); ! 449: exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE); ! 450: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.