recog.h (INSN_OUTPUT_FORMAT_*): New.

* recog.h (INSN_OUTPUT_FORMAT_*): New.
        (struct insn_data): Merge `template' and `outfun' into `output'.
        Add `output_format'.
        * genoutput.c (INSN_OUTPUT_FORMAT_*): New.
        (struct data): Remove `outfun'; add `output_format'.
        (name_for_index): Remove declaration.
        (output_insn_data): Handle output formats.
        (process_template): Emit the bare array for @.
        (gen_expand, gen_split): Set output_format to NONE.
        * output.h (get_insn_template): Declare.
        * final.c (get_insn_template): New.
        (final_scan_insn): Use it.
        * toplev.c (compile_file): Likewise.

        * c4x/c4x.c (c4x_process_after_reload): Likewise.
        * i860/i860.c (output_delayed_branch): Likewise.
        (output_delay_insn): Likewise.

From-SVN: r29389
This commit is contained in:
Richard Henderson 1999-09-13 21:19:34 -07:00 committed by Richard Henderson
parent c452dcde0a
commit 4bbf910eef
8 changed files with 126 additions and 99 deletions

View File

@ -1,3 +1,23 @@
Mon Sep 13 21:06:01 1999 Richard Henderson <rth@cygnus.com>
* recog.h (INSN_OUTPUT_FORMAT_*): New.
(struct insn_data): Merge `template' and `outfun' into `output'.
Add `output_format'.
* genoutput.c (INSN_OUTPUT_FORMAT_*): New.
(struct data): Remove `outfun'; add `output_format'.
(name_for_index): Remove declaration.
(output_insn_data): Handle output formats.
(process_template): Emit the bare array for @.
(gen_expand, gen_split): Set output_format to NONE.
* output.h (get_insn_template): Declare.
* final.c (get_insn_template): New.
(final_scan_insn): Use it.
* toplev.c (compile_file): Likewise.
* c4x/c4x.c (c4x_process_after_reload): Likewise.
* i860/i860.c (output_delayed_branch): Likewise.
(output_delay_insn): Likewise.
1999-09-13 Alexandre Oliva <oliva@lsd.ic.unicamp.br>
* rtl.c (obstack_alloc_rtx): Removed.

View File

@ -2196,7 +2196,7 @@ c4x_process_after_reload (first)
{
const char *template;
template = insn_data[insn_code_number].template;
template = get_insn_template (insn_code_number, insn);
if (template && template[0] == '#' && template[1] == '\0')
{
rtx new = try_split (PATTERN(insn), insn, 0);

View File

@ -1456,10 +1456,7 @@ output_delayed_branch (template, operands, insn)
if (! constrain_operands (1))
fatal_insn_not_found (delay_insn);
template = insn_data[insn_code_number].template;
if (template == 0)
template = ((*insn_data[insn_code_number].outfun)
(recog_data.operand, delay_insn));
template = get_insn_template (insn_code_number, delay_insn);
output_asm_insn (template, recog_data.operand);
}
CC_STATUS_INIT;
@ -1513,10 +1510,7 @@ output_delay_insn (delay_insn)
/* Now get the template for what this insn would
have been, without the branch. */
template = insn_data[insn_code_number].template;
if (template == 0)
template = ((*insn_data[insn_code_number].outfun)
(recog_data.operand, delay_insn));
template = get_insn_template (insn_code_number, delay_insn);
output_asm_insn (template, recog_data.operand);
return "";
}

View File

