/* Generate code from machine description to emit insns as rtl.
Copyright (C) 1987, 1988, 1991, 1994, 1995, 1997, 1998, 1999, 2000, 2001,
- 2003, 2004, 2005, 2007, 2008, 2009 Free Software Foundation, Inc.
+ 2003, 2004, 2005, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
This file is part of GCC.
#include "tm.h"
#include "rtl.h"
#include "errors.h"
+#include "read-md.h"
#include "gensupport.h"
-static int max_opno;
-static int max_dup_opno;
-static int max_scratch_opno;
static int insn_code_number;
static int insn_index_number;
struct clobber_ent *next;
};
-static void max_operand_1 (rtx);
-static int max_operand_vec (rtx, int);
static void print_code (RTX_CODE);
static void gen_exp (rtx, enum rtx_code, char *);
static void gen_insn (rtx, int);
\f
static void
-max_operand_1 (rtx x)
-{
- RTX_CODE code;
- int i;
- int len;
- const char *fmt;
-
- if (x == 0)
- return;
-
- code = GET_CODE (x);
-
- if (code == MATCH_OPERAND || code == MATCH_OPERATOR
- || code == MATCH_PARALLEL)
- max_opno = MAX (max_opno, XINT (x, 0));
- if (code == MATCH_DUP || code == MATCH_OP_DUP || code == MATCH_PAR_DUP)
- max_dup_opno = MAX (max_dup_opno, XINT (x, 0));
- if (code == MATCH_SCRATCH)
- max_scratch_opno = MAX (max_scratch_opno, XINT (x, 0));
-
- fmt = GET_RTX_FORMAT (code);
- len = GET_RTX_LENGTH (code);
- for (i = 0; i < len; i++)
- {
- if (fmt[i] == 'e' || fmt[i] == 'u')
- max_operand_1 (XEXP (x, i));
- else if (fmt[i] == 'E')
- {
- int j;
- for (j = 0; j < XVECLEN (x, i); j++)
- max_operand_1 (XVECEXP (x, i, j));
- }
- }
-}
-
-static int
-max_operand_vec (rtx insn, int arg)
-{
- int len = XVECLEN (insn, arg);
- int i;
-
- max_opno = -1;
- max_dup_opno = -1;
- max_scratch_opno = -1;
-
- for (i = 0; i < len; i++)
- max_operand_1 (XVECEXP (insn, arg, i));
-
- return max_opno + 1;
-}
-\f
-static void
print_code (RTX_CODE code)
{
const char *p1;
case PC:
printf ("pc_rtx");
return;
+ case RETURN:
+ printf ("ret_rtx");
+ return;
+ case SIMPLE_RETURN:
+ printf ("simple_return_rtx");
+ return;
case CLOBBER:
if (REG_P (XEXP (x, 0)))
{
static void
gen_insn (rtx insn, int lineno)
{
- int operands;
+ struct pattern_stats stats;
int i;
/* See if the pattern for this insn ends with a group of CLOBBERs of (hard)
if (XSTR (insn, 0)[0] == 0 || XSTR (insn, 0)[0] == '*')
return;
- printf ("/* %s:%d */\n", read_rtx_filename, lineno);
+ printf ("/* %s:%d */\n", read_md_filename, lineno);
/* Find out how many operands this function has. */
- operands = max_operand_vec (insn, 1);
- if (max_dup_opno >= operands)
+ get_pattern_stats (&stats, XVEC (insn, 1));
+ if (stats.max_dup_opno > stats.max_opno)
fatal ("match_dup operand number has no match_operand");
/* Output the function name and argument declarations. */
printf ("rtx\ngen_%s (", XSTR (insn, 0));
- if (operands)
- for (i = 0; i < operands; i++)
+ if (stats.num_generator_args)
+ for (i = 0; i < stats.num_generator_args; i++)
if (i)
printf (",\n\trtx operand%d ATTRIBUTE_UNUSED", i);
else
}
else
{
- char *used = XCNEWVEC (char, operands);
+ char *used = XCNEWVEC (char, stats.num_generator_args);
printf (" return gen_rtx_PARALLEL (VOIDmode, gen_rtvec (%d",
XVECLEN (insn, 1));
static void
gen_expand (rtx expand)
{
- int operands;
+ struct pattern_stats stats;
int i;
char *used;
fatal ("define_expand for %s lacks a pattern", XSTR (expand, 0));
/* Find out how many operands this function has. */
- operands = max_operand_vec (expand, 1);
+ get_pattern_stats (&stats, XVEC (expand, 1));
/* Output the function name and argument declarations. */
printf ("rtx\ngen_%s (", XSTR (expand, 0));
- if (operands)
- for (i = 0; i < operands; i++)
+ if (stats.num_generator_args)
+ for (i = 0; i < stats.num_generator_args; i++)
if (i)
printf (",\n\trtx operand%d", i);
else
and no MATCH_DUPs are present, we can just return the desired insn
like we do for a DEFINE_INSN. This saves memory. */
if ((XSTR (expand, 3) == 0 || *XSTR (expand, 3) == '\0')
- && operands > max_dup_opno
+ && stats.max_opno >= stats.max_dup_opno
&& XVECLEN (expand, 1) == 1)
{
printf (" return ");
/* For each operand referred to only with MATCH_DUPs,
make a local variable. */
- for (i = operands; i <= max_dup_opno; i++)
+ for (i = stats.num_generator_args; i <= stats.max_dup_opno; i++)
printf (" rtx operand%d;\n", i);
- for (; i <= max_scratch_opno; i++)
+ for (; i <= stats.max_scratch_opno; i++)
printf (" rtx operand%d ATTRIBUTE_UNUSED;\n", i);
printf (" rtx _val = 0;\n");
printf (" start_sequence ();\n");
if (XSTR (expand, 3) && *XSTR (expand, 3))
{
printf (" {\n");
- if (operands > 0 || max_dup_opno >= 0 || max_scratch_opno >= 0)
- printf (" rtx operands[%d];\n",
- MAX (operands, MAX (max_scratch_opno, max_dup_opno) + 1));
+ if (stats.num_operand_vars > 0)
+ printf (" rtx operands[%d];\n", stats.num_operand_vars);
+
/* Output code to copy the arguments into `operands'. */
- for (i = 0; i < operands; i++)
+ for (i = 0; i < stats.num_generator_args; i++)
printf (" operands[%d] = operand%d;\n", i, i);
/* Output the special code to be executed before the sequence
is generated. */
- print_rtx_ptr_loc (XSTR (expand, 3));
+ print_md_ptr_loc (XSTR (expand, 3));
printf ("%s\n", XSTR (expand, 3));
/* Output code to copy the arguments back out of `operands'
(unless we aren't going to use them at all). */
if (XVEC (expand, 1) != 0)
{
- for (i = 0; i < operands; i++)
- printf (" operand%d = operands[%d];\n", i, i);
- for (; i <= max_dup_opno; i++)
- printf (" operand%d = operands[%d];\n", i, i);
- for (; i <= max_scratch_opno; i++)
- printf (" operand%d = operands[%d];\n", i, i);
+ for (i = 0; i < stats.num_operand_vars; i++)
+ {
+ printf (" operand%d = operands[%d];\n", i, i);
+ printf (" (void) operand%d;\n", i);
+ }
}
printf (" }\n");
}
Use emit_insn to add them to the sequence being accumulated.
But don't do this if the user's code has set `no_more' nonzero. */
- used = XCNEWVEC (char,
- MAX (operands, MAX (max_scratch_opno, max_dup_opno) + 1));
+ used = XCNEWVEC (char, stats.num_operand_vars);
for (i = 0; i < XVECLEN (expand, 1); i++)
{
|| (GET_CODE (next) == PARALLEL
&& ((GET_CODE (XVECEXP (next, 0, 0)) == SET
&& GET_CODE (SET_DEST (XVECEXP (next, 0, 0))) == PC)
- || GET_CODE (XVECEXP (next, 0, 0)) == RETURN))
- || GET_CODE (next) == RETURN)
+ || ANY_RETURN_P (XVECEXP (next, 0, 0))))
+ || ANY_RETURN_P (next))
printf (" emit_jump_insn (");
else if ((GET_CODE (next) == SET && GET_CODE (SET_SRC (next)) == CALL)
|| GET_CODE (next) == CALL
static void
gen_split (rtx split)
{
+ struct pattern_stats stats;
int i;
- int operands;
const char *const name =
((GET_CODE (split) == DEFINE_PEEPHOLE2) ? "peephole2" : "split");
const char *unused;
/* Find out how many operands this function has. */
- max_operand_vec (split, 2);
- operands = MAX (max_opno, MAX (max_dup_opno, max_scratch_opno)) + 1;
- unused = (operands == 0 ? " ATTRIBUTE_UNUSED" : "");
- used = XCNEWVEC (char, operands);
+ get_pattern_stats (&stats, XVEC (split, 2));
+ unused = (stats.num_operand_vars == 0 ? " ATTRIBUTE_UNUSED" : "");
+ used = XCNEWVEC (char, stats.num_operand_vars);
/* Output the prototype, function name and argument declarations. */
if (GET_CODE (split) == DEFINE_PEEPHOLE2)
printf ("{\n");
/* Declare all local variables. */
- for (i = 0; i < operands; i++)
+ for (i = 0; i < stats.num_operand_vars; i++)
printf (" rtx operand%d;\n", i);
printf (" rtx _val = 0;\n");
if (XSTR (split, 3))
{
- print_rtx_ptr_loc (XSTR (split, 3));
+ print_md_ptr_loc (XSTR (split, 3));
printf ("%s\n", XSTR (split, 3));
}
/* Output code to copy the arguments back out of `operands' */
- for (i = 0; i < operands; i++)
- printf (" operand%d = operands[%d];\n", i, i);
+ for (i = 0; i < stats.num_operand_vars; i++)
+ {
+ printf (" operand%d = operands[%d];\n", i, i);
+ printf (" (void) operand%d;\n", i);
+ }
/* Output code to construct the rtl for the instruction bodies.
Use emit_insn to add them to the sequence being accumulated.
|| (GET_CODE (next) == PARALLEL
&& GET_CODE (XVECEXP (next, 0, 0)) == SET
&& GET_CODE (SET_DEST (XVECEXP (next, 0, 0))) == PC)
- || GET_CODE (next) == RETURN)
+ || ANY_RETURN_P (next))
printf (" emit_jump_insn (");
else if ((GET_CODE (next) == SET && GET_CODE (SET_SRC (next)) == CALL)
|| GET_CODE (next) == CALL
progname = "genemit";
- if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
+ if (!init_rtx_reader_args (argc, argv))
return (FATAL_EXIT_CODE);
/* Assign sequential codes to all entries in the machine description
printf ("#include \"function.h\"\n");
printf ("#include \"expr.h\"\n");
printf ("#include \"optabs.h\"\n");
- printf ("#include \"real.h\"\n");
printf ("#include \"dfp.h\"\n");
printf ("#include \"flags.h\"\n");
printf ("#include \"output.h\"\n");
printf ("#include \"recog.h\"\n");
printf ("#include \"resource.h\"\n");
printf ("#include \"reload.h\"\n");
- printf ("#include \"toplev.h\"\n");
+ printf ("#include \"diagnostic-core.h\"\n");
printf ("#include \"regs.h\"\n");
printf ("#include \"tm-constrs.h\"\n");
printf ("#include \"ggc.h\"\n");
break;
case DEFINE_EXPAND:
- printf ("/* %s:%d */\n", read_rtx_filename, line_no);
+ printf ("/* %s:%d */\n", read_md_filename, line_no);
gen_expand (desc);
break;
case DEFINE_SPLIT:
- printf ("/* %s:%d */\n", read_rtx_filename, line_no);
+ printf ("/* %s:%d */\n", read_md_filename, line_no);
gen_split (desc);
break;
case DEFINE_PEEPHOLE2:
- printf ("/* %s:%d */\n", read_rtx_filename, line_no);
+ printf ("/* %s:%d */\n", read_md_filename, line_no);
gen_split (desc);
break;