/* Generate code from machine description to emit insns as rtl.
- Copyright (C) 1987, 88, 91, 94, 95, 97, 98, 1999 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1988, 1991, 1994, 1995, 1997, 1998, 1999, 2000, 2001
+ Free Software Foundation, Inc.
This file is part of GNU CC.
#include "hconfig.h"
#include "system.h"
#include "rtl.h"
-#include "obstack.h"
#include "errors.h"
+#include "gensupport.h"
-static struct obstack obstack;
-struct obstack *rtl_obstack = &obstack;
-
-#define obstack_chunk_alloc xmalloc
-#define obstack_chunk_free free
-
-/* Define this so we can link with print-rtl.o to get debug_rtx function. */
-char **insn_name_ptr = 0;
static int max_opno;
static int max_dup_opno;
rtx pattern;
int first_clobber;
struct clobber_pat *next;
+ int has_hard_reg;
} *clobber_list;
/* Records one insn that uses the clobber list. */
struct clobber_ent *next;
};
-static void max_operand_1 PROTO((rtx));
-static int max_operand_vec PROTO((rtx, int));
-static void print_code PROTO((RTX_CODE));
-static void gen_exp PROTO((rtx, enum rtx_code));
-static void gen_insn PROTO((rtx));
-static void gen_expand PROTO((rtx));
-static void gen_split PROTO((rtx));
-static void output_add_clobbers PROTO((void));
-static void gen_rtx_scratch PROTO((rtx, enum rtx_code));
-static void output_peephole2_scratches PROTO((rtx));
+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));
\f
static void
{
register const char *p1;
for (p1 = GET_RTX_NAME (code); *p1; p1++)
- {
- if (ISLOWER(*p1))
- putchar (toupper(*p1));
- else
- putchar (*p1);
- }
+ putchar (TOUPPER(*p1));
}
static void
if (XVEC (insn, 1))
{
+ int has_hard_reg = 0;
+
for (i = XVECLEN (insn, 1) - 1; i > 0; i--)
- if (GET_CODE (XVECEXP (insn, 1, i)) != CLOBBER
- || (GET_CODE (XEXP (XVECEXP (insn, 1, i), 0)) != REG
- && GET_CODE (XEXP (XVECEXP (insn, 1, i), 0)) != MATCH_SCRATCH))
- break;
+ {
+ if (GET_CODE (XVECEXP (insn, 1, i)) != CLOBBER)
+ break;
+
+ if (GET_CODE (XEXP (XVECEXP (insn, 1, i), 0)) == REG)
+ has_hard_reg = 1;
+ else if (GET_CODE (XEXP (XVECEXP (insn, 1, i), 0)) != MATCH_SCRATCH)
+ break;
+ }
if (i != XVECLEN (insn, 1) - 1)
{
p->pattern = insn;
p->first_clobber = i + 1;
p->next = clobber_list;
+ p->has_hard_reg = has_hard_reg;
clobber_list = p;
}
/* Output the function name and argument declarations. */
printf ("rtx\ngen_%s (", XSTR (insn, 0));
for (i = 0; i < operands; i++)
- printf (i ? ", operand%d" : "operand%d", i);
+ if (i)
+ printf (", operand%d", i);
+ else
+ printf ("operand%d", i);
printf (")\n");
for (i = 0; i < operands; i++)
printf (" rtx operand%d;\n", i);
/* Output the function name and argument declarations. */
printf ("rtx\ngen_%s (", XSTR (expand, 0));
for (i = 0; i < operands; i++)
- printf (i ? ", operand%d" : "operand%d", i);
+ if (i)
+ printf (", operand%d", i);
+ else
+ printf ("operand%d", i);
printf (")\n");
for (i = 0; i < operands; i++)
printf (" rtx operand%d;\n", i);
{
register int i;
int operands;
- char *name = "split";
+ const char *name = "split";
+ const char *unused;
if (GET_CODE (split) == DEFINE_PEEPHOLE2)
name = "peephole2";
max_operand_vec (split, 2);
operands = MAX (max_opno, MAX (max_dup_opno, max_scratch_opno)) + 1;
+ unused = (operands == 0 ? " ATTRIBUTE_UNUSED" : "");
/* Output the prototype, function name and argument declarations. */
if (GET_CODE (split) == DEFINE_PEEPHOLE2)
{
- printf ("extern rtx gen_%s_%d PROTO ((rtx, rtx *));\n",
+ printf ("extern rtx gen_%s_%d PARAMS ((rtx, rtx *));\n",
name, insn_code_number);
- printf ("rtx\ngen_%s_%d (curr_insn, operands)\n\
- rtx curr_insn ATTRIBUTE_UNUSED;\n\
- rtx *operands;\n",
+ printf ("rtx\ngen_%s_%d (curr_insn, operands)\n",
name, insn_code_number);
+ printf (" rtx curr_insn ATTRIBUTE_UNUSED;\n");
+ printf (" rtx *operands%s;\n", unused);
}
else
{
- printf ("extern rtx gen_split_%d PROTO ((rtx *));\n", insn_code_number);
- printf ("rtx\ngen_%s_%d (operands)\n rtx *operands;\n", name,
- insn_code_number);
+ 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 ("{\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. */
+
+static void
+output_added_clobbers_hard_reg_p ()
+{
+ struct clobber_pat *clobber;
+ struct clobber_ent *ent;
+ int clobber_p;
+
+ printf ("\n\nint\nadded_clobbers_hard_reg_p (insn_code_number)\n");
+ printf (" int insn_code_number;\n");
+ printf ("{\n");
+ printf (" switch (insn_code_number)\n");
+ printf (" {\n");
+
+ for (clobber_p = 0; clobber_p <= 1; clobber_p++)
+ {
+ 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 (" return %d;\n\n", clobber_p);
+ }
+
+ printf (" default:\n");
+ printf (" abort ();\n");
+ printf (" }\n");
+ printf ("}\n");
+}
+\f
/* Generate code to invoke find_free_register () as needed for the
- scratch registers used by the peephole2 pattern in SPLIT. */
+ scratch registers used by the peephole2 pattern in SPLIT. */
static void
output_peephole2_scratches (split)
int i;
int insn_nr = 0;
- printf (" rtx first_insn ATTRIBUTE_UNUSED;\n");
- printf (" rtx last_insn ATTRIBUTE_UNUSED;\n");
printf (" HARD_REG_SET _regs_allocated;\n");
-
printf (" CLEAR_HARD_REG_SET (_regs_allocated);\n");
for (i = 0; i < XVECLEN (split, 0); i++)
}
else if (GET_CODE (XVECEXP (split, 0, j)) != MATCH_SCRATCH)
cur_insn_nr++;
- printf (" first_insn = recog_next_insn (curr_insn, %d);\n", insn_nr);
- if (last_insn_nr > insn_nr)
- printf (" last_insn = recog_next_insn (curr_insn, %d);\n",
- last_insn_nr - 1);
- else
- printf (" last_insn = 0;\n");
- printf (" if ((operands[%d] = find_free_register (first_insn, last_insn, \"%s\", %smode, &_regs_allocated)) == NULL_RTX)\n\
+
+ printf (" if ((operands[%d] = peep2_find_free_register (%d, %d, \"%s\", %smode, &_regs_allocated)) == NULL_RTX)\n\
return NULL;\n",
XINT (elt, 0),
+ insn_nr, last_insn_nr,
XSTR (elt, 1),
GET_MODE_NAME (GET_MODE (elt)));
insn_nr++;
}
}
-\f
-PTR
-xmalloc (size)
- size_t size;
-{
- register PTR val = (PTR) malloc (size);
-
- if (val == 0)
- fatal ("virtual memory exhausted");
-
- return val;
-}
-PTR
-xrealloc (old, size)
- PTR old;
- size_t size;
-{
- register PTR ptr;
- if (old)
- ptr = (PTR) realloc (old, size);
- else
- ptr = (PTR) malloc (size);
- if (!ptr)
- fatal ("virtual memory exhausted");
- return ptr;
-}
+extern int main PARAMS ((int, char **));
int
main (argc, argv)
char **argv;
{
rtx desc;
- FILE *infile;
- register int c;
progname = "genemit";
- 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);
- }
+ if (init_md_reader (argv[1]) != SUCCESS_EXIT_CODE)
+ return (FATAL_EXIT_CODE);
/* Assign sequential codes to all entries in the machine description
in parallel with the tables in insn-output.c. */
printf ("#include \"config.h\"\n");
printf ("#include \"system.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 \"flags.h\"\n");
printf ("#include \"output.h\"\n");
printf ("#include \"insn-config.h\"\n");
- printf ("#include \"insn-flags.h\"\n");
- printf ("#include \"insn-codes.h\"\n");
- printf ("#include \"recog.h\"\n");
printf ("#include \"hard-reg-set.h\"\n");
+ printf ("#include \"recog.h\"\n");
printf ("#include \"resource.h\"\n");
- printf ("#include \"reload.h\"\n\n");
- printf ("extern rtx recog_operand[];\n");
+ printf ("#include \"reload.h\"\n");
+ printf ("#include \"toplev.h\"\n");
+ printf ("#include \"ggc.h\"\n\n");
printf ("#define FAIL return (end_sequence (), _val)\n");
printf ("#define DONE return (_val = gen_sequence (), end_sequence (), _val)\n");
while (1)
{
- c = read_skip_spaces (infile);
- if (c == EOF)
- break;
- ungetc (c, infile);
+ int line_no;
- desc = read_rtx (infile);
+ desc = read_md_rtx (&line_no, &insn_code_number);
+ if (desc == NULL)
+ break;
- if (GET_CODE (desc) == DEFINE_INSN)
- {
- gen_insn (desc);
- ++insn_code_number;
- }
- if (GET_CODE (desc) == DEFINE_EXPAND)
+ switch (GET_CODE (desc))
{
- gen_expand (desc);
- ++insn_code_number;
- }
- if (GET_CODE (desc) == DEFINE_SPLIT)
- {
- gen_split (desc);
- ++insn_code_number;
- }
- if (GET_CODE (desc) == DEFINE_PEEPHOLE2)
- {
- gen_split (desc);
- ++insn_code_number;
- }
- if (GET_CODE (desc) == DEFINE_PEEPHOLE)
- {
- ++insn_code_number;
- }
+ 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;
+ }
++insn_index_number;
}
- /* Write out the routine to add CLOBBERs to a pattern. */
+ /* Write out the routines to add CLOBBERs to a pattern and say whether they
+ clobber a hard reg. */
output_add_clobbers ();
+ output_added_clobbers_hard_reg_p ();
fflush (stdout);
- exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
- /* NOTREACHED */
- return 0;
+ 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;
}