* 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.
This commit is contained in:
Per Bothner 1995-01-20 23:45:21 +00:00
parent f34c87666e
commit dcda44a07a
6 changed files with 399 additions and 172 deletions

View File

@ -1,3 +1,26 @@
Fri Jan 20 15:23:55 1995 Per Bothner <bothner@kalessin.cygnus.com>
* 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 <shebs@andros.cygnus.com>
* 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 <kung@mexican.cygnus.com>
* remote-os9k.c (rombug_open): Fix a bug in exception handling

View File

@ -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);

View File

@ -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++)
{

View File

@ -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 ",

View File

@ -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:

View File

@ -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 <type x> - pointer to <type x>. */
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;
}
}