📄 genoutput.c
字号:
return; case MATCH_DUP: case MATCH_OP_DUP: case MATCH_PAR_DUP: ++num_dups; return; case ADDRESS: scan_operands (XEXP (part, 0), 1, 0); return; case STRICT_LOW_PART: scan_operands (XEXP (part, 0), 0, 1); return; } format_ptr = GET_RTX_FORMAT (GET_CODE (part)); for (i = 0; i < GET_RTX_LENGTH (GET_CODE (part)); i++) switch (*format_ptr++) { case 'e': scan_operands (XEXP (part, i), 0, 0); break; case 'E': if (XVEC (part, i) != NULL) for (j = 0; j < XVECLEN (part, i); j++) scan_operands (XVECEXP (part, i, j), 0, 0); break; }}/* Process an assembler template from a define_insn or a define_peephole. It is either the assembler code template, a list of assembler code templates, or C code to generate the assembler code template. */static voidprocess_template (d, template) struct data *d; char *template;{ register char *cp; register int i; /* We need to consider only the instructions whose assembler code template starts with a * or @. These are the ones where C code is run to decide on a template to use. So for all others just return now. */ if (template[0] != '*' && template[0] != '@') { d->template = template; d->outfun = 0; return; } d->template = 0; d->outfun = 1; printf ("\nstatic char *\n"); printf ("output_%d (operands, insn)\n", d->code_number); printf (" rtx *operands;\n"); printf (" rtx insn;\n"); printf ("{\n"); /* If the assembler code template starts with a @ it is a newline-separated list of assembler code templates, one for each alternative. So produce a routine to select the correct one. */ if (template[0] == '@') { printf (" static /*const*/ char *const strings_%d[] = {\n", d->code_number); for (i = 0, cp = &template[1]; *cp; ) { while (*cp == '\n' || *cp == ' ' || *cp== '\t') cp++; printf (" \""); while (*cp != '\n' && *cp != '\0') putchar (*cp++); printf ("\",\n"); i++; } printf (" };\n"); printf (" return strings_%d[which_alternative];\n", d->code_number); if (i != d->n_alternatives) fatal ("Insn pattern %d has %d alternatives but %d assembler choices", d->index_number, d->n_alternatives, i); } else { /* The following is done in a funny way to get around problems in VAX-11 "C" on VMS. It is the equivalent of: printf ("%s\n", &template[1])); */ cp = &template[1]; while (*cp) putchar (*cp++); putchar ('\n'); } printf ("}\n");}/* Check insn D for consistency in number of constraint alternatives. */static voidvalidate_insn_alternatives (d) struct data *d;{ register int n = 0, start; /* Make sure all the operands have the same number of alternatives in their constraints. Let N be that number. */ for (start = 0; start < d->n_operands; start++) if (d->op_n_alternatives[start] > 0) { if (n == 0) n = d->op_n_alternatives[start]; else if (n != d->op_n_alternatives[start]) error ("wrong number of alternatives in operand %d of insn number %d", start, d->index_number); } /* Record the insn's overall number of alternatives. */ d->n_alternatives = n;}/* Look at a define_insn just read. Assign its code number. Record on insn_data the template and the number of arguments. If the insn has a hairy output action, output a function for now. */static voidgen_insn (insn) rtx insn;{ register struct data *d = (struct data *) xmalloc (sizeof (struct data)); register int i; d->code_number = next_code_number++; d->index_number = next_index_number; if (XSTR (insn, 0)[0]) d->name = XSTR (insn, 0); else d->name = 0; /* Build up the list in the same order as the insns are seen in the machine description. */ d->next = 0; if (end_of_insn_data) end_of_insn_data->next = d; else insn_data = d; end_of_insn_data = d; max_opno = -1; num_dups = 0; mybzero (constraints, sizeof constraints); mybzero (op_n_alternatives, sizeof op_n_alternatives); mybzero (predicates, sizeof predicates); mybzero (address_p, sizeof address_p); mybzero (modes, sizeof modes); mybzero (strict_low, sizeof strict_low); mybzero (seen, sizeof seen); for (i = 0; i < XVECLEN (insn, 1); i++) scan_operands (XVECEXP (insn, 1, i), 0, 0); d->n_operands = max_opno + 1; d->n_dups = num_dups; mybcopy (constraints, d->constraints, sizeof constraints); mybcopy (op_n_alternatives, d->op_n_alternatives, sizeof op_n_alternatives); mybcopy (predicates, d->predicates, sizeof predicates); mybcopy (address_p, d->address_p, sizeof address_p); mybcopy (modes, d->modes, sizeof modes); mybcopy (strict_low, d->strict_low, sizeof strict_low); validate_insn_alternatives (d); process_template (d, XSTR (insn, 3));}/* Look at a define_peephole just read. Assign its code number. Record on insn_data the template and the number of arguments. If the insn has a hairy output action, output it now. */static voidgen_peephole (peep) rtx peep;{ register struct data *d = (struct data *) xmalloc (sizeof (struct data)); register int i; d->code_number = next_code_number++; d->index_number = next_index_number; d->name = 0; /* Build up the list in the same order as the insns are seen in the machine description. */ d->next = 0; if (end_of_insn_data) end_of_insn_data->next = d; else insn_data = d; end_of_insn_data = d; max_opno = -1; mybzero (constraints, sizeof constraints); mybzero (op_n_alternatives, sizeof op_n_alternatives); mybzero (predicates, sizeof predicates); mybzero (address_p, sizeof address_p); mybzero (modes, sizeof modes); mybzero (strict_low, sizeof strict_low); mybzero (seen, sizeof seen); /* Get the number of operands by scanning all the patterns of the peephole optimizer. But ignore all the rest of the information thus obtained. */ for (i = 0; i < XVECLEN (peep, 0); i++) scan_operands (XVECEXP (peep, 0, i), 0, 0); d->n_operands = max_opno + 1; d->n_dups = 0; mybcopy (constraints, d->constraints, sizeof constraints); mybcopy (op_n_alternatives, d->op_n_alternatives, sizeof op_n_alternatives); mybzero (d->predicates, sizeof predicates); mybzero (d->address_p, sizeof address_p); mybzero (d->modes, sizeof modes); mybzero (d->strict_low, sizeof strict_low); validate_insn_alternatives (d); process_template (d, XSTR (peep, 2));}/* Process a define_expand just read. Assign its code number, only for the purposes of `insn_gen_function'. */static voidgen_expand (insn) rtx insn;{ register struct data *d = (struct data *) xmalloc (sizeof (struct data)); register int i; d->code_number = next_code_number++; d->index_number = next_index_number; if (XSTR (insn, 0)[0]) d->name = XSTR (insn, 0); else d->name = 0; /* Build up the list in the same order as the insns are seen in the machine description. */ d->next = 0; if (end_of_insn_data) end_of_insn_data->next = d; else insn_data = d; end_of_insn_data = d; max_opno = -1; num_dups = 0; /* Scan the operands to get the specified predicates and modes, since expand_binop needs to know them. */ mybzero (constraints, sizeof constraints); mybzero (op_n_alternatives, sizeof op_n_alternatives); mybzero (predicates, sizeof predicates); mybzero (address_p, sizeof address_p); mybzero (modes, sizeof modes); mybzero (strict_low, sizeof strict_low); mybzero (seen, sizeof seen); if (XVEC (insn, 1)) for (i = 0; i < XVECLEN (insn, 1); i++) scan_operands (XVECEXP (insn, 1, i), 0, 0); d->n_operands = max_opno + 1; d->n_dups = num_dups; mybcopy (constraints, d->constraints, sizeof constraints); mybcopy (op_n_alternatives, d->op_n_alternatives, sizeof op_n_alternatives); mybcopy (predicates, d->predicates, sizeof predicates); mybcopy (address_p, d->address_p, sizeof address_p); mybcopy (modes, d->modes, sizeof modes); mybcopy (strict_low, d->strict_low, sizeof strict_low); d->template = 0; d->outfun = 0; validate_insn_alternatives (d);}/* Process a define_split just read. Assign its code number, only for reasons of consistency and to simplify genrecog. */static voidgen_split (split) rtx split;{ register struct data *d = (struct data *) xmalloc (sizeof (struct data)); register int i; d->code_number = next_code_number++; d->index_number = next_index_number; d->name = 0; /* Build up the list in the same order as the insns are seen in the machine description. */ d->next = 0; if (end_of_insn_data) end_of_insn_data->next = d; else insn_data = d; end_of_insn_data = d; max_opno = -1; num_dups = 0; mybzero (constraints, sizeof constraints); mybzero (op_n_alternatives, sizeof op_n_alternatives); mybzero (predicates, sizeof predicates); mybzero (address_p, sizeof address_p); mybzero (modes, sizeof modes); mybzero (strict_low, sizeof strict_low); mybzero (seen, sizeof seen); /* Get the number of operands by scanning all the patterns of the split patterns. But ignore all the rest of the information thus obtained. */ for (i = 0; i < XVECLEN (split, 0); i++) scan_operands (XVECEXP (split, 0, i), 0, 0); d->n_operands = max_opno + 1; mybzero (d->constraints, sizeof constraints); mybzero (d->op_n_alternatives, sizeof op_n_alternatives); mybzero (d->predicates, sizeof predicates); mybzero (d->address_p, sizeof address_p); mybzero (d->modes, sizeof modes); mybzero (d->strict_low, sizeof strict_low); d->n_dups = 0; d->n_alternatives = 0; d->template = 0; d->outfun = 0;}char *xmalloc (size) unsigned size;{ register char *val = (char *) malloc (size); if (val == 0) fatal ("virtual memory exhausted"); return val;}char *xrealloc (ptr, size) char *ptr; unsigned size;{ char *result = (char *) realloc (ptr, size); if (!result) fatal ("virtual memory exhausted"); return result;}static voidmybzero (b, length) register char *b; register unsigned length;{ while (length-- > 0) *b++ = 0;}static voidmybcopy (b1, b2, length) register char *b1; register char *b2; register unsigned length;{ while (length-- > 0) *b2++ = *b1++;}static voidfatal (s, a1, a2, a3, a4) char *s;{ fprintf (stderr, "genoutput: "); fprintf (stderr, s, a1, a2, a3, a4); fprintf (stderr, "\n"); 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.");}static voiderror (s, a1, a2) char *s;{ fprintf (stderr, "genoutput: "); fprintf (stderr, s, a1, a2); fprintf (stderr, "\n"); have_error = 1;}intmain (argc, argv) int argc; char **argv;{ rtx desc; FILE *infile; 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 (); output_prologue (); next_code_number = 0; next_index_number = 0; have_constraints = 0; /* 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) gen_insn (desc); if (GET_CODE (desc) == DEFINE_PEEPHOLE) gen_peephole (desc); if (GET_CODE (desc) == DEFINE_EXPAND) gen_expand (desc); if (GET_CODE (desc) == DEFINE_SPLIT) gen_split (desc); next_index_number++; } output_epilogue (); fflush (stdout); exit (ferror (stdout) != 0 || have_error ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE); /* NOTREACHED */ return 0;}static intn_occurrences (c, s) int c; char *s;{ int n = 0; while (*s) n += (*s++ == c); return n;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -