📄 genrecog.c
字号:
printf ("XVECLEN (x%d, 0) == %d && ", depth, p->veclen); if (p->dupno >= 0) printf ("rtx_equal_p (x%d, ro[%d]) && ", depth, p->dupno); if (p->num_clobbers_to_add) printf ("pnum_clobbers != 0 && "); if (p->tests) printf ("%s (x%d, %smode)", p->tests, depth, GET_MODE_NAME (p->mode)); else printf ("1"); printf (")\n"); inner_indent += 2; } else uncond = 1; need_bracket = ! uncond; if (p->opno >= 0) { if (need_bracket) { printf ("%s{\n", indents[inner_indent]); inner_indent += 2; wrote_bracket = 1; need_bracket = 0; } printf ("%sro[%d] = x%d;\n", indents[inner_indent], p->opno, depth); } if (p->c_test) { printf ("%sif (%s)\n", indents[inner_indent], p->c_test); inner_indent += 2; uncond = 0; need_bracket = 1; } if (p->insn_code_number >= 0) { if (type == SPLIT) printf ("%sreturn gen_split_%d (operands);\n", indents[inner_indent], p->insn_code_number); else { if (p->num_clobbers_to_add) { if (need_bracket) { printf ("%s{\n", indents[inner_indent]); inner_indent += 2; } printf ("%s*pnum_clobbers = %d;\n", indents[inner_indent], p->num_clobbers_to_add); printf ("%sreturn %d;\n", indents[inner_indent], p->insn_code_number); if (need_bracket) { inner_indent -= 2; printf ("%s}\n", indents[inner_indent]); } } else printf ("%sreturn %d;\n", indents[inner_indent], p->insn_code_number); } } else printf ("%sgoto L%d;\n", indents[inner_indent], p->success.first->number); if (wrote_bracket) printf ("%s}\n", indents[inner_indent - 2]); } /* We have now tested all alternatives. End any switches we have open and branch to the alternative node unless we know that we can't fall through to the branch. */ if (switch_code != UNKNOWN) { printf ("%s}\n", indents[indent - 2]); indent -= 4; uncond = 0; } if (switch_mode != VOIDmode) { printf ("%s}\n", indents[indent - 2]); indent -= 4; uncond = 0; } if (indent != 2) abort (); if (uncond) return; if (afterward) { change_state (prevpos, afterward->position, 2); printf (" goto L%d;\n", afterward->number); } else printf (" goto ret0;\n");}static voidprint_code (code) enum 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); }}static intsame_codes (p, code) register struct decision *p; register enum rtx_code code;{ for (; p; p = p->next) if (p->code != code) return 0; return 1;}static voidclear_codes (p) register struct decision *p;{ for (; p; p = p->next) p->ignore_code = 1;}static intsame_modes (p, mode) register struct decision *p; register enum machine_mode mode;{ for (; p; p = p->next) if ((p->enforce_mode ? p->mode : VOIDmode) != mode) return 0; return 1;}static voidclear_modes (p) register struct decision *p;{ for (; p; p = p->next) p->enforce_mode = 0;}/* Write out the decision tree starting at TREE for a subroutine of type TYPE. PREVPOS is the position at the node that branched to this node. INITIAL is nonzero if this is the first node we are writing in a subroutine. If all nodes are false, branch to the node AFTERWARD. */static voidwrite_tree (tree, prevpos, afterward, initial, type) struct decision *tree; char *prevpos; struct decision *afterward; int initial; enum routine_type type;{ register struct decision *p; char *name_prefix = (type == SPLIT ? "split" : "recog"); char *call_suffix = (type == SPLIT ? "" : ", pnum_clobbers"); if (! initial && tree->subroutine_number > 0) { printf (" L%d:\n", tree->number); if (afterward) { printf (" tem = %s_%d (x0, insn%s);\n", name_prefix, tree->subroutine_number, call_suffix); if (type == SPLIT) printf (" if (tem != 0) return tem;\n"); else printf (" if (tem >= 0) return tem;\n"); change_state (tree->position, afterward->position, 2); printf (" goto L%d;\n", afterward->number); } else printf (" return %s_%d (x0, insn%s);\n", name_prefix, tree->subroutine_number, call_suffix); return; } write_tree_1 (tree, prevpos, afterward, type); for (p = tree; p; p = p->next) if (p->success.first) write_tree (p->success.first, p->position, p->afterward ? p->afterward : afterward, 0, type);}/* Assuming that the state of argument is denoted by OLDPOS, take whatever actions are necessary to move to NEWPOS. INDENT says how many blanks to place at the front of lines. */static voidchange_state (oldpos, newpos, indent) char *oldpos; char *newpos; int indent;{ 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] >= 'a' && newpos[depth] <= 'z') printf ("%sx%d = XVECEXP (x%d, 0, %d);\n", indents[indent], depth + 1, depth, newpos[depth] - 'a'); else printf ("%sx%d = XEXP (x%d, %c);\n", indents[indent], depth + 1, depth, newpos[depth]); ++depth; }}static char *copystr (s1) char *s1;{ register char *tem; if (s1 == 0) return 0; tem = (char *) xmalloc (strlen (s1) + 1); strcpy (tem, s1); return tem;}static voidmybzero (b, length) register char *b; register unsigned length;{ while (length-- > 0) *b++ = 0;}static voidmybcopy (in, out, length) register char *in, *out; register unsigned length;{ while (length-- > 0) *out++ = *in++;}static 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;}char *xrealloc (ptr, size) char *ptr; unsigned size;{ char *result = (char *) realloc (ptr, size); if (!result) fatal ("virtual memory exhausted"); return result;}char *xmalloc (size) unsigned size;{ register char *val = (char *) malloc (size); if (val == 0) fatal ("virtual memory exhausted"); return val;}static voidfatal (s) char *s;{ fprintf (stderr, "genrecog: "); fprintf (stderr, s); fprintf (stderr, "\n"); fprintf (stderr, "after %d definitions\n", next_index); 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_head recog_tree; struct decision_head split_tree; FILE *infile; register int c; obstack_init (rtl_obstack); recog_tree.first = recog_tree.last = split_tree.first = split_tree.last = 0; 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; next_index = 0; printf ("/* Generated automatically by the program `genrecog'\n\from the machine description file `md'. */\n\n"); 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 ("#include \"output.h\"\n"); printf ("#include \"flags.h\"\n"); printf ("\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) recog_tree = merge_trees (recog_tree, make_insn_sequence (desc, RECOG)); else if (GET_CODE (desc) == DEFINE_SPLIT) split_tree = merge_trees (split_tree, make_insn_sequence (desc, SPLIT)); if (GET_CODE (desc) == DEFINE_PEEPHOLE || GET_CODE (desc) == DEFINE_EXPAND) next_insn_code++; next_index++; } 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\ entry that matched. This number can be used as an index into various\n\ insn_* tables, such as insn_templates, insn_outfun, and insn_n_operands\n\ (found in insn-output.c).\n\n"); printf (" The third argument to recog is an optional pointer to an int.\n\ If present, recog will accept a pattern if it matches except for\n\ missing CLOBBER expressions at the end. In that case, the value\n\ pointed to by the optional pointer will be set to the number of\n\ CLOBBERs that need to be added (it should be initialized to zero by\n\ the caller). If it is set nonzero, the caller should allocate a\n\ PARALLEL of the appropriate size, copy the initial entries, and call\n\ add_clobbers (found in insn-emit.c) to fill in the CLOBBERs."); if (split_tree.first) printf ("\n\n The function split_insns returns 0 if the rtl could not\n\ be split or the split rtl in a SEQUENCE if it can be."); printf ("*/\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 ("#define operands recog_operand\n\n"); next_subroutine_number = 0; break_out_subroutines (recog_tree, RECOG, 1); write_subroutine (recog_tree.first, RECOG); next_subroutine_number = 0; break_out_subroutines (split_tree, SPLIT, 1); write_subroutine (split_tree.first, SPLIT); fflush (stdout); exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE); /* NOTREACHED */ return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -