X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fgenattrtab.c;h=2dab1b6f5bbd09dfa027d15e96bc652f43f45691;hb=91c766436dee1f486f5b7e43801f197a4c2c9685;hp=b71c15c82bff43efe5aa436826deb88f3cee144f;hpb=5d13fcf0cf7516b3a3f63ff0704aed47bdb1725f;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/genattrtab.c b/gcc/genattrtab.c index b71c15c82bf..2dab1b6f5bb 100644 --- a/gcc/genattrtab.c +++ b/gcc/genattrtab.c @@ -1,5 +1,6 @@ /* Generate code from machine description to compute values of attributes. - Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc. + Copyright (C) 1991, 1993, 1994, 1995, 1996, 1997, 1998, + 1999, 2000 Free Software Foundation, Inc. Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu) This file is part of GNU CC. @@ -16,7 +17,8 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ /* This program handles insn attributes and the DEFINE_DELAY and DEFINE_FUNCTION_UNIT definitions. @@ -33,7 +35,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ If the attribute `alternative', or a random C expression is present, `constrain_operands' is called. If either of these cases of a reference to - an operand is found, `insn_extract' is called. + an operand is found, `extract_insn' is called. The special attribute `length' is also recognized. For this operand, expressions involving the address of an operand or the current insn, @@ -95,26 +97,18 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "hconfig.h" -/* varargs must always be included after *config.h. */ -#ifdef __STDC__ -#include -#else -#include -#endif +#include "system.h" #include "rtl.h" -#include "insn-config.h" /* For REGISTER_CONSTRAINTS */ -#include +#include "ggc.h" -#ifndef VMS -#ifndef USG -#include -#include -#endif +#ifdef HAVE_SYS_RESOURCE_H +# include #endif /* We must include obstack.h after , to avoid lossage with /usr/include/sys/stdtypes.h on Sun OS 4.x. */ #include "obstack.h" +#include "errors.h" static struct obstack obstack, obstack1, obstack2; struct obstack *rtl_obstack = &obstack; @@ -124,15 +118,6 @@ struct obstack *temp_obstack = &obstack2; #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; - -extern void free (); -extern rtx read_rtx (); - -static void fatal (); -void fancy_abort (); - /* enough space to reserve for printing out ints */ #define MAX_DIGITS (HOST_BITS_PER_INT * 3 / 10 + 3) @@ -145,12 +130,12 @@ void fancy_abort (); struct insn_def { - int insn_code; /* Instruction number. */ - int insn_index; /* Expression numer in file, for errors. */ - struct insn_def *next; /* Next insn in chain. */ - rtx def; /* The DEFINE_... */ + int insn_code; /* Instruction number. */ + int insn_index; /* Expression numer in file, for errors. */ + struct insn_def *next; /* Next insn in chain. */ + rtx def; /* The DEFINE_... */ int num_alternatives; /* Number of alternatives. */ - int vec_idx; /* Index of attribute vector in `def'. */ + int vec_idx; /* Index of attribute vector in `def'. */ }; /* Once everything has been read in, we store in each attribute value a list @@ -181,15 +166,17 @@ struct attr_value struct attr_desc { - char *name; /* Name of attribute. */ - struct attr_desc *next; /* Next attribute. */ - int is_numeric; /* Values of this attribute are numeric. */ - int negative_ok; /* Allow negative numeric values. */ - int unsigned_p; /* Make the output function unsigned int. */ - int is_const; /* Attribute value constant for each run. */ - int is_special; /* Don't call `write_attr_set'. */ - struct attr_value *first_value; /* First value of this attribute. */ - struct attr_value *default_val; /* Default value for this attribute. */ + char *name; /* Name of attribute. */ + struct attr_desc *next; /* Next attribute. */ + unsigned is_numeric : 1; /* Values of this attribute are numeric. */ + unsigned negative_ok : 1; /* Allow negative numeric values. */ + unsigned unsigned_p : 1; /* Make the output function unsigned int. */ + unsigned is_const : 1; /* Attribute value constant for each run. */ + unsigned is_special : 1; /* Don't call `write_attr_set'. */ + unsigned func_units_p : 1; /* this is the function_units attribute */ + unsigned blockage_p : 1; /* this is the blockage range function */ + struct attr_value *first_value; /* First value of this attribute. */ + struct attr_value *default_val; /* Default value for this attribute. */ }; #define NULL_ATTR (struct attr_desc *) NULL @@ -207,7 +194,7 @@ struct range struct delay_desc { rtx def; /* DEFINE_DELAY expression. */ - struct delay_desc *next; /* Next DEFINE_DELAY. */ + struct delay_desc *next; /* Next DEFINE_DELAY. */ int num; /* Number of DEFINE_DELAY, starting at 1. */ }; @@ -229,13 +216,13 @@ struct function_unit_op struct function_unit { - char *name; /* Function unit name. */ + const char *name; /* Function unit name. */ struct function_unit *next; /* Next function unit. */ int num; /* Ordinal of this unit type. */ int multiplicity; /* Number of units of this type. */ int simultaneity; /* Maximum number of simultaneous insns on this function unit or 0 if unlimited. */ - rtx condexp; /* Expression TRUE for insn needing unit. */ + rtx condexp; /* Expression TRUE for insn needing unit. */ int num_opclasses; /* Number of different operation types. */ struct function_unit_op *ops; /* Pointer to first operation type. */ int needs_conflict_function; /* Nonzero if a conflict function required. */ @@ -298,7 +285,7 @@ struct dimension int num_values; /* Length of the values list. */ }; -/* Other variables. */ +/* Other variables. */ static int insn_code_number; static int insn_index_number; @@ -309,12 +296,12 @@ static int address_used; static int length_used; static int num_delays; static int have_annul_true, have_annul_false; -static int num_units; +static int num_units, num_unit_opclasses; static int num_insn_ents; /* Used as operand to `operate_exp': */ -enum operator {PLUS_OP, MINUS_OP, POS_MINUS_OP, EQ_OP, OR_OP, MAX_OP, MIN_OP, RANGE_OP}; +enum operator {PLUS_OP, MINUS_OP, POS_MINUS_OP, EQ_OP, OR_OP, ORX_OP, MAX_OP, MIN_OP, RANGE_OP}; /* Stores, for each insn code, the number of constraint alternatives. */ @@ -329,7 +316,7 @@ static int *insn_alternatives; This is the hashed, unique string for the numeral whose value is chosen alternative. */ -static char *current_alternative_string; +static const char *current_alternative_string; /* Used to simplify expressions. */ @@ -339,6 +326,16 @@ static rtx true_rtx, false_rtx; static char *alternative_name; +/* Indicate that REG_DEAD notes are valid if dead_or_set_p is ever + called. */ + +int reload_completed = 0; + +/* Some machines test `optimize' in macros called from rtlanal.c, so we need + to define it here. */ + +int optimize = 0; + /* Simplify an expression. Only call the routine if there is something to simplify. */ #define SIMPLIFY_TEST_EXP(EXP,INSN_CODE,INSN_INDEX) \ @@ -357,96 +354,107 @@ static char *alternative_name; /* These are referenced by rtlanal.c and hence need to be defined somewhere. They won't actually be used. */ -rtx frame_pointer_rtx, hard_frame_pointer_rtx, stack_pointer_rtx; -rtx arg_pointer_rtx; - -static rtx attr_rtx PVPROTO((enum rtx_code, ...)); -#ifdef HAVE_VPRINTF -static char *attr_printf PVPROTO((int, char *, ...)); -#else -static char *attr_printf (); +rtx global_rtl[GR_MAX]; +rtx pic_offset_table_rtx; + +static void attr_hash_add_rtx PARAMS ((int, rtx)); +static void attr_hash_add_string PARAMS ((int, char *)); +static rtx attr_rtx PARAMS ((enum rtx_code, ...)); +static char *attr_printf PARAMS ((int, const char *, ...)) + ATTRIBUTE_PRINTF_2; +static char *attr_string PARAMS ((const char *, int)); +static rtx check_attr_test PARAMS ((rtx, int)); +static rtx check_attr_value PARAMS ((rtx, struct attr_desc *)); +static rtx convert_set_attr_alternative PARAMS ((rtx, int, int)); +static rtx convert_set_attr PARAMS ((rtx, int, int)); +static void check_defs PARAMS ((void)); +#if 0 +static rtx convert_const_symbol_ref PARAMS ((rtx, struct attr_desc *)); #endif - -static char *attr_string PROTO((char *, int)); -static rtx check_attr_test PROTO((rtx, int)); -static rtx check_attr_value PROTO((rtx, struct attr_desc *)); -static rtx convert_set_attr_alternative PROTO((rtx, int, int, int)); -static rtx convert_set_attr PROTO((rtx, int, int, int)); -static void check_defs PROTO((void)); -static rtx convert_const_symbol_ref PROTO((rtx, struct attr_desc *)); -static rtx make_canonical PROTO((struct attr_desc *, rtx)); -static struct attr_value *get_attr_value PROTO((rtx, struct attr_desc *, int)); -static rtx copy_rtx_unchanging PROTO((rtx)); -static rtx copy_boolean PROTO((rtx)); -static void expand_delays PROTO((void)); -static rtx operate_exp PROTO((enum operator, rtx, rtx)); -static void expand_units PROTO((void)); -static rtx simplify_knowing PROTO((rtx, rtx)); -static rtx encode_units_mask PROTO((rtx)); -static void fill_attr PROTO((struct attr_desc *)); +static rtx make_canonical PARAMS ((struct attr_desc *, rtx)); +static struct attr_value *get_attr_value PARAMS ((rtx, struct attr_desc *, int)); +static rtx copy_rtx_unchanging PARAMS ((rtx)); +static rtx copy_boolean PARAMS ((rtx)); +static void expand_delays PARAMS ((void)); +static rtx operate_exp PARAMS ((enum operator, rtx, rtx)); +static void expand_units PARAMS ((void)); +static rtx simplify_knowing PARAMS ((rtx, rtx)); +static rtx encode_units_mask PARAMS ((rtx)); +static void fill_attr PARAMS ((struct attr_desc *)); /* dpx2 compiler chokes if we specify the arg types of the args. */ -static rtx substitute_address PROTO((rtx, rtx (*) (), rtx (*) ())); -static void make_length_attrs PROTO((void)); -static rtx identity_fn PROTO((rtx)); -static rtx zero_fn PROTO((rtx)); -static rtx one_fn PROTO((rtx)); -static rtx max_fn PROTO((rtx)); -static rtx simplify_cond PROTO((rtx, int, int)); -static rtx simplify_by_alternatives PROTO((rtx, int, int)); -static rtx simplify_by_exploding PROTO((rtx)); -static int find_and_mark_used_attributes PROTO((rtx, rtx *, int *)); -static void unmark_used_attributes PROTO((rtx, struct dimension *, int)); -static int add_values_to_cover PROTO((struct dimension *)); -static int increment_current_value PROTO((struct dimension *, int)); -static rtx test_for_current_value PROTO((struct dimension *, int)); -static rtx simplify_with_current_value PROTO((rtx, struct dimension *, int)); -static rtx simplify_with_current_value_aux PROTO((rtx)); -static void clear_struct_flag PROTO((rtx)); -static int count_sub_rtxs PROTO((rtx, int)); -static void remove_insn_ent PROTO((struct attr_value *, struct insn_ent *)); -static void insert_insn_ent PROTO((struct attr_value *, struct insn_ent *)); -static rtx insert_right_side PROTO((enum rtx_code, rtx, rtx, int, int)); -static rtx make_alternative_compare PROTO((int)); -static int compute_alternative_mask PROTO((rtx, enum rtx_code)); -static rtx evaluate_eq_attr PROTO((rtx, rtx, int, int)); -static rtx simplify_and_tree PROTO((rtx, rtx *, int, int)); -static rtx simplify_or_tree PROTO((rtx, rtx *, int, int)); -static rtx simplify_test_exp PROTO((rtx, int, int)); -static void optimize_attrs PROTO((void)); -static void gen_attr PROTO((rtx)); -static int count_alternatives PROTO((rtx)); -static int compares_alternatives_p PROTO((rtx)); -static int contained_in_p PROTO((rtx, rtx)); -static void gen_insn PROTO((rtx)); -static void gen_delay PROTO((rtx)); -static void gen_unit PROTO((rtx)); -static void write_test_expr PROTO((rtx, int)); -static int max_attr_value PROTO((rtx)); -static void walk_attr_value PROTO((rtx)); -static void write_attr_get PROTO((struct attr_desc *)); -static rtx eliminate_known_true PROTO((rtx, rtx, int, int)); -static void write_attr_set PROTO((struct attr_desc *, int, rtx, char *, - char *, rtx, int, int)); -static void write_attr_case PROTO((struct attr_desc *, struct attr_value *, - int, char *, char *, int, rtx)); -static void write_attr_valueq PROTO((struct attr_desc *, char *)); -static void write_attr_value PROTO((struct attr_desc *, rtx)); -static void write_upcase PROTO((char *)); -static void write_indent PROTO((int)); -static void write_eligible_delay PROTO((char *)); -static void write_function_unit_info PROTO((void)); -static void write_complex_function PROTO((struct function_unit *, char *, - char *)); -static int n_comma_elts PROTO((char *)); -static char *next_comma_elt PROTO((char **)); -static struct attr_desc *find_attr PROTO((char *, int)); -static void make_internal_attr PROTO((char *, rtx, int)); -static struct attr_value *find_most_used PROTO((struct attr_desc *)); -static rtx find_single_value PROTO((struct attr_desc *)); -static rtx make_numeric_value PROTO((int)); -static void extend_range PROTO((struct range *, int, int)); -char *xrealloc PROTO((char *, unsigned)); -char *xmalloc PROTO((unsigned)); +static rtx substitute_address PARAMS ((rtx, rtx (*) (rtx), rtx (*) (rtx))); +static void make_length_attrs PARAMS ((void)); +static rtx identity_fn PARAMS ((rtx)); +static rtx zero_fn PARAMS ((rtx)); +static rtx one_fn PARAMS ((rtx)); +static rtx max_fn PARAMS ((rtx)); +static void write_length_unit_log PARAMS ((void)); +static rtx simplify_cond PARAMS ((rtx, int, int)); +#if 0 +static rtx simplify_by_alternatives PARAMS ((rtx, int, int)); +#endif +static rtx simplify_by_exploding PARAMS ((rtx)); +static int find_and_mark_used_attributes PARAMS ((rtx, rtx *, int *)); +static void unmark_used_attributes PARAMS ((rtx, struct dimension *, int)); +static int add_values_to_cover PARAMS ((struct dimension *)); +static int increment_current_value PARAMS ((struct dimension *, int)); +static rtx test_for_current_value PARAMS ((struct dimension *, int)); +static rtx simplify_with_current_value PARAMS ((rtx, struct dimension *, int)); +static rtx simplify_with_current_value_aux PARAMS ((rtx)); +static void clear_struct_flag PARAMS ((rtx)); +static int count_sub_rtxs PARAMS ((rtx, int)); +static void remove_insn_ent PARAMS ((struct attr_value *, struct insn_ent *)); +static void insert_insn_ent PARAMS ((struct attr_value *, struct insn_ent *)); +static rtx insert_right_side PARAMS ((enum rtx_code, rtx, rtx, int, int)); +static rtx make_alternative_compare PARAMS ((int)); +static int compute_alternative_mask PARAMS ((rtx, enum rtx_code)); +static rtx evaluate_eq_attr PARAMS ((rtx, rtx, int, int)); +static rtx simplify_and_tree PARAMS ((rtx, rtx *, int, int)); +static rtx simplify_or_tree PARAMS ((rtx, rtx *, int, int)); +static rtx simplify_test_exp PARAMS ((rtx, int, int)); +static void optimize_attrs PARAMS ((void)); +static void gen_attr PARAMS ((rtx)); +static int count_alternatives PARAMS ((rtx)); +static int compares_alternatives_p PARAMS ((rtx)); +static int contained_in_p PARAMS ((rtx, rtx)); +static void gen_insn PARAMS ((rtx)); +static void gen_delay PARAMS ((rtx)); +static void gen_unit PARAMS ((rtx)); +static void write_test_expr PARAMS ((rtx, int)); +static int max_attr_value PARAMS ((rtx, int*)); +static int or_attr_value PARAMS ((rtx, int*)); +static void walk_attr_value PARAMS ((rtx)); +static void write_attr_get PARAMS ((struct attr_desc *)); +static rtx eliminate_known_true PARAMS ((rtx, rtx, int, int)); +static void write_attr_set PARAMS ((struct attr_desc *, int, rtx, + const char *, const char *, rtx, + int, int)); +static void write_attr_case PARAMS ((struct attr_desc *, struct attr_value *, + int, const char *, const char *, int, rtx)); +static void write_unit_name PARAMS ((const char *, int, const char *)); +static void write_attr_valueq PARAMS ((struct attr_desc *, const char *)); +static void write_attr_value PARAMS ((struct attr_desc *, rtx)); +static void write_upcase PARAMS ((const char *)); +static void write_indent PARAMS ((int)); +static void write_eligible_delay PARAMS ((const char *)); +static void write_function_unit_info PARAMS ((void)); +static void write_complex_function PARAMS ((struct function_unit *, const char *, + const char *)); +static int write_expr_attr_cache PARAMS ((rtx, struct attr_desc *)); +static void write_toplevel_expr PARAMS ((rtx)); +static void write_const_num_delay_slots PARAMS ((void)); +static int n_comma_elts PARAMS ((const char *)); +static char *next_comma_elt PARAMS ((const char **)); +static struct attr_desc *find_attr PARAMS ((const char *, int)); +static void make_internal_attr PARAMS ((const char *, rtx, int)); +static struct attr_value *find_most_used PARAMS ((struct attr_desc *)); +static rtx find_single_value PARAMS ((struct attr_desc *)); +static rtx make_numeric_value PARAMS ((int)); +static void extend_range PARAMS ((struct range *, int, int)); +static rtx attr_eq PARAMS ((const char *, const char *)); +static const char *attr_numeral PARAMS ((int)); +static int attr_equal_p PARAMS ((rtx, rtx)); +static rtx attr_copy_rtx PARAMS ((rtx)); #define oballoc(size) obstack_alloc (hash_obstack, size) @@ -480,7 +488,7 @@ struct attr_hash *attr_hash_table[RTL_HASH_SIZE]; /* Here is how primitive or already-shared RTL's hash codes are made. */ -#define RTL_HASH(RTL) ((HOST_WIDE_INT) (RTL) & 0777777) +#define RTL_HASH(RTL) ((long) (RTL) & 0777777) /* Add an entry to the hash table for RTL with hash code HASHCODE. */ @@ -528,22 +536,22 @@ attr_hash_add_string (hashcode, str) /*VARARGS1*/ static rtx -attr_rtx VPROTO((enum rtx_code code, ...)) +attr_rtx VPARAMS ((enum rtx_code code, ...)) { -#ifndef __STDC__ +#ifndef ANSI_PROTOTYPES enum rtx_code code; #endif va_list p; register int i; /* Array indices... */ - register char *fmt; /* Current rtx's format... */ - register rtx rt_val; /* RTX to return to caller... */ + register const char *fmt; /* Current rtx's format... */ + register rtx rt_val = NULL_RTX;/* RTX to return to caller... */ int hashcode; register struct attr_hash *h; struct obstack *old_obstack = rtl_obstack; VA_START (p, code); -#ifndef __STDC__ +#ifndef ANSI_PROTOTYPES code = va_arg (p, enum rtx_code); #endif @@ -614,7 +622,7 @@ attr_rtx VPROTO((enum rtx_code code, ...)) else if (GET_RTX_LENGTH (code) == 1 && GET_RTX_FORMAT (code)[0] == 's') { - char * arg0 = va_arg (p, char *); + char *arg0 = va_arg (p, char *); if (code == SYMBOL_REF) arg0 = attr_string (arg0, strlen (arg0)); @@ -660,9 +668,15 @@ attr_rtx VPROTO((enum rtx_code code, ...)) { HOST_WIDE_INT arg0 = va_arg (p, HOST_WIDE_INT); if (arg0 == 0) - return false_rtx; + { + va_end (p); + return false_rtx; + } if (arg0 == 1) - return true_rtx; + { + va_end (p); + return true_rtx; + } goto nohash; } else @@ -723,24 +737,22 @@ attr_rtx VPROTO((enum rtx_code code, ...)) rtx attr_printf (len, format, [arg1, ..., argn]) */ -#ifdef HAVE_VPRINTF - /*VARARGS2*/ static char * -attr_printf VPROTO((register int len, char *fmt, ...)) +attr_printf VPARAMS ((register int len, const char *fmt, ...)) { -#ifndef __STDC__ +#ifndef ANSI_PROTOTYPES register int len; - char *fmt; + const char *fmt; #endif va_list p; register char *str; VA_START (p, fmt); -#ifndef __STDC__ +#ifndef ANSI_PROTOTYPES len = va_arg (p, int); - fmt = va_arg (p, char*); + fmt = va_arg (p, const char *); #endif /* Print the string into a temporary location. */ @@ -751,33 +763,15 @@ attr_printf VPROTO((register int len, char *fmt, ...)) return attr_string (str, strlen (str)); } -#else /* not HAVE_VPRINTF */ - -static char * -attr_printf (len, fmt, arg1, arg2, arg3) - int len; - char *fmt; - char *arg1, *arg2, *arg3; /* also int */ -{ - register char *str; - - /* Print the string into a temporary location. */ - str = (char *) alloca (len); - sprintf (str, fmt, arg1, arg2, arg3); - - return attr_string (str, strlen (str)); -} -#endif /* not HAVE_VPRINTF */ - -rtx +static rtx attr_eq (name, value) - char *name, *value; + const char *name, *value; { return attr_rtx (EQ_ATTR, attr_string (name, strlen (name)), attr_string (value, strlen (value))); } -char * +static const char * attr_numeral (n) int n; { @@ -789,7 +783,7 @@ attr_numeral (n) static char * attr_string (str, len) - char *str; + const char *str; int len; { register struct attr_hash *h; @@ -823,7 +817,7 @@ attr_string (str, len) taking advantage of the fact that if both are hashed then they can't be equal unless they are the same object. */ -int +static int attr_equal_p (x, y) rtx x, y; { @@ -835,14 +829,14 @@ attr_equal_p (x, y) descending to all depths, but not copying any permanent hashed subexpressions. */ -rtx +static rtx attr_copy_rtx (orig) register rtx orig; { register rtx copy; register int i, j; register RTX_CODE code; - register char *format_ptr; + register const char *format_ptr; /* No need to copy a permanent object. */ if (RTX_INTEGRATED_P (orig)) @@ -861,6 +855,9 @@ attr_copy_rtx (orig) case PC: case CC0: return orig; + + default: + break; } copy = rtx_alloc (code); @@ -935,7 +932,7 @@ check_attr_test (exp, is_const) { struct attr_desc *attr; struct attr_value *av; - char *name_ptr, *p; + const char *name_ptr, *p; rtx orexp, newexp; switch (GET_CODE (exp)) @@ -961,12 +958,12 @@ check_attr_test (exp, is_const) return exp; } else - fatal ("Unknown attribute `%s' in EQ_ATTR", XEXP (exp, 0)); + fatal ("Unknown attribute `%s' in EQ_ATTR", XSTR (exp, 0)); } if (is_const && ! attr->is_const) fatal ("Constant expression uses insn attribute `%s' in EQ_ATTR", - XEXP (exp, 0)); + XSTR (exp, 0)); /* Copy this just to make it permanent, so expressions using it can be permanent too. */ @@ -983,7 +980,7 @@ check_attr_test (exp, is_const) for (p = XSTR (exp, 1); *p; p++) if (*p < '0' || *p > '9') fatal ("Attribute `%s' takes only numeric values", - XEXP (exp, 0)); + XSTR (exp, 0)); } else { @@ -994,7 +991,7 @@ check_attr_test (exp, is_const) if (av == NULL) fatal ("Unknown value `%s' for `%s' attribute", - XEXP (exp, 1), XEXP (exp, 0)); + XSTR (exp, 1), XSTR (exp, 0)); } } else @@ -1032,14 +1029,15 @@ check_attr_test (exp, is_const) XEXP (exp, 0) = check_attr_test (XEXP (exp, 0), is_const); break; + case MATCH_INSN: case MATCH_OPERAND: if (is_const) fatal ("RTL operator \"%s\" not valid in constant attribute test", - GET_RTX_NAME (MATCH_OPERAND)); + GET_RTX_NAME (GET_CODE (exp))); /* These cases can't be simplified. */ RTX_UNCHANGING_P (exp) = 1; break; - + case LE: case LT: case GT: case GE: case LEU: case LTU: case GTU: case GEU: case NE: case EQ: @@ -1081,7 +1079,7 @@ check_attr_value (exp, attr) struct attr_desc *attr; { struct attr_value *av; - char *p; + const char *p; int i; switch (GET_CODE (exp)) @@ -1091,7 +1089,7 @@ check_attr_value (exp, attr) fatal ("CONST_INT not valid for non-numeric `%s' attribute", attr->name); - if (INTVAL (exp) < 0) + if (INTVAL (exp) < 0 && ! attr->negative_ok) fatal ("Negative numeric value specified for `%s' attribute", attr->name); @@ -1131,6 +1129,26 @@ check_attr_value (exp, attr) XEXP (exp, 2) = check_attr_value (XEXP (exp, 2), attr); break; + case PLUS: + case MINUS: + case MULT: + case DIV: + case MOD: + if (attr && !attr->is_numeric) + fatal ("Invalid operation `%s' for non-numeric attribute value", + GET_RTX_NAME (GET_CODE (exp))); + /* FALLTHRU */ + + case IOR: + case AND: + XEXP (exp, 0) = check_attr_value (XEXP (exp, 0), attr); + XEXP (exp, 1) = check_attr_value (XEXP (exp, 1), attr); + break; + + case FFS: + XEXP (exp, 0) = check_attr_value (XEXP (exp, 0), attr); + break; + case COND: if (XVECLEN (exp, 0) % 2 != 0) fatal ("First operand of COND must have even length"); @@ -1146,12 +1164,27 @@ check_attr_value (exp, attr) XEXP (exp, 1) = check_attr_value (XEXP (exp, 1), attr); break; + case ATTR: + { + struct attr_desc *attr2 = find_attr (XSTR (exp, 0), 0); + if (attr2 == NULL) + fatal ("Unknown attribute `%s' in ATTR", XSTR (exp, 0)); + else if ((attr && attr->is_const) && ! attr2->is_const) + fatal ("Non-constant attribute `%s' referenced from `%s'", + XSTR (exp, 0), attr->name); + else if (attr + && (attr->is_numeric != attr2->is_numeric + || (! attr->negative_ok && attr2->negative_ok))) + fatal ("Numeric attribute mismatch calling `%s' from `%s'", + XSTR (exp, 0), attr->name); + } + break; + case SYMBOL_REF: - if (attr && attr->is_const) - /* A constant SYMBOL_REF is valid as a constant attribute test and - is expanded later by make_canonical into a COND. */ - return attr_rtx (SYMBOL_REF, XSTR (exp, 0)); - /* Otherwise, fall through... */ + /* A constant SYMBOL_REF is valid as a constant attribute test and + is expanded later by make_canonical into a COND. In a non-constant + attribute test, it is left be. */ + return attr_rtx (SYMBOL_REF, XSTR (exp, 0)); default: fatal ("Invalid operation `%s' for attribute value", @@ -1165,10 +1198,10 @@ check_attr_value (exp, attr) It becomes a COND with each test being (eq_attr "alternative "n") */ static rtx -convert_set_attr_alternative (exp, num_alt, insn_code, insn_index) +convert_set_attr_alternative (exp, num_alt, insn_index) rtx exp; int num_alt; - int insn_code, insn_index; + int insn_index; { rtx condexp; int i; @@ -1184,7 +1217,7 @@ convert_set_attr_alternative (exp, num_alt, insn_code, insn_index) for (i = 0; i < num_alt - 1; i++) { - char *p; + const char *p; p = attr_numeral (i); XVECEXP (condexp, 0, 2 * i) = attr_eq (alternative_name, p); @@ -1206,13 +1239,13 @@ convert_set_attr_alternative (exp, num_alt, insn_code, insn_index) list of values is given, convert to SET_ATTR_ALTERNATIVE first. */ static rtx -convert_set_attr (exp, num_alt, insn_code, insn_index) +convert_set_attr (exp, num_alt, insn_index) rtx exp; int num_alt; - int insn_code, insn_index; + int insn_index; { rtx newexp; - char *name_ptr; + const char *name_ptr; char *p; int n; @@ -1233,12 +1266,12 @@ convert_set_attr (exp, num_alt, insn_code, insn_index) while ((p = next_comma_elt (&name_ptr)) != NULL) XVECEXP (newexp, 1, n++) = attr_rtx (CONST_STRING, p); - return convert_set_attr_alternative (newexp, num_alt, insn_code, insn_index); + return convert_set_attr_alternative (newexp, num_alt, insn_index); } /* Scan all definitions, checking for validity. Also, convert any SET_ATTR and SET_ATTR_ALTERNATIVE expressions to the corresponding SET - expressions. */ + expressions. */ static void check_defs () @@ -1266,13 +1299,12 @@ check_defs () case SET_ATTR_ALTERNATIVE: value = convert_set_attr_alternative (value, id->num_alternatives, - id->insn_code, id->insn_index); break; case SET_ATTR: value = convert_set_attr (value, id->num_alternatives, - id->insn_code, id->insn_index); + id->insn_index); break; default: @@ -1290,6 +1322,7 @@ check_defs () } } +#if 0 /* Given a constant SYMBOL_REF expression, convert to a COND that explicitly tests each enumerated value. */ @@ -1327,8 +1360,7 @@ convert_const_symbol_ref (exp, attr) strcat (p, "_"); strcat (p, XSTR (av->value, 0)); for (; *p != '\0'; p++) - if (*p >= 'a' && *p <= 'z') - *p -= 'a' - 'A'; + *p = TOUPPER (*p); value = attr_rtx (SYMBOL_REF, string); RTX_UNCHANGING_P (value) = 1; @@ -1340,6 +1372,7 @@ convert_const_symbol_ref (exp, attr) return condexp; } +#endif /* Given a valid expression for an attribute value, remove any IF_THEN_ELSE expressions by converting them into a COND. This removes cases from this @@ -1377,13 +1410,21 @@ make_canonical (attr, exp) This makes the COND something that won't be considered an arbitrary expression by walk_attr_value. */ RTX_UNCHANGING_P (exp) = 1; +#if 0 + /* ??? Why do we do this? With attribute values { A B C D E }, this + tends to generate (!(x==A) && !(x==B) && !(x==C) && !(x==D)) rather + than (x==E). */ exp = convert_const_symbol_ref (exp, attr); RTX_UNCHANGING_P (exp) = 1; exp = check_attr_value (exp, attr); /* Goto COND case since this is now a COND. Note that while the - new expression is rescanned, all symbol_ref notes are mared as + new expression is rescanned, all symbol_ref notes are marked as unchanging. */ goto cond; +#else + exp = check_attr_value (exp, attr); + break; +#endif case IF_THEN_ELSE: newexp = rtx_alloc (COND); @@ -1397,12 +1438,11 @@ make_canonical (attr, exp) /* Fall through to COND case since this is now a COND. */ case COND: - cond: { int allsame = 1; rtx defval; - /* First, check for degenerate COND. */ + /* First, check for degenerate COND. */ if (XVECLEN (exp, 0) == 0) return make_canonical (attr, XEXP (exp, 1)); defval = XEXP (exp, 1) = make_canonical (attr, XEXP (exp, 1)); @@ -1417,8 +1457,11 @@ make_canonical (attr, exp) } if (allsame) return defval; - break; } + break; + + default: + break; } return exp; @@ -1618,6 +1661,7 @@ operate_exp (op, left, right) break; case OR_OP: + case ORX_OP: i = left_value | right_value; break; @@ -1647,6 +1691,10 @@ operate_exp (op, left, right) abort (); } + if (i == left_value) + return left; + if (i == right_value) + return right; return make_numeric_value (i); } else if (GET_CODE (right) == IF_THEN_ELSE) @@ -1681,7 +1729,8 @@ operate_exp (op, left, right) give the same value), optimize it away. */ if (allsame) { - obstack_free (rtl_obstack, newexp); + if (!ggc_p) + obstack_free (rtl_obstack, newexp); return operate_exp (op, left, XEXP (right, 1)); } @@ -1689,7 +1738,8 @@ operate_exp (op, left, right) just use that. */ if (rtx_equal_p (newexp, right)) { - obstack_free (rtl_obstack, newexp); + if (!ggc_p) + obstack_free (rtl_obstack, newexp); return right; } @@ -1699,6 +1749,13 @@ operate_exp (op, left, right) fatal ("Badly formed attribute value"); } + /* A hack to prevent expand_units from completely blowing up: ORX_OP does + not associate through IF_THEN_ELSE. */ + else if (op == ORX_OP && GET_CODE (right) == IF_THEN_ELSE) + { + return attr_rtx (IOR, left, right); + } + /* Otherwise, do recursion the other way. */ else if (GET_CODE (left) == IF_THEN_ELSE) { @@ -1731,7 +1788,8 @@ operate_exp (op, left, right) optimize it away. */ if (allsame) { - obstack_free (rtl_obstack, newexp); + if (!ggc_p) + obstack_free (rtl_obstack, newexp); return operate_exp (op, XEXP (left, 1), right); } @@ -1739,7 +1797,8 @@ operate_exp (op, left, right) just use that. */ if (rtx_equal_p (newexp, left)) { - obstack_free (rtl_obstack, newexp); + if (!ggc_p) + obstack_free (rtl_obstack, newexp); return left; } @@ -1792,7 +1851,7 @@ expand_units () rtx unitsmask; rtx readycost; rtx newexp; - char *str; + const char *str; int i, j, u, num, nvalues; /* Rebuild the condition for the unit to share the RTL expressions. @@ -1841,19 +1900,49 @@ expand_units () newexp = rtx_alloc (IF_THEN_ELSE); XEXP (newexp, 2) = make_numeric_value (0); - /* Merge each function unit into the unit mask attributes. */ - for (unit = units; unit; unit = unit->next) + /* If we have just a few units, we may be all right expanding the whole + thing. But the expansion is 2**N in space on the number of opclasses, + so we can't do this for very long -- Alpha and MIPS in particular have + problems with this. So in that situation, we fall back on an alternate + implementation method. */ +#define NUM_UNITOP_CUTOFF 20 + + if (num_unit_opclasses < NUM_UNITOP_CUTOFF) { - XEXP (newexp, 0) = unit->condexp; - XEXP (newexp, 1) = make_numeric_value (1 << unit->num); - unitsmask = operate_exp (OR_OP, unitsmask, newexp); + /* Merge each function unit into the unit mask attributes. */ + for (unit = units; unit; unit = unit->next) + { + XEXP (newexp, 0) = unit->condexp; + XEXP (newexp, 1) = make_numeric_value (1 << unit->num); + unitsmask = operate_exp (OR_OP, unitsmask, newexp); + } + } + else + { + /* Merge each function unit into the unit mask attributes. */ + for (unit = units; unit; unit = unit->next) + { + XEXP (newexp, 0) = unit->condexp; + XEXP (newexp, 1) = make_numeric_value (1 << unit->num); + unitsmask = operate_exp (ORX_OP, unitsmask, attr_copy_rtx (newexp)); + } } /* Simplify the unit mask expression, encode it, and make an attribute for the function_units_used function. */ unitsmask = simplify_by_exploding (unitsmask); - unitsmask = encode_units_mask (unitsmask); - make_internal_attr ("*function_units_used", unitsmask, 2); + + if (num_unit_opclasses < NUM_UNITOP_CUTOFF) + unitsmask = encode_units_mask (unitsmask); + else + { + /* We can no longer encode unitsmask at compile time, so emit code to + calculate it at runtime. Rather, put a marker for where we'd do + the code, and actually output it in write_attr_get(). */ + unitsmask = attr_rtx (FFS, unitsmask); + } + + make_internal_attr ("*function_units_used", unitsmask, 10); /* Create an array of ops for each unit. Add an extra unit for the result_ready_cost function that has the ops of all other units. */ @@ -2002,21 +2091,7 @@ expand_units () for (op = unit->ops; op; op = op->next) { - rtx blockage = operate_exp (POS_MINUS_OP, readycost, - make_numeric_value (1)); - - if (unit->simultaneity != 0) - { - rtx filltime = make_numeric_value ((unit->simultaneity - 1) - * unit->issue_delay.min); - blockage = operate_exp (MIN_OP, blockage, filltime); - } - - blockage = operate_exp (POS_MINUS_OP, - make_numeric_value (op->ready), - blockage); - - blockage = operate_exp (MAX_OP, blockage, op->issue_exp); + rtx blockage = op->issue_exp; blockage = simplify_knowing (blockage, unit->condexp); /* Add this op's contribution to MAX (BLOCKAGE (E,*)) and @@ -2042,7 +2117,10 @@ expand_units () } /* Record MAX (BLOCKAGE (*,*)). */ - unit->max_blockage = max_attr_value (max_blockage); + { + int unknown; + unit->max_blockage = max_attr_value (max_blockage, &unknown); + } /* See if the upper and lower bounds of BLOCKAGE (E,*) are the same. If so, the blockage function carries no additional @@ -2062,13 +2140,13 @@ expand_units () if (unit->needs_range_function) { /* Compute the blockage range function and make an attribute - for writing it's value. */ + for writing its value. */ newexp = operate_exp (RANGE_OP, min_blockage, max_blockage); newexp = simplify_knowing (newexp, unit->condexp); str = attr_printf (strlen (unit->name) + sizeof ("*_unit_blockage_range"), "*%s_unit_blockage_range", unit->name); - make_internal_attr (str, newexp, 4); + make_internal_attr (str, newexp, 20); } str = attr_printf (strlen (unit->name) + sizeof ("*_unit_ready_cost"), @@ -2127,9 +2205,14 @@ simplify_knowing (exp, known_true) { if (GET_CODE (exp) != CONST_STRING) { - exp = attr_rtx (IF_THEN_ELSE, known_true, exp, - make_numeric_value (max_attr_value (exp))); - exp = simplify_by_exploding (exp); + int unknown = 0, max; + max = max_attr_value (exp, &unknown); + if (! unknown) + { + exp = attr_rtx (IF_THEN_ELSE, known_true, exp, + make_numeric_value (max)); + exp = simplify_by_exploding (exp); + } } return exp; } @@ -2146,7 +2229,7 @@ encode_units_mask (x) register int i; register int j; register enum rtx_code code; - register char *fmt; + register const char *fmt; code = GET_CODE (x); @@ -2174,6 +2257,9 @@ encode_units_mask (x) case CC0: case EQ_ATTR: return x; + + default: + break; } /* Compare the elements. If any pair of corresponding elements @@ -2250,8 +2336,8 @@ fill_attr (attr) static rtx substitute_address (exp, no_address_fn, address_fn) rtx exp; - rtx (*no_address_fn) (); - rtx (*address_fn) (); + rtx (*no_address_fn) PARAMS ((rtx)); + rtx (*address_fn) PARAMS ((rtx)); { int i; rtx newexp; @@ -2324,12 +2410,12 @@ substitute_address (exp, no_address_fn, address_fn) static void make_length_attrs () { - static char *new_names[] = {"*insn_default_length", - "*insn_variable_length_p", - "*insn_current_length"}; - static rtx (*no_address_fn[]) PROTO((rtx)) = {identity_fn, zero_fn, zero_fn}; - static rtx (*address_fn[]) PROTO((rtx)) = {max_fn, one_fn, identity_fn}; - int i; + static const char *new_names[] = {"*insn_default_length", + "*insn_variable_length_p", + "*insn_current_length"}; + static rtx (*no_address_fn[]) PARAMS ((rtx)) = {identity_fn, zero_fn, zero_fn}; + static rtx (*address_fn[]) PARAMS ((rtx)) = {max_fn, one_fn, identity_fn}; + size_t i; struct attr_desc *length_attr, *new_attr; struct attr_value *av, *new_av; struct insn_ent *ie, *new_ie; @@ -2380,14 +2466,14 @@ identity_fn (exp) static rtx zero_fn (exp) - rtx exp; + rtx exp ATTRIBUTE_UNUSED; { return make_numeric_value (0); } static rtx one_fn (exp) - rtx exp; + rtx exp ATTRIBUTE_UNUSED; { return make_numeric_value (1); } @@ -2396,7 +2482,35 @@ static rtx max_fn (exp) rtx exp; { - return make_numeric_value (max_attr_value (exp)); + int unknown; + return make_numeric_value (max_attr_value (exp, &unknown)); +} + +static void +write_length_unit_log () +{ + struct attr_desc *length_attr = find_attr ("length", 0); + struct attr_value *av; + struct insn_ent *ie; + unsigned int length_unit_log, length_or; + int unknown = 0; + + if (length_attr == 0) + return; + length_or = or_attr_value (length_attr->default_val->value, &unknown); + for (av = length_attr->first_value; av; av = av->next) + for (ie = av->first_insn; ie; ie = ie->next) + length_or |= or_attr_value (av->value, &unknown); + + if (unknown) + length_unit_log = 0; + else + { + length_or = ~length_or; + for (length_unit_log = 0; length_or & 1; length_or >>= 1) + length_unit_log++; + } + printf ("int length_unit_log = %u;\n", length_unit_log); } /* Take a COND expression and see if any of the conditions in it can be @@ -2417,7 +2531,6 @@ simplify_cond (exp, insn_code, insn_index) then build a new expression if they don't match EXP. */ rtx defval = XEXP (exp, 1); rtx new_defval = XEXP (exp, 1); - int len = XVECLEN (exp, 0); rtx *tests = (rtx *) alloca (len * sizeof (rtx)); int allsame = 1; @@ -2426,7 +2539,7 @@ simplify_cond (exp, insn_code, insn_index) /* This lets us free all storage allocated below, if appropriate. */ first_spacer = (char *) obstack_finish (rtl_obstack); - bcopy ((char *) &XVECEXP (exp, 0, 0), (char *) tests, len * sizeof (rtx)); + bcopy ((char *) XVEC (exp, 0)->elem, (char *) tests, len * sizeof (rtx)); /* See if default value needs simplification. */ if (GET_CODE (defval) == COND) @@ -2503,14 +2616,16 @@ simplify_cond (exp, insn_code, insn_index) if (len == 0) { - obstack_free (rtl_obstack, first_spacer); + if (!ggc_p) + obstack_free (rtl_obstack, first_spacer); if (GET_CODE (defval) == COND) return simplify_cond (defval, insn_code, insn_index); return defval; } else if (allsame) { - obstack_free (rtl_obstack, first_spacer); + if (!ggc_p) + obstack_free (rtl_obstack, first_spacer); return exp; } else @@ -2518,7 +2633,7 @@ simplify_cond (exp, insn_code, insn_index) rtx newexp = rtx_alloc (COND); XVEC (newexp, 0) = rtvec_alloc (len); - bcopy ((char *) tests, (char *) &XVECEXP (newexp, 0, 0), + bcopy ((char *) tests, (char *) XVEC (newexp, 0)->elem, len * sizeof (rtx)); XEXP (newexp, 1) = new_defval; return newexp; @@ -2646,7 +2761,7 @@ compute_alternative_mask (exp, code) rtx exp; enum rtx_code code; { - char *string; + const char *string; if (GET_CODE (exp) == code) return compute_alternative_mask (XEXP (exp, 0), code) | compute_alternative_mask (XEXP (exp, 1), code); @@ -2715,6 +2830,25 @@ evaluate_eq_attr (exp, value, insn_code, insn_index) else newexp = false_rtx; } + else if (GET_CODE (value) == SYMBOL_REF) + { + char *p, *string; + + if (GET_CODE (exp) != EQ_ATTR) + abort(); + + string = (char *) alloca (2 + strlen (XSTR (exp, 0)) + + strlen (XSTR (exp, 1))); + strcpy (string, XSTR (exp, 0)); + strcat (string, "_"); + strcat (string, XSTR (exp, 1)); + for (p = string; *p ; p++) + *p = TOUPPER (*p); + + newexp = attr_rtx (EQ, value, + attr_rtx (SYMBOL_REF, + attr_string(string, strlen(string)))); + } else if (GET_CODE (value) == COND) { /* We construct an IOR of all the cases for which the requested attribute @@ -2727,7 +2861,7 @@ evaluate_eq_attr (exp, value, insn_code, insn_index) For each possible COND value, call ourselves recursively. The extra TRUE and FALSE expressions will be eliminated by another - call to the simplification routine. */ + call to the simplification routine. */ orexp = false_rtx; andexp = true_rtx; @@ -3020,14 +3154,16 @@ simplify_test_exp (exp, insn_code, insn_index) SIMPLIFY_ALTERNATIVE (left); if (left == false_rtx) { - obstack_free (rtl_obstack, spacer); + if (!ggc_p) + obstack_free (rtl_obstack, spacer); return false_rtx; } right = SIMPLIFY_TEST_EXP (XEXP (exp, 1), insn_code, insn_index); SIMPLIFY_ALTERNATIVE (right); if (left == false_rtx) { - obstack_free (rtl_obstack, spacer); + if (!ggc_p) + obstack_free (rtl_obstack, spacer); return false_rtx; } @@ -3059,7 +3195,8 @@ simplify_test_exp (exp, insn_code, insn_index) if (left == false_rtx || right == false_rtx) { - obstack_free (rtl_obstack, spacer); + if (!ggc_p) + obstack_free (rtl_obstack, spacer); return false_rtx; } else if (left == true_rtx) @@ -3088,7 +3225,7 @@ simplify_test_exp (exp, insn_code, insn_index) fatal ("Invalid alternative specified for pattern number %d", insn_index); - /* If all alternatives are excluded, this is false. */ + /* If all alternatives are excluded, this is false. */ i ^= insn_alternatives[insn_code]; if (i == 0) return false_rtx; @@ -3118,14 +3255,16 @@ simplify_test_exp (exp, insn_code, insn_index) SIMPLIFY_ALTERNATIVE (left); if (left == true_rtx) { - obstack_free (rtl_obstack, spacer); + if (!ggc_p) + obstack_free (rtl_obstack, spacer); return true_rtx; } right = SIMPLIFY_TEST_EXP (XEXP (exp, 1), insn_code, insn_index); SIMPLIFY_ALTERNATIVE (right); if (right == true_rtx) { - obstack_free (rtl_obstack, spacer); + if (!ggc_p) + obstack_free (rtl_obstack, spacer); return true_rtx; } @@ -3135,7 +3274,8 @@ simplify_test_exp (exp, insn_code, insn_index) if (right == true_rtx || left == true_rtx) { - obstack_free (rtl_obstack, spacer); + if (!ggc_p) + obstack_free (rtl_obstack, spacer); return true_rtx; } else if (left == false_rtx) @@ -3181,7 +3321,7 @@ simplify_test_exp (exp, insn_code, insn_index) fatal ("Invalid alternative specified for pattern number %d", insn_index); - /* If all alternatives are included, this is true. */ + /* If all alternatives are included, this is true. */ i ^= insn_alternatives[insn_code]; if (i == 0) return true_rtx; @@ -3222,12 +3362,14 @@ simplify_test_exp (exp, insn_code, insn_index) if (left == false_rtx) { - obstack_free (rtl_obstack, spacer); + if (!ggc_p) + obstack_free (rtl_obstack, spacer); return true_rtx; } else if (left == true_rtx) { - obstack_free (rtl_obstack, spacer); + if (!ggc_p) + obstack_free (rtl_obstack, spacer); return false_rtx; } @@ -3268,6 +3410,10 @@ simplify_test_exp (exp, insn_code, insn_index) for (ie = av->first_insn; ie; ie = ie->next) if (ie->insn_code == insn_code) return evaluate_eq_attr (exp, av->value, insn_code, insn_index); + break; + + default: + break; } /* We have already simplified this expression. Simplifying it again @@ -3385,7 +3531,8 @@ optimize_attrs () insert_insn_ent (av, ie); something_changed = 1; } - obstack_free (temp_obstack, spacer); + if (!ggc_p) + obstack_free (temp_obstack, spacer); } } } @@ -3435,7 +3582,7 @@ static rtx simplify_by_exploding (exp) rtx exp; { - rtx list = 0, link, condexp, defval; + rtx list = 0, link, condexp, defval = NULL_RTX; struct dimension *space; rtx *condtest, *condval; int i, j, total, ndim = 0; @@ -3461,7 +3608,7 @@ simplify_by_exploding (exp) { /* Pull the first attribute value from the list and record that attribute as another dimension in the attribute space. */ - char *name = XSTR (XEXP (list, 0), 0); + const char *name = XSTR (XEXP (list, 0), 0); rtx *prev; if ((space[ndim].attr = find_attr (name, 0)) == 0 @@ -3598,7 +3745,10 @@ find_and_mark_used_attributes (exp, terms, nterms) *nterms += 1; MEM_VOLATILE_P (exp) = 1; } + return 1; + case CONST_STRING: + case CONST_INT: return 1; case IF_THEN_ELSE: @@ -3620,9 +3770,10 @@ find_and_mark_used_attributes (exp, terms, nterms) if (! find_and_mark_used_attributes (XEXP (exp, 1), terms, nterms)) return 0; return 1; - } - return 0; + default: + return 0; + } } /* Clear the MEM_VOLATILE_P flag in all EQ_ATTR expressions on LIST and @@ -3803,6 +3954,7 @@ simplify_with_current_value_aux (exp) else return true_rtx; case CONST_STRING: + case CONST_INT: return exp; case IF_THEN_ELSE: @@ -3858,8 +4010,10 @@ simplify_with_current_value_aux (exp) have been selected. */ } return simplify_with_current_value_aux (XEXP (exp, 1)); + + default: + abort (); } - abort (); } /* Clear the MEM_IN_STRUCT_P flag in EXP and its subexpressions. */ @@ -3871,7 +4025,7 @@ clear_struct_flag (x) register int i; register int j; register enum rtx_code code; - register char *fmt; + register const char *fmt; MEM_IN_STRUCT_P (x) = 0; if (RTX_UNCHANGING_P (x)) @@ -3892,6 +4046,9 @@ clear_struct_flag (x) case EQ_ATTR: case ATTR_FLAG: return; + + default: + break; } /* Compare the elements. If any pair of corresponding elements @@ -3916,7 +4073,7 @@ clear_struct_flag (x) } /* Return the number of RTX objects making up the expression X. - But if we count more more than MAX objects, stop counting. */ + But if we count more than MAX objects, stop counting. */ static int count_sub_rtxs (x, max) @@ -3926,7 +4083,7 @@ count_sub_rtxs (x, max) register int i; register int j; register enum rtx_code code; - register char *fmt; + register const char *fmt; int total = 0; code = GET_CODE (x); @@ -3944,6 +4101,9 @@ count_sub_rtxs (x, max) case EQ_ATTR: case ATTR_FLAG: return 1; + + default: + break; } /* Compare the elements. If any pair of corresponding elements @@ -3980,7 +4140,7 @@ gen_attr (exp) { struct attr_desc *attr; struct attr_value *av; - char *name_ptr; + const char *name_ptr; char *p; /* Make a new attribute structure. Check for duplicate by looking at @@ -3990,7 +4150,7 @@ gen_attr (exp) fatal ("Duplicate definition for `%s' attribute", attr->name); if (*XSTR (exp, 1) == '\0') - attr->is_numeric = 1; + attr->is_numeric = 1; else { name_ptr = XSTR (exp, 1); @@ -4018,7 +4178,7 @@ gen_attr (exp) if (! strcmp (attr->name, "length") && ! attr->is_numeric) fatal ("`length' attribute must take numeric values"); - /* Set up the default value. */ + /* Set up the default value. */ XEXP (exp, 2) = check_attr_value (XEXP (exp, 2), attr); attr->default_val = get_attr_value (XEXP (exp, 2), attr, -2); } @@ -4032,7 +4192,7 @@ count_alternatives (exp) rtx exp; { int i, j, n; - char *fmt; + const char *fmt; if (GET_CODE (exp) == MATCH_OPERAND) return n_comma_elts (XSTR (exp, 2)); @@ -4070,7 +4230,7 @@ compares_alternatives_p (exp) rtx exp; { int i, j; - char *fmt; + const char *fmt; if (GET_CODE (exp) == EQ_ATTR && XSTR (exp, 0) == alternative_name) return 1; @@ -4103,7 +4263,7 @@ contained_in_p (inner, exp) rtx exp; { int i, j; - char *fmt; + const char *fmt; if (rtx_equal_p (inner, exp)) return 1; @@ -4168,6 +4328,9 @@ gen_insn (exp) id->vec_idx = 0; got_define_asm_attributes = 1; break; + + default: + abort (); } } @@ -4211,7 +4374,7 @@ gen_unit (def) { struct function_unit *unit; struct function_unit_op *op; - char *name = XSTR (def, 0); + const char *name = XSTR (def, 0); int multiplicity = XINT (def, 1); int simultaneity = XINT (def, 2); rtx condexp = XEXP (def, 3); @@ -4254,6 +4417,7 @@ gen_unit (def) op->issue_delay = issue_delay; op->next = unit->ops; unit->ops = op; + num_unit_opclasses++; /* Set our issue expression based on whether or not an optional conflict vector was specified. */ @@ -4280,15 +4444,18 @@ gen_unit (def) unit->condexp = insert_right_side (IOR, unit->condexp, op->condexp, -2, -2); } -/* Given a piece of RTX, print a C expression to test it's truth value. +/* Given a piece of RTX, print a C expression to test its truth value. We use AND and IOR both for logical and bit-wise operations, so interpret them as logical unless they are inside a comparison expression. - The second operand of this function will be non-zero in that case. */ + The first bit of FLAGS will be non-zero in that case. + + Set the second bit of FLAGS to make references to attribute values use + a cached local variable instead of calling a function. */ static void -write_test_expr (exp, in_comparison) +write_test_expr (exp, flags) rtx exp; - int in_comparison; + int flags; { int comparison_operator = 0; RTX_CODE code; @@ -4310,7 +4477,7 @@ write_test_expr (exp, in_comparison) case PLUS: case MINUS: case MULT: case DIV: case MOD: case AND: case IOR: case XOR: case ASHIFT: case LSHIFTRT: case ASHIFTRT: - write_test_expr (XEXP (exp, 0), in_comparison || comparison_operator); + write_test_expr (XEXP (exp, 0), flags | comparison_operator); switch (code) { case EQ: @@ -4359,13 +4526,13 @@ write_test_expr (exp, in_comparison) printf (" %% "); break; case AND: - if (in_comparison) + if (flags & 1) printf (" & "); else printf (" && "); break; case IOR: - if (in_comparison) + if (flags & 1) printf (" | "); else printf (" || "); @@ -4380,14 +4547,16 @@ write_test_expr (exp, in_comparison) case ASHIFTRT: printf (" >> "); break; + default: + abort (); } - write_test_expr (XEXP (exp, 1), in_comparison || comparison_operator); + write_test_expr (XEXP (exp, 1), flags | comparison_operator); break; case NOT: /* Special-case (not (eq_attrq "alternative" "x")) */ - if (! in_comparison && GET_CODE (XEXP (exp, 0)) == EQ_ATTR + if (! (flags & 1) && GET_CODE (XEXP (exp, 0)) == EQ_ATTR && XSTR (XEXP (exp, 0), 0) == alternative_name) { printf ("which_alternative != %s", XSTR (XEXP (exp, 0), 1)); @@ -4401,7 +4570,7 @@ write_test_expr (exp, in_comparison) switch (code) { case NOT: - if (in_comparison) + if (flags & 1) printf ("~ "); else printf ("! "); @@ -4412,16 +4581,18 @@ write_test_expr (exp, in_comparison) case NEG: printf ("-"); break; + default: + abort (); } - write_test_expr (XEXP (exp, 0), in_comparison); + write_test_expr (XEXP (exp, 0), flags); break; /* Comparison test of an attribute with a value. Most of these will have been removed by optimization. Handle "alternative" specially and give error if EQ_ATTR present inside a comparison. */ case EQ_ATTR: - if (in_comparison) + if (flags & 1) fatal ("EQ_ATTR not valid inside comparison"); if (XSTR (exp, 0) == alternative_name) @@ -4438,18 +4609,22 @@ write_test_expr (exp, in_comparison) { write_test_expr (evaluate_eq_attr (exp, attr->default_val->value, -2, -2), - in_comparison); + flags); } else { - printf ("get_attr_%s (insn) == ", attr->name); - write_attr_valueq (attr, XSTR (exp, 1)); + if (flags & 2) + printf ("attr_%s", attr->name); + else + printf ("get_attr_%s (insn)", attr->name); + printf (" == "); + write_attr_valueq (attr, XSTR (exp, 1)); } break; /* Comparison test of flags for define_delays. */ case ATTR_FLAG: - if (in_comparison) + if (flags & 1) fatal ("ATTR_FLAG not valid inside comparison"); printf ("(flags & ATTR_FLAG_%s) != 0", XSTR (exp, 0)); break; @@ -4471,31 +4646,45 @@ write_test_expr (exp, in_comparison) XSTR (exp, 1), XINT (exp, 0), GET_MODE_NAME (GET_MODE (exp))); break; - /* Constant integer. */ + case MATCH_INSN: + printf ("%s (insn)", XSTR (exp, 0)); + break; + + /* Constant integer. */ case CONST_INT: -#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT - printf ("%d", XWINT (exp, 0)); -#else - printf ("%ld", XWINT (exp, 0)); -#endif + printf (HOST_WIDE_INT_PRINT_DEC, XWINT (exp, 0)); break; - /* A random C expression. */ + /* A random C expression. */ case SYMBOL_REF: printf ("%s", XSTR (exp, 0)); break; /* The address of the branch target. */ case MATCH_DUP: - printf ("insn_addresses[INSN_UID (operands[%d])]", XINT (exp, 0)); + printf ("insn_addresses[INSN_UID (GET_CODE (operands[%d]) == LABEL_REF ? XEXP (operands[%d], 0) : operands[%d])]", + XINT (exp, 0), XINT (exp, 0), XINT (exp, 0)); break; - /* The address of the current insn. It would be more consistent with - other usage to make this the address of the NEXT insn, but this gets - too confusing because of the ambiguity regarding the length of the - current insn. */ case PC: - printf ("insn_current_address"); + /* The address of the current insn. We implement this actually as the + address of the current insn for backward branches, but the last + address of the next insn for forward branches, and both with + adjustments that account for the worst-case possible stretching of + intervening alignments between this insn and its destination. */ + printf("insn_current_reference_address (insn)"); + break; + + case CONST_STRING: + printf ("%s", XSTR (exp, 0)); + break; + + case IF_THEN_ELSE: + write_test_expr (XEXP (exp, 0), flags & 2); + printf (" ? "); + write_test_expr (XEXP (exp, 1), flags | 1); + printf (" : "); + write_test_expr (XEXP (exp, 2), flags | 1); break; default: @@ -4507,45 +4696,84 @@ write_test_expr (exp, in_comparison) } /* Given an attribute value, return the maximum CONST_STRING argument - encountered. It is assumed that they are all numeric. */ + encountered. Set *UNKNOWNP and return INT_MAX if the value is unknown. */ static int -max_attr_value (exp) +max_attr_value (exp, unknownp) rtx exp; + int *unknownp; { - int current_max = 0; - int n; - int i; - - if (GET_CODE (exp) == CONST_STRING) - return atoi (XSTR (exp, 0)); + int current_max; + int i, n; - else if (GET_CODE (exp) == COND) + switch (GET_CODE (exp)) { + case CONST_STRING: + current_max = atoi (XSTR (exp, 0)); + break; + + case COND: + current_max = max_attr_value (XEXP (exp, 1), unknownp); for (i = 0; i < XVECLEN (exp, 0); i += 2) { - n = max_attr_value (XVECEXP (exp, 0, i + 1)); + n = max_attr_value (XVECEXP (exp, 0, i + 1), unknownp); if (n > current_max) current_max = n; } + break; - n = max_attr_value (XEXP (exp, 1)); + case IF_THEN_ELSE: + current_max = max_attr_value (XEXP (exp, 1), unknownp); + n = max_attr_value (XEXP (exp, 2), unknownp); if (n > current_max) current_max = n; + break; + + default: + *unknownp = 1; + current_max = INT_MAX; + break; } - else if (GET_CODE (exp) == IF_THEN_ELSE) + return current_max; +} + +/* Given an attribute value, return the result of ORing together all + CONST_STRING arguments encountered. Set *UNKNOWNP and return -1 + if the numeric value is not known. */ + +static int +or_attr_value (exp, unknownp) + rtx exp; + int *unknownp; +{ + int current_or; + int i; + + switch (GET_CODE (exp)) { - current_max = max_attr_value (XEXP (exp, 1)); - n = max_attr_value (XEXP (exp, 2)); - if (n > current_max) - current_max = n; - } + case CONST_STRING: + current_or = atoi (XSTR (exp, 0)); + break; - else - abort (); + case COND: + current_or = or_attr_value (XEXP (exp, 1), unknownp); + for (i = 0; i < XVECLEN (exp, 0); i += 2) + current_or |= or_attr_value (XVECEXP (exp, 0, i + 1), unknownp); + break; - return current_max; + case IF_THEN_ELSE: + current_or = or_attr_value (XEXP (exp, 1), unknownp); + current_or |= or_attr_value (XEXP (exp, 2), unknownp); + break; + + default: + *unknownp = 1; + current_or = -1; + break; + } + + return current_or; } /* Scan an attribute value, possibly a conditional, and record what actions @@ -4563,7 +4791,7 @@ walk_attr_value (exp) rtx exp; { register int i, j; - register char *fmt; + register const char *fmt; RTX_CODE code; if (exp == NULL) @@ -4602,6 +4830,9 @@ walk_attr_value (exp) case ATTR_FLAG: return; + + default: + break; } for (i = 0, fmt = GET_RTX_FORMAT (code); i < GET_RTX_LENGTH (code); i++) @@ -4629,9 +4860,24 @@ write_attr_get (attr) struct attr_value *av, *common_av; /* Find the most used attribute value. Handle that as the `default' of the - switch we will generate. */ + switch we will generate. */ common_av = find_most_used (attr); + /* Write out prototype of function. */ + if (!attr->is_numeric) + printf ("extern enum attr_%s ", attr->name); + else if (attr->unsigned_p) + printf ("extern unsigned int "); + else + printf ("extern int "); + /* If the attribute name starts with a star, the remainder is the name of + the subroutine to use, instead of `get_attr_...'. */ + if (attr->name[0] == '*') + printf ("%s PARAMS ((rtx));\n", &attr->name[1]); + else + printf ("get_attr_%s PARAMS ((%s));\n", attr->name, + (attr->is_const ? "void" : "rtx")); + /* Write out start of function, then all values with explicit `case' lines, then a `default', then the value with the most uses. */ if (!attr->is_numeric) @@ -4661,17 +4907,40 @@ write_attr_get (attr) printf ("}\n\n"); return; } + printf (" rtx insn;\n"); printf ("{\n"); - printf (" switch (recog_memoized (insn))\n"); - printf (" {\n"); - for (av = attr->first_value; av; av = av->next) - if (av != common_av) - write_attr_case (attr, av, 1, "return", ";", 4, true_rtx); + if (GET_CODE (common_av->value) == FFS) + { + rtx p = XEXP (common_av->value, 0); - write_attr_case (attr, common_av, 0, "return", ";", 4, true_rtx); - printf (" }\n}\n\n"); + /* No need to emit code to abort if the insn is unrecognized; the + other get_attr_foo functions will do that when we call them. */ + + write_toplevel_expr (p); + + printf ("\n if (accum && accum == (accum & -accum))\n"); + printf (" {\n"); + printf (" int i;\n"); + printf (" for (i = 0; accum >>= 1; ++i) continue;\n"); + printf (" accum = i;\n"); + printf (" }\n else\n"); + printf (" accum = ~accum;\n"); + printf (" return accum;\n}\n\n"); + } + else + { + printf (" switch (recog_memoized (insn))\n"); + printf (" {\n"); + + for (av = attr->first_value; av; av = av->next) + if (av != common_av) + write_attr_case (attr, av, 1, "return", ";", 4, true_rtx); + + write_attr_case (attr, common_av, 0, "return", ";", 4, true_rtx); + printf (" }\n}\n\n"); + } } /* Given an AND tree of known true terms (because we are inside an `if' with @@ -4716,19 +4985,12 @@ write_attr_set (attr, indent, value, prefix, suffix, known_true, struct attr_desc *attr; int indent; rtx value; - char *prefix; - char *suffix; + const char *prefix; + const char *suffix; rtx known_true; int insn_code, insn_index; { - if (GET_CODE (value) == CONST_STRING) - { - write_indent (indent); - printf ("%s ", prefix); - write_attr_value (attr, value); - printf ("%s\n", suffix); - } - else if (GET_CODE (value) == COND) + if (GET_CODE (value) == COND) { /* Assume the default value will be the default of the COND unless we find an always true expression. */ @@ -4802,7 +5064,12 @@ write_attr_set (attr, indent, value, prefix, suffix, known_true, } } else - abort (); + { + write_indent (indent); + printf ("%s ", prefix); + write_attr_value (attr, value); + printf ("%s\n", suffix); + } } /* Write out the computation for one attribute value. */ @@ -4813,7 +5080,7 @@ write_attr_case (attr, av, write_case_lines, prefix, suffix, indent, struct attr_desc *attr; struct attr_value *av; int write_case_lines; - char *prefix, *suffix; + const char *prefix, *suffix; int indent; rtx known_true; { @@ -4856,17 +5123,15 @@ write_attr_case (attr, av, write_case_lines, prefix, suffix, indent, if (must_extract) { write_indent (indent + 2); - printf ("insn_extract (insn);\n"); + printf ("extract_insn (insn);\n"); } if (must_constrain) { -#ifdef REGISTER_CONSTRAINTS write_indent (indent + 2); - printf ("if (! constrain_operands (INSN_CODE (insn), reload_completed))\n"); + printf ("if (! constrain_operands (reload_completed))\n"); write_indent (indent + 2); printf (" fatal_insn_not_found (insn);\n"); -#endif } write_attr_set (attr, indent + 2, av->value, prefix, suffix, @@ -4881,19 +5146,148 @@ write_attr_case (attr, av, write_case_lines, prefix, suffix, indent, printf ("\n"); } +/* Search for uses of non-const attributes and write code to cache them. */ + +static int +write_expr_attr_cache (p, attr) + rtx p; + struct attr_desc *attr; +{ + const char *fmt; + int i, ie, j, je; + + if (GET_CODE (p) == EQ_ATTR) + { + if (XSTR (p, 0) != attr->name) + return 0; + + if (!attr->is_numeric) + printf (" register enum attr_%s ", attr->name); + else if (attr->unsigned_p) + printf (" register unsigned int "); + else + printf (" register int "); + + printf ("attr_%s = get_attr_%s (insn);\n", attr->name, attr->name); + return 1; + } + + fmt = GET_RTX_FORMAT (GET_CODE (p)); + ie = GET_RTX_LENGTH (GET_CODE (p)); + for (i = 0; i < ie; i++) + { + switch (*fmt++) + { + case 'e': + if (write_expr_attr_cache (XEXP (p, i), attr)) + return 1; + break; + + case 'E': + je = XVECLEN (p, i); + for (j = 0; j < je; ++j) + if (write_expr_attr_cache (XVECEXP (p, i, j), attr)) + return 1; + break; + } + } + + return 0; +} + +/* Evaluate an expression at top level. A front end to write_test_expr, + in which we cache attribute values and break up excessively large + expressions to cater to older compilers. */ + +static void +write_toplevel_expr (p) + rtx p; +{ + struct attr_desc *attr; + int i; + + for (i = 0; i < MAX_ATTRS_INDEX; ++i) + for (attr = attrs[i]; attr ; attr = attr->next) + if (!attr->is_const) + write_expr_attr_cache (p, attr); + + printf(" register unsigned long accum = 0;\n\n"); + + while (GET_CODE (p) == IOR) + { + rtx e; + if (GET_CODE (XEXP (p, 0)) == IOR) + e = XEXP (p, 1), p = XEXP (p, 0); + else + e = XEXP (p, 0), p = XEXP (p, 1); + + printf (" accum |= "); + write_test_expr (e, 3); + printf (";\n"); + } + printf (" accum |= "); + write_test_expr (p, 3); + printf (";\n"); +} + /* Utilities to write names in various forms. */ static void +write_unit_name (prefix, num, suffix) + const char *prefix; + int num; + const char *suffix; +{ + struct function_unit *unit; + + for (unit = units; unit; unit = unit->next) + if (unit->num == num) + { + printf ("%s%s%s", prefix, unit->name, suffix); + return; + } + + printf ("%s%s", prefix, suffix); +} + +static void write_attr_valueq (attr, s) struct attr_desc *attr; - char *s; + const char *s; { if (attr->is_numeric) { - printf ("%s", s); - /* Make the blockage range values easier to read. */ - if (strlen (s) > 1) - printf (" /* 0x%x */", atoi (s)); + int num = atoi (s); + + printf ("%d", num); + + /* Make the blockage range values and function units used values easier + to read. */ + if (attr->func_units_p) + { + if (num == -1) + printf (" /* units: none */"); + else if (num >= 0) + write_unit_name (" /* units: ", num, " */"); + else + { + int i; + const char *sep = " /* units: "; + for (i = 0, num = ~num; num; i++, num >>= 1) + if (num & 1) + { + write_unit_name (sep, i, (num == 1) ? " */" : ""); + sep = ", "; + } + } + } + + else if (attr->blockage_p) + printf (" /* min %d, max %d */", num >> (HOST_BITS_PER_INT / 2), + num & ((1 << (HOST_BITS_PER_INT / 2)) - 1)); + + else if (num > 9 || num < 0) + printf (" /* 0x%x */", num); } else { @@ -4908,21 +5302,65 @@ write_attr_value (attr, value) struct attr_desc *attr; rtx value; { - if (GET_CODE (value) != CONST_STRING) - abort (); + int op; - write_attr_valueq (attr, XSTR (value, 0)); + switch (GET_CODE (value)) + { + case CONST_STRING: + write_attr_valueq (attr, XSTR (value, 0)); + break; + + case SYMBOL_REF: + fputs (XSTR (value, 0), stdout); + break; + + case ATTR: + { + struct attr_desc *attr2 = find_attr (XSTR (value, 0), 0); + printf ("get_attr_%s (%s)", attr2->name, + (attr2->is_const ? "" : "insn")); + } + break; + + case PLUS: + op = '+'; + goto do_operator; + case MINUS: + op = '-'; + goto do_operator; + case MULT: + op = '*'; + goto do_operator; + case DIV: + op = '/'; + goto do_operator; + case MOD: + op = '%'; + goto do_operator; + + do_operator: + write_attr_value (attr, XEXP (value, 0)); + putchar (' '); + putchar (op); + putchar (' '); + write_attr_value (attr, XEXP (value, 1)); + break; + + default: + abort (); + } } static void write_upcase (str) - char *str; + const char *str; { while (*str) - if (*str < 'a' || *str > 'z') - printf ("%c", *str++); - else - printf ("%c", *str++ - 'a' + 'A'); + { + /* The argument of TOUPPER should not have side effects. */ + putchar (TOUPPER(*str)); + str++; + } } static void @@ -4950,7 +5388,7 @@ write_indent (indent) static void write_eligible_delay (kind) - char *kind; + const char *kind; { struct delay_desc *delay; int max_slots; @@ -4975,7 +5413,7 @@ write_eligible_delay (kind) printf (" rtx delay_insn;\n"); printf (" int slot;\n"); printf (" rtx candidate_insn;\n"); - printf (" int flags;\n"); + printf (" int flags ATTRIBUTE_UNUSED;\n"); printf ("{\n"); printf (" rtx insn;\n"); printf ("\n"); @@ -5139,7 +5577,7 @@ write_function_unit_info () static void write_complex_function (unit, name, connection) struct function_unit *unit; - char *name, *connection; + const char *name, *connection; { struct attr_desc *case_attr, *attr; struct attr_value *av, *common_av; @@ -5148,6 +5586,7 @@ write_complex_function (unit, name, connection) int using_case; int i; + printf ("static int %s_unit_%s PARAMS ((rtx, rtx));\n", unit->name, name); printf ("static int\n"); printf ("%s_unit_%s (executing_insn, candidate_insn)\n", unit->name, name); @@ -5220,6 +5659,10 @@ write_complex_function (unit, name, connection) } } + /* This default case should not be needed, but gcc's analysis is not + good enough to realize that the default case is not needed for the + second switch statement. */ + printf (" default:\n abort ();\n"); printf (" }\n}\n\n"); } @@ -5230,7 +5673,7 @@ write_complex_function (unit, name, connection) static int n_comma_elts (s) - char *s; + const char *s; { int n; @@ -5250,10 +5693,10 @@ n_comma_elts (s) static char * next_comma_elt (pstr) - char **pstr; + const char **pstr; { char *out_str; - char *p; + const char *p; if (**pstr == '\0') return NULL; @@ -5276,7 +5719,7 @@ next_comma_elt (pstr) static struct attr_desc * find_attr (name, create) - char *name; + const char *name; int create; { struct attr_desc *attr; @@ -5304,6 +5747,7 @@ find_attr (name, create) attr->name = attr_string (name, strlen (name)); attr->first_value = attr->default_val = NULL; attr->is_numeric = attr->negative_ok = attr->is_const = attr->is_special = 0; + attr->unsigned_p = attr->func_units_p = attr->blockage_p = 0; attr->next = attrs[index]; attrs[index] = attr; @@ -5314,7 +5758,7 @@ find_attr (name, create) static void make_internal_attr (name, value, special) - char *name; + const char *name; rtx value; int special; { @@ -5329,6 +5773,8 @@ make_internal_attr (name, value, special) attr->is_special = (special & 1) != 0; attr->negative_ok = (special & 2) != 0; attr->unsigned_p = (special & 4) != 0; + attr->func_units_p = (special & 8) != 0; + attr->blockage_p = (special & 16) != 0; attr->default_val = get_attr_value (value, attr, -2); } @@ -5410,22 +5856,26 @@ extend_range (range, min, max) if (range->max < max) range->max = max; } -char * -xrealloc (ptr, size) - char *ptr; - unsigned size; +PTR +xrealloc (old, size) + PTR old; + size_t size; { - char *result = (char *) realloc (ptr, size); - if (!result) + register PTR ptr; + if (old) + ptr = (PTR) realloc (old, size); + else + ptr = (PTR) malloc (size); + if (!ptr) fatal ("virtual memory exhausted"); - return result; + return ptr; } -char * +PTR xmalloc (size) - unsigned size; + size_t size; { - register char *val = (char *) malloc (size); + register PTR val = (PTR) malloc (size); if (val == 0) fatal ("virtual memory exhausted"); @@ -5456,6 +5906,9 @@ copy_rtx_unchanging (orig) case SYMBOL_REF: case CODE_LABEL: return orig; + + default: + break; } copy = rtx_alloc (code); @@ -5468,35 +5921,15 @@ copy_rtx_unchanging (orig) #endif } -static void -fatal (s, a1, a2) - char *s; -{ - fprintf (stderr, "genattrtab: "); - fprintf (stderr, s, a1, a2); - fprintf (stderr, "\n"); - exit (FATAL_EXIT_CODE); -} - -/* More 'friendly' abort that prints the line and file. - config.h can #define abort fancy_abort if you like that sort of thing. */ - -void -fancy_abort () -{ - fatal ("Internal gcc abort."); -} - /* Determine if an insn has a constant number of delay slots, i.e., the number of delay slots is not a function of the length of the insn. */ -void +static void write_const_num_delay_slots () { struct attr_desc *attr = find_attr ("*num_delay_slots", 0); struct attr_value *av; struct insn_ent *ie; - int i; if (attr) { @@ -5521,11 +5954,13 @@ write_const_num_delay_slots () printf (" default:\n"); printf (" return 1;\n"); - printf (" }\n}\n"); + printf (" }\n}\n\n"); } } +extern int main PARAMS ((int, char **)); + int main (argc, argv) int argc; @@ -5539,18 +5974,21 @@ main (argc, argv) rtx tem; int i; -#ifdef RLIMIT_STACK + progname = "genattrtab"; + +#if defined (RLIMIT_STACK) && defined (HAVE_GETRLIMIT) && defined (HAVE_SETRLIMIT) /* Get rid of any avoidable limit on stack size. */ { struct rlimit rlim; - /* Set the stack limit huge so that alloca does not fail. */ + /* Set the stack limit huge so that alloca does not fail. */ getrlimit (RLIMIT_STACK, &rlim); rlim.rlim_cur = rlim.rlim_max; setrlimit (RLIMIT_STACK, &rlim); } -#endif /* RLIMIT_STACK defined */ +#endif + progname = "genattrtab"; obstack_init (rtl_obstack); obstack_init (hash_obstack); obstack_init (temp_obstack); @@ -5562,10 +6000,9 @@ main (argc, argv) if (infile == 0) { perror (argv[1]); - exit (FATAL_EXIT_CODE); + return (FATAL_EXIT_CODE); } - - init_rtl (); + read_rtx_filename = argv[1]; /* Set up true and false rtx's */ true_rtx = rtx_alloc (CONST_INT); @@ -5601,6 +6038,9 @@ from the machine description file `md'. */\n\n"); else if (GET_CODE (desc) == DEFINE_SPLIT) insn_code_number++, insn_index_number++; + else if (GET_CODE (desc) == DEFINE_PEEPHOLE2) + insn_code_number++, insn_index_number++; + else if (GET_CODE (desc) == DEFINE_ATTR) { gen_attr (desc); @@ -5637,15 +6077,18 @@ from the machine description file `md'. */\n\n"); expand_units (); printf ("#include \"config.h\"\n"); + printf ("#include \"system.h\"\n"); printf ("#include \"rtl.h\"\n"); + printf ("#include \"tm_p.h\"\n"); printf ("#include \"insn-config.h\"\n"); printf ("#include \"recog.h\"\n"); printf ("#include \"regs.h\"\n"); printf ("#include \"real.h\"\n"); printf ("#include \"output.h\"\n"); printf ("#include \"insn-attr.h\"\n"); + printf ("#include \"toplev.h\"\n"); printf ("\n"); - printf ("#define operands recog_operand\n\n"); + printf ("#define operands recog_data.operand\n\n"); /* Make `insn_alternatives'. */ insn_alternatives = (int *) oballoc (insn_code_number * sizeof (int)); @@ -5674,7 +6117,7 @@ from the machine description file `md'. */\n\n"); /* Construct extra attributes for `length'. */ make_length_attrs (); - /* Perform any possible optimizations to speed up compilation. */ + /* Perform any possible optimizations to speed up compilation. */ optimize_attrs (); /* Now write out all the `gen_attr_...' routines. Do these before the @@ -5684,7 +6127,7 @@ from the machine description file `md'. */\n\n"); for (i = 0; i < MAX_ATTRS_INDEX; i++) for (attr = attrs[i]; attr; attr = attr->next) { - if (! attr->is_special) + if (! attr->is_special && ! attr->is_const) write_attr_get (attr); } @@ -5707,8 +6150,16 @@ from the machine description file `md'. */\n\n"); /* Write out constant delay slot info */ write_const_num_delay_slots (); + write_length_unit_log (); + 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; }