From: Per Bothner Date: Fri, 20 Jan 1995 23:45:21 +0000 (+0000) Subject: * expression.h (OP_LABELED): New operator, for Chill X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=dcda44a07a5fae20fc6ab26e07229984f87b7172;p=binutils-gdb.git * expression.h (OP_LABELED): New operator, for Chill labeled structre tuples. * ch-exp.y (tuple_element, named_record_element, tuple_elements): New non-terminals, to handle labeled structure tuples. (tuple): Re-define using tuple_elements. * eval.c (evaluate_labeled_field_init): New function, to handle initialization of structure fields, possibly using OP_LABELED. (evaluate_subexp): Use it. * expprint.c (print_subexp case): For OP_ARRAY, use Chill syntax for Chill. Handled OP_LABELED. * parse.c (length_of_subexp, prefixify_subexp): Handle OP_LABELED. * eval.c (evaluate_subexp): Handle Chill Powerset tuples. * valarith.c (value_bit_index): Just treat bitstring as represented by an array of bytes. Alignment is handled by compiler. --- diff --git a/gdb/ChangeLog b/gdb/ChangeLog index a4f2df52305..fef8d2d546d 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,26 @@ +Fri Jan 20 15:23:55 1995 Per Bothner + + * expression.h (OP_LABELED): New operator, for Chill + labeled structre tuples. + * ch-exp.y (tuple_element, named_record_element, tuple_elements): + New non-terminals, to handle labeled structure tuples. + (tuple): Re-define using tuple_elements. + * eval.c (evaluate_labeled_field_init): New function, to handle + initialization of structure fields, possibly using OP_LABELED. + (evaluate_subexp): Use it. + * expprint.c (print_subexp case): For OP_ARRAY, use Chill syntax + for Chill. Handled OP_LABELED. + * parse.c (length_of_subexp, prefixify_subexp): Handle OP_LABELED. + + * eval.c (evaluate_subexp): Handle Chill Powerset tuples. + * valarith.c (value_bit_index): Just treat bitstring as represented + by an array of bytes. Alignment is handled by compiler. + +Wed Jan 18 19:00:29 1995 Stan Shebs + + * h8300-tdep.c (gdb_print_insn_h8300): Fix typo (&info -> info). + * sh-tdep.c (gdb_print_insn_sh): Ditto. + Wed Jan 18 11:25:43 1995 Kung Hsu * remote-os9k.c (rombug_open): Fix a bug in exception handling diff --git a/gdb/ch-exp.y b/gdb/ch-exp.y index a68c68451b9..9bb7526208a 100644 --- a/gdb/ch-exp.y +++ b/gdb/ch-exp.y @@ -374,6 +374,8 @@ expression_list : expression { arglist_len++; } + ; + /* Z.200, 5.2.1 */ @@ -533,9 +535,35 @@ literal : INTEGER_LITERAL /* Z.200, 5.2.5 */ +tuple_element : expression + | named_record_element + ; + +named_record_element: FIELD_NAME ',' named_record_element + { write_exp_elt_opcode (OP_LABELED); + write_exp_string ($1); + write_exp_elt_opcode (OP_LABELED); + } + | FIELD_NAME ':' expression + { write_exp_elt_opcode (OP_LABELED); + write_exp_string ($1); + write_exp_elt_opcode (OP_LABELED); + } + ; + +tuple_elements : tuple_element + { + arglist_len = 1; + } + | tuple_elements ',' tuple_element + { + arglist_len++; + } + ; + tuple : '[' { start_arglist (); } - expression_list ']' + tuple_elements ']' { write_exp_elt_opcode (OP_ARRAY); write_exp_elt_longcst ((LONGEST) 0); @@ -545,7 +573,7 @@ tuple : '[' | mode_name '[' { start_arglist (); } - expression_list ']' + tuple_elements ']' { write_exp_elt_opcode (OP_ARRAY); write_exp_elt_longcst ((LONGEST) 0); diff --git a/gdb/eval.c b/gdb/eval.c index b2c7abd753a..a179840b70e 100644 --- a/gdb/eval.c +++ b/gdb/eval.c @@ -152,6 +152,77 @@ evaluate_type (exp) return evaluate_subexp (NULL_TYPE, exp, &pc, EVAL_AVOID_SIDE_EFFECTS); } +/* Helper function called by evaluate_subexp to initialize a field + a structure from a tuple in Chill. This is recursive, to handle + more than one field name labels. + + STRUCT_VAL is the structure value we are constructing. + (*FIELDNOP) is the field to set, if there is no label. + It is set to the field following this one. + EXP, POS, and NOSIDE are as for evaluate_subexp. + + This function does not handle variant records. FIXME */ + +static value_ptr +evaluate_labeled_field_init (struct_val, fieldnop, exp, pos, noside) + value_ptr struct_val; + int *fieldnop; + register struct expression *exp; + register int *pos; + enum noside noside; +{ + int fieldno = *fieldnop; + value_ptr val; + int bitpos, bitsize; + char *addr; + struct type *struct_type = VALUE_TYPE (struct_val); + if (exp->elts[*pos].opcode == OP_LABELED) + { + int pc = (*pos)++; + char *name = &exp->elts[pc + 2].string; + int tem = longest_to_int (exp->elts[pc + 1].longconst); + (*pos) += 3 + BYTES_TO_EXP_ELEM (tem + 1); + for (fieldno = 0; ; fieldno++) + { + if (fieldno >= TYPE_NFIELDS (struct_type)) + error ("there is no field named %s", name); + if (STREQ (TYPE_FIELD_NAME (struct_type, fieldno), name)) + break; + } + *fieldnop = fieldno; + val = evaluate_labeled_field_init (struct_val, fieldnop, + exp, pos, noside); + } + else + { + fieldno = (*fieldnop)++; + if (fieldno >= TYPE_NFIELDS (struct_type)) + error ("too many initializers"); + val = evaluate_subexp (TYPE_FIELD_TYPE (struct_type, fieldno), + exp, pos, noside); + } + + /* Assign val to field fieldno. */ + if (VALUE_TYPE (val) != TYPE_FIELD_TYPE (struct_type, fieldno)) + val = value_cast (TYPE_FIELD_TYPE (struct_type, fieldno), val); +#if 1 + bitsize = TYPE_FIELD_BITSIZE (struct_type, fieldno); + bitpos = TYPE_FIELD_BITPOS (struct_type, fieldno); + addr = VALUE_CONTENTS (struct_val); + addr += bitpos / 8; + if (bitsize) + modify_field (addr, value_as_long (val), + bitpos % 8, bitsize); + else + memcpy (addr, VALUE_CONTENTS (val), + TYPE_LENGTH (VALUE_TYPE (val))); +#else + value_assign (value_primitive_field (struct_val, 0, fieldno, struct_type), + val); +#endif + return val; +} + static value_ptr evaluate_subexp (expect_type, exp, pos, noside) struct type *expect_type; @@ -181,8 +252,8 @@ evaluate_subexp (expect_type, exp, pos, noside) implement it). CHILL has the tuple stuff; I don't know enough about CHILL to know whether expected types is the way to do it. FORTRAN I don't know. */ - if (current_language->la_language != language_cplus - && current_language->la_language != language_chill) + if (exp->language_defn->la_language != language_cplus + && exp->language_defn->la_language != language_chill) expect_type = NULL_TYPE; pc = (*pos)++; @@ -288,33 +359,11 @@ evaluate_subexp (expect_type, exp, pos, noside) && TYPE_CODE (expect_type) == TYPE_CODE_STRUCT) { value_ptr rec = allocate_value (expect_type); - if (TYPE_NFIELDS (expect_type) != nargs) - error ("wrong number of initialiers for structure type"); + int fieldno = 0; + memset (VALUE_CONTENTS_RAW (rec), '\0', + TYPE_LENGTH (expect_type) / TARGET_CHAR_BIT); for (tem = 0; tem < nargs; tem++) - { - struct type *field_type = TYPE_FIELD_TYPE (expect_type, tem); - value_ptr field_val = evaluate_subexp (field_type, - exp, pos, noside); - int bitsize, bitpos; - char *addr; - if (VALUE_TYPE (field_val) != field_type) - field_val = value_cast (field_type, field_val); -#if 1 - bitsize = TYPE_FIELD_BITSIZE (expect_type, tem); - bitpos = TYPE_FIELD_BITPOS (expect_type, tem); - addr = VALUE_CONTENTS (rec); - addr += bitpos / 8; - if (bitsize) - modify_field (addr, value_as_long (field_val), - bitpos % 8, bitsize); - else - memcpy (addr, VALUE_CONTENTS (field_val), - TYPE_LENGTH (VALUE_TYPE (field_val))); -#else - value_assign (value_primitive_field (rec, 0, tem, expect_type), - field_val); -#endif - } + evaluate_labeled_field_init (rec, &fieldno, exp, pos, noside); return rec; } @@ -341,6 +390,33 @@ evaluate_subexp (expect_type, exp, pos, noside) return rec; } + if (expect_type != NULL_TYPE && noside != EVAL_SKIP + && TYPE_CODE (expect_type) == TYPE_CODE_SET) + { + value_ptr set = allocate_value (expect_type); + struct type *element_type = TYPE_INDEX_TYPE (expect_type); + int low_bound = TYPE_LOW_BOUND (element_type); + int high_bound = TYPE_HIGH_BOUND (element_type); + char *valaddr = VALUE_CONTENTS_RAW (set); + memset (valaddr, '\0', TYPE_LENGTH (expect_type) / TARGET_CHAR_BIT); + for (tem = 0; tem < nargs; tem++) + { + value_ptr element_val = evaluate_subexp (element_type, + exp, pos, noside); + /* FIXME check that element_val has appropriate type. */ + LONGEST element = value_as_long (element_val); + int bit_index; + if (element < low_bound || element > high_bound) + error ("POWERSET tuple element out of range"); + element -= low_bound; + bit_index = (unsigned) element % TARGET_CHAR_BIT; + if (BITS_BIG_ENDIAN) + bit_index = TARGET_CHAR_BIT - 1 - bit_index; + valaddr [(unsigned) element / TARGET_CHAR_BIT] |= 1 << bit_index; + } + return set; + } + argvec = (value_ptr *) alloca (sizeof (value_ptr) * nargs); for (tem = 0; tem < nargs; tem++) { diff --git a/gdb/expprint.c b/gdb/expprint.c index 18b0ac766e7..7eda09728b9 100644 --- a/gdb/expprint.c +++ b/gdb/expprint.c @@ -28,15 +28,15 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* Prototypes for local functions */ static void -print_subexp PARAMS ((struct expression *, int *, FILE *, enum precedence)); +print_subexp PARAMS ((struct expression *, int *, GDB_FILE *, enum precedence)); static void -print_simple_m2_func PARAMS ((char *, struct expression *, int *, FILE *)); +print_simple_m2_func PARAMS ((char *, struct expression *, int *, GDB_FILE *)); void print_expression (exp, stream) struct expression *exp; - FILE *stream; + GDB_FILE *stream; { int pc = 0; print_subexp (exp, &pc, stream, PREC_NULL); @@ -51,7 +51,7 @@ static void print_subexp (exp, pos, stream, prec) register struct expression *exp; register int *pos; - FILE *stream; + GDB_FILE *stream; enum precedence prec; { register unsigned tem; @@ -61,11 +61,11 @@ print_subexp (exp, pos, stream, prec) register char *op_str; int assign_modify = 0; enum exp_opcode opcode; - enum precedence myprec; + enum precedence myprec = PREC_NULL; /* Set to 1 for a right-associative operator. */ - int assoc; - value val; - char *tempstr; + int assoc = 0; + value_ptr val; + char *tempstr = NULL; op_print_tab = exp->language_defn->la_op_print_tab; pc = (*pos)++; @@ -99,8 +99,19 @@ print_subexp (exp, pos, stream, prec) return; case OP_VAR_VALUE: - (*pos) += 2; - fputs_filtered (SYMBOL_SOURCE_NAME (exp->elts[pc + 1].symbol), stream); + { + struct block *b; + (*pos) += 3; + b = exp->elts[pc + 1].block; + if (b != NULL + && BLOCK_FUNCTION (b) != NULL + && SYMBOL_SOURCE_NAME (BLOCK_FUNCTION (b)) != NULL) + { + fputs_filtered (SYMBOL_SOURCE_NAME (BLOCK_FUNCTION (b)), stream); + fputs_filtered ("::", stream); + } + fputs_filtered (SYMBOL_SOURCE_NAME (exp->elts[pc + 2].symbol), stream); + } return; case OP_LAST: @@ -198,7 +209,8 @@ print_subexp (exp, pos, stream, prec) } else { - fputs_filtered (" {", stream); + int is_chill = exp->language_defn->la_language == language_chill; + fputs_filtered (is_chill ? " [" : " {", stream); for (tem = 0; tem < nargs; tem++) { if (tem != 0) @@ -207,10 +219,37 @@ print_subexp (exp, pos, stream, prec) } print_subexp (exp, pos, stream, PREC_ABOVE_COMMA); } - fputs_filtered ("}", stream); + fputs_filtered (is_chill ? "]" : "}", stream); } return; + case OP_LABELED: + tem = longest_to_int (exp->elts[pc + 1].longconst); + (*pos) += 3 + BYTES_TO_EXP_ELEM (tem + 1); + + if (exp->language_defn->la_language == language_chill) + { + fputs_filtered (".", stream); + fputs_filtered (&exp->elts[pc + 2].string, stream); + fputs_filtered (exp->elts[*pos].opcode == OP_LABELED ? ", " + : ": ", + stream); + } + else + { + /* Gcc support both these syntaxes. Unsure which is preferred. */ +#if 1 + fputs_filtered (&exp->elts[pc + 2].string, stream); + fputs_filtered (": ", stream); +#else + fputs_filtered (".", stream); + fputs_filtered (&exp->elts[pc + 2].string, stream); + fputs_filtered ("=", stream); +#endif + } + print_subexp (exp, pos, stream, PREC_SUFFIX); + return; + case TERNOP_COND: if ((int) prec > (int) PREC_COMMA) fputs_filtered ("(", stream); @@ -329,23 +368,23 @@ print_subexp (exp, pos, stream, prec) (*pos) += 2; nargs = longest_to_int (exp->elts[pc + 1].longconst); print_subexp (exp, pos, stream, PREC_SUFFIX); - fprintf (stream, " ["); + fprintf_unfiltered (stream, " ["); for (tem = 0; tem < nargs; tem++) { if (tem != 0) - fprintf (stream, ", "); + fprintf_unfiltered (stream, ", "); print_subexp (exp, pos, stream, PREC_ABOVE_COMMA); } - fprintf (stream, "]"); + fprintf_unfiltered (stream, "]"); return; case BINOP_VAL: (*pos)+=2; - fprintf(stream,"VAL("); + fprintf_unfiltered(stream,"VAL("); type_print(exp->elts[pc+1].type,"",stream,0); - fprintf(stream,","); + fprintf_unfiltered(stream,","); print_subexp(exp,pos,stream,PREC_PREFIX); - fprintf(stream,")"); + fprintf_unfiltered(stream,")"); return; case UNOP_CAP: @@ -415,9 +454,18 @@ print_subexp (exp, pos, stream, prec) fputs_filtered ("(", stream); if ((int) opcode > (int) BINOP_END) { - /* Unary prefix operator. */ - fputs_filtered (op_str, stream); - print_subexp (exp, pos, stream, PREC_PREFIX); + if (assoc) + { + /* Unary postfix operator. */ + print_subexp (exp, pos, stream, PREC_SUFFIX); + fputs_filtered (op_str, stream); + } + else + { + /* Unary prefix operator. */ + fputs_filtered (op_str, stream); + print_subexp (exp, pos, stream, PREC_PREFIX); + } } else { @@ -455,11 +503,11 @@ print_simple_m2_func(s,exp,pos,stream) char *s; register struct expression *exp; register int *pos; - FILE *stream; + GDB_FILE *stream; { - fprintf(stream,"%s(",s); + fprintf_unfiltered(stream,"%s(",s); print_subexp(exp,pos,stream,PREC_PREFIX); - fprintf(stream,")"); + fprintf_unfiltered(stream,")"); } /* Return the operator corresponding to opcode OP as @@ -487,7 +535,7 @@ op_string(op) void dump_expression (exp, stream, note) struct expression *exp; - FILE *stream; + GDB_FILE *stream; char *note; { int elt; @@ -495,7 +543,9 @@ dump_expression (exp, stream, note) char *eltscan; int eltsize; - fprintf_filtered (stream, "Dump of expression @ 0x%x, %s:\n", exp, note); + fprintf_filtered (stream, "Dump of expression @ "); + gdb_print_address (exp, stream); + fprintf_filtered (stream, ", %s:\n", note); fprintf_filtered (stream, "\tLanguage %s, %d elements, %d bytes each.\n", exp->language_defn->la_name, exp -> nelts, sizeof (union exp_element)); @@ -586,10 +636,11 @@ dump_expression (exp, stream, note) case OP_THIS: opcode_name = "OP_THIS"; break; case OP_SCOPE: opcode_name = "OP_SCOPE"; break; case OP_TYPE: opcode_name = "OP_TYPE"; break; + case OP_LABELED: opcode_name = "OP_LABELED"; break; } fprintf_filtered (stream, "%20s ", opcode_name); fprintf_filtered (stream, -#if defined (LONG_LONG) +#if defined (PRINTF_HAS_LONG_LONG) "%ll16x ", #else "%l16x ", diff --git a/gdb/parse.c b/gdb/parse.c index 4b7d541e0b5..a6d95757650 100644 --- a/gdb/parse.c +++ b/gdb/parse.c @@ -510,6 +510,7 @@ length_of_subexp (expr, endpos) args = 1; break; + case OP_LABELED: case STRUCTOP_STRUCT: case STRUCTOP_PTR: args = 1; @@ -653,6 +654,7 @@ prefixify_subexp (inexpr, outexpr, inend, outbeg) case STRUCTOP_STRUCT: case STRUCTOP_PTR: + case OP_LABELED: args = 1; /* fall through */ case OP_M2_STRING: diff --git a/gdb/valarith.c b/gdb/valarith.c index 3848029891d..79c09438b07 100644 --- a/gdb/valarith.c +++ b/gdb/valarith.c @@ -1,5 +1,6 @@ /* Perform arithmetic and other operations on values, for GDB. - Copyright 1986, 1989, 1991, 1992 Free Software Foundation, Inc. + Copyright 1986, 1989, 1991, 1992, 1993, 1994 + Free Software Foundation, Inc. This file is part of GDB. @@ -34,15 +35,14 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #define TRUNCATION_TOWARDS_ZERO ((-5 / 2) == -2) #endif -static value -value_subscripted_rvalue PARAMS ((value, value)); +static value_ptr value_subscripted_rvalue PARAMS ((value_ptr, value_ptr)); -value +value_ptr value_add (arg1, arg2) - value arg1, arg2; + value_ptr arg1, arg2; { - register value valint, valptr; + register value_ptr valint, valptr; register int len; COERCE_ARRAY (arg1); @@ -75,9 +75,9 @@ value_add (arg1, arg2) return value_binop (arg1, arg2, BINOP_ADD); } -value +value_ptr value_sub (arg1, arg2) - value arg1, arg2; + value_ptr arg1, arg2; { COERCE_ARRAY (arg1); @@ -94,13 +94,15 @@ value_sub (arg1, arg2) - (TYPE_LENGTH (TYPE_TARGET_TYPE (VALUE_TYPE (arg1))) * value_as_long (arg2))); } - else if (VALUE_TYPE (arg1) == VALUE_TYPE (arg2)) + else if (TYPE_CODE (VALUE_TYPE (arg2)) == TYPE_CODE_PTR + && TYPE_LENGTH (TYPE_TARGET_TYPE (VALUE_TYPE (arg1))) + == TYPE_LENGTH (TYPE_TARGET_TYPE (VALUE_TYPE (arg2)))) { /* pointer to - pointer to . */ return value_from_longest (builtin_type_long, /* FIXME -- should be ptrdiff_t */ (value_as_long (arg1) - value_as_long (arg2)) - / TYPE_LENGTH (TYPE_TARGET_TYPE (VALUE_TYPE (arg1)))); + / (LONGEST) (TYPE_LENGTH (TYPE_TARGET_TYPE (VALUE_TYPE (arg1))))); } else { @@ -119,12 +121,12 @@ an integer nor a pointer of the same type."); FIXME: Perhaps we should validate that the index is valid and if verbosity is set, warn about invalid indices (but still use them). */ -value +value_ptr value_subscript (array, idx) - value array, idx; + value_ptr array, idx; { int lowerbound; - value bound; + value_ptr bound; struct type *range_type; COERCE_REF (array); @@ -152,14 +154,14 @@ value_subscript (array, idx) (eg, a vector register). This routine used to promote floats to doubles, but no longer does. */ -static value +static value_ptr value_subscripted_rvalue (array, idx) - value array, idx; + value_ptr array, idx; { struct type *elt_type = TYPE_TARGET_TYPE (VALUE_TYPE (array)); int elt_size = TYPE_LENGTH (elt_type); int elt_offs = elt_size * longest_to_int (value_as_long (idx)); - value v; + value_ptr v; if (elt_offs >= TYPE_LENGTH (VALUE_TYPE (array))) error ("no such vector element"); @@ -186,7 +188,7 @@ value_subscripted_rvalue (array, idx) int binop_user_defined_p (op, arg1, arg2) enum exp_opcode op; - value arg1, arg2; + value_ptr arg1, arg2; { if (op == BINOP_ASSIGN) return 0; @@ -206,7 +208,7 @@ binop_user_defined_p (op, arg1, arg2) int unop_user_defined_p (op, arg1) enum exp_opcode op; - value arg1; + value_ptr arg1; { if (op == UNOP_ADDR) return 0; @@ -224,14 +226,14 @@ int unop_user_defined_p (op, arg1) is the opcode saying how to modify it. Otherwise, OTHEROP is unused. */ -value +value_ptr value_x_binop (arg1, arg2, op, otherop) - value arg1, arg2; + value_ptr arg1, arg2; enum exp_opcode op, otherop; { - value * argvec; - char *ptr, *mangle_ptr; - char tstr[13], mangle_tstr[13]; + value_ptr * argvec; + char *ptr; + char tstr[13]; int static_memfuncp; COERCE_REF (arg1); @@ -245,7 +247,7 @@ value_x_binop (arg1, arg2, op, otherop) if (TYPE_CODE (VALUE_TYPE (arg1)) != TYPE_CODE_STRUCT) error ("Can't do that binary op on that type"); /* FIXME be explicit */ - argvec = (value *) alloca (sizeof (value) * 4); + argvec = (value_ptr *) alloca (sizeof (value_ptr) * 4); argvec[1] = value_addr (arg1); argvec[2] = arg2; argvec[3] = 0; @@ -321,12 +323,12 @@ value_x_binop (arg1, arg2, op, otherop) and return that value (where '@' is (almost) any unary operator which is legal for GNU C++). */ -value +value_ptr value_x_unop (arg1, op) - value arg1; + value_ptr arg1; enum exp_opcode op; { - value * argvec; + value_ptr * argvec; char *ptr, *mangle_ptr; char tstr[13], mangle_tstr[13]; int static_memfuncp; @@ -339,7 +341,7 @@ value_x_unop (arg1, op) if (TYPE_CODE (VALUE_TYPE (arg1)) != TYPE_CODE_STRUCT) error ("Can't do that unary op on that type"); /* FIXME be explicit */ - argvec = (value *) alloca (sizeof (value) * 3); + argvec = (value_ptr *) alloca (sizeof (value_ptr) * 3); argvec[1] = value_addr (arg1); argvec[2] = 0; @@ -398,11 +400,11 @@ value_x_unop (arg1, op) string values of length 1. */ -value +value_ptr value_concat (arg1, arg2) - value arg1, arg2; + value_ptr arg1, arg2; { - register value inval1, inval2, outval; + register value_ptr inval1, inval2, outval; int inval1len, inval2len; int count, idx; char *ptr; @@ -517,14 +519,6 @@ value_concat (arg1, arg2) } -/* The type we give to value_binop results. This is a kludge to get around - the fact that we don't know how to determine the result type from - the types of the operands. (I'm not really sure how much we feel - the need to duplicate the exact rules of the current language. - They can get really hairy. But not to do so makes it hard to document - just what we *do* do). */ -static struct type *signed_operation_result; -static struct type *unsigned_operation_result; /* Perform a binary operation on two operands which have reasonable representations as integers or floats. This includes booleans, @@ -532,31 +526,27 @@ static struct type *unsigned_operation_result; Does not support addition and subtraction on pointers; use value_add or value_sub if you want to handle those possibilities. */ -value +value_ptr value_binop (arg1, arg2, op) - value arg1, arg2; + value_ptr arg1, arg2; enum exp_opcode op; { - register value val; + register value_ptr val; COERCE_ENUM (arg1); COERCE_ENUM (arg2); if ((TYPE_CODE (VALUE_TYPE (arg1)) != TYPE_CODE_FLT - && - TYPE_CODE (VALUE_TYPE (arg1)) != TYPE_CODE_CHAR - && - TYPE_CODE (VALUE_TYPE (arg1)) != TYPE_CODE_INT - && - TYPE_CODE (VALUE_TYPE (arg1)) != TYPE_CODE_BOOL) + && TYPE_CODE (VALUE_TYPE (arg1)) != TYPE_CODE_CHAR + && TYPE_CODE (VALUE_TYPE (arg1)) != TYPE_CODE_INT + && TYPE_CODE (VALUE_TYPE (arg1)) != TYPE_CODE_BOOL + && TYPE_CODE (VALUE_TYPE (arg1)) != TYPE_CODE_RANGE) || (TYPE_CODE (VALUE_TYPE (arg2)) != TYPE_CODE_FLT - && - TYPE_CODE (VALUE_TYPE (arg2)) != TYPE_CODE_CHAR - && - TYPE_CODE (VALUE_TYPE (arg2)) != TYPE_CODE_INT - && - TYPE_CODE (VALUE_TYPE (arg2)) != TYPE_CODE_BOOL)) + && TYPE_CODE (VALUE_TYPE (arg2)) != TYPE_CODE_CHAR + && TYPE_CODE (VALUE_TYPE (arg2)) != TYPE_CODE_INT + && TYPE_CODE (VALUE_TYPE (arg2)) != TYPE_CODE_BOOL + && TYPE_CODE (VALUE_TYPE (arg2)) != TYPE_CODE_RANGE)) error ("Argument to arithmetic operation not a number or boolean."); if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_FLT @@ -629,16 +619,64 @@ value_binop (arg1, arg2, op) else /* Integral operations here. */ /* FIXME: Also mixed integral/booleans, with result an integer. */ + /* FIXME: This implements ANSI C rules (also correct for C++). + What about FORTRAN and chill? */ { - /* Should we promote to unsigned longest? */ - if ((TYPE_UNSIGNED (VALUE_TYPE (arg1)) - || TYPE_UNSIGNED (VALUE_TYPE (arg2))) - && (TYPE_LENGTH (VALUE_TYPE (arg1)) >= sizeof (unsigned LONGEST) - || TYPE_LENGTH (VALUE_TYPE (arg2)) >= sizeof (unsigned LONGEST))) + struct type *type1 = VALUE_TYPE (arg1); + struct type *type2 = VALUE_TYPE (arg2); + int promoted_len1 = TYPE_LENGTH (type1); + int promoted_len2 = TYPE_LENGTH (type2); + int is_unsigned1 = TYPE_UNSIGNED (type1); + int is_unsigned2 = TYPE_UNSIGNED (type2); + int result_len; + int unsigned_operation; + + /* Determine type length and signedness after promotion for + both operands. */ + if (promoted_len1 < TYPE_LENGTH (builtin_type_int)) + { + is_unsigned1 = 0; + promoted_len1 = TYPE_LENGTH (builtin_type_int); + } + if (promoted_len2 < TYPE_LENGTH (builtin_type_int)) + { + is_unsigned2 = 0; + promoted_len2 = TYPE_LENGTH (builtin_type_int); + } + + /* Determine type length of the result, and if the operation should + be done unsigned. + Use the signedness of the operand with the greater length. + If both operands are of equal length, use unsigned operation + if one of the operands is unsigned. */ + if (promoted_len1 > promoted_len2) + { + unsigned_operation = is_unsigned1; + result_len = promoted_len1; + } + else if (promoted_len2 > promoted_len1) + { + unsigned_operation = is_unsigned2; + result_len = promoted_len2; + } + else + { + unsigned_operation = is_unsigned1 || is_unsigned2; + result_len = promoted_len1; + } + + if (unsigned_operation) { unsigned LONGEST v1, v2, v; v1 = (unsigned LONGEST) value_as_long (arg1); v2 = (unsigned LONGEST) value_as_long (arg2); + + /* Truncate values to the type length of the result. */ + if (result_len < sizeof (unsigned LONGEST)) + { + v1 &= ((LONGEST) 1 << HOST_CHAR_BIT * result_len) - 1; + v2 &= ((LONGEST) 1 << HOST_CHAR_BIT * result_len) - 1; + } switch (op) { @@ -718,12 +756,32 @@ value_binop (arg1, arg2, op) case BINOP_MAX: v = v1 > v2 ? v1 : v2; break; + + case BINOP_EQUAL: + v = v1 == v2; + break; + + case BINOP_LESS: + v = v1 < v2; + break; default: error ("Invalid binary operation on numbers."); } - val = allocate_value (unsigned_operation_result); + /* This is a kludge to get around the fact that we don't + know how to determine the result type from the types of + the operands. (I'm not really sure how much we feel the + need to duplicate the exact rules of the current + language. They can get really hairy. But not to do so + makes it hard to document just what we *do* do). */ + + /* Can't just call init_type because we wouldn't know what + name to give the type. */ + val = allocate_value + (result_len > TARGET_LONG_BIT / HOST_CHAR_BIT + ? builtin_type_unsigned_long_long + : builtin_type_unsigned_long); store_unsigned_integer (VALUE_CONTENTS_RAW (val), TYPE_LENGTH (VALUE_TYPE (val)), v); @@ -816,12 +874,32 @@ value_binop (arg1, arg2, op) case BINOP_MAX: v = v1 > v2 ? v1 : v2; break; + + case BINOP_EQUAL: + v = v1 == v2; + break; + + case BINOP_LESS: + v = v1 < v2; + break; default: error ("Invalid binary operation on numbers."); } - - val = allocate_value (signed_operation_result); + + /* This is a kludge to get around the fact that we don't + know how to determine the result type from the types of + the operands. (I'm not really sure how much we feel the + need to duplicate the exact rules of the current + language. They can get really hairy. But not to do so + makes it hard to document just what we *do* do). */ + + /* Can't just call init_type because we wouldn't know what + name to give the type. */ + val = allocate_value + (result_len > TARGET_LONG_BIT / HOST_CHAR_BIT + ? builtin_type_long_long + : builtin_type_long); store_signed_integer (VALUE_CONTENTS_RAW (val), TYPE_LENGTH (VALUE_TYPE (val)), v); @@ -835,7 +913,7 @@ value_binop (arg1, arg2, op) int value_logical_not (arg1) - value arg1; + value_ptr arg1; { register int len; register char *p; @@ -862,7 +940,7 @@ value_logical_not (arg1) int value_equal (arg1, arg2) - register value arg1, arg2; + register value_ptr arg1, arg2; { register int len; @@ -877,7 +955,8 @@ value_equal (arg1, arg2) code2 = TYPE_CODE (VALUE_TYPE (arg2)); if (code1 == TYPE_CODE_INT && code2 == TYPE_CODE_INT) - return value_as_long (arg1) == value_as_long (arg2); + return longest_to_int (value_as_long (value_binop (arg1, arg2, + BINOP_EQUAL))); else if ((code1 == TYPE_CODE_FLT || code1 == TYPE_CODE_INT) && (code2 == TYPE_CODE_FLT || code2 == TYPE_CODE_INT)) return value_as_double (arg1) == value_as_double (arg2); @@ -914,7 +993,7 @@ value_equal (arg1, arg2) int value_less (arg1, arg2) - register value arg1, arg2; + register value_ptr arg1, arg2; { register enum type_code code1; register enum type_code code2; @@ -926,14 +1005,8 @@ value_less (arg1, arg2) code2 = TYPE_CODE (VALUE_TYPE (arg2)); if (code1 == TYPE_CODE_INT && code2 == TYPE_CODE_INT) - { - if (TYPE_UNSIGNED (VALUE_TYPE (arg1)) - || TYPE_UNSIGNED (VALUE_TYPE (arg2))) - return ((unsigned LONGEST) value_as_long (arg1) - < (unsigned LONGEST) value_as_long (arg2)); - else - return value_as_long (arg1) < value_as_long (arg2); - } + return longest_to_int (value_as_long (value_binop (arg1, arg2, + BINOP_LESS))); else if ((code1 == TYPE_CODE_FLT || code1 == TYPE_CODE_INT) && (code2 == TYPE_CODE_FLT || code2 == TYPE_CODE_INT)) return value_as_double (arg1) < value_as_double (arg2); @@ -956,9 +1029,9 @@ value_less (arg1, arg2) /* The unary operators - and ~. Both free the argument ARG1. */ -value +value_ptr value_neg (arg1) - register value arg1; + register value_ptr arg1; { register struct type *type; @@ -976,9 +1049,9 @@ value_neg (arg1) } } -value +value_ptr value_complement (arg1) - register value arg1; + register value_ptr arg1; { COERCE_ENUM (arg1); @@ -999,8 +1072,9 @@ value_bit_index (type, valaddr, index) int index; { struct type *range; - int low_bound, high_bound, bit_length; + int low_bound, high_bound; LONGEST word; + unsigned rel_index; range = TYPE_FIELD_TYPE (type, 0); if (TYPE_CODE (range) != TYPE_CODE_RANGE) return -2; @@ -1008,33 +1082,18 @@ value_bit_index (type, valaddr, index) high_bound = TYPE_HIGH_BOUND (range); if (index < low_bound || index > high_bound) return -1; - bit_length = high_bound - low_bound + 1; - index -= low_bound; - if (bit_length <= TARGET_CHAR_BIT) - word = unpack_long (builtin_type_unsigned_char, valaddr); - else if (bit_length <= TARGET_SHORT_BIT) - word = unpack_long (builtin_type_unsigned_short, valaddr); - else - { - int word_start_index = (index / TARGET_INT_BIT) * TARGET_INT_BIT; - index -= word_start_index; - word = unpack_long (builtin_type_unsigned_int, - valaddr + (word_start_index / HOST_CHAR_BIT)); - } -#if BITS_BIG_ENDIAN - if (bit_length <= TARGET_CHAR_BIT) - index = TARGET_CHAR_BIT - 1 - index; - else if (bit_length <= TARGET_SHORT_BIT) - index = TARGET_SHORT_BIT - 1 - index; - else - index = TARGET_INT_BIT - 1 - index; -#endif - return (word >> index) & 1; + rel_index = index - low_bound; + word = unpack_long (builtin_type_unsigned_char, + valaddr + (rel_index / TARGET_CHAR_BIT)); + rel_index %= TARGET_CHAR_BIT; + if (BITS_BIG_ENDIAN) + rel_index = TARGET_CHAR_BIT - 1 - rel_index; + return (word >> rel_index) & 1; } -value +value_ptr value_in (element, set) - value element, set; + value_ptr element, set; { int member; if (TYPE_CODE (VALUE_TYPE (set)) != TYPE_CODE_SET) @@ -1054,16 +1113,4 @@ value_in (element, set) void _initialize_valarith () { - /* Can't just call init_type because we wouldn't know what names to give - them. */ - if (sizeof (LONGEST) > TARGET_LONG_BIT / HOST_CHAR_BIT) - { - unsigned_operation_result = builtin_type_unsigned_long_long; - signed_operation_result = builtin_type_long_long; - } - else - { - unsigned_operation_result = builtin_type_unsigned_long; - signed_operation_result = builtin_type_long; - } }