ChangeLog: 2010-09-17 Ken Werner * value.h (widen_scalar_to_vector): Declare. * valops.c (widen_scalar_to_vector): New function. (value_assign): Add call to widen_scalar_to_vector. * eval.c (binop_promote, evaluate_subexp_standard) : Likewise. testsuite/ChangeLog: 2010-09-17 Ken Werner * gdb.base/gnu_vector.c (ia, ib, fa, fb): New variables. * gdb.base/gnu_vector.exp: Add tests for scalar to vector widening. Index: gdb/eval.c =================================================================== RCS file: /cvs/src/src/gdb/eval.c,v retrieving revision 1.139 diff -p -u -r1.139 eval.c --- gdb/eval.c 11 Aug 2010 16:48:26 -0000 1.139 +++ gdb/eval.c 17 Sep 2010 10:56:28 -0000 @@ -574,6 +574,7 @@ binop_promote (const struct language_def struct type *promoted_type = NULL; struct type *type1; struct type *type2; + int t1_is_vec, t2_is_vec; *arg1 = coerce_ref (*arg1); *arg2 = coerce_ref (*arg2); @@ -581,15 +582,26 @@ binop_promote (const struct language_def type1 = check_typedef (value_type (*arg1)); type2 = check_typedef (value_type (*arg2)); - if ((TYPE_CODE (type1) != TYPE_CODE_FLT - && TYPE_CODE (type1) != TYPE_CODE_DECFLOAT - && !is_integral_type (type1)) - || (TYPE_CODE (type2) != TYPE_CODE_FLT - && TYPE_CODE (type2) != TYPE_CODE_DECFLOAT - && !is_integral_type (type2))) + t1_is_vec = (TYPE_CODE (type1) == TYPE_CODE_ARRAY && TYPE_VECTOR (type1)); + t2_is_vec = (TYPE_CODE (type2) == TYPE_CODE_ARRAY && TYPE_VECTOR (type2)); + + if (((TYPE_CODE (type1) != TYPE_CODE_FLT + && TYPE_CODE (type1) != TYPE_CODE_DECFLOAT + && !is_integral_type (type1)) + || (TYPE_CODE (type2) != TYPE_CODE_FLT + && TYPE_CODE (type2) != TYPE_CODE_DECFLOAT + && !is_integral_type (type2))) + && t1_is_vec == t2_is_vec) return; - if (TYPE_CODE (type1) == TYPE_CODE_DECFLOAT + if (t1_is_vec != t2_is_vec) + { + /* Wide the scalar operand to vector. */ + struct value **v = t1_is_vec ? arg2 : arg1; + struct type *t = t1_is_vec ? type1 : type2; + *v = widen_scalar_to_vector (t, *v); + } + else if (TYPE_CODE (type1) == TYPE_CODE_DECFLOAT || TYPE_CODE (type2) == TYPE_CODE_DECFLOAT) { /* No promotion required. */ @@ -2035,8 +2047,13 @@ evaluate_subexp_standard (struct type *e /* For shift and integer exponentiation operations, only promote the first argument. */ - if ((op == BINOP_LSH || op == BINOP_RSH || op == BINOP_EXP) - && is_integral_type (value_type (arg2))) + if (op == BINOP_LSH || op == BINOP_RSH) + { + arg2 = widen_scalar_to_vector (check_typedef (value_type (arg1)), + arg2); + unop_promote (exp->language_defn, exp->gdbarch, &tmp); + } + else if (op == BINOP_EXP && is_integral_type (value_type (arg2))) unop_promote (exp->language_defn, exp->gdbarch, &tmp); else binop_promote (exp->language_defn, exp->gdbarch, &tmp, &arg2); @@ -2130,8 +2147,14 @@ evaluate_subexp_standard (struct type *e { /* For shift and integer exponentiation operations, only promote the first argument. */ - if ((op == BINOP_LSH || op == BINOP_RSH || op == BINOP_EXP) - && is_integral_type (value_type (arg2))) + if (op == BINOP_LSH || op == BINOP_RSH) + { + arg2 = + widen_scalar_to_vector (check_typedef (value_type (arg1)), + arg2); + unop_promote (exp->language_defn, exp->gdbarch, &arg1); + } + else if (op == BINOP_EXP && is_integral_type (value_type (arg2))) unop_promote (exp->language_defn, exp->gdbarch, &arg1); else binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2); Index: gdb/valops.c =================================================================== RCS file: /cvs/src/src/gdb/valops.c,v retrieving revision 1.249 diff -p -u -r1.249 valops.c --- gdb/valops.c 14 Jul 2010 14:54:58 -0000 1.249 +++ gdb/valops.c 17 Sep 2010 10:56:29 -0000 @@ -1079,7 +1079,15 @@ value_assign (struct value *toval, struc type = value_type (toval); if (VALUE_LVAL (toval) != lval_internalvar) - fromval = value_cast (type, fromval); + { + struct type *fromtype = check_typedef (value_type (fromval)); + struct type *totype = check_typedef (type); + if (!(TYPE_CODE (fromtype) == TYPE_CODE_ARRAY && TYPE_VECTOR (fromtype)) + && (TYPE_CODE (totype) == TYPE_CODE_ARRAY && TYPE_VECTOR (totype))) + fromval = widen_scalar_to_vector (type, fromval); + else + fromval = value_cast (type, fromval); + } else { /* Coerce arrays and functions to pointers, except for arrays @@ -3607,6 +3615,37 @@ cast_into_complex (struct type *type, st error (_("cannot cast non-number to complex")); } +/* Widens the scalar val to a vector of type dst_type. */ + +struct value * +widen_scalar_to_vector (struct type *dst_type, struct value *val) +{ + struct type *val_type, *eltype; + struct value *ret; + int i, n; + + val_type = check_typedef (value_type (val)); + + if ((TYPE_CODE (val_type) == TYPE_CODE_ARRAY && TYPE_VECTOR (val_type)) + || !(TYPE_CODE (dst_type) == TYPE_CODE_ARRAY && TYPE_VECTOR (dst_type))) + return val; + + eltype = check_typedef (TYPE_TARGET_TYPE (dst_type)); + val = value_cast (eltype, val); + + ret = allocate_value (dst_type); + + n = TYPE_LENGTH (dst_type) / TYPE_LENGTH (eltype); + for (i = 0; i < n; i++) + { + /* Duplicate the contents of val into the destination vector. */ + memcpy (value_contents_writeable (ret) + (i * TYPE_LENGTH (eltype)), + value_contents_all (val), + TYPE_LENGTH (eltype)); + } + return ret; +} + void _initialize_valops (void) { Index: gdb/value.h =================================================================== RCS file: /cvs/src/src/gdb/value.h,v retrieving revision 1.161 diff -p -u -r1.161 value.h --- gdb/value.h 7 Jul 2010 16:15:18 -0000 1.161 +++ gdb/value.h 17 Sep 2010 10:56:29 -0000 @@ -721,6 +721,9 @@ extern struct value *value_slice (struct extern struct value *value_literal_complex (struct value *, struct value *, struct type *); +extern struct value *widen_scalar_to_vector (struct type *dst_type, + struct value *val); + extern struct value *find_function_in_inferior (const char *, struct objfile **); Index: gdb/testsuite/gdb.base/gnu_vector.c =================================================================== RCS file: /cvs/src/src/gdb/testsuite/gdb.base/gnu_vector.c,v retrieving revision 1.1 diff -p -u -r1.1 gnu_vector.c --- gdb/testsuite/gdb.base/gnu_vector.c 11 Aug 2010 16:48:26 -0000 1.1 +++ gdb/testsuite/gdb.base/gnu_vector.c 17 Sep 2010 10:56:29 -0000 @@ -17,10 +17,16 @@ Contributed by Ken Werner */ +int ia = 2; +int ib = 1; int __attribute__ ((vector_size (4 * sizeof(int)))) i4a = {2, 4, 8, 16}; int __attribute__ ((vector_size (4 * sizeof(int)))) i4b = {1, 2, 8, 4}; + +float fa = 2; +float fb = 1; float __attribute__ ((vector_size (4 * sizeof(float)))) f4a = {2, 4, 8, 16}; float __attribute__ ((vector_size (4 * sizeof(float)))) f4b = {1, 2, 8, 4}; + unsigned int __attribute__ ((vector_size (4 * sizeof(unsigned int)))) ui4 = {2, 4, 8, 16}; int __attribute__ ((vector_size (2 * sizeof(int)))) i2 = {1, 2}; long long __attribute__ ((vector_size (2 * sizeof(long long)))) ll2 = {1, 2}; Index: gdb/testsuite/gdb.base/gnu_vector.exp =================================================================== RCS file: /cvs/src/src/gdb/testsuite/gdb.base/gnu_vector.exp,v retrieving revision 1.1 diff -p -u -r1.1 gnu_vector.exp --- gdb/testsuite/gdb.base/gnu_vector.exp 11 Aug 2010 16:48:26 -0000 1.1 +++ gdb/testsuite/gdb.base/gnu_vector.exp 17 Sep 2010 10:56:29 -0000 @@ -72,9 +72,28 @@ gdb_test "print f4a - f4b" "\\\$$decimal gdb_test "print f4a * f4b" "\\\$$decimal = \\{2, 8, 64, 64\\}" gdb_test "print f4a / f4b" "\\\$$decimal = \\{2, 2, 1, 4\\}" -# Test error conditions -gdb_test "print i4a + 1" "Vector operations are only supported among vectors" -gdb_test "print 1 + f4a" "Vector operations are only supported among vectors" +# Test scalar to vector widening +gdb_test "print i4a + ib" "\\\$$decimal = \\{3, 5, 9, 17\\}" +gdb_test "print fa - f4b" "\\\$$decimal = \\{1, 0, -6, -2\\}" +gdb_test "print f4a * fb" "\\\$$decimal = \\{2, 4, 8, 16\\}" +gdb_test "print ia / i4b" "\\\$$decimal = \\{2, 1, 0, 0\\}" +gdb_test "print i4a % ib" "\\\$$decimal = \\{0, 0, 0, 0\\}" + +gdb_test "print ia & i4b" "\\\$$decimal = \\{0, 2, 0, 0\\}" +gdb_test "print i4a | ib" "\\\$$decimal = \\{3, 5, 9, 17\\}" +gdb_test "print ia ^ i4b" "\\\$$decimal = \\{3, 0, 10, 6\\}" +gdb_test "print i4a << ib" "\\\$$decimal = \\{4, 8, 16, 32\\}" +gdb_test "print i4a >> ib" "\\\$$decimal = \\{1, 2, 4, 8\\}" + +gdb_test "print i4b = ia" "\\\$$decimal = \\{2, 2, 2, 2\\}" +gdb_test "print i4a = 3" "\\\$$decimal = \\{3, 3, 3, 3\\}" +gdb_test "print f4a = fb" "\\\$$decimal = \\{1, 1, 1, 1\\}" +gdb_test "print f4b = 2" "\\\$$decimal = \\{2, 2, 2, 2\\}" + +gdb_test "print i4a = \{2, 4, 8, 16\}" "\\\$$decimal = \\{2, 4, 8, 16\\}" +gdb_test "print i4a <<= ib" "\\\$$decimal = \\{4, 8, 16, 32\\}" + +# Test some error scenarios gdb_test "print i4a + d2" "Cannot perform operation on vectors with different types" gdb_test "print d2 + i4a" "Cannot perform operation on vectors with different types" gdb_test "print f4a + ll2" "Cannot perform operation on vectors with different types"