@ -2034,6 +2034,27 @@ final (first, file, optimize, prescan)
free_insn_eh_region ();
}
const char *
get_insn_template (code, insn)
int code;
rtx insn;
{
const void *output = insn_data[code].output;
switch (insn_data[code].output_format)
{
case INSN_OUTPUT_FORMAT_SINGLE:
return (const char *) output;
case INSN_OUTPUT_FORMAT_MULTI:
return ((const char * const *) output)[which_alternative];
case INSN_OUTPUT_FORMAT_FUNCTION:
if (insn == NULL)
abort ();
return (* (insn_output_fn) output) (recog_data.operand, insn);
default:
abort ();
}
}
/* The final scan for one insn, INSN.
Args are same as in `final', except that INSN
is the insn being scanned.
@ -2895,25 +2916,18 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
dwarf2out_frame_debug (insn);
#endif
/* If the proper template needs to be chosen by some C code,
run that code and get the real template. */
/* Find the proper template for this insn. */
template = get_insn_template (insn_code_number, insn);
template = insn_data[insn_code_number].template;
/* If the C code returns 0, it means that it is a jump insn
which follows a deleted test insn, and that test insn
needs to be reinserted. */
if (template == 0)
{
template = ((*insn_data[insn_code_number].outfun)
(recog_data.operand, insn));
/* If the C code returns 0, it means that it is a jump insn
which follows a deleted test insn, and that test insn
needs to be reinserted. */
if (template == 0)
{
if (prev_nonnote_insn (insn) != last_ignored_compare)
abort ();
new_block = 0;
return prev_nonnote_insn (insn);
}
if (prev_nonnote_insn (insn) != last_ignored_compare)
abort ();
new_block = 0;
return prev_nonnote_insn (insn);
}
/* If the template is the string "#", it means that this insn must

View File

@ -29,27 +29,24 @@ Boston, MA 02111-1307, USA. */
a. `name' is the name for that pattern. Nameless patterns are
given a name.
b. `template' is the template for output of that insn,
b. `output' hold either the output template, an array of output
templates, or an output function.
c. `outfun' is 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 `template'.
d. `genfun' is the function to generate a body for that pattern,
c. `genfun' is the function to generate a body for that pattern,
given operands as arguments.
e. `n_operands' is the number of distinct operands in the pattern
d. `n_operands' is the number of distinct operands in the pattern
for that insn,
f. `n_dups' is the number of match_dup's that appear in the insn's
e. `n_dups' is the number of match_dup's that appear in the insn's
pattern. This says how many elements of `recog_data.dup_loc' are
significant after an insn has been recognized.
g. `n_alternatives' is the number of alternatives in the constraints
f. `n_alternatives' is the number of alternatives in the constraints
of each pattern.
g. `output_format' tells what type of thing `output' is.
h. `operand' is the base of an array of operand data for the insn.
2. An array of `struct insn_operand data', used by `operand' above.
@ -144,6 +141,13 @@ static struct operand_data null_operand =
static struct operand_data *odata = &null_operand;
static struct operand_data **odata_end = &null_operand.next;
/* Must match the constants in recog.h. */
#define INSN_OUTPUT_FORMAT_NONE 0 /* abort */
#define INSN_OUTPUT_FORMAT_SINGLE 1 /* const char * */
#define INSN_OUTPUT_FORMAT_MULTI 2 /* const char * const * */
#define INSN_OUTPUT_FORMAT_FUNCTION 3 /* const char * (*)(...) */
/* Record in this chain all information that we will output,
associated with the code number of the insn. */
@ -151,14 +155,14 @@ struct data
{
struct data *next;
char *name;
char *template; /* string such as "movl %1,%0" */
char *template;
int code_number;
int index_number;
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 */
char outfun; /* Nonzero means this has an output function */
int operand_number; /* Operand index in the big array. */
int output_format; /* INSN_OUTPUT_FORMAT_*. */
struct operand_data operand[MAX_MAX_OPERANDS];
};
@ -172,7 +176,6 @@ static struct data *idata, **idata_end = &idata;
static int have_constraints;
static char * name_for_index PROTO((int));
static void output_prologue PROTO((void));
static void output_predicate_decls PROTO((void));
static void output_operand_data PROTO((void));
@ -353,15 +356,21 @@ output_insn_data ()
printf (" \"%s+%d\",\n", last_name, name_offset);
}
if (d->template)
printf (" \"%s\",\n", d->template);
else
printf (" 0,\n");
if (d->outfun)
printf (" output_%d,\n", d->code_number);
else
printf (" 0,\n");
switch (d->output_format)
{
case INSN_OUTPUT_FORMAT_NONE:
printf (" 0,\n");
break;
case INSN_OUTPUT_FORMAT_SINGLE:
printf (" \"%s\",\n", d->template);
break;
case INSN_OUTPUT_FORMAT_MULTI:
case INSN_OUTPUT_FORMAT_FUNCTION:
printf (" output_%d,\n", d->code_number);
break;
default:
abort ();
}
if (d->name && d->name[0] != '*')
printf (" gen_%s,\n", d->name);
@ -371,7 +380,8 @@ output_insn_data ()
printf (" &operand_data[%d],\n", d->operand_number);
printf (" %d,\n", d->n_operands);
printf (" %d,\n", d->n_dups);
printf (" %d\n", d->n_alternatives);
printf (" %d,\n", d->n_alternatives);
printf (" %d\n", d->output_format);
printf(" },\n");
}
@ -637,44 +647,39 @@ process_template (d, template)
register char *cp;
register int i;
/* We need to consider only the instructions whose assembler code template
starts with a * or @. These are the ones where C code is run to decide
on a template to use. So for all others just return now. */
if (template[0] != '*' && template[0] != '@')
/* Templates starting with * contain straight code to be run. */
if (template[0] == '*')
{
d->template = template;
d->outfun = 0;
return;
d->template = 0;
d->output_format = INSN_OUTPUT_FORMAT_FUNCTION;
printf ("\nstatic const char *output_%d PROTO ((rtx *, rtx));\n",
d->code_number);
puts ("\nstatic const char *");
printf ("output_%d (operands, insn)\n", d->code_number);
puts (" rtx *operands ATTRIBUTE_UNUSED;");
puts (" rtx insn ATTRIBUTE_UNUSED;");
puts ("{");
puts (template + 1);
puts ("}");
}
d->template = 0;
d->outfun = 1;
printf ("\nstatic const char *output_%d PROTO ((rtx *, rtx));\n",
d->code_number);
printf ("\nstatic const char *\n");
printf ("output_%d (operands, insn)\n", d->code_number);
printf (" rtx *operands ATTRIBUTE_UNUSED;\n");
printf (" rtx insn ATTRIBUTE_UNUSED;\n");
printf ("{\n");
/* If the assembler code template starts with a @ it is a newline-separated
list of assembler code templates, one for each alternative. So produce
a routine to select the correct one. */
if (template[0] == '@')
list of assembler code templates, one for each alternative. */
else if (template[0] == '@')
{
d->template = 0;
d->output_format = INSN_OUTPUT_FORMAT_MULTI;
printf (" static const char *const strings_%d[] = {\n",
d->code_number);
printf ("\nstatic const char * const output_%d[] = {\n", d->code_number);
for (i = 0, cp = &template[1]; *cp; )
{
while (*cp == '\n' || *cp == ' ' || *cp== '\t')
cp++;
printf (" \"");
printf (" \"");
while (*cp != '\n' && *cp != '\0')
{
putchar (*cp);
@ -685,29 +690,13 @@ process_template (d, template)
i++;
}
printf (" };\n");
printf (" return strings_%d[which_alternative];\n", d->code_number);
if (i != d->n_alternatives)
fatal ("Insn pattern %d has %d alternatives but %d assembler choices",
d->index_number, d->n_alternatives, i);
printf ("};\n");
}
else
{
/* The following is done in a funny way to get around problems in
VAX-11 "C" on VMS. It is the equivalent of:
printf ("%s\n", &template[1])); */
cp = &template[1];
while (*cp)
{
putchar (*cp);
cp++;
}
putchar ('\n');
d->template = template;
d->output_format = INSN_OUTPUT_FORMAT_SINGLE;
}
printf ("}\n");
}
/* Check insn D for consistency in number of constraint alternatives. */
@ -849,7 +838,7 @@ gen_expand (insn)
d->n_operands = max_opno + 1;
d->n_dups = num_dups;
d->template = 0;
d->outfun = 0;
d->output_format = INSN_OUTPUT_FORMAT_NONE;
validate_insn_alternatives (d);
place_operands (d);
@ -889,7 +878,7 @@ gen_split (split)
d->n_dups = 0;
d->n_alternatives = 0;
d->template = 0;
d->outfun = 0;
d->output_format = INSN_OUTPUT_FORMAT_NONE;
place_operands (d);
}

