/* Generate code from machine description to emit insns as rtl.
- Copyright (C) 1987, 1988, 1991, 1994, 1995, 1997, 1998, 1999, 2000, 2001
- Free Software Foundation, Inc.
+ Copyright (C) 1987, 1988, 1991, 1994, 1995, 1997, 1998, 1999, 2000, 2001,
+ 2003, 2004, 2005, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
+Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
for more details.
You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
-#include "hconfig.h"
+#include "bconfig.h"
#include "system.h"
+#include "coretypes.h"
+#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 register_constraints;
static int insn_code_number;
static int insn_index_number;
/* Data structure for recording the patterns of insns that have CLOBBERs.
- We use this to output a function that adds these CLOBBERs to a
+ We use this to output a function that adds these CLOBBERs to a
previously-allocated PARALLEL expression. */
struct clobber_pat
struct clobber_ent *next;
};
-static void max_operand_1 PARAMS ((rtx));
-static int max_operand_vec PARAMS ((rtx, int));
-static void print_code PARAMS ((RTX_CODE));
-static void gen_exp PARAMS ((rtx, enum rtx_code));
-static void gen_insn PARAMS ((rtx));
-static void gen_expand PARAMS ((rtx));
-static void gen_split PARAMS ((rtx));
-static void output_add_clobbers PARAMS ((void));
-static void output_added_clobbers_hard_reg_p PARAMS ((void));
-static void gen_rtx_scratch PARAMS ((rtx, enum rtx_code));
-static void output_peephole2_scratches PARAMS ((rtx));
+static void print_code (RTX_CODE);
+static void gen_exp (rtx, enum rtx_code, char *);
+static void gen_insn (rtx, int);
+static void gen_expand (rtx);
+static void gen_split (rtx);
+static void output_add_clobbers (void);
+static void output_added_clobbers_hard_reg_p (void);
+static void gen_rtx_scratch (rtx, enum rtx_code);
+static void output_peephole2_scratches (rtx);
\f
static void
-max_operand_1 (x)
- rtx x;
-{
- RTX_CODE code;
- int i;
- int len;
- const char *fmt;
-
- if (x == 0)
- return;
-
- code = GET_CODE (x);
-
- if (code == MATCH_OPERAND && XSTR (x, 2) != 0 && *XSTR (x, 2) != '\0')
- register_constraints = 1;
- if (code == MATCH_SCRATCH && XSTR (x, 1) != 0 && *XSTR (x, 1) != '\0')
- register_constraints = 1;
- 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 (insn, arg)
- 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 (code)
- RTX_CODE code;
+print_code (RTX_CODE code)
{
const char *p1;
for (p1 = GET_RTX_NAME (code); *p1; p1++)
}
static void
-gen_rtx_scratch (x, subroutine_type)
- rtx x;
- enum rtx_code subroutine_type;
+gen_rtx_scratch (rtx x, enum rtx_code subroutine_type)
{
if (subroutine_type == DEFINE_PEEPHOLE2)
{
substituting any operand references appearing within. */
static void
-gen_exp (x, subroutine_type)
- rtx x;
- enum rtx_code subroutine_type;
+gen_exp (rtx x, enum rtx_code subroutine_type, char *used)
{
RTX_CODE code;
int i;
{
case MATCH_OPERAND:
case MATCH_DUP:
+ if (used)
+ {
+ if (used[XINT (x, 0)])
+ {
+ printf ("copy_rtx (operand%d)", XINT (x, 0));
+ return;
+ }
+ used[XINT (x, 0)] = 1;
+ }
printf ("operand%d", XINT (x, 0));
return;
case MATCH_OP_DUP:
- printf ("gen_rtx (GET_CODE (operand%d), ", XINT (x, 0));
+ printf ("gen_rtx_fmt_");
+ for (i = 0; i < XVECLEN (x, 1); i++)
+ printf ("e");
+ printf (" (GET_CODE (operand%d), ", XINT (x, 0));
if (GET_MODE (x) == VOIDmode)
printf ("GET_MODE (operand%d)", XINT (x, 0));
else
for (i = 0; i < XVECLEN (x, 1); i++)
{
printf (",\n\t\t");
- gen_exp (XVECEXP (x, 1, i), subroutine_type);
+ gen_exp (XVECEXP (x, 1, i), subroutine_type, used);
}
printf (")");
return;
case MATCH_OPERATOR:
- printf ("gen_rtx (GET_CODE (operand%d)", XINT (x, 0));
+ printf ("gen_rtx_fmt_");
+ for (i = 0; i < XVECLEN (x, 2); i++)
+ printf ("e");
+ printf (" (GET_CODE (operand%d)", XINT (x, 0));
printf (", %smode", GET_MODE_NAME (GET_MODE (x)));
for (i = 0; i < XVECLEN (x, 2); i++)
{
printf (",\n\t\t");
- gen_exp (XVECEXP (x, 2, i), subroutine_type);
+ gen_exp (XVECEXP (x, 2, i), subroutine_type, used);
}
printf (")");
return;
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)))
+ {
+ printf ("gen_hard_reg_clobber (%smode, %i)", GET_MODE_NAME (GET_MODE (XEXP (x, 0))),
+ REGNO (XEXP (x, 0)));
+ return;
+ }
+ break;
case CC0:
printf ("cc0_rtx");
printf ("const1_rtx");
else if (INTVAL (x) == -1)
printf ("constm1_rtx");
+ else if (-MAX_SAVED_CONST_INT <= INTVAL (x)
+ && INTVAL (x) <= MAX_SAVED_CONST_INT)
+ printf ("const_int_rtx[MAX_SAVED_CONST_INT + (%d)]",
+ (int) INTVAL (x));
else if (INTVAL (x) == STORE_FLAG_VALUE)
printf ("const_true_rtx");
else
{
printf ("GEN_INT (");
- printf (HOST_WIDE_INT_PRINT_DEC, INTVAL (x));
+ printf (HOST_WIDE_INT_PRINT_DEC_C, INTVAL (x));
printf (")");
}
return;
case CONST_DOUBLE:
+ case CONST_FIXED:
/* These shouldn't be written in MD files. Instead, the appropriate
routines in varasm.c should be called. */
- abort ();
+ gcc_unreachable ();
default:
break;
if (fmt[i] == '0')
break;
printf (",\n\t");
- if (fmt[i] == 'e' || fmt[i] == 'u')
- gen_exp (XEXP (x, i), subroutine_type);
- else if (fmt[i] == 'i')
- printf ("%u", XINT (x, i));
- else if (fmt[i] == 's')
- printf ("\"%s\"", XSTR (x, i));
- else if (fmt[i] == 'E')
+ switch (fmt[i])
{
- int j;
- printf ("gen_rtvec (%d", XVECLEN (x, i));
- for (j = 0; j < XVECLEN (x, i); j++)
- {
- printf (",\n\t\t");
- gen_exp (XVECEXP (x, i, j), subroutine_type);
- }
- printf (")");
+ case 'e': case 'u':
+ gen_exp (XEXP (x, i), subroutine_type, used);
+ break;
+
+ case 'i':
+ printf ("%u", XINT (x, i));
+ break;
+
+ case 's':
+ printf ("\"%s\"", XSTR (x, i));
+ break;
+
+ case 'E':
+ {
+ int j;
+ printf ("gen_rtvec (%d", XVECLEN (x, i));
+ for (j = 0; j < XVECLEN (x, i); j++)
+ {
+ printf (",\n\t\t");
+ gen_exp (XVECEXP (x, i, j), subroutine_type, used);
+ }
+ printf (")");
+ break;
+ }
+
+ default:
+ gcc_unreachable ();
}
- else
- abort ();
}
printf (")");
-}
+}
\f
/* Generate the `gen_...' function for a DEFINE_INSN. */
static void
-gen_insn (insn)
- rtx insn;
+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 (GET_CODE (XVECEXP (insn, 1, i)) != CLOBBER)
break;
- if (GET_CODE (XEXP (XVECEXP (insn, 1, i), 0)) == REG)
+ if (REG_P (XEXP (XVECEXP (insn, 1, i), 0)))
has_hard_reg = 1;
else if (GET_CODE (XEXP (XVECEXP (insn, 1, i), 0)) != MATCH_SCRATCH)
break;
if (i != XVECLEN (insn, 1) - 1)
{
struct clobber_pat *p;
- struct clobber_ent *link
- = (struct clobber_ent *) xmalloc (sizeof (struct clobber_ent));
+ struct clobber_ent *link = XNEW (struct clobber_ent);
int j;
link->code_number = insn_code_number;
for (j = i + 1; j < XVECLEN (insn, 1); j++)
{
- rtx old = XEXP (XVECEXP (p->pattern, 1, j), 0);
- rtx new = XEXP (XVECEXP (insn, 1, j), 0);
+ rtx old_rtx = XEXP (XVECEXP (p->pattern, 1, j), 0);
+ rtx new_rtx = XEXP (XVECEXP (insn, 1, j), 0);
- /* OLD and NEW are the same if both are to be a SCRATCH
- of the same mode,
+ /* OLD and NEW_INSN are the same if both are to be a SCRATCH
+ of the same mode,
or if both are registers of the same mode and number. */
- if (! (GET_MODE (old) == GET_MODE (new)
- && ((GET_CODE (old) == MATCH_SCRATCH
- && GET_CODE (new) == MATCH_SCRATCH)
- || (GET_CODE (old) == REG && GET_CODE (new) == REG
- && REGNO (old) == REGNO (new)))))
+ if (! (GET_MODE (old_rtx) == GET_MODE (new_rtx)
+ && ((GET_CODE (old_rtx) == MATCH_SCRATCH
+ && GET_CODE (new_rtx) == MATCH_SCRATCH)
+ || (REG_P (old_rtx) && REG_P (new_rtx)
+ && REGNO (old_rtx) == REGNO (new_rtx)))))
break;
}
-
+
if (j == XVECLEN (insn, 1))
break;
}
if (p == 0)
{
- p = (struct clobber_pat *) xmalloc (sizeof (struct clobber_pat));
-
+ p = XNEW (struct clobber_pat);
+
p->insns = 0;
p->pattern = insn;
p->first_clobber = i + 1;
if (XSTR (insn, 0)[0] == 0 || XSTR (insn, 0)[0] == '*')
return;
- /* Find out how many operands this function has,
- and also whether any of them have register constraints. */
- register_constraints = 0;
- operands = max_operand_vec (insn, 1);
- if (max_dup_opno >= operands)
+ printf ("/* %s:%d */\n", read_md_filename, lineno);
+
+ /* Find out how many operands this function has. */
+ 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));
- for (i = 0; i < operands; i++)
- if (i)
- printf (", operand%d", i);
- else
- printf ("operand%d", 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
+ printf ("rtx operand%d ATTRIBUTE_UNUSED", i);
+ else
+ printf ("void");
printf (")\n");
- for (i = 0; i < operands; i++)
- printf (" rtx operand%d;\n", i);
printf ("{\n");
- /* Output code to construct and return the rtl for the instruction body */
+ /* Output code to construct and return the rtl for the instruction body. */
if (XVECLEN (insn, 1) == 1)
{
printf (" return ");
- gen_exp (XVECEXP (insn, 1, 0), DEFINE_INSN);
+ gen_exp (XVECEXP (insn, 1, 0), DEFINE_INSN, NULL);
printf (";\n}\n\n");
}
else
{
+ char *used = XCNEWVEC (char, stats.num_generator_args);
+
printf (" return gen_rtx_PARALLEL (VOIDmode, gen_rtvec (%d",
XVECLEN (insn, 1));
for (i = 0; i < XVECLEN (insn, 1); i++)
{
printf (",\n\t\t");
- gen_exp (XVECEXP (insn, 1, i), DEFINE_INSN);
+ gen_exp (XVECEXP (insn, 1, i), DEFINE_INSN, used);
}
printf ("));\n}\n\n");
+ XDELETEVEC (used);
}
}
\f
/* Generate the `gen_...' function for a DEFINE_EXPAND. */
static void
-gen_expand (expand)
- rtx expand;
+gen_expand (rtx expand)
{
- int operands;
+ struct pattern_stats stats;
int i;
+ char *used;
if (strlen (XSTR (expand, 0)) == 0)
fatal ("define_expand lacks a name");
if (XVEC (expand, 1) == 0)
fatal ("define_expand for %s lacks a pattern", XSTR (expand, 0));
- /* Find out how many operands this function has,
- and also whether any of them have register constraints. */
- register_constraints = 0;
-
- operands = max_operand_vec (expand, 1);
+ /* Find out how many operands this function has. */
+ get_pattern_stats (&stats, XVEC (expand, 1));
/* Output the function name and argument declarations. */
printf ("rtx\ngen_%s (", XSTR (expand, 0));
- for (i = 0; i < operands; i++)
- if (i)
- printf (", operand%d", i);
- else
- printf ("operand%d", i);
+ if (stats.num_generator_args)
+ for (i = 0; i < stats.num_generator_args; i++)
+ if (i)
+ printf (",\n\trtx operand%d", i);
+ else
+ printf ("rtx operand%d", i);
+ else
+ printf ("void");
printf (")\n");
- for (i = 0; i < operands; i++)
- printf (" rtx operand%d;\n", i);
printf ("{\n");
/* If we don't have any C code to write, only one insn is being written,
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 ");
- gen_exp (XVECEXP (expand, 1, 0), DEFINE_EXPAND);
+ gen_exp (XVECEXP (expand, 1, 0), DEFINE_EXPAND, NULL);
printf (";\n}\n\n");
return;
}
/* For each operand referred to only with MATCH_DUPs,
make a local variable. */
- for (i = operands; i <= max_dup_opno; i++)
- printf (" rtx operand%d;\n", i);
- for (; i <= max_scratch_opno; i++)
+ for (i = stats.num_generator_args; i <= stats.max_dup_opno; i++)
printf (" rtx operand%d;\n", 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_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, stats.num_operand_vars);
+
for (i = 0; i < XVECLEN (expand, 1); i++)
{
rtx next = XVECEXP (expand, 1, i);
if ((GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC)
|| (GET_CODE (next) == PARALLEL
- && GET_CODE (XVECEXP (next, 0, 0)) == SET
- && GET_CODE (SET_DEST (XVECEXP (next, 0, 0))) == PC)
- || GET_CODE (next) == RETURN)
+ && ((GET_CODE (XVECEXP (next, 0, 0)) == SET
+ && GET_CODE (SET_DEST (XVECEXP (next, 0, 0))) == PC)
+ || 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
|| (GET_CODE (next) == PARALLEL
&& GET_CODE (XVECEXP (next, 0, 0)) == CALL))
printf (" emit_call_insn (");
- else if (GET_CODE (next) == CODE_LABEL)
+ else if (LABEL_P (next))
printf (" emit_label (");
else if (GET_CODE (next) == MATCH_OPERAND
|| GET_CODE (next) == MATCH_DUP
printf (" emit (");
else
printf (" emit_insn (");
- gen_exp (next, DEFINE_EXPAND);
+ gen_exp (next, DEFINE_EXPAND, used);
printf (");\n");
if (GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC
&& GET_CODE (SET_SRC (next)) == LABEL_REF)
printf (" emit_barrier ();");
}
- /* Call `gen_sequence' to make a SEQUENCE out of all the
+ XDELETEVEC (used);
+
+ /* Call `get_insns' to extract the list of all the
insns emitted within this gen_... function. */
- printf (" _val = gen_sequence ();\n");
+ printf (" _val = get_insns ();\n");
printf (" end_sequence ();\n");
printf (" return _val;\n}\n\n");
}
-/* Like gen_expand, but generates a SEQUENCE. */
+/* Like gen_expand, but generates insns resulting from splitting SPLIT. */
static void
-gen_split (split)
- rtx split;
+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;
+ char *used;
if (XVEC (split, 0) == 0)
fatal ("define_%s (definition %d) lacks a pattern", name,
/* 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" : "");
+ 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 ("extern rtx gen_%s_%d PARAMS ((rtx, rtx *));\n",
- name, insn_code_number);
- printf ("rtx\ngen_%s_%d (curr_insn, operands)\n",
+ printf ("extern rtx gen_%s_%d (rtx, rtx *);\n",
name, insn_code_number);
- printf (" rtx curr_insn ATTRIBUTE_UNUSED;\n");
- printf (" rtx *operands%s;\n", unused);
+ printf ("rtx\ngen_%s_%d (rtx curr_insn ATTRIBUTE_UNUSED, rtx *operands%s)\n",
+ name, insn_code_number, unused);
}
else
{
- printf ("extern rtx gen_split_%d PARAMS ((rtx *));\n", insn_code_number);
- printf ("rtx\ngen_%s_%d (operands)\n", name, insn_code_number);
- printf (" rtx *operands%s;\n", unused);
+ printf ("extern rtx gen_split_%d (rtx, rtx *);\n", insn_code_number);
+ printf ("rtx\ngen_split_%d (rtx curr_insn ATTRIBUTE_UNUSED, rtx *operands%s)\n",
+ insn_code_number, unused);
}
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");
before the actual construction. */
if (XSTR (split, 3))
- printf ("%s\n", 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
|| (GET_CODE (next) == PARALLEL
&& GET_CODE (XVECEXP (next, 0, 0)) == CALL))
printf (" emit_call_insn (");
- else if (GET_CODE (next) == CODE_LABEL)
+ else if (LABEL_P (next))
printf (" emit_label (");
else if (GET_CODE (next) == MATCH_OPERAND
|| GET_CODE (next) == MATCH_OPERATOR
printf (" emit (");
else
printf (" emit_insn (");
- gen_exp (next, GET_CODE (split));
+ gen_exp (next, GET_CODE (split), used);
printf (");\n");
if (GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC
&& GET_CODE (SET_SRC (next)) == LABEL_REF)
printf (" emit_barrier ();");
}
- /* Call `gen_sequence' to make a SEQUENCE out of all the
+ /* Call `get_insns' to make a list of all the
insns emitted within this gen_... function. */
- printf (" _val = gen_sequence ();\n");
+ printf (" _val = get_insns ();\n");
printf (" end_sequence ();\n");
printf (" return _val;\n}\n\n");
+
+ free (used);
}
\f
/* Write a function, `add_clobbers', that is given a PARALLEL of sufficient
the end of the vector. */
static void
-output_add_clobbers ()
+output_add_clobbers (void)
{
struct clobber_pat *clobber;
struct clobber_ent *ent;
int i;
- printf ("\n\nvoid\nadd_clobbers (pattern, insn_code_number)\n");
- printf (" rtx pattern ATTRIBUTE_UNUSED;\n int insn_code_number;\n");
+ printf ("\n\nvoid\nadd_clobbers (rtx pattern ATTRIBUTE_UNUSED, int insn_code_number)\n");
printf ("{\n");
printf (" switch (insn_code_number)\n");
printf (" {\n");
{
printf (" XVECEXP (pattern, 0, %d) = ", i);
gen_exp (XVECEXP (clobber->pattern, 1, i),
- GET_CODE (clobber->pattern));
+ GET_CODE (clobber->pattern), NULL);
printf (";\n");
}
}
printf (" default:\n");
- printf (" abort ();\n");
+ printf (" gcc_unreachable ();\n");
printf (" }\n");
printf ("}\n");
}
\f
-/* Write a function, `added_clobbers_hard_reg_p' this is given an insn_code
- number that needs clobbers and returns 1 if they include a clobber of a
- hard reg and 0 if they just clobber SCRATCH. */
+/* Write a function, `added_clobbers_hard_reg_p' that is given an insn_code
+ number that will have clobbers added (as indicated by `recog') and returns
+ 1 if those include a clobber of a hard reg or 0 if all of them just clobber
+ SCRATCH. */
static void
-output_added_clobbers_hard_reg_p ()
+output_added_clobbers_hard_reg_p (void)
{
struct clobber_pat *clobber;
struct clobber_ent *ent;
- int clobber_p;
+ int clobber_p, used;
- printf ("\n\nint\nadded_clobbers_hard_reg_p (insn_code_number)\n");
- printf (" int insn_code_number;\n");
+ printf ("\n\nint\nadded_clobbers_hard_reg_p (int insn_code_number)\n");
printf ("{\n");
printf (" switch (insn_code_number)\n");
printf (" {\n");
for (clobber_p = 0; clobber_p <= 1; clobber_p++)
{
+ used = 0;
for (clobber = clobber_list; clobber; clobber = clobber->next)
if (clobber->has_hard_reg == clobber_p)
for (ent = clobber->insns; ent; ent = ent->next)
- printf (" case %d:\n", ent->code_number);
+ {
+ printf (" case %d:\n", ent->code_number);
+ used++;
+ }
- printf (" return %d;\n\n", clobber_p);
+ if (used)
+ printf (" return %d;\n\n", clobber_p);
}
printf (" default:\n");
- printf (" abort ();\n");
+ printf (" gcc_unreachable ();\n");
printf (" }\n");
printf ("}\n");
}
scratch registers used by the peephole2 pattern in SPLIT. */
static void
-output_peephole2_scratches (split)
- rtx split;
+output_peephole2_scratches (rtx split)
{
int i;
int insn_nr = 0;
-
- printf (" HARD_REG_SET _regs_allocated;\n");
- printf (" CLEAR_HARD_REG_SET (_regs_allocated);\n");
+ bool first = true;
for (i = 0; i < XVECLEN (split, 0); i++)
{
else if (GET_CODE (XVECEXP (split, 0, j)) != MATCH_SCRATCH)
cur_insn_nr++;
+ if (first)
+ {
+ printf (" HARD_REG_SET _regs_allocated;\n");
+ printf (" CLEAR_HARD_REG_SET (_regs_allocated);\n");
+ first = false;
+ }
+
printf (" if ((operands[%d] = peep2_find_free_register (%d, %d, \"%s\", %smode, &_regs_allocated)) == NULL_RTX)\n\
- return NULL;\n",
+ return NULL;\n",
XINT (elt, 0),
insn_nr, last_insn_nr,
XSTR (elt, 1),
}
}
-extern int main PARAMS ((int, char **));
-
int
-main (argc, argv)
- int argc;
- char **argv;
+main (int argc, char **argv)
{
rtx desc;
progname = "genemit";
- if (argc <= 1)
- fatal ("No input file name");
-
- 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 \"config.h\"\n");
printf ("#include \"system.h\"\n");
+ printf ("#include \"coretypes.h\"\n");
+ printf ("#include \"tm.h\"\n");
printf ("#include \"rtl.h\"\n");
printf ("#include \"tm_p.h\"\n");
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 \"insn-config.h\"\n");
printf ("#include \"recog.h\"\n");
printf ("#include \"resource.h\"\n");
printf ("#include \"reload.h\"\n");
- printf ("#include \"toplev.h\"\n");
- printf ("#include \"ggc.h\"\n\n");
+ printf ("#include \"diagnostic-core.h\"\n");
+ printf ("#include \"regs.h\"\n");
+ printf ("#include \"tm-constrs.h\"\n");
+ printf ("#include \"ggc.h\"\n");
+ printf ("#include \"basic-block.h\"\n");
+ printf ("#include \"integrate.h\"\n\n");
printf ("#define FAIL return (end_sequence (), _val)\n");
- printf ("#define DONE return (_val = gen_sequence (), end_sequence (), _val)\n");
+ printf ("#define DONE return (_val = get_insns (), end_sequence (), _val)\n\n");
/* Read the machine description. */
switch (GET_CODE (desc))
{
- case DEFINE_INSN:
- gen_insn (desc);
- break;
-
- case DEFINE_EXPAND:
- gen_expand (desc);
- break;
-
- case DEFINE_SPLIT:
- gen_split (desc);
- break;
-
- case DEFINE_PEEPHOLE2:
- gen_split (desc);
- break;
-
- default:
- break;
- }
+ case DEFINE_INSN:
+ gen_insn (desc, line_no);
+ break;
+
+ case DEFINE_EXPAND:
+ printf ("/* %s:%d */\n", read_md_filename, line_no);
+ gen_expand (desc);
+ break;
+
+ case DEFINE_SPLIT:
+ printf ("/* %s:%d */\n", read_md_filename, line_no);
+ gen_split (desc);
+ break;
+
+ case DEFINE_PEEPHOLE2:
+ printf ("/* %s:%d */\n", read_md_filename, line_no);
+ gen_split (desc);
+ break;
+
+ default:
+ break;
+ }
++insn_index_number;
}
fflush (stdout);
return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
}
-
-/* Define this so we can link with print-rtl.o to get debug_rtx function. */
-const char *
-get_insn_name (code)
- int code ATTRIBUTE_UNUSED;
-{
- return NULL;
-}