123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983 |
- /* OpenCL language support for GDB, the GNU debugger.
- Copyright (C) 2010-2022 Free Software Foundation, Inc.
- Contributed by Ken Werner <ken.werner@de.ibm.com>.
- This file is part of GDB.
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>. */
- #include "defs.h"
- #include "gdbtypes.h"
- #include "symtab.h"
- #include "expression.h"
- #include "parser-defs.h"
- #include "language.h"
- #include "varobj.h"
- #include "c-lang.h"
- #include "gdbarch.h"
- #include "c-exp.h"
- /* Returns the corresponding OpenCL vector type from the given type code,
- the length of the element type, the unsigned flag and the amount of
- elements (N). */
- static struct type *
- lookup_opencl_vector_type (struct gdbarch *gdbarch, enum type_code code,
- unsigned int el_length, unsigned int flag_unsigned,
- int n)
- {
- unsigned int length;
- /* 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)
- error (_("Invalid OpenCL vector size: %d"), n);
- /* Triple vectors have the size of a quad vector. */
- length = (n == 3) ? el_length * 4 : el_length * n;
- auto filter = [&] (struct type *type)
- {
- LONGEST lowb, highb;
- return (type->code () == TYPE_CODE_ARRAY && type->is_vector ()
- && get_array_bounds (type, &lowb, &highb)
- && TYPE_TARGET_TYPE (type)->code () == code
- && TYPE_TARGET_TYPE (type)->is_unsigned () == flag_unsigned
- && TYPE_LENGTH (TYPE_TARGET_TYPE (type)) == el_length
- && TYPE_LENGTH (type) == length
- && highb - lowb + 1 == n);
- };
- const struct language_defn *lang = language_def (language_opencl);
- return language_lookup_primitive_type (lang, gdbarch, filter);
- }
- /* Returns nonzero if the array ARR contains duplicates within
- the first N elements. */
- static int
- array_has_dups (int *arr, int n)
- {
- int i, j;
- for (i = 0; i < n; i++)
- {
- for (j = i + 1; j < n; j++)
- {
- if (arr[i] == arr[j])
- return 1;
- }
- }
- return 0;
- }
- /* The OpenCL component access syntax allows to create lvalues referring to
- selected elements of an original OpenCL vector in arbitrary order. This
- structure holds the information to describe such lvalues. */
- struct lval_closure
- {
- /* Reference count. */
- int refc;
- /* The number of indices. */
- int n;
- /* The element indices themselves. */
- int *indices;
- /* A pointer to the original value. */
- struct value *val;
- };
- /* Allocates an instance of struct lval_closure. */
- static struct lval_closure *
- allocate_lval_closure (int *indices, int n, struct value *val)
- {
- struct lval_closure *c = XCNEW (struct lval_closure);
- c->refc = 1;
- c->n = n;
- c->indices = XCNEWVEC (int, n);
- memcpy (c->indices, indices, n * sizeof (int));
- value_incref (val); /* Increment the reference counter of the value. */
- c->val = val;
- return c;
- }
- static void
- lval_func_read (struct value *v)
- {
- struct lval_closure *c = (struct lval_closure *) value_computed_closure (v);
- struct type *type = check_typedef (value_type (v));
- struct type *eltype = TYPE_TARGET_TYPE (check_typedef (value_type (c->val)));
- LONGEST offset = value_offset (v);
- LONGEST elsize = TYPE_LENGTH (eltype);
- int n, i, j = 0;
- LONGEST lowb = 0;
- LONGEST highb = 0;
- if (type->code () == TYPE_CODE_ARRAY
- && !get_array_bounds (type, &lowb, &highb))
- error (_("Could not determine the vector bounds"));
- /* Assume elsize aligned offset. */
- gdb_assert (offset % elsize == 0);
- offset /= elsize;
- n = offset + highb - lowb + 1;
- gdb_assert (n <= c->n);
- for (i = offset; i < n; i++)
- memcpy (value_contents_raw (v).data () + j++ * elsize,
- value_contents (c->val).data () + c->indices[i] * elsize,
- elsize);
- }
- static void
- lval_func_write (struct value *v, struct value *fromval)
- {
- struct value *mark = value_mark ();
- struct lval_closure *c = (struct lval_closure *) value_computed_closure (v);
- struct type *type = check_typedef (value_type (v));
- struct type *eltype = TYPE_TARGET_TYPE (check_typedef (value_type (c->val)));
- LONGEST offset = value_offset (v);
- LONGEST elsize = TYPE_LENGTH (eltype);
- int n, i, j = 0;
- LONGEST lowb = 0;
- LONGEST highb = 0;
- if (type->code () == TYPE_CODE_ARRAY
- && !get_array_bounds (type, &lowb, &highb))
- error (_("Could not determine the vector bounds"));
- /* Assume elsize aligned offset. */
- gdb_assert (offset % elsize == 0);
- offset /= elsize;
- n = offset + highb - lowb + 1;
- /* Since accesses to the fourth component of a triple vector is undefined we
- just skip writes to the fourth element. Imagine something like this:
- int3 i3 = (int3)(0, 1, 2);
- i3.hi.hi = 5;
- In this case n would be 4 (offset=12/4 + 1) while c->n would be 3. */
- if (n > c->n)
- n = c->n;
- for (i = offset; i < n; i++)
- {
- struct value *from_elm_val = allocate_value (eltype);
- struct value *to_elm_val = value_subscript (c->val, c->indices[i]);
- memcpy (value_contents_writeable (from_elm_val).data (),
- value_contents (fromval).data () + j++ * elsize,
- elsize);
- value_assign (to_elm_val, from_elm_val);
- }
- value_free_to_mark (mark);
- }
- /* Return nonzero if bits in V from OFFSET and LENGTH represent a
- synthetic pointer. */
- static int
- lval_func_check_synthetic_pointer (const struct value *v,
- LONGEST offset, int length)
- {
- struct lval_closure *c = (struct lval_closure *) value_computed_closure (v);
- /* Size of the target type in bits. */
- int elsize =
- TYPE_LENGTH (TYPE_TARGET_TYPE (check_typedef (value_type (c->val)))) * 8;
- int startrest = offset % elsize;
- int start = offset / elsize;
- int endrest = (offset + length) % elsize;
- int end = (offset + length) / elsize;
- int i;
- if (endrest)
- end++;
- if (end > c->n)
- return 0;
- for (i = start; i < end; i++)
- {
- 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 + comp_offset,
- comp_length))
- return 0;
- }
- return 1;
- }
- static void *
- lval_func_copy_closure (const struct value *v)
- {
- struct lval_closure *c = (struct lval_closure *) value_computed_closure (v);
- ++c->refc;
- return c;
- }
- static void
- lval_func_free_closure (struct value *v)
- {
- struct lval_closure *c = (struct lval_closure *) value_computed_closure (v);
- --c->refc;
- if (c->refc == 0)
- {
- value_decref (c->val); /* Decrement the reference counter of the value. */
- xfree (c->indices);
- xfree (c);
- }
- }
- static const struct lval_funcs opencl_value_funcs =
- {
- lval_func_read,
- lval_func_write,
- nullptr,
- NULL, /* indirect */
- NULL, /* coerce_ref */
- lval_func_check_synthetic_pointer,
- lval_func_copy_closure,
- lval_func_free_closure
- };
- /* Creates a sub-vector from VAL. The elements are selected by the indices of
- an array with the length of N. Supported values for NOSIDE are
- EVAL_NORMAL and EVAL_AVOID_SIDE_EFFECTS. */
- static struct value *
- create_value (struct gdbarch *gdbarch, struct value *val, enum noside noside,
- int *indices, int n)
- {
- struct type *type = check_typedef (value_type (val));
- struct type *elm_type = TYPE_TARGET_TYPE (type);
- struct value *ret;
- /* Check if a single component of a vector is requested which means
- the resulting type is a (primitive) scalar type. */
- if (n == 1)
- {
- if (noside == EVAL_AVOID_SIDE_EFFECTS)
- ret = value_zero (elm_type, not_lval);
- else
- ret = value_subscript (val, indices[0]);
- }
- else
- {
- /* Multiple components of the vector are requested which means the
- resulting type is a vector as well. */
- struct type *dst_type =
- lookup_opencl_vector_type (gdbarch, elm_type->code (),
- TYPE_LENGTH (elm_type),
- elm_type->is_unsigned (), n);
- if (dst_type == NULL)
- dst_type = init_vector_type (elm_type, n);
- make_cv_type (TYPE_CONST (type), TYPE_VOLATILE (type), dst_type, NULL);
- if (noside == EVAL_AVOID_SIDE_EFFECTS)
- ret = allocate_value (dst_type);
- else
- {
- /* Check whether to create a lvalue or not. */
- if (VALUE_LVAL (val) != not_lval && !array_has_dups (indices, n))
- {
- struct lval_closure *c = allocate_lval_closure (indices, n, val);
- ret = allocate_computed_value (dst_type, &opencl_value_funcs, c);
- }
- else
- {
- int i;
- ret = allocate_value (dst_type);
- /* Copy src val contents into the destination value. */
- for (i = 0; i < n; i++)
- memcpy (value_contents_writeable (ret).data ()
- + (i * TYPE_LENGTH (elm_type)),
- value_contents (val).data ()
- + (indices[i] * TYPE_LENGTH (elm_type)),
- TYPE_LENGTH (elm_type));
- }
- }
- }
- return ret;
- }
- /* OpenCL vector component access. */
- static struct value *
- opencl_component_ref (struct expression *exp, struct value *val,
- const char *comps, enum noside noside)
- {
- LONGEST lowb, highb;
- int src_len;
- struct value *v;
- int indices[16], i;
- int dst_len;
- if (!get_array_bounds (check_typedef (value_type (val)), &lowb, &highb))
- error (_("Could not determine the vector bounds"));
- src_len = highb - lowb + 1;
- /* Throw an error if the amount of array elements does not fit a
- valid OpenCL vector size (2, 3, 4, 8, 16). */
- if (src_len != 2 && src_len != 3 && src_len != 4 && src_len != 8
- && src_len != 16)
- error (_("Invalid OpenCL vector size"));
- if (strcmp (comps, "lo") == 0 )
- {
- dst_len = (src_len == 3) ? 2 : src_len / 2;
- for (i = 0; i < dst_len; i++)
- indices[i] = i;
- }
- else if (strcmp (comps, "hi") == 0)
- {
- dst_len = (src_len == 3) ? 2 : src_len / 2;
- for (i = 0; i < dst_len; i++)
- indices[i] = dst_len + i;
- }
- else if (strcmp (comps, "even") == 0)
- {
- dst_len = (src_len == 3) ? 2 : src_len / 2;
- for (i = 0; i < dst_len; i++)
- indices[i] = i*2;
- }
- else if (strcmp (comps, "odd") == 0)
- {
- dst_len = (src_len == 3) ? 2 : src_len / 2;
- for (i = 0; i < dst_len; i++)
- indices[i] = i*2+1;
- }
- else if (strncasecmp (comps, "s", 1) == 0)
- {
- #define HEXCHAR_TO_INT(C) ((C >= '0' && C <= '9') ? \
- C-'0' : ((C >= 'A' && C <= 'F') ? \
- C-'A'+10 : ((C >= 'a' && C <= 'f') ? \
- C-'a'+10 : -1)))
- dst_len = strlen (comps);
- /* Skip the s/S-prefix. */
- dst_len--;
- for (i = 0; i < dst_len; i++)
- {
- indices[i] = HEXCHAR_TO_INT(comps[i+1]);
- /* Check if the requested component is invalid or exceeds
- the vector. */
- if (indices[i] < 0 || indices[i] >= src_len)
- error (_("Invalid OpenCL vector component accessor %s"), comps);
- }
- }
- else
- {
- dst_len = strlen (comps);
- for (i = 0; i < dst_len; i++)
- {
- /* x, y, z, w */
- switch (comps[i])
- {
- case 'x':
- indices[i] = 0;
- break;
- case 'y':
- indices[i] = 1;
- break;
- case 'z':
- if (src_len < 3)
- error (_("Invalid OpenCL vector component accessor %s"), comps);
- indices[i] = 2;
- break;
- case 'w':
- if (src_len < 4)
- error (_("Invalid OpenCL vector component accessor %s"), comps);
- indices[i] = 3;
- break;
- default:
- error (_("Invalid OpenCL vector component accessor %s"), comps);
- break;
- }
- }
- }
- /* Throw an error if the amount of requested components does not
- result in a valid length (1, 2, 3, 4, 8, 16). */
- if (dst_len != 1 && dst_len != 2 && dst_len != 3 && dst_len != 4
- && dst_len != 8 && dst_len != 16)
- error (_("Invalid OpenCL vector component accessor %s"), comps);
- v = create_value (exp->gdbarch, val, noside, indices, dst_len);
- return v;
- }
- /* Perform the unary logical not (!) operation. */
- struct value *
- opencl_logical_not (struct type *expect_type, struct expression *exp,
- enum noside noside, enum exp_opcode op,
- struct value *arg)
- {
- struct type *type = check_typedef (value_type (arg));
- struct type *rettype;
- struct value *ret;
- if (type->code () == TYPE_CODE_ARRAY && type->is_vector ())
- {
- struct type *eltype = check_typedef (TYPE_TARGET_TYPE (type));
- LONGEST lowb, highb;
- int i;
- if (!get_array_bounds (type, &lowb, &highb))
- error (_("Could not determine the vector bounds"));
- /* Determine the resulting type of the operation and allocate the
- value. */
- rettype = lookup_opencl_vector_type (exp->gdbarch, TYPE_CODE_INT,
- TYPE_LENGTH (eltype), 0,
- highb - lowb + 1);
- ret = allocate_value (rettype);
- for (i = 0; i < highb - lowb + 1; i++)
- {
- /* For vector types, the unary operator shall return a 0 if the
- value of its operand compares unequal to 0, and -1 (i.e. all bits
- set) if the value of its operand compares equal to 0. */
- int tmp = value_logical_not (value_subscript (arg, i)) ? -1 : 0;
- memset ((value_contents_writeable (ret).data ()
- + i * TYPE_LENGTH (eltype)),
- tmp, TYPE_LENGTH (eltype));
- }
- }
- else
- {
- rettype = language_bool_type (exp->language_defn, exp->gdbarch);
- ret = value_from_longest (rettype, value_logical_not (arg));
- }
- return ret;
- }
- /* Perform a relational operation on two scalar operands. */
- static int
- scalar_relop (struct value *val1, struct value *val2, enum exp_opcode op)
- {
- int ret;
- switch (op)
- {
- case BINOP_EQUAL:
- ret = value_equal (val1, val2);
- break;
- case BINOP_NOTEQUAL:
- ret = !value_equal (val1, val2);
- break;
- case BINOP_LESS:
- ret = value_less (val1, val2);
- break;
- case BINOP_GTR:
- ret = value_less (val2, val1);
- break;
- case BINOP_GEQ:
- ret = value_less (val2, val1) || value_equal (val1, val2);
- break;
- case BINOP_LEQ:
- ret = value_less (val1, val2) || value_equal (val1, val2);
- break;
- case BINOP_LOGICAL_AND:
- ret = !value_logical_not (val1) && !value_logical_not (val2);
- break;
- case BINOP_LOGICAL_OR:
- ret = !value_logical_not (val1) || !value_logical_not (val2);
- break;
- default:
- error (_("Attempt to perform an unsupported operation"));
- break;
- }
- return ret;
- }
- /* Perform a relational operation on two vector operands. */
- static struct value *
- vector_relop (struct expression *exp, struct value *val1, struct value *val2,
- enum exp_opcode op)
- {
- struct value *ret;
- struct type *type1, *type2, *eltype1, *eltype2, *rettype;
- int t1_is_vec, t2_is_vec, i;
- LONGEST lowb1, lowb2, highb1, highb2;
- type1 = check_typedef (value_type (val1));
- type2 = check_typedef (value_type (val2));
- t1_is_vec = (type1->code () == TYPE_CODE_ARRAY && type1->is_vector ());
- t2_is_vec = (type2->code () == TYPE_CODE_ARRAY && type2->is_vector ());
- if (!t1_is_vec || !t2_is_vec)
- error (_("Vector operations are not supported on scalar types"));
- eltype1 = check_typedef (TYPE_TARGET_TYPE (type1));
- eltype2 = check_typedef (TYPE_TARGET_TYPE (type2));
- if (!get_array_bounds (type1,&lowb1, &highb1)
- || !get_array_bounds (type2, &lowb2, &highb2))
- error (_("Could not determine the vector bounds"));
- /* Check whether the vector types are compatible. */
- if (eltype1->code () != eltype2->code ()
- || TYPE_LENGTH (eltype1) != TYPE_LENGTH (eltype2)
- || eltype1->is_unsigned () != eltype2->is_unsigned ()
- || lowb1 != lowb2 || highb1 != highb2)
- error (_("Cannot perform operation on vectors with different types"));
- /* Determine the resulting type of the operation and allocate the value. */
- rettype = lookup_opencl_vector_type (exp->gdbarch, TYPE_CODE_INT,
- TYPE_LENGTH (eltype1), 0,
- highb1 - lowb1 + 1);
- ret = allocate_value (rettype);
- for (i = 0; i < highb1 - lowb1 + 1; i++)
- {
- /* For vector types, the relational, equality and logical operators shall
- return 0 if the specified relation is false and -1 (i.e. all bits set)
- if the specified relation is true. */
- int tmp = scalar_relop (value_subscript (val1, i),
- value_subscript (val2, i), op) ? -1 : 0;
- memset ((value_contents_writeable (ret).data ()
- + i * TYPE_LENGTH (eltype1)),
- tmp, TYPE_LENGTH (eltype1));
- }
- 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. */
- 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 = to_type->code ();
- code2 = check_typedef (value_type (arg))->code ();
- if (code2 == TYPE_CODE_REF)
- code2 = check_typedef (value_type (coerce_ref(arg)))->code ();
- 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 && to_type->is_vector () && 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. */
- struct value *
- opencl_relop (struct type *expect_type, struct expression *exp,
- enum noside noside, enum exp_opcode op,
- struct value *arg1, struct value *arg2)
- {
- struct value *val;
- struct type *type1 = check_typedef (value_type (arg1));
- struct type *type2 = check_typedef (value_type (arg2));
- int t1_is_vec = (type1->code () == TYPE_CODE_ARRAY
- && type1->is_vector ());
- int t2_is_vec = (type2->code () == TYPE_CODE_ARRAY
- && type2->is_vector ());
- if (!t1_is_vec && !t2_is_vec)
- {
- int tmp = scalar_relop (arg1, arg2, op);
- struct type *type =
- language_bool_type (exp->language_defn, exp->gdbarch);
- val = value_from_longest (type, tmp);
- }
- else if (t1_is_vec && t2_is_vec)
- {
- val = vector_relop (exp, arg1, arg2, op);
- }
- else
- {
- /* Widen the scalar operand to a vector. */
- struct value **v = t1_is_vec ? &arg2 : &arg1;
- struct type *t = t1_is_vec ? type2 : type1;
- if (t->code () != TYPE_CODE_FLT && !is_integral_type (t))
- error (_("Argument to operation not a number or boolean."));
- *v = opencl_value_cast (t1_is_vec ? type1 : type2, *v);
- val = vector_relop (exp, arg1, arg2, op);
- }
- return val;
- }
- /* A helper function for BINOP_ASSIGN. */
- struct value *
- eval_opencl_assign (struct type *expect_type, struct expression *exp,
- enum noside noside, enum exp_opcode op,
- struct value *arg1, struct value *arg2)
- {
- if (noside == EVAL_AVOID_SIDE_EFFECTS)
- return arg1;
- struct type *type1 = value_type (arg1);
- if (deprecated_value_modifiable (arg1)
- && VALUE_LVAL (arg1) != lval_internalvar)
- arg2 = opencl_value_cast (type1, arg2);
- return value_assign (arg1, arg2);
- }
- namespace expr
- {
- value *
- opencl_structop_operation::evaluate (struct type *expect_type,
- struct expression *exp,
- enum noside noside)
- {
- value *arg1 = std::get<0> (m_storage)->evaluate (nullptr, exp, noside);
- struct type *type1 = check_typedef (value_type (arg1));
- if (type1->code () == TYPE_CODE_ARRAY && type1->is_vector ())
- return opencl_component_ref (exp, arg1, std::get<1> (m_storage).c_str (),
- noside);
- else
- {
- struct value *v = value_struct_elt (&arg1, {},
- std::get<1> (m_storage).c_str (),
- NULL, "structure");
- if (noside == EVAL_AVOID_SIDE_EFFECTS)
- v = value_zero (value_type (v), VALUE_LVAL (v));
- return v;
- }
- }
- value *
- opencl_logical_binop_operation::evaluate (struct type *expect_type,
- struct expression *exp,
- enum noside noside)
- {
- enum exp_opcode op = std::get<0> (m_storage);
- value *arg1 = std::get<1> (m_storage)->evaluate (nullptr, exp, noside);
- /* For scalar operations we need to avoid evaluating operands
- unnecessarily. However, for vector operations we always need to
- evaluate both operands. Unfortunately we only know which of the
- two cases apply after we know the type of the second operand.
- Therefore we evaluate it once using EVAL_AVOID_SIDE_EFFECTS. */
- value *arg2 = std::get<2> (m_storage)->evaluate (nullptr, exp,
- EVAL_AVOID_SIDE_EFFECTS);
- struct type *type1 = check_typedef (value_type (arg1));
- struct type *type2 = check_typedef (value_type (arg2));
- if ((type1->code () == TYPE_CODE_ARRAY && type1->is_vector ())
- || (type2->code () == TYPE_CODE_ARRAY && type2->is_vector ()))
- {
- arg2 = std::get<2> (m_storage)->evaluate (nullptr, exp, noside);
- return opencl_relop (nullptr, exp, noside, op, arg1, arg2);
- }
- else
- {
- /* For scalar built-in types, only evaluate the right
- hand operand if the left hand operand compares
- unequal(&&)/equal(||) to 0. */
- bool tmp = value_logical_not (arg1);
- if (op == BINOP_LOGICAL_OR)
- tmp = !tmp;
- if (!tmp)
- {
- arg2 = std::get<2> (m_storage)->evaluate (nullptr, exp, noside);
- tmp = value_logical_not (arg2);
- if (op == BINOP_LOGICAL_OR)
- tmp = !tmp;
- }
- type1 = language_bool_type (exp->language_defn, exp->gdbarch);
- return value_from_longest (type1, tmp);
- }
- }
- value *
- opencl_ternop_cond_operation::evaluate (struct type *expect_type,
- struct expression *exp,
- enum noside noside)
- {
- value *arg1 = std::get<0> (m_storage)->evaluate (nullptr, exp, noside);
- struct type *type1 = check_typedef (value_type (arg1));
- if (type1->code () == TYPE_CODE_ARRAY && type1->is_vector ())
- {
- struct value *arg2, *arg3, *tmp, *ret;
- struct type *eltype2, *type2, *type3, *eltype3;
- int t2_is_vec, t3_is_vec, i;
- LONGEST lowb1, lowb2, lowb3, highb1, highb2, highb3;
- arg2 = std::get<1> (m_storage)->evaluate (nullptr, exp, noside);
- arg3 = std::get<2> (m_storage)->evaluate (nullptr, exp, noside);
- type2 = check_typedef (value_type (arg2));
- type3 = check_typedef (value_type (arg3));
- t2_is_vec
- = type2->code () == TYPE_CODE_ARRAY && type2->is_vector ();
- t3_is_vec
- = type3->code () == TYPE_CODE_ARRAY && type3->is_vector ();
- /* Widen the scalar operand to a vector if necessary. */
- if (t2_is_vec || !t3_is_vec)
- {
- arg3 = opencl_value_cast (type2, arg3);
- type3 = value_type (arg3);
- }
- else if (!t2_is_vec || t3_is_vec)
- {
- arg2 = opencl_value_cast (type3, arg2);
- type2 = value_type (arg2);
- }
- else if (!t2_is_vec || !t3_is_vec)
- {
- /* Throw an error if arg2 or arg3 aren't vectors. */
- error (_("\
- Cannot perform conditional operation on incompatible types"));
- }
- eltype2 = check_typedef (TYPE_TARGET_TYPE (type2));
- eltype3 = check_typedef (TYPE_TARGET_TYPE (type3));
- if (!get_array_bounds (type1, &lowb1, &highb1)
- || !get_array_bounds (type2, &lowb2, &highb2)
- || !get_array_bounds (type3, &lowb3, &highb3))
- error (_("Could not determine the vector bounds"));
- /* Throw an error if the types of arg2 or arg3 are incompatible. */
- if (eltype2->code () != eltype3->code ()
- || TYPE_LENGTH (eltype2) != TYPE_LENGTH (eltype3)
- || eltype2->is_unsigned () != eltype3->is_unsigned ()
- || lowb2 != lowb3 || highb2 != highb3)
- error (_("\
- Cannot perform operation on vectors with different types"));
- /* Throw an error if the sizes of arg1 and arg2/arg3 differ. */
- if (lowb1 != lowb2 || lowb1 != lowb3
- || highb1 != highb2 || highb1 != highb3)
- error (_("\
- Cannot perform conditional operation on vectors with different sizes"));
- ret = allocate_value (type2);
- for (i = 0; i < highb1 - lowb1 + 1; i++)
- {
- tmp = value_logical_not (value_subscript (arg1, i)) ?
- value_subscript (arg3, i) : value_subscript (arg2, i);
- memcpy (value_contents_writeable (ret).data () +
- i * TYPE_LENGTH (eltype2), value_contents_all (tmp).data (),
- TYPE_LENGTH (eltype2));
- }
- return ret;
- }
- else
- {
- if (value_logical_not (arg1))
- return std::get<2> (m_storage)->evaluate (nullptr, exp, noside);
- else
- return std::get<1> (m_storage)->evaluate (nullptr, exp, noside);
- }
- }
- } /* namespace expr */
- /* Class representing the OpenCL language. */
- class opencl_language : public language_defn
- {
- public:
- opencl_language ()
- : language_defn (language_opencl)
- { /* Nothing. */ }
- /* See language.h. */
- const char *name () const override
- { return "opencl"; }
- /* See language.h. */
- const char *natural_name () const override
- { return "OpenCL C"; }
- /* See language.h. */
- void language_arch_info (struct gdbarch *gdbarch,
- struct language_arch_info *lai) const override
- {
- /* Helper function to allow shorter lines below. */
- auto add = [&] (struct type * t) -> struct type *
- {
- lai->add_primitive_type (t);
- return t;
- };
- /* 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, ELEMENT_TYPE) \
- do \
- { \
- struct type *tmp; \
- tmp = add (init_vector_type (ELEMENT_TYPE, 2)); \
- tmp->set_name (OCL_STRING(TYPE ## 2)); \
- tmp = add (init_vector_type (ELEMENT_TYPE, 3)); \
- tmp->set_name (OCL_STRING(TYPE ## 3)); \
- TYPE_LENGTH (tmp) = 4 * TYPE_LENGTH (ELEMENT_TYPE); \
- tmp = add (init_vector_type (ELEMENT_TYPE, 4)); \
- tmp->set_name (OCL_STRING(TYPE ## 4)); \
- tmp = add (init_vector_type (ELEMENT_TYPE, 8)); \
- tmp->set_name (OCL_STRING(TYPE ## 8)); \
- tmp = init_vector_type (ELEMENT_TYPE, 16); \
- tmp->set_name (OCL_STRING(TYPE ## 16)); \
- } \
- while (false)
- struct type *el_type, *char_type, *int_type;
- char_type = el_type = add (arch_integer_type (gdbarch, 8, 0, "char"));
- BUILD_OCL_VTYPES (char, el_type);
- el_type = add (arch_integer_type (gdbarch, 8, 1, "uchar"));
- BUILD_OCL_VTYPES (uchar, el_type);
- el_type = add (arch_integer_type (gdbarch, 16, 0, "short"));
- BUILD_OCL_VTYPES (short, el_type);
- el_type = add (arch_integer_type (gdbarch, 16, 1, "ushort"));
- BUILD_OCL_VTYPES (ushort, el_type);
- int_type = el_type = add (arch_integer_type (gdbarch, 32, 0, "int"));
- BUILD_OCL_VTYPES (int, el_type);
- el_type = add (arch_integer_type (gdbarch, 32, 1, "uint"));
- BUILD_OCL_VTYPES (uint, el_type);
- el_type = add (arch_integer_type (gdbarch, 64, 0, "long"));
- BUILD_OCL_VTYPES (long, el_type);
- el_type = add (arch_integer_type (gdbarch, 64, 1, "ulong"));
- BUILD_OCL_VTYPES (ulong, el_type);
- el_type = add (arch_float_type (gdbarch, 16, "half", floatformats_ieee_half));
- BUILD_OCL_VTYPES (half, el_type);
- el_type = add (arch_float_type (gdbarch, 32, "float", floatformats_ieee_single));
- BUILD_OCL_VTYPES (float, el_type);
- el_type = add (arch_float_type (gdbarch, 64, "double", floatformats_ieee_double));
- BUILD_OCL_VTYPES (double, el_type);
- add (arch_boolean_type (gdbarch, 8, 1, "bool"));
- add (arch_integer_type (gdbarch, 8, 1, "unsigned char"));
- add (arch_integer_type (gdbarch, 16, 1, "unsigned short"));
- add (arch_integer_type (gdbarch, 32, 1, "unsigned int"));
- add (arch_integer_type (gdbarch, 64, 1, "unsigned long"));
- add (arch_integer_type (gdbarch, gdbarch_ptr_bit (gdbarch), 1, "size_t"));
- add (arch_integer_type (gdbarch, gdbarch_ptr_bit (gdbarch), 0, "ptrdiff_t"));
- add (arch_integer_type (gdbarch, gdbarch_ptr_bit (gdbarch), 0, "intptr_t"));
- add (arch_integer_type (gdbarch, gdbarch_ptr_bit (gdbarch), 1, "uintptr_t"));
- add (arch_type (gdbarch, TYPE_CODE_VOID, TARGET_CHAR_BIT, "void"));
- /* Type of elements of strings. */
- lai->set_string_char_type (char_type);
- /* Specifies the return type of logical and relational operations. */
- lai->set_bool_type (int_type, "int");
- }
- /* See language.h. */
- void print_type (struct type *type, const char *varstring,
- struct ui_file *stream, int show, int level,
- const struct type_print_options *flags) const override
- {
- /* 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)
- {
- type = check_typedef (type);
- if (type->code () == TYPE_CODE_ARRAY && type->is_vector ()
- && type->name () != NULL)
- show = 0;
- }
- c_print_type (type, varstring, stream, show, level, flags);
- }
- /* See language.h. */
- enum macro_expansion macro_expansion () const override
- { return macro_expansion_c; }
- };
- /* Single instance of the OpenCL language class. */
- static opencl_language opencl_language_defn;
|