View File

@ -123,6 +123,9 @@ extern int only_leaf_regs_used PROTO((void));
available in leaf functions. */
extern void leaf_renumber_regs_insn PROTO((rtx));
/* Locate the proper template for the given insn-code. */
extern const char *get_insn_template PROTO((int, rtx));
/* Functions in flow.c */
extern void allocate_for_life_analysis PROTO((void));
extern int regno_uninitialized PROTO((int));

View File

@ -211,17 +211,24 @@ struct insn_operand_data
char strict_low;
};
/* Legal values for insn_data.output_format. Indicate what type of data
is stored in insn_data.output. */
#define INSN_OUTPUT_FORMAT_NONE 0 /* abort */
#define INSN_OUTPUT_FORMAT_SINGLE 1 /* const char * */
#define INSN_OUTPUT_FORMAT_MULTI 2 /* const char * const * */
#define INSN_OUTPUT_FORMAT_FUNCTION 3 /* const char * (*)(...) */
struct insn_data
{
const char *name;
const char *template;
insn_output_fn outfun;
const PTR output;
insn_gen_fn genfun;
const struct insn_operand_data *operand;
unsigned char n_operands;
unsigned char n_dups;
unsigned char n_alternatives;
unsigned char output_format;
};
extern const struct insn_data insn_data[];

View File

@ -3172,7 +3172,7 @@ compile_file (name)
/* It's best if we can write a nop here since some
assemblers don't tolerate zeros in the text section. */
if (insn_data[CODE_FOR_nop].template != 0)
output_asm_insn (insn_data[CODE_FOR_nop].template, NULL_PTR);
output_asm_insn (get_insn_template (CODE_FOR_nop, NULL), NULL_PTR);
else
assemble_zeros (UNITS_PER_WORD);
}