/* OpenCL language support for GDB, the GNU debugger.
- Copyright (C) 2010, 2011 Free Software Foundation, Inc.
+ Copyright (C) 2010-2013 Free Software Foundation, Inc.
#include "parser-defs.h"
#include "symtab.h"
#include "language.h"
+#include "varobj.h"
#include "c-lang.h"
#include "gdb_assert.h"
nr_opencl_primitive_types
};
-/* This macro generates the type struct declarations from a given type. */
-
-#define STRUCT_OCL_TYPE(TYPE)\
- struct type *builtin_##TYPE;\
- struct type *builtin_##TYPE##2;\
- struct type *builtin_##TYPE##3;\
- struct type *builtin_##TYPE##4;\
- struct type *builtin_##TYPE##8;\
- struct type *builtin_##TYPE##16
-
-struct builtin_opencl_type
-{
- STRUCT_OCL_TYPE (char);
- STRUCT_OCL_TYPE (uchar);
- STRUCT_OCL_TYPE (short);
- STRUCT_OCL_TYPE (ushort);
- STRUCT_OCL_TYPE (int);
- STRUCT_OCL_TYPE (uint);
- STRUCT_OCL_TYPE (long);
- STRUCT_OCL_TYPE (ulong);
- STRUCT_OCL_TYPE (half);
- STRUCT_OCL_TYPE (float);
- STRUCT_OCL_TYPE (double);
- struct type *builtin_bool;
- struct type *builtin_unsigned_char;
- struct type *builtin_unsigned_short;
- struct type *builtin_unsigned_int;
- struct type *builtin_unsigned_long;
- struct type *builtin_size_t;
- struct type *builtin_ptrdiff_t;
- struct type *builtin_intptr_t;
- struct type *builtin_uintptr_t;
- struct type *builtin_void;
-};
-
static struct gdbarch_data *opencl_type_data;
-const struct builtin_opencl_type *
+static struct type **
builtin_opencl_type (struct gdbarch *gdbarch)
{
return gdbarch_data (gdbarch, opencl_type_data);
int i;
unsigned int length;
struct type *type = NULL;
- struct type **types = (struct type **) builtin_opencl_type (gdbarch);
+ struct type **types = builtin_opencl_type (gdbarch);
/* Check if n describes a valid OpenCL vector size (2, 3, 4, 8, 16). */
if (n != 2 && n != 3 && n != 4 && n != 8 && n != 16)
for (i = start; i < end; i++)
{
- int startoffset = (i == start) ? startrest : 0;
- int length = (i == end) ? endrest : elsize;
+ int comp_offset = (i == start) ? startrest : 0;
+ int comp_length = (i == end) ? endrest : elsize;
- if (!value_bits_valid (c->val, c->indices[i] * elsize + startoffset,
- length))
+ if (!value_bits_valid (c->val, c->indices[i] * elsize + comp_offset,
+ comp_length))
return 0;
}
for (i = start; i < end; i++)
{
- int startoffset = (i == start) ? startrest : 0;
- int length = (i == end) ? endrest : elsize;
+ int comp_offset = (i == start) ? startrest : 0;
+ int comp_length = (i == end) ? endrest : elsize;
if (!value_bits_synthetic_pointer (c->val,
- c->indices[i] * elsize + startoffset,
- length))
+ c->indices[i] * elsize + comp_offset,
+ comp_length))
return 0;
}
if (c->refc == 0)
{
+ value_free (c->val); /* Decrement the reference counter of the value. */
xfree (c->indices);
xfree (c);
- value_free (c->val); /* Decrement the reference counter of the value. */
}
}
-static struct lval_funcs opencl_value_funcs =
+static const struct lval_funcs opencl_value_funcs =
{
lval_func_read,
lval_func_write,
lval_func_check_validity,
lval_func_check_any_valid,
- NULL,
+ NULL, /* indirect */
+ NULL, /* coerce_ref */
lval_func_check_synthetic_pointer,
lval_func_copy_closure,
lval_func_free_closure
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 *
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);
}
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:
if (noside == EVAL_SKIP)
{
- arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ evaluate_subexp (NULL_TYPE, exp, pos, noside);
return value_from_longest (builtin_type (exp->gdbarch)->
builtin_int, 1);
/* 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)
}
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:
return evaluate_subexp_c (expect_type, exp, pos, noside);
}
-void
+/* 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)
+ struct language_arch_info *lai)
{
- const struct builtin_opencl_type *builtin = builtin_opencl_type (gdbarch);
+ struct type **types = builtin_opencl_type (gdbarch);
- lai->string_char_type = builtin->builtin_char;
- lai->primitive_type_vector
- = GDBARCH_OBSTACK_CALLOC (gdbarch, nr_opencl_primitive_types + 1,
- struct type *);
+ /* Copy primitive types vector from gdbarch. */
+ lai->primitive_type_vector = types;
-/* This macro fills the primitive_type_vector from a given type. */
-#define FILL_TYPE_VECTOR(LAI, TYPE)\
- LAI->primitive_type_vector [opencl_primitive_type_##TYPE]\
- = builtin->builtin_##TYPE;\
- LAI->primitive_type_vector [opencl_primitive_type_##TYPE##2]\
- = builtin->builtin_##TYPE##2;\
- LAI->primitive_type_vector [opencl_primitive_type_##TYPE##3]\
- = builtin->builtin_##TYPE##3;\
- LAI->primitive_type_vector [opencl_primitive_type_##TYPE##4]\
- = builtin->builtin_##TYPE##4;\
- LAI->primitive_type_vector [opencl_primitive_type_##TYPE##8]\
- = builtin->builtin_##TYPE##8;\
- LAI->primitive_type_vector [opencl_primitive_type_##TYPE##16]\
- = builtin->builtin_##TYPE##16
-
- FILL_TYPE_VECTOR (lai, char);
- FILL_TYPE_VECTOR (lai, uchar);
- FILL_TYPE_VECTOR (lai, short);
- FILL_TYPE_VECTOR (lai, ushort);
- FILL_TYPE_VECTOR (lai, int);
- FILL_TYPE_VECTOR (lai, uint);
- FILL_TYPE_VECTOR (lai, long);
- FILL_TYPE_VECTOR (lai, ulong);
- FILL_TYPE_VECTOR (lai, half);
- FILL_TYPE_VECTOR (lai, float);
- FILL_TYPE_VECTOR (lai, double);
- lai->primitive_type_vector [opencl_primitive_type_bool]
- = builtin->builtin_bool;
- lai->primitive_type_vector [opencl_primitive_type_unsigned_char]
- = builtin->builtin_unsigned_char;
- lai->primitive_type_vector [opencl_primitive_type_unsigned_short]
- = builtin->builtin_unsigned_short;
- lai->primitive_type_vector [opencl_primitive_type_unsigned_int]
- = builtin->builtin_unsigned_int;
- lai->primitive_type_vector [opencl_primitive_type_unsigned_long]
- = builtin->builtin_unsigned_long;
- lai->primitive_type_vector [opencl_primitive_type_half]
- = builtin->builtin_half;
- lai->primitive_type_vector [opencl_primitive_type_size_t]
- = builtin->builtin_size_t;
- lai->primitive_type_vector [opencl_primitive_type_ptrdiff_t]
- = builtin->builtin_ptrdiff_t;
- lai->primitive_type_vector [opencl_primitive_type_intptr_t]
- = builtin->builtin_intptr_t;
- lai->primitive_type_vector [opencl_primitive_type_uintptr_t]
- = builtin->builtin_uintptr_t;
- lai->primitive_type_vector [opencl_primitive_type_void]
- = builtin->builtin_void;
+ /* Type of elements of strings. */
+ lai->string_char_type = types [opencl_primitive_type_char];
/* Specifies the return type of logical and relational operations. */
lai->bool_type_symbol = "int";
- lai->bool_type_default = builtin->builtin_int;
+ lai->bool_type_default = types [opencl_primitive_type_int];
}
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,
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 */
+ default_read_var_value, /* la_read_var_value */
NULL, /* Language specific skip_trampoline */
NULL, /* name_of_this */
basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
default_print_array_index,
default_pass_by_reference,
c_get_string,
+ NULL, /* la_get_symbol_name_cmp */
+ iterate_over_symbols,
+ &default_varobj_ops,
LANG_MAGIC
};
static void *
build_opencl_types (struct gdbarch *gdbarch)
{
- struct builtin_opencl_type *builtin_opencl_type
- = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct builtin_opencl_type);
+ struct type **types
+ = GDBARCH_OBSTACK_CALLOC (gdbarch, nr_opencl_primitive_types + 1,
+ struct type *);
/* Helper macro to create strings. */
#define OCL_STRING(S) #S
/* This macro allocates and assigns the type struct pointers
for the vector types. */
#define BUILD_OCL_VTYPES(TYPE)\
- builtin_opencl_type->builtin_##TYPE##2\
- = init_vector_type (builtin_opencl_type->builtin_##TYPE, 2);\
- TYPE_NAME (builtin_opencl_type->builtin_##TYPE##2) = OCL_STRING(TYPE ## 2);\
- builtin_opencl_type->builtin_##TYPE##3\
- = init_vector_type (builtin_opencl_type->builtin_##TYPE, 3);\
- TYPE_NAME (builtin_opencl_type->builtin_##TYPE##3) = OCL_STRING(TYPE ## 3);\
- TYPE_LENGTH (builtin_opencl_type->builtin_##TYPE##3)\
- = 4 * TYPE_LENGTH (builtin_opencl_type->builtin_##TYPE);\
- builtin_opencl_type->builtin_##TYPE##4\
- = init_vector_type (builtin_opencl_type->builtin_##TYPE, 4);\
- TYPE_NAME (builtin_opencl_type->builtin_##TYPE##4) = OCL_STRING(TYPE ## 4);\
- builtin_opencl_type->builtin_##TYPE##8\
- = init_vector_type (builtin_opencl_type->builtin_##TYPE, 8);\
- TYPE_NAME (builtin_opencl_type->builtin_##TYPE##8) = OCL_STRING(TYPE ## 8);\
- builtin_opencl_type->builtin_##TYPE##16\
- = init_vector_type (builtin_opencl_type->builtin_##TYPE, 16);\
- TYPE_NAME (builtin_opencl_type->builtin_##TYPE##16) = OCL_STRING(TYPE ## 16)
-
- builtin_opencl_type->builtin_char
+ types[opencl_primitive_type_##TYPE##2] \
+ = init_vector_type (types[opencl_primitive_type_##TYPE], 2); \
+ TYPE_NAME (types[opencl_primitive_type_##TYPE##2]) = OCL_STRING(TYPE ## 2); \
+ types[opencl_primitive_type_##TYPE##3] \
+ = init_vector_type (types[opencl_primitive_type_##TYPE], 3); \
+ TYPE_NAME (types[opencl_primitive_type_##TYPE##3]) = OCL_STRING(TYPE ## 3); \
+ TYPE_LENGTH (types[opencl_primitive_type_##TYPE##3]) \
+ = 4 * TYPE_LENGTH (types[opencl_primitive_type_##TYPE]); \
+ types[opencl_primitive_type_##TYPE##4] \
+ = init_vector_type (types[opencl_primitive_type_##TYPE], 4); \
+ TYPE_NAME (types[opencl_primitive_type_##TYPE##4]) = OCL_STRING(TYPE ## 4); \
+ types[opencl_primitive_type_##TYPE##8] \
+ = init_vector_type (types[opencl_primitive_type_##TYPE], 8); \
+ TYPE_NAME (types[opencl_primitive_type_##TYPE##8]) = OCL_STRING(TYPE ## 8); \
+ types[opencl_primitive_type_##TYPE##16] \
+ = init_vector_type (types[opencl_primitive_type_##TYPE], 16); \
+ TYPE_NAME (types[opencl_primitive_type_##TYPE##16]) = OCL_STRING(TYPE ## 16)
+
+ types[opencl_primitive_type_char]
= arch_integer_type (gdbarch, 8, 0, "char");
BUILD_OCL_VTYPES (char);
- builtin_opencl_type->builtin_uchar
+ types[opencl_primitive_type_uchar]
= arch_integer_type (gdbarch, 8, 1, "uchar");
BUILD_OCL_VTYPES (uchar);
- builtin_opencl_type->builtin_short
+ types[opencl_primitive_type_short]
= arch_integer_type (gdbarch, 16, 0, "short");
BUILD_OCL_VTYPES (short);
- builtin_opencl_type->builtin_ushort
+ types[opencl_primitive_type_ushort]
= arch_integer_type (gdbarch, 16, 1, "ushort");
BUILD_OCL_VTYPES (ushort);
- builtin_opencl_type->builtin_int
+ types[opencl_primitive_type_int]
= arch_integer_type (gdbarch, 32, 0, "int");
BUILD_OCL_VTYPES (int);
- builtin_opencl_type->builtin_uint
+ types[opencl_primitive_type_uint]
= arch_integer_type (gdbarch, 32, 1, "uint");
BUILD_OCL_VTYPES (uint);
- builtin_opencl_type->builtin_long
+ types[opencl_primitive_type_long]
= arch_integer_type (gdbarch, 64, 0, "long");
BUILD_OCL_VTYPES (long);
- builtin_opencl_type->builtin_ulong
+ types[opencl_primitive_type_ulong]
= arch_integer_type (gdbarch, 64, 1, "ulong");
BUILD_OCL_VTYPES (ulong);
- builtin_opencl_type->builtin_half
+ types[opencl_primitive_type_half]
= arch_float_type (gdbarch, 16, "half", floatformats_ieee_half);
BUILD_OCL_VTYPES (half);
- builtin_opencl_type->builtin_float
+ types[opencl_primitive_type_float]
= arch_float_type (gdbarch, 32, "float", floatformats_ieee_single);
BUILD_OCL_VTYPES (float);
- builtin_opencl_type->builtin_double
+ types[opencl_primitive_type_double]
= arch_float_type (gdbarch, 64, "double", floatformats_ieee_double);
BUILD_OCL_VTYPES (double);
- builtin_opencl_type->builtin_bool
+ types[opencl_primitive_type_bool]
= arch_boolean_type (gdbarch, 8, 1, "bool");
- builtin_opencl_type->builtin_unsigned_char
+ types[opencl_primitive_type_unsigned_char]
= arch_integer_type (gdbarch, 8, 1, "unsigned char");
- builtin_opencl_type->builtin_unsigned_short
+ types[opencl_primitive_type_unsigned_short]
= arch_integer_type (gdbarch, 16, 1, "unsigned short");
- builtin_opencl_type->builtin_unsigned_int
+ types[opencl_primitive_type_unsigned_int]
= arch_integer_type (gdbarch, 32, 1, "unsigned int");
- builtin_opencl_type->builtin_unsigned_long
+ types[opencl_primitive_type_unsigned_long]
= arch_integer_type (gdbarch, 64, 1, "unsigned long");
- builtin_opencl_type->builtin_size_t
+ types[opencl_primitive_type_size_t]
= arch_integer_type (gdbarch, gdbarch_ptr_bit (gdbarch), 1, "size_t");
- builtin_opencl_type->builtin_ptrdiff_t
+ types[opencl_primitive_type_ptrdiff_t]
= arch_integer_type (gdbarch, gdbarch_ptr_bit (gdbarch), 0, "ptrdiff_t");
- builtin_opencl_type->builtin_intptr_t
+ types[opencl_primitive_type_intptr_t]
= arch_integer_type (gdbarch, gdbarch_ptr_bit (gdbarch), 0, "intptr_t");
- builtin_opencl_type->builtin_uintptr_t
+ types[opencl_primitive_type_uintptr_t]
= arch_integer_type (gdbarch, gdbarch_ptr_bit (gdbarch), 1, "uintptr_t");
- builtin_opencl_type->builtin_void
+ types[opencl_primitive_type_void]
= arch_type (gdbarch, TYPE_CODE_VOID, 1, "void");
- return builtin_opencl_type;
+ return types;
}
+/* Provide a prototype to silence -Wmissing-prototypes. */
+extern initialize_file_ftype _initialize_opencl_language;
+
void
_initialize_opencl_language (void)
{