/* Generate code from machine description to emit insns as rtl.
Copyright (C) 1987, 1988, 1991, 1994, 1995, 1997, 1998, 1999, 2000, 2001,
- 2003 Free Software Foundation, Inc.
+ 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 "bconfig.h"
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
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++)
{
case PC:
printf ("pc_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
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, used);
- 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, used);
- }
- 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 (")");
}
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 = 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
+ /* 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 (p == 0)
{
- p = xmalloc (sizeof (struct clobber_pat));
+ p = XNEW (struct clobber_pat);
p->insns = 0;
p->pattern = insn;
printf (")\n");
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)
{
}
else
{
+ char *used = XCNEWVEC (char, operands);
+
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, NULL);
+ gen_exp (XVECEXP (insn, 1, i), DEFINE_INSN, used);
}
printf ("));\n}\n\n");
+ XDELETEVEC (used);
}
}
\f
{
int operands;
int i;
+ char *used;
if (strlen (XSTR (expand, 0)) == 0)
fatal ("define_expand lacks a name");
/* Output the special code to be executed before the sequence
is generated. */
+ print_rtx_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 < MAX (operands, MAX (max_scratch_opno, max_dup_opno) + 1);
+ 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));
+
for (i = 0; i < XVECLEN (expand, 1); i++)
{
rtx next = XVECEXP (expand, 1, i);
|| (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, NULL);
+ 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 ();");
}
+ XDELETEVEC (used);
+
/* Call `get_insns' to extract the list of all the
insns emitted within this gen_... function. */
max_operand_vec (split, 2);
operands = MAX (max_opno, MAX (max_dup_opno, max_scratch_opno)) + 1;
unused = (operands == 0 ? " ATTRIBUTE_UNUSED" : "");
- used = xcalloc (1, operands);
+ used = XCNEWVEC (char, operands);
/* Output the prototype, function name and argument declarations. */
if (GET_CODE (split) == DEFINE_PEEPHOLE2)
}
else
{
- printf ("extern rtx gen_split_%d (rtx *);\n", insn_code_number);
- printf ("rtx\ngen_%s_%d (rtx *operands%s)\n", name, insn_code_number, 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");
before the actual construction. */
if (XSTR (split, 3))
- printf ("%s\n", XSTR (split, 3));
+ {
+ print_rtx_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);
+ {
+ 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)) == 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 (" 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 (void)
}
printf (" default:\n");
- printf (" abort ();\n");
+ printf (" gcc_unreachable ();\n");
printf (" }\n");
printf ("}\n");
}
{
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",
XINT (elt, 0),
progname = "genemit";
- if (argc <= 1)
- fatal ("no input file name");
-
if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
return (FATAL_EXIT_CODE);
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 \"resource.h\"\n");
printf ("#include \"reload.h\"\n");
printf ("#include \"toplev.h\"\n");
- printf ("#include \"ggc.h\"\n\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 = get_insns (), end_sequence (), _val)\n\n");
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 (int code ATTRIBUTE_UNUSED)
-{
- return NULL;
-}