From 8954db33ac73962ac337cc456a782db7e9539c06 Mon Sep 17 00:00:00 2001 From: Andrew Burgess Date: Fri, 25 Jan 2013 17:16:43 +0000 Subject: [PATCH] http://sourceware.org/ml/gdb-patches/2012-11/msg00312.html gdb/ChangeLog * valarith.c (value_vector_widen): New function for replicating a scalar into a vector. (value_binop): Use value_vector_widen to widen scalar to vector rather than casting, this better matches gcc C behaviour. * valops.c (value_casst): Update logic for casting between vector types, and for casting from scalar to vector, try to match gcc C behaviour. * value.h (value_vector_widen): Declare. * opencl-lang.c (opencl_value_cast): New opencl specific casting function, handle special case for casting scalar to vector. (opencl_relop): Use opencl_value_cast. (evaluate_subexp_opencl): Use opencl_value_cast instead of value_cast, and handle BINOP_ASSIGN, UNOP_CAST, and UNOP_CAST_TYPE in order to use opencl_value_cast. gdb/testsuite/ChangeLog * gdb.base/gnu_vector.c: New variable for use in tests. * gdb.base/gnu_vector.exp: Update and extend tests to reflect changes in scalar to vector casting and widening. * gdb.python/py-type.c: New variables for use in tests. * gdb.python/py-type.exp: Update vector related tests to reflect changes in scalar to vector casting and widening. --- gdb/ChangeLog | 18 +++++ gdb/opencl-lang.c | 98 ++++++++++++++++++++++++++- gdb/testsuite/ChangeLog | 9 +++ gdb/testsuite/gdb.base/gnu_vector.c | 1 + gdb/testsuite/gdb.base/gnu_vector.exp | 54 +++++++++++---- gdb/testsuite/gdb.python/py-type.c | 3 + gdb/testsuite/gdb.python/py-type.exp | 25 ++++--- gdb/valarith.c | 47 ++++++++++++- gdb/valops.c | 30 ++------ gdb/value.h | 6 ++ 10 files changed, 238 insertions(+), 53 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 23f6f074cd..af0d7e6b9a 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,21 @@ +2013-01-25 Andrew Burgess + Ulrich Weigand + + * valarith.c (value_vector_widen): New function for replicating a + scalar into a vector. + (value_binop): Use value_vector_widen to widen scalar to vector + rather than casting, this better matches gcc C behaviour. + * valops.c (value_casst): Update logic for casting between vector + types, and for casting from scalar to vector, try to match gcc C + behaviour. + * value.h (value_vector_widen): Declare. + * opencl-lang.c (opencl_value_cast): New opencl specific casting + function, handle special case for casting scalar to vector. + (opencl_relop): Use opencl_value_cast. + (evaluate_subexp_opencl): Use opencl_value_cast instead of + value_cast, and handle BINOP_ASSIGN, UNOP_CAST, and UNOP_CAST_TYPE + in order to use opencl_value_cast. + 2013-01-25 Yao Qi * event-loop.c: Include "queue.h". diff --git a/gdb/opencl-lang.c b/gdb/opencl-lang.c index 01e02c823f..819a83202a 100644 --- a/gdb/opencl-lang.c +++ b/gdb/opencl-lang.c @@ -683,6 +683,58 @@ vector_relop (struct expression *exp, struct value *val1, struct value *val2, return ret; } +/* Perform a cast of ARG into TYPE. There's sadly a lot of duplication in + here from valops.c:value_cast, opencl is different only in the + behaviour of scalar to vector casting. As far as possibly we're going + to try and delegate back to the standard value_cast function. */ + +static struct value * +opencl_value_cast (struct type *type, struct value *arg) +{ + if (type != value_type (arg)) + { + /* Casting scalar to vector is a special case for OpenCL, scalar + is cast to element type of vector then replicated into each + element of the vector. First though, we need to work out if + this is a scalar to vector cast; code lifted from + valops.c:value_cast. */ + enum type_code code1, code2; + struct type *to_type; + int scalar; + + to_type = check_typedef (type); + + code1 = TYPE_CODE (to_type); + code2 = TYPE_CODE (check_typedef (value_type (arg))); + + if (code2 == TYPE_CODE_REF) + code2 = TYPE_CODE (check_typedef (value_type (coerce_ref (arg)))); + + scalar = (code2 == TYPE_CODE_INT || code2 == TYPE_CODE_BOOL + || code2 == TYPE_CODE_CHAR || code2 == TYPE_CODE_FLT + || code2 == TYPE_CODE_DECFLOAT || code2 == TYPE_CODE_ENUM + || code2 == TYPE_CODE_RANGE); + + if (code1 == TYPE_CODE_ARRAY && TYPE_VECTOR (to_type) && scalar) + { + struct type *eltype; + + /* Cast to the element type of the vector here as + value_vector_widen will error if the scalar value is + truncated by the cast. To avoid the error, cast (and + possibly truncate) here. */ + eltype = check_typedef (TYPE_TARGET_TYPE (to_type)); + arg = value_cast (eltype, arg); + + return value_vector_widen (arg, type); + } + else + /* Standard cast handler. */ + arg = value_cast (type, arg); + } + return arg; +} + /* Perform a relational operation on two operands. */ static struct value * @@ -718,7 +770,7 @@ opencl_relop (struct expression *exp, struct value *arg1, struct value *arg2, if (TYPE_CODE (t) != TYPE_CODE_FLT && !is_integral_type (t)) error (_("Argument to operation not a number or boolean.")); - *v = value_cast (t1_is_vec ? type1 : type2, *v); + *v = opencl_value_cast (t1_is_vec ? type1 : type2, *v); val = vector_relop (exp, arg1, arg2, op); } @@ -740,6 +792,46 @@ evaluate_subexp_opencl (struct type *expect_type, struct expression *exp, switch (op) { + /* Handle assignment and cast operators to support OpenCL-style + scalar-to-vector widening. */ + case BINOP_ASSIGN: + (*pos)++; + arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside); + type1 = value_type (arg1); + arg2 = evaluate_subexp (type1, exp, pos, noside); + + if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS) + return arg1; + + if (deprecated_value_modifiable (arg1) + && VALUE_LVAL (arg1) != lval_internalvar) + arg2 = opencl_value_cast (type1, arg2); + + return value_assign (arg1, arg2); + + case UNOP_CAST: + type1 = exp->elts[*pos + 1].type; + (*pos) += 2; + arg1 = evaluate_subexp (type1, exp, pos, noside); + + if (noside == EVAL_SKIP) + return value_from_longest (builtin_type (exp->gdbarch)-> + builtin_int, 1); + + return opencl_value_cast (type1, arg1); + + case UNOP_CAST_TYPE: + (*pos)++; + arg1 = evaluate_subexp (NULL, exp, pos, EVAL_AVOID_SIDE_EFFECTS); + type1 = value_type (arg1); + arg1 = evaluate_subexp (type1, exp, pos, noside); + + if (noside == EVAL_SKIP) + return value_from_longest (builtin_type (exp->gdbarch)-> + builtin_int, 1); + + return opencl_value_cast (type1, arg1); + /* Handle binary relational and equality operators that are either not or differently defined for GNU vectors. */ case BINOP_EQUAL: @@ -852,12 +944,12 @@ evaluate_subexp_opencl (struct type *expect_type, struct expression *exp, /* Widen the scalar operand to a vector if necessary. */ if (t2_is_vec || !t3_is_vec) { - arg3 = value_cast (type2, arg3); + arg3 = opencl_value_cast (type2, arg3); type3 = value_type (arg3); } else if (!t2_is_vec || t3_is_vec) { - arg2 = value_cast (type3, arg2); + arg2 = opencl_value_cast (type3, arg2); type2 = value_type (arg2); } else if (!t2_is_vec || !t3_is_vec) diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 46c7c5713f..433dd9bc6c 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,12 @@ +2013-01-25 Andrew Burgess + + * gdb.base/gnu_vector.c: New variable for use in tests. + * gdb.base/gnu_vector.exp: Update and extend tests to reflect + changes in scalar to vector casting and widening. + * gdb.python/py-type.c: New variables for use in tests. + * gdb.python/py-type.exp: Update vector related tests to reflect + changes in scalar to vector casting and widening. + 2013-01-24 Tiago Stürmer Daitx * gdb.base/prologue-include.c: New file. diff --git a/gdb/testsuite/gdb.base/gnu_vector.c b/gdb/testsuite/gdb.base/gnu_vector.c index 76eefed346..062aadbb2c 100644 --- a/gdb/testsuite/gdb.base/gnu_vector.c +++ b/gdb/testsuite/gdb.base/gnu_vector.c @@ -31,6 +31,7 @@ int ia = 2; int ib = 1; float fa = 2; float fb = 1; +long long lla __attribute__ ((mode(DI))) = 0x0000000100000001ll; char4 c4 = {1, 2, 3, 4}; int4 i4a = {2, 4, 8, 16}; int4 i4b = {1, 2, 8, 4}; diff --git a/gdb/testsuite/gdb.base/gnu_vector.exp b/gdb/testsuite/gdb.base/gnu_vector.exp index 5f5b40f080..f65627ba76 100644 --- a/gdb/testsuite/gdb.base/gnu_vector.exp +++ b/gdb/testsuite/gdb.base/gnu_vector.exp @@ -82,32 +82,52 @@ gdb_test "print f4a / f4b" "\\\$$decimal = \\{2, 2, 1, 4\\}" gdb_test "print +f4a" "\\\$$decimal = \\{2, 4, 8, 16\\}" gdb_test "print -f4a" "\\\$$decimal = \\{-2, -4, -8, -16\\}" -# Test scalar to vector widening -gdb_test "print (int2) 1" "\\\$$decimal = \\{1, 1\\}" -gdb_test "print (longlong2) 2" "\\\$$decimal = \\{2, 2\\}" -gdb_test "print (float2) 3" "\\\$$decimal = \\{3, 3\\}" -gdb_test "print (double2) 4" "\\\$$decimal = \\{4, 4\\}" -gdb_test "print (char4) 12" "\\\$$decimal = \\{12, 12, 12, 12\\}" -gdb_test "print (uint4) ia" "\\\$$decimal = \\{2, 2, 2, 2\\}" -gdb_test "print (int4) -3" "\\\$$decimal = \\{-3, -3, -3, -3\\}" -gdb_test "print (float4) 4" "\\\$$decimal = \\{4, 4, 4, 4\\}" +# When casting to vector the input type must have the same length as +# the total length of the vector. +gdb_test "print (char4) 0x01010101" "\\\$$decimal = \\{1, 1, 1, 1\\}" +gdb_test "print (char4) ia" "\\\$$decimal = \\{2, 0, 0, 0\\}" +gdb_test "print (int2) lla" "\\\$$decimal = \\{1, 1\\}" +gdb_test "print (int2) 1" "can only cast scalar to vector of same size" +gdb_test "print (longlong2) 2" "can only cast scalar to vector of same size" +gdb_test "print (float2) 3" "can only cast scalar to vector of same size" +gdb_test "print (double2) 4" "can only cast scalar to vector of same size" +gdb_test "print (uint4) ia" "can only cast scalar to vector of same size" +gdb_test "print (int4) -3" "can only cast scalar to vector of same size" +gdb_test "print (float4) 4" "can only cast scalar to vector of same size" + +gdb_test "print i4b = ia" "can only cast scalar to vector of same size" +gdb_test "print i4a = 3" "can only cast scalar to vector of same size" +gdb_test "print f4a = fb" "can only cast scalar to vector of same size" +gdb_test "print f4b = 2" "can only cast scalar to vector of same size" + +gdb_test "print c4 + lla" "conversion of scalar to vector involves truncation" +gdb_test "print i4a + lla" "conversion of scalar to vector involves truncation" +gdb_test "print lla + c4" "conversion of scalar to vector involves truncation" +gdb_test "print lla + i4a" "conversion of scalar to vector involves truncation" + +gdb_test "print c4 + ib" "\\\$$decimal = \\{2, 3, 4, 5\\}" gdb_test "print i4a + ib" "\\\$$decimal = \\{3, 5, 9, 17\\}" +gdb_test "print i4a + 1" "\\\$$decimal = \\{3, 5, 9, 17\\}" +gdb_test "print 1 + i4a" "\\\$$decimal = \\{3, 5, 9, 17\\}" gdb_test "print fa - f4b" "\\\$$decimal = \\{1, 0, -6, -2\\}" +gdb_test "print 2 - f4b" "\\\$$decimal = \\{1, 0, -6, -2\\}" gdb_test "print f4a * fb" "\\\$$decimal = \\{2, 4, 8, 16\\}" +gdb_test "print f4a * 1" "\\\$$decimal = \\{2, 4, 8, 16\\}" gdb_test "print ia / i4b" "\\\$$decimal = \\{2, 1, 0, 0\\}" +gdb_test "print 2 / i4b" "\\\$$decimal = \\{2, 1, 0, 0\\}" gdb_test "print i4a % ib" "\\\$$decimal = \\{0, 0, 0, 0\\}" - +gdb_test "print i4a % 1" "\\\$$decimal = \\{0, 0, 0, 0\\}" gdb_test "print ia & i4b" "\\\$$decimal = \\{0, 2, 0, 0\\}" +gdb_test "print 2 & i4b" "\\\$$decimal = \\{0, 2, 0, 0\\}" gdb_test "print i4a | ib" "\\\$$decimal = \\{3, 5, 9, 17\\}" +gdb_test "print i4a | 1" "\\\$$decimal = \\{3, 5, 9, 17\\}" gdb_test "print ia ^ i4b" "\\\$$decimal = \\{3, 0, 10, 6\\}" +gdb_test "print 2 ^ i4b" "\\\$$decimal = \\{3, 0, 10, 6\\}" gdb_test "print i4a << ib" "\\\$$decimal = \\{4, 8, 16, 32\\}" +gdb_test "print i4a << 1" "\\\$$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 >> 1" "\\\$$decimal = \\{1, 2, 4, 8\\}" gdb_test "print i4a = \{2, 4, 8, 16\}" "\\\$$decimal = \\{2, 4, 8, 16\\}" gdb_test "print i4a <<= ib" "\\\$$decimal = \\{4, 8, 16, 32\\}" @@ -130,6 +150,10 @@ gdb_test "print i2 + i4a" "Cannot perform operation on vectors with different ty gdb_test "print f4a + f2" "Cannot perform operation on vectors with different types" gdb_test "print f2 + f4a" "Cannot perform operation on vectors with different types" +gdb_test "print (double2) f2" "Cannot convert between vector values of different sizes" +gdb_test "print (int4) c4" "Cannot convert between vector values of different sizes" +gdb_test "print (char4) i4a" "Cannot convert between vector values of different sizes" + # Test ptype on vector types. gdb_test "ptype c4" "type = char __attribute__ \\(\\(vector_size\\(4\\)\\)\\)" gdb_test "ptype char4" "type = char __attribute__ \\(\\(vector_size\\(4\\)\\)\\)" diff --git a/gdb/testsuite/gdb.python/py-type.c b/gdb/testsuite/gdb.python/py-type.c index 641844efd1..03015a8fdd 100644 --- a/gdb/testsuite/gdb.python/py-type.c +++ b/gdb/testsuite/gdb.python/py-type.c @@ -50,6 +50,9 @@ enum E { v1, v2, v3 }; +struct s vec_data_1 = {1, 1}; +struct s vec_data_2 = {1, 2}; + int main () { diff --git a/gdb/testsuite/gdb.python/py-type.exp b/gdb/testsuite/gdb.python/py-type.exp index ec59bc8e75..16b2de21ba 100644 --- a/gdb/testsuite/gdb.python/py-type.exp +++ b/gdb/testsuite/gdb.python/py-type.exp @@ -118,7 +118,7 @@ proc test_fields {lang} { # Test gdb.Type.array. gdb_test "python print (ar\[0\].cast(ar\[0\].type.array(1)))" \ ".1, 2." "cast to array with one argument" - gdb_test "python print (ar\[0\].cast(ar\[0\].type.array(0, 1)))" \ + gdb_test "python print ar\[0\].cast(ar\[0\].type.array(0, 1))" \ ".1, 2." "cast to array with two arguments" gdb_test "python print (ar\[0\].type == ar\[0\].type)" "True" @@ -126,16 +126,19 @@ proc test_fields {lang} { # Test gdb.Type.vector. # Note: vectors cast differently than arrays. Here ar[0] is replicated # for the size of the vector. - gdb_py_test_silent_cmd \ - "python vec1 = ar\[0\].cast(ar\[0\].type.vector(1))" "set vec1" 1 - gdb_test "python print (vec1)" ".1, 1." "cast to vector with one argument" - gdb_py_test_silent_cmd \ - "python vec2 = ar\[0\].cast(ar\[0\].type.vector(0, 1))" "set vec2" 1 - gdb_test "python print (vec2)" ".1, 1." "cast to vector with two arguments" - gdb_test "python print (vec1 == vec2)" "True" - gdb_py_test_silent_cmd \ - "python vec3 = ar\[1\].cast(ar\[1\].type.vector(1))" "set vec3" 1 - gdb_test "python print (vec1 == vec3)" "False" + gdb_py_test_silent_cmd "print vec_data_1" "print value (vec_data_1)" 1 + gdb_py_test_silent_cmd "python vec_data_1 = gdb.history (0)" "get value (vec_data_1) from history" 1 + + gdb_py_test_silent_cmd "print vec_data_2" "print value (vec_data_2)" 1 + gdb_py_test_silent_cmd "python vec_data_2 = gdb.history (0)" "get value (vec_data_2) from history" 1 + + gdb_py_test_silent_cmd "python vec1 = vec_data_1.cast(ar\[0\].type.vector(1))" "set vec1" 1 + gdb_test "python print vec1" ".1, 1." "cast to vector with one argument" + gdb_py_test_silent_cmd "python vec2 = vec_data_1.cast(ar\[0\].type.vector(0, 1))" "set vec2" 1 + gdb_test "python print vec2" ".1, 1." "cast to vector with two arguments" + gdb_test "python print vec1 == vec2" "True" + gdb_py_test_silent_cmd "python vec3 = vec_data_2.cast(ar\[0\].type.vector(1))" "set vec3" 1 + gdb_test "python print vec1 == vec3" "False" } } diff --git a/gdb/valarith.c b/gdb/valarith.c index 074cf36fba..894a87ac04 100644 --- a/gdb/valarith.c +++ b/gdb/valarith.c @@ -1346,6 +1346,49 @@ scalar_binop (struct value *arg1, struct value *arg2, enum exp_opcode op) return val; } +/* Widen a scalar value SCALAR_VALUE to vector type VECTOR_TYPE by + replicating SCALAR_VALUE for each element of the vector. Only scalar + types that can be cast to the type of one element of the vector are + acceptable. The newly created vector value is returned upon success, + otherwise an error is thrown. */ + +struct value * +value_vector_widen (struct value *scalar_value, struct type *vector_type) +{ + /* Widen the scalar to a vector. */ + struct type *eltype, *scalar_type; + struct value *val, *elval; + LONGEST low_bound, high_bound; + int i; + + CHECK_TYPEDEF (vector_type); + + gdb_assert (TYPE_CODE (vector_type) == TYPE_CODE_ARRAY + && TYPE_VECTOR (vector_type)); + + if (!get_array_bounds (vector_type, &low_bound, &high_bound)) + error (_("Could not determine the vector bounds")); + + eltype = check_typedef (TYPE_TARGET_TYPE (vector_type)); + elval = value_cast (eltype, scalar_value); + + scalar_type = check_typedef (value_type (scalar_value)); + + /* If we reduced the length of the scalar then check we didn't loose any + important bits. */ + if (TYPE_LENGTH (eltype) < TYPE_LENGTH (scalar_type) + && !value_equal (elval, scalar_value)) + error (_("conversion of scalar to vector involves truncation")); + + val = allocate_value (vector_type); + for (i = 0; i < high_bound - low_bound + 1; i++) + /* Duplicate the contents of elval into the destination vector. */ + memcpy (value_contents_writeable (val) + (i * TYPE_LENGTH (eltype)), + value_contents_all (elval), TYPE_LENGTH (eltype)); + + return val; +} + /* Performs a binary operation on two vector operands by calling scalar_binop for each pair of vector components. */ @@ -1425,7 +1468,9 @@ value_binop (struct value *arg1, struct value *arg2, enum exp_opcode op) && !is_integral_type (t)) error (_("Argument to operation not a number or boolean.")); - *v = value_cast (t1_is_vec ? type1 : type2, *v); + /* Replicate the scalar value to make a vector value. */ + *v = value_vector_widen (*v, t1_is_vec ? type1 : type2); + val = vector_binop (arg1, arg2, op); } diff --git a/gdb/valops.c b/gdb/valops.c index e3d36a12ca..b9bc460fa6 100644 --- a/gdb/valops.c +++ b/gdb/valops.c @@ -546,29 +546,13 @@ value_cast (struct type *type, struct value *arg2) minus one, instead of biasing the normal case. */ return value_from_longest (type, -1); } - else if (code1 == TYPE_CODE_ARRAY && TYPE_VECTOR (type) && scalar) - { - /* Widen the scalar to a vector. */ - struct type *eltype; - struct value *val; - LONGEST low_bound, high_bound; - int i; - - if (!get_array_bounds (type, &low_bound, &high_bound)) - error (_("Could not determine the vector bounds")); - - eltype = check_typedef (TYPE_TARGET_TYPE (type)); - arg2 = value_cast (eltype, arg2); - val = allocate_value (type); - - for (i = 0; i < high_bound - low_bound + 1; i++) - { - /* Duplicate the contents of arg2 into the destination vector. */ - memcpy (value_contents_writeable (val) + (i * TYPE_LENGTH (eltype)), - value_contents_all (arg2), TYPE_LENGTH (eltype)); - } - return val; - } + else if (code1 == TYPE_CODE_ARRAY && TYPE_VECTOR (type) + && code2 == TYPE_CODE_ARRAY && TYPE_VECTOR (type2) + && TYPE_LENGTH (type) != TYPE_LENGTH (type2)) + error (_("Cannot convert between vector values of different sizes")); + else if (code1 == TYPE_CODE_ARRAY && TYPE_VECTOR (type) && scalar + && TYPE_LENGTH (type) != TYPE_LENGTH (type2)) + error (_("can only cast scalar to vector of same size")); else if (code1 == TYPE_CODE_VOID) { return value_zero (type, not_lval); diff --git a/gdb/value.h b/gdb/value.h index 67f1d04850..5825f6eca1 100644 --- a/gdb/value.h +++ b/gdb/value.h @@ -482,6 +482,12 @@ extern void read_value_memory (struct value *val, int embedded_offset, int stack, CORE_ADDR memaddr, gdb_byte *buffer, size_t length); +/* Cast SCALAR_VALUE to the element type of VECTOR_TYPE, then replicate + into each element of a new vector value with VECTOR_TYPE. */ + +struct value *value_vector_widen (struct value *scalar_value, + struct type *vector_type); + #include "symtab.h"