From 4bbf910eefafa77900eb9234feac7dce5451e18b Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 13 Sep 1999 21:19:34 -0700 Subject: [PATCH] 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 --- gcc/ChangeLog | 20 +++++++ gcc/config/c4x/c4x.c | 2 +- gcc/config/i860/i860.c | 10 +--- gcc/final.c | 46 ++++++++++----- gcc/genoutput.c | 131 +++++++++++++++++++---------------------- gcc/output.h | 3 + gcc/recog.h | 11 +++- gcc/toplev.c | 2 +- 8 files changed, 126 insertions(+), 99 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6d2aae3881a..b694c997ab0 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,23 @@ +Mon Sep 13 21:06:01 1999 Richard Henderson + + * 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 * rtl.c (obstack_alloc_rtx): Removed. diff --git a/gcc/config/c4x/c4x.c b/gcc/config/c4x/c4x.c index b3f5a54345e..517ba0f189b 100644 --- a/gcc/config/c4x/c4x.c +++ b/gcc/config/c4x/c4x.c @@ -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); diff --git a/gcc/config/i860/i860.c b/gcc/config/i860/i860.c index a6e9458a8b9..bdbccfb1f81 100644 --- a/gcc/config/i860/i860.c +++ b/gcc/config/i860/i860.c @@ -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 ""; } diff --git a/gcc/final.c b/gcc/final.c index e81895bd3bc..7046344e36d 100644 --- a/gcc/final.c +++ b/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 diff --git a/gcc/genoutput.c b/gcc/genoutput.c index 9c44d7e6475..d40433f2942 100644 --- a/gcc/genoutput.c +++ b/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); } diff --git a/gcc/output.h b/gcc/output.h index 97794d1f781..db94ddfd120 100644 --- a/gcc/output.h +++ b/gcc/output.h @@ -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)); diff --git a/gcc/recog.h b/gcc/recog.h index 0d4cc977cf5..e5875d59293 100644 --- a/gcc/recog.h +++ b/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[]; diff --git a/gcc/toplev.c b/gcc/toplev.c index b1b3b8fa318..0be8824e753 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -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); }