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:
parent
c452dcde0a
commit
4bbf910eef
8 changed files with 126 additions and 99 deletions
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 "";
|
||||
}
|
||||
|
|
46
gcc/final.c
46
gcc/final.c
|
@ -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
|
||||
|
|
131
gcc/genoutput.c
131
gcc/genoutput.c
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
|
|
11
gcc/recog.h
11
gcc/recog.h
|
@ -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[];
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue