📄 genrecog.c
字号:
}/* Write out C code to perform the decisions in the tree. */voidwrite_tree (tree, prevpos, afterward, afterpos, initial) struct decision *tree; char *prevpos; int afterward; char *afterpos; int initial;{ register struct decision *p, *p1; char *pos; register int depth; int ignmode; enum anon1 { NO_SWITCH, CODE_SWITCH, MODE_SWITCH } in_switch = NO_SWITCH; char modemap[NUM_MACHINE_MODES]; char codemap[NUM_RTX_CODE]; pos = prevpos; if (tree->subroutine_number > 0 && ! initial) { printf (" L%d:\n", tree->number); if (afterward) { printf (" tem = recog_%d (x0, insn);\n", tree->subroutine_number); printf (" if (tem >= 0) return tem;\n"); change_state (pos, afterpos); printf (" goto L%d;\n", afterward); } else printf (" return recog_%d (x0, insn);\n", tree->subroutine_number); return; } tree->label_needed = 1; for (p = tree; p; p = p->next) { /* Find the next alternative to p that might be true when p is true. Test that one next if p's successors fail. Note that when the `tests' field is nonzero it is up to the specified test-function to compare machine modes and some (such as general_operand) don't always do so. But when inside a switch-on-modes we ignore this and consider all modes mutually exclusive. */ for (p1 = p->next; p1; p1 = p1->next) if (((p->code == UNKNOWN || p1->code == UNKNOWN || p->code == p1->code) && (p->mode == VOIDmode || p1->mode == VOIDmode || p->mode == p1->mode || (in_switch != MODE_SWITCH && (p->tests || p1->tests)))) || strcmp (p1->position, p->position)) break; p->afterward = p1; if (p1) p1->label_needed = 1; if (in_switch == MODE_SWITCH && (p->mode == VOIDmode || (! p->enforce_mode && p->tests != 0))) { in_switch = NO_SWITCH; printf (" }\n"); } if (in_switch == CODE_SWITCH && p->code == UNKNOWN) { in_switch = NO_SWITCH; printf (" }\n"); } if (p->label_needed) printf (" L%d:\n", p->number); if (p->success == 0 && p->insn_code_number < 0) abort (); change_state (pos, p->position); pos = p->position; depth = strlen (pos); ignmode = p->ignmode || pos[depth - 1] == '*' || p->tests; if (in_switch == NO_SWITCH) { /* If p and its alternatives all want the same mode, reject all others at once, first, then ignore the mode. */ if (!ignmode && p->mode != VOIDmode && p->next && same_modes (p, p->mode)) { printf (" if (GET_MODE (x%d) != %smode)\n", depth, GET_MODE_NAME (p->mode)); if (afterward) { printf (" {\n "); change_state (pos, afterpos); printf (" goto L%d;\n }\n", afterward); } else printf (" goto ret0;\n"); clear_modes (p); ignmode = 1; } /* If p and its alternatives all want the same code, reject all others at once, first, then ignore the code. */ if (p->code != UNKNOWN && p->next && same_codes (p, p->code)) { printf (" if (GET_CODE (x%d) != ", depth); print_code (p->code); printf (")\n"); if (afterward) { printf (" {"); change_state (pos, afterpos); printf (" goto L%d; }\n", afterward); } else printf (" goto ret0;\n"); clear_codes (p); } } /* If p and its alternatives all have different modes and there are at least 4 of them, make a switch. */ if (in_switch == NO_SWITCH && pos[depth-1] != '*') { register int i; int lose = 0; mybzero (modemap, sizeof modemap); for (p1 = p, i = 0; (p1 && p1->mode != VOIDmode && (p1->tests == 0 || p1->enforce_mode)); p1 = p1->next, i++) { if (! p->enforce_mode && modemap[(int) p1->mode]) { lose = 1; break; } modemap[(int) p1->mode] = 1; } if (!lose && i >= 4) { in_switch = MODE_SWITCH; printf (" switch (GET_MODE (x%d))\n {\n", depth); } } if (in_switch == NO_SWITCH) { register int i; mybzero (codemap, sizeof codemap); for (p1 = p, i = 0; p1 && p1->code != UNKNOWN; p1 = p1->next, i++) { if (codemap[(int) p1->code]) break; codemap[(int) p1->code] = 1; } if ((p1 == 0 || p1->code == UNKNOWN) && i >= 4) { in_switch = CODE_SWITCH; printf (" switch (GET_CODE (x%d))\n {\n", depth); } } if (in_switch == MODE_SWITCH) { if (modemap[(int) p->mode]) { printf (" case %smode:\n", GET_MODE_NAME (p->mode)); modemap[(int) p->mode] = 0; } } if (in_switch == CODE_SWITCH) { if (codemap[(int) p->code]) { printf (" case "); print_code (p->code); printf (":\n"); codemap[(int) p->code] = 0; } } printf (" if ("); if (p->exact || (p->code != UNKNOWN && in_switch != CODE_SWITCH)) { if (p->exact) printf ("x%d == %s", depth, p->exact); else { printf ("GET_CODE (x%d) == ", depth); print_code (p->code); } printf (" && "); } if (p->mode != VOIDmode && !ignmode && in_switch != MODE_SWITCH) printf ("GET_MODE (x%d) == %smode && ", depth, GET_MODE_NAME (p->mode)); if (p->test_elt_zero_int) printf ("XINT (x%d, 0) == %d && ", depth, p->elt_zero_int); if (p->veclen) printf ("XVECLEN (x%d, 0) == %d && ", depth, p->veclen); if (p->test_elt_one_int) printf ("XINT (x%d, 1) == %d && ", depth, p->elt_one_int); if (p->dupno >= 0) printf ("rtx_equal_p (x%d, recog_operand[%d]) && ", depth, p->dupno); if (p->tests) printf ("%s (x%d, %smode)", p->tests, depth, GET_MODE_NAME (p->mode)); else printf ("1"); if (p->opno >= 0) printf (")\n { recog_operand[%d] = x%d; ", p->opno, depth); else printf (")\n "); if (p->c_test) printf ("if (%s) ", p->c_test); if (p->insn_code_number >= 0) printf ("return %d;", p->insn_code_number); else printf ("goto L%d;", p->success->number); if (p->opno >= 0) printf (" }\n"); else printf ("\n"); /* Now, if inside a switch, branch to next switch member that might also need to be tested if this one fails. */ if (in_switch == CODE_SWITCH) { /* Find the next alternative to p that might be applicable if p was applicable. */ for (p1 = p->next; p1; p1 = p1->next) if (p1->code == UNKNOWN || p->code == p1->code) break; if (p1 == 0 || p1->code == UNKNOWN) printf (" break;\n"); else if (p1 != p->next) { printf (" goto L%d;\n", p1->number); p1->label_needed = 1; } } if (in_switch == MODE_SWITCH) { /* Find the next alternative to p that might be applicable if p was applicable. */ for (p1 = p->next; p1; p1 = p1->next) if (p1->mode == VOIDmode || p->mode == p1->mode) break; if (p1 == 0 || p1->mode == VOIDmode) printf (" break;\n"); else if (p1 != p->next) { printf (" goto L%d;\n", p1->number); p1->label_needed = 1; } } } if (in_switch != NO_SWITCH) printf (" }\n"); if (afterward) { change_state (pos, afterpos); printf (" goto L%d;\n", afterward); } else printf (" goto ret0;\n"); for (p = tree; p; p = p->next) if (p->success) { { pos = p->position; write_tree (p->success, pos, p->afterward ? p->afterward->number : afterward, p->afterward ? pos : afterpos, 0); } }}voidprint_code (code) RTX_CODE code;{ register char *p1; for (p1 = GET_RTX_NAME (code); *p1; p1++) { if (*p1 >= 'a' && *p1 <= 'z') putchar (*p1 + 'A' - 'a'); else putchar (*p1); }}intsame_codes (p, code) register struct decision *p; register RTX_CODE code;{ for (; p; p = p->next) if (p->code != code) return 0; return 1;}voidclear_codes (p) register struct decision *p;{ for (; p; p = p->next) p->code = UNKNOWN;}intsame_modes (p, mode) register struct decision *p; register enum machine_mode mode;{ for (; p; p = p->next) if (p->mode != mode || p->tests) return 0; return 1;}voidclear_modes (p) register struct decision *p;{ for (; p; p = p->next) p->ignmode = 1;}voidchange_state (oldpos, newpos) char *oldpos; char *newpos;{ int odepth = strlen (oldpos); int depth = odepth; int ndepth = strlen (newpos); /* Pop up as many levels as necessary. */ while (strncmp (oldpos, newpos, depth)) --depth; /* Go down to desired level. */ while (depth < ndepth) { if (newpos[depth] == '*') printf (" x%d = recog_addr_dummy;\n XEXP (x%d, 0) = x%d;\n", depth + 1, depth + 1, depth); else if (newpos[depth] >= 'a' && newpos[depth] <= 'z') printf (" x%d = XVECEXP (x%d, 0, %d);\n", depth + 1, depth, newpos[depth] - 'a'); else printf (" x%d = XEXP (x%d, %c);\n", depth + 1, depth, newpos[depth]); ++depth; }}char *copystr (s1) char *s1;{ register char *tem; if (s1 == 0) return 0; tem = (char *) xmalloc (strlen (s1) + 1); strcpy (tem, s1); return tem;}voidmybzero (b, length) register char *b; register int length;{ while (length-- > 0) *b++ = 0;}char *concat (s1, s2) char *s1, *s2;{ register char *tem; if (s1 == 0) return s2; if (s2 == 0) return s1; tem = (char *) xmalloc (strlen (s1) + strlen (s2) + 2); strcpy (tem, s1); strcat (tem, " "); strcat (tem, s2); return tem;}intxrealloc (ptr, size) char *ptr; int size;{ int result = realloc (ptr, size); if (!result) fatal ("virtual memory exhausted"); return result;}intxmalloc (size){ register int val = malloc (size); if (val == 0) fatal ("virtual memory exhausted"); return val;}voidfatal (s, a1, a2) char *s;{ fprintf (stderr, "genrecog: "); fprintf (stderr, s, a1, a2); fprintf (stderr, "\n"); fprintf (stderr, "after %d instruction definitions\n", next_insn_code); exit (FATAL_EXIT_CODE);}/* More 'friendly' abort that prints the line and file. config.h can #define abort fancy_abort if you like that sort of thing. */voidfancy_abort (){ fatal ("Internal gcc abort.");}intmain (argc, argv) int argc; char **argv;{ rtx desc; struct decision *tree = 0; FILE *infile; extern rtx read_rtx (); register int c; obstack_init (rtl_obstack); if (argc <= 1) fatal ("No input file name."); infile = fopen (argv[1], "r"); if (infile == 0) { perror (argv[1]); exit (FATAL_EXIT_CODE); } init_rtl (); next_insn_code = 0; printf ("/* Generated automatically by the program `genrecog'\n\from the machine description file `md'. */\n\n"); /* Read the machine description. */ while (1) { c = read_skip_spaces (infile); if (c == EOF) break; ungetc (c, infile); desc = read_rtx (infile); if (GET_CODE (desc) == DEFINE_INSN) tree = merge_trees (tree, make_insn_sequence (desc)); if (GET_CODE (desc) == DEFINE_PEEPHOLE || GET_CODE (desc) == DEFINE_EXPAND) next_insn_code++; } printf ("#include \"config.h\"\n"); printf ("#include \"rtl.h\"\n"); printf ("#include \"insn-config.h\"\n"); printf ("#include \"recog.h\"\n"); printf ("#include \"real.h\"\n"); printf ("\n\/* `recog' contains a decision tree\n\ that recognizes whether the rtx X0 is a valid instruction.\n\\n\ recog returns -1 if the rtx is not valid.\n\ If the rtx is valid, recog returns a nonnegative number\n\ which is the insn code number for the pattern that matched.\n"); printf (" This is the same as the order in the machine description of\n\ the entry that matched. This number can be used as an index into\n\ insn_templates and insn_n_operands (found in insn-output.c)\n\ or as an argument to output_insn_hairy (also in insn-output.c). */\n\n"); printf ("rtx recog_operand[MAX_RECOG_OPERANDS];\n\n"); printf ("rtx *recog_operand_loc[MAX_RECOG_OPERANDS];\n\n"); printf ("rtx *recog_dup_loc[MAX_DUP_OPERANDS];\n\n"); printf ("char recog_dup_num[MAX_DUP_OPERANDS];\n\n"); printf ("extern rtx recog_addr_dummy;\n\n"); printf ("#define operands recog_operand\n\n"); break_out_subroutines (tree); printf ("int\nrecog (x0, insn)\n register rtx x0;\n rtx insn;\n{\n"); printf (" register rtx x1, x2, x3, x4, x5;\n rtx x6, x7, x8, x9, x10, x11;\n"); printf (" int tem;\n"); write_tree (tree, "", 0, "", 1); printf (" ret0: return -1;\n}\n"); fflush (stdout); exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -