📄 genoutput.c
字号:
/* Generate code from to output assembler insns as recognized from rtl. Copyright (C) 1987, 1988, 1992 Free Software Foundation, Inc.This file is part of GNU CC.GNU CC is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2, or (at your option)any later version.GNU CC is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with GNU CC; see the file COPYING. If not, write tothe Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. *//* This program reads the machine description for the compiler target machine and produces a file containing these things: 1. An array of strings `insn_template' which is indexed by insn code number and contains the template for output of that insn, 2. An array of functions `insn_outfun' which, indexed by the insn code number, gives the function that returns a template to use for output of that insn. This is used only in the cases where the template is not constant. These cases are specified by a * or @ at the beginning of the template string in the machine description. They are identified for the sake of other parts of the compiler by a zero element in `insn_template'. 3. An array of functions `insn_gen_function' which, indexed by insn code number, gives the function to generate a body for that pattern, given operands as arguments. 4. An array of strings `insn_name' which, indexed by insn code number, gives the name for that pattern. Nameless patterns are given a name. 5. An array of ints `insn_n_operands' which is indexed by insn code number and contains the number of distinct operands in the pattern for that insn, 6. An array of ints `insn_n_dups' which is indexed by insn code number and contains the number of match_dup's that appear in the insn's pattern. This says how many elements of `recog_dup_loc' are significant after an insn has been recognized. 7. An array of arrays of operand constraint strings, `insn_operand_constraint', indexed first by insn code number and second by operand number, containing the constraint for that operand. This array is generated only if register constraints appear in match_operand rtx's. 8. An array of arrays of chars which indicate which operands of which insn patterns appear within ADDRESS rtx's. This array is called `insn_operand_address_p' and is generated only if there are *no* register constraints in the match_operand rtx's. 9. An array of arrays of machine modes, `insn_operand_mode', indexed first by insn code number and second by operand number, containing the machine mode that that operand is supposed to have. Also `insn_operand_strict_low', which is nonzero for operands contained in a STRICT_LOW_PART. 10. An array of arrays of int-valued functions, `insn_operand_predicate', indexed first by insn code number and second by operand number, containing the match_operand predicate for this operand. 11. An array of ints, `insn_n_alternatives', that gives the number of alternatives in the constraints of each pattern.The code number of an insn is simply its position in the machine description;code numbers are assigned sequentially to entries in the description,starting with code number 0.Thus, the following entry in the machine description (define_insn "clrdf" [(set (match_operand:DF 0 "general_operand" "") (const_int 0))] "" "clrd %0")assuming it is the 25th entry present, would causeinsn_template[24] to be "clrd %0", and insn_n_operands[24] to be 1.It would not make an case in output_insn_hairy because the templategiven in the entry is a constant (it does not start with `*'). */#include <stdio.h>#include "hconfig.h"#include "rtl.h"#include "obstack.h"/* No instruction can have more operands than this. Sorry for this arbitrary limit, but what machine will have an instruction with this many operands? */#define MAX_MAX_OPERANDS 40static struct obstack obstack;struct obstack *rtl_obstack = &obstack;#define obstack_chunk_alloc xmalloc#define obstack_chunk_free freeextern void free ();extern rtx read_rtx ();char *xmalloc ();static void fatal ();void fancy_abort ();static void error ();static void mybcopy ();static void mybzero ();static int n_occurrences ();/* insns in the machine description are assigned sequential code numbers that are used by insn-recog.c (produced by genrecog) to communicate to insn-output.c (produced by this program). */static int next_code_number;/* This counts all definitions in the md file, for the sake of error messages. */static int next_index_number;/* Record in this chain all information that we will output, associated with the code number of the insn. */struct data{ int code_number; int index_number; char *name; char *template; /* string such as "movl %1,%0" */ int n_operands; /* Number of operands this insn recognizes */ int n_dups; /* Number times match_dup appears in pattern */ int n_alternatives; /* Number of alternatives in each constraint */ struct data *next; char *constraints[MAX_MAX_OPERANDS]; /* Number of alternatives in constraints of operand N. */ int op_n_alternatives[MAX_MAX_OPERANDS]; char *predicates[MAX_MAX_OPERANDS]; char address_p[MAX_MAX_OPERANDS]; enum machine_mode modes[MAX_MAX_OPERANDS]; char strict_low[MAX_MAX_OPERANDS]; char outfun; /* Nonzero means this has an output function */};/* This variable points to the first link in the chain. */struct data *insn_data;/* Pointer to the last link in the chain, so new elements can be added at the end. */struct data *end_of_insn_data;/* Nonzero if any match_operand has a constraint string; implies that REGISTER_CONSTRAINTS will be defined for this machine description. */int have_constraints;static voidoutput_prologue (){ printf ("/* Generated automatically by the program `genoutput'\n\from the machine description file `md'. */\n\n"); printf ("#include \"config.h\"\n"); printf ("#include \"rtl.h\"\n"); printf ("#include \"regs.h\"\n"); printf ("#include \"hard-reg-set.h\"\n"); printf ("#include \"real.h\"\n"); printf ("#include \"insn-config.h\"\n\n"); printf ("#include \"conditions.h\"\n"); printf ("#include \"insn-flags.h\"\n"); printf ("#include \"insn-attr.h\"\n\n"); printf ("#include \"insn-codes.h\"\n\n"); printf ("#include \"recog.h\"\n\n"); printf ("#include <stdio.h>\n"); printf ("#include \"output.h\"\n");}static voidoutput_epilogue (){ register struct data *d; printf ("\nchar * const insn_template[] =\n {\n"); for (d = insn_data; d; d = d->next) { if (d->template) printf (" \"%s\",\n", d->template); else printf (" 0,\n"); } printf (" };\n"); printf ("\nchar *(*const insn_outfun[])() =\n {\n"); for (d = insn_data; d; d = d->next) { if (d->outfun) printf (" output_%d,\n", d->code_number); else printf (" 0,\n"); } printf (" };\n"); printf ("\nrtx (*const insn_gen_function[]) () =\n {\n"); for (d = insn_data; d; d = d->next) { if (d->name) printf (" gen_%s,\n", d->name); else printf (" 0,\n"); } printf (" };\n"); printf ("\nchar *insn_name[] =\n {\n"); { int offset = 0; int next; char * last_name = 0; char * next_name; register struct data *n; for (n = insn_data, next = 0; n; n = n->next, next++) if (n->name) { next_name = n->name; break; } for (d = insn_data; d; d = d->next) { if (d->name) { printf (" \"%s\",\n", d->name); offset = 0; last_name = d->name; next_name = 0; for (n = d->next, next = 1; n; n = n->next, next++) if (n->name) { next_name = n->name; break; } } else { offset++; if (next_name && (last_name == 0 || offset > next / 2)) printf (" \"%s-%d\",\n", next_name, next - offset); else printf (" \"%s+%d\",\n", last_name, offset); } } } printf (" };\n"); printf ("char **insn_name_ptr = insn_name;\n"); printf ("\nconst int insn_n_operands[] =\n {\n"); for (d = insn_data; d; d = d->next) printf (" %d,\n", d->n_operands); printf (" };\n"); printf ("\nconst int insn_n_dups[] =\n {\n"); for (d = insn_data; d; d = d->next) printf (" %d,\n", d->n_dups); printf (" };\n"); if (have_constraints) { printf ("\nchar *const insn_operand_constraint[][MAX_RECOG_OPERANDS] =\n {\n"); for (d = insn_data; d; d = d->next) { register int i; printf (" {"); for (i = 0; i < d->n_operands; i++) { if (d->constraints[i] == 0) printf (" \"\","); else printf (" \"%s\",", d->constraints[i]); } if (d->n_operands == 0) printf (" 0"); printf (" },\n"); } printf (" };\n"); } else { printf ("\nconst char insn_operand_address_p[][MAX_RECOG_OPERANDS] =\n {\n"); for (d = insn_data; d; d = d->next) { register int i; printf (" {"); for (i = 0; i < d->n_operands; i++) printf (" %d,", d->address_p[i]); if (d->n_operands == 0) printf (" 0"); printf (" },\n"); } printf (" };\n"); } printf ("\nconst enum machine_mode insn_operand_mode[][MAX_RECOG_OPERANDS] =\n {\n"); for (d = insn_data; d; d = d->next) { register int i; printf (" {"); for (i = 0; i < d->n_operands; i++) printf (" %smode,", GET_MODE_NAME (d->modes[i])); if (d->n_operands == 0) printf (" VOIDmode"); printf (" },\n"); } printf (" };\n"); printf ("\nconst char insn_operand_strict_low[][MAX_RECOG_OPERANDS] =\n {\n"); for (d = insn_data; d; d = d->next) { register int i; printf (" {"); for (i = 0; i < d->n_operands; i++) printf (" %d,", d->strict_low[i]); if (d->n_operands == 0) printf (" 0"); printf (" },\n"); } printf (" };\n"); { /* We need to define all predicates used. Keep a list of those we have defined so far. There normally aren't very many predicates used, so a linked list should be fast enough. */ struct predicate { char *name; struct predicate *next; } *predicates = 0; struct predicate *p; int i; printf ("\n"); for (d = insn_data; d; d = d->next) for (i = 0; i < d->n_operands; i++) if (d->predicates[i] && d->predicates[i][0]) { for (p = predicates; p; p = p->next) if (! strcmp (p->name, d->predicates[i])) break; if (p == 0) { printf ("extern int %s ();\n", d->predicates[i]); p = (struct predicate *) alloca (sizeof (struct predicate)); p->name = d->predicates[i]; p->next = predicates; predicates = p; } } printf ("\nint (*const insn_operand_predicate[][MAX_RECOG_OPERANDS])() =\n {\n"); for (d = insn_data; d; d = d->next) { printf (" {"); for (i = 0; i < d->n_operands; i++) printf (" %s,", ((d->predicates[i] && d->predicates[i][0]) ? d->predicates[i] : "0")); if (d->n_operands == 0) printf (" 0"); printf (" },\n"); } printf (" };\n"); } printf ("\nconst int insn_n_alternatives[] =\n {\n"); for (d = insn_data; d; d = d->next) printf (" %d,\n", d->n_alternatives); printf(" };\n");}/* scan_operands (X) stores in max_opno the largest operand number present in X, if that is larger than the previous value of max_opno. It stores all the constraints in `constraints' and all the machine modes in `modes'. THIS_ADDRESS_P is nonzero if the containing rtx was an ADDRESS. THIS_STRICT_LOW is nonzero if the containing rtx was a STRICT_LOW_PART. */static int max_opno;static int num_dups;static char *constraints[MAX_MAX_OPERANDS];static int op_n_alternatives[MAX_MAX_OPERANDS];static char *predicates[MAX_MAX_OPERANDS];static char address_p[MAX_MAX_OPERANDS];static enum machine_mode modes[MAX_MAX_OPERANDS];static char strict_low[MAX_MAX_OPERANDS];static char seen[MAX_MAX_OPERANDS];static voidscan_operands (part, this_address_p, this_strict_low) rtx part; int this_address_p; int this_strict_low;{ register int i, j; register char *format_ptr; int opno; if (part == 0) return; switch (GET_CODE (part)) { case MATCH_OPERAND: opno = XINT (part, 0); if (opno > max_opno) max_opno = opno; if (max_opno >= MAX_MAX_OPERANDS) { error ("Too many operands (%d) in definition %d.\n", max_opno + 1, next_index_number); return; } if (seen[opno]) error ("Definition %d specified operand number %d more than once.\n", next_index_number, opno); seen[opno] = 1; modes[opno] = GET_MODE (part); strict_low[opno] = this_strict_low; predicates[opno] = XSTR (part, 1); constraints[opno] = XSTR (part, 2); if (XSTR (part, 2) != 0 && *XSTR (part, 2) != 0) { op_n_alternatives[opno] = n_occurrences (',', XSTR (part, 2)) + 1; have_constraints = 1; } address_p[opno] = this_address_p; return; case MATCH_SCRATCH: opno = XINT (part, 0); if (opno > max_opno) max_opno = opno; if (max_opno >= MAX_MAX_OPERANDS) { error ("Too many operands (%d) in definition %d.\n", max_opno + 1, next_index_number); return; } if (seen[opno]) error ("Definition %d specified operand number %d more than once.\n", next_index_number, opno); seen[opno] = 1; modes[opno] = GET_MODE (part); strict_low[opno] = 0; predicates[opno] = "scratch_operand"; constraints[opno] = XSTR (part, 1); if (XSTR (part, 1) != 0 && *XSTR (part, 1) != 0) { op_n_alternatives[opno] = n_occurrences (',', XSTR (part, 1)) + 1; have_constraints = 1; } address_p[opno] = 0; return; case MATCH_OPERATOR: case MATCH_PARALLEL: opno = XINT (part, 0); if (opno > max_opno) max_opno = opno; if (max_opno >= MAX_MAX_OPERANDS) { error ("Too many operands (%d) in definition %d.\n", max_opno + 1, next_index_number); return; } if (seen[opno]) error ("Definition %d specified operand number %d more than once.\n", next_index_number, opno); seen[opno] = 1; modes[opno] = GET_MODE (part); strict_low[opno] = 0; predicates[opno] = XSTR (part, 1); constraints[opno] = 0; address_p[opno] = 0; for (i = 0; i < XVECLEN (part, 2); i++) scan_operands (XVECEXP (part, 2, i), 0, 0); return;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -