Index: gdb/opencl-lang.c |
diff --git a/gdb/opencl-lang.c b/gdb/opencl-lang.c |
index 54075a4194757fa36a222fdafd9c52050a9198a5..37852544d3b37f90a67f61bb566add56aab9d7a6 100644 |
--- a/gdb/opencl-lang.c |
+++ b/gdb/opencl-lang.c |
@@ -1,5 +1,5 @@ |
/* OpenCL language support for GDB, the GNU debugger. |
- Copyright (C) 2010-2012 Free Software Foundation, Inc. |
+ Copyright (C) 2010-2013 Free Software Foundation, Inc. |
Contributed by Ken Werner <ken.werner@de.ibm.com>. |
@@ -19,13 +19,14 @@ |
along with this program. If not, see <http://www.gnu.org/licenses/>. */ |
#include "defs.h" |
-#include "gdb_string.h" |
+#include <string.h> |
#include "gdbtypes.h" |
#include "symtab.h" |
#include "expression.h" |
#include "parser-defs.h" |
#include "symtab.h" |
#include "language.h" |
+#include "varobj.h" |
#include "c-lang.h" |
#include "gdb_assert.h" |
@@ -683,6 +684,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 +771,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 +793,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 +945,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) |
@@ -943,15 +1036,13 @@ Cannot perform conditional operation on vectors with different sizes")); |
} |
else |
{ |
+ struct value *v = value_struct_elt (&arg1, NULL, |
+ &exp->elts[pc + 2].string, NULL, |
+ "structure"); |
+ |
if (noside == EVAL_AVOID_SIDE_EFFECTS) |
- return |
- value_zero (lookup_struct_elt_type |
- (value_type (arg1),&exp->elts[pc + 2].string, 0), |
- lval_memory); |
- else |
- return value_struct_elt (&arg1, NULL, |
- &exp->elts[pc + 2].string, NULL, |
- "structure"); |
+ v = value_zero (value_type (v), not_lval); |
+ return v; |
} |
} |
default: |
@@ -961,6 +1052,27 @@ Cannot perform conditional operation on vectors with different sizes")); |
return evaluate_subexp_c (expect_type, exp, pos, noside); |
} |
+/* Print OpenCL types. */ |
+ |
+static void |
+opencl_print_type (struct type *type, const char *varstring, |
+ struct ui_file *stream, int show, int level, |
+ const struct type_print_options *flags) |
+{ |
+ /* We nearly always defer to C type printing, except that vector |
+ types are considered primitive in OpenCL, and should always |
+ be printed using their TYPE_NAME. */ |
+ if (show > 0) |
+ { |
+ CHECK_TYPEDEF (type); |
+ if (TYPE_CODE (type) == TYPE_CODE_ARRAY && TYPE_VECTOR (type) |
+ && TYPE_NAME (type) != NULL) |
+ show = 0; |
+ } |
+ |
+ c_print_type (type, varstring, stream, show, level, flags); |
+} |
+ |
static void |
opencl_language_arch_info (struct gdbarch *gdbarch, |
struct language_arch_info *lai) |
@@ -991,9 +1103,9 @@ const struct exp_descriptor exp_descriptor_opencl = |
const struct language_defn opencl_language_defn = |
{ |
"opencl", /* Language name */ |
+ "OpenCL C", |
language_opencl, |
range_check_off, |
- type_check_off, |
case_sensitive_on, |
array_row_major, |
macro_expansion_c, |
@@ -1004,7 +1116,7 @@ const struct language_defn opencl_language_defn = |
c_printchar, /* Print a character constant */ |
c_printstr, /* Function to print string constant */ |
c_emit_char, /* Print a single char */ |
- c_print_type, /* Print a type using appropriate syntax */ |
+ opencl_print_type, /* Print a type using appropriate syntax */ |
c_print_typedef, /* Print a typedef using appropriate syntax */ |
c_val_print, /* Print a value using appropriate syntax */ |
c_value_print, /* Print a top-level value */ |
@@ -1027,6 +1139,7 @@ const struct language_defn opencl_language_defn = |
c_get_string, |
NULL, /* la_get_symbol_name_cmp */ |
iterate_over_symbols, |
+ &default_varobj_ops, |
LANG_MAGIC |
}; |