diff options
author | Andrew Burgess <aburgess@broadcom.com> | 2013-01-25 17:16:43 +0000 |
---|---|---|
committer | Andrew Burgess <aburgess@broadcom.com> | 2013-01-25 17:16:43 +0000 |
commit | 8954db33ac73962ac337cc456a782db7e9539c06 (patch) | |
tree | 9ca8b23663dcfd7823bc8f3ecbc8641c397e7613 /gdb/opencl-lang.c | |
parent | d79dcc73ac46dad924acf843a2c3546517506f9e (diff) | |
download | gdb-8954db33ac73962ac337cc456a782db7e9539c06.zip gdb-8954db33ac73962ac337cc456a782db7e9539c06.tar.gz gdb-8954db33ac73962ac337cc456a782db7e9539c06.tar.bz2 |
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.
Diffstat (limited to 'gdb/opencl-lang.c')
-rw-r--r-- | gdb/opencl-lang.c | 98 |
1 files changed, 95 insertions, 3 deletions
diff --git a/gdb/opencl-lang.c b/gdb/opencl-lang.c index 01e02c8..819a832 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) |