Re: [PATCH] Vector to scalar casting and widening

Andrew Burgess
2012-11-23T16:26:15Z

On 19/11/2012 9:16 PM, Tom Tromey wrote:
>>>>>> "Andrew" == Andrew Burgess <aburgess@broadcom.com> writes:
>
> Andrew> I'd like to change the way gdb handles scalar to vector
> Andrew> widening. I believe that the changes I propose will bring gdb
> Andrew> expression evaluation into line with how gcc handles these
> Andrew> things; this seems a good thing to me, but I'd be interested to
> Andrew> hear why anyone things we should stick with the current scheme.
>
> I agree that we should generally follow the compiler.
>
> In this case what I would suggest is looking up the original vector
> patches to gdb to see whether there is some rationale given for the
> chosen behavior.
>
> I'm in favor of this change unless that research turns up something; in
> which case we should probably discuss it more.

The original change that introduced the scalar to vector casting behaviour
was added in this mail chain:
http://sourceware.org/ml/gdb-patches/2010-09/msg00317.html
specifically,
http://sourceware.org/ml/gdb-patches/2010-10/msg00142.html

So it would seem that the current behaviour; first cast the scalar to the
vector element type, then replicate over each element of the vector was
picked to match OpenCL behaviour, see "6.2.2 Explicit Casts" in:
http://www.khronos.org/registry/cl/specs/opencl-1.2.pdf

I have to confess to no experience of OpenCL, so feel free to correct any
mistakes I make...

The current gdb behaviour has one case in valops.c:value_cast that
covers casting from scalar to vector.

In my original patch I have two cases in value_cast for,
1. Vector to vector cast where the sizes are different, this is
not allowed.
2. Scalar to vector cast where the sizes are different, this is
not allowed.

In order to maintain current opencl behaviour I've created a new patch,
this one has a flag on the language_defn structure to control how vector
casting functions. I reuse the vector widening code where appropriate.
The choices then are:
1. vector to vector cast
1.1 This is not allowed in OpenCL (see above pdf) so I throw an error.
1.2 This is only allowed for gcc/c vectors if they are the same size,
otherwise throw an error.
2. scalar to vector cast
2.1 For OpenCL, cast scalar to vector element type and replicate.
2.2 For gcc/c vectors, only allow if the scalar is the same size as
the vector.

For now I've defaulted all languages to match the opencl like behaviour as
this will keep things the most consistent, I don't know if this is important
as I don't know if it's possible to create vector types in other languages
or not.

I've tested the standard non-opencl side of things, but haven't been able
to figure out how to run the opencl tests (any pointers welcome), so I don't
know if I've broken any of those tests.

>
> Andrew> +static struct value *
> Andrew> +vector_widen (struct value *scalar_value, struct type *vector_type)
> Andrew> +{
> Andrew> + /* Widen the scalar to a vector. */
> Andrew> + struct type *eltype, *scalar_type;
> Andrew> + struct value *val, *elval;
> Andrew> + LONGEST low_bound, high_bound;
> Andrew> + int i;
> Andrew> +
> Andrew> + gdb_assert (TYPE_CODE (check_typedef (vector_type)) == TYPE_CODE_ARRAY);
> Andrew> + gdb_assert (TYPE_VECTOR (vector_type));
> Andrew> +
> Andrew> + if (!get_array_bounds (vector_type, &low_bound, &high_bound))
> Andrew> + error (_("Could not determine the vector bounds"));
> Andrew> +
> Andrew> + eltype = check_typedef (TYPE_TARGET_TYPE (vector_type));
> Andrew> + elval = value_cast (eltype, scalar_value);
>
> I think check_typedef is being applied inconsistently here.
> I'd suggest starting the function with a call to the macro:
>
> CHECK_TYPEDEF (vector_type);
>
> then you can drop check_typedef from the first assert.

Done.

>
> Andrew> + else if (code1 == TYPE_CODE_ARRAY && TYPE_VECTOR (type)
> Andrew> + && code2 == TYPE_CODE_ARRAY && TYPE_VECTOR (type2)
> Andrew> + && TYPE_LENGTH (type) != TYPE_LENGTH (type2))
> Andrew> + error (_("can't convert between vector values of different size"));
>
> I didn't see a test case for this error.
> Could you add one?

Done.

>
> Andrew> +++ b/gdb/testsuite/gdb.base/gnu_vector.c
> Andrew> @@ -31,6 +31,7 @@ int ia = 2;
> Andrew> int ib = 1;
> Andrew> float fa = 2;
> Andrew> float fb = 1;
> Andrew> +long long lla = 0x0000000100000001ll;
>
> Here I don't think we can assume that lla has a particular size, can we?
> But since this is a gcc-specific test, I think you can work around it by
> using the 'mode' attribute to pick a particular size.

Done.

>
> Andrew> +++ b/gdb/testsuite/gdb.python/py-type.c
> Andrew> @@ -15,6 +15,8 @@
> Andrew> You should have received a copy of the GNU General Public License
> Andrew> along with this program. If not, see <http://www.gnu.org/licenses/>. */
>
> Andrew> +#include <stdint.h>
>
> I'm mildly concerned that this will mean that we can't run this test on
> some platform. But only mildly, I'm inclined to let it go.

I've changed the test to avoid using this header file.

Cheers,
Andrew

gdb/ChangeLog

2012-11-23 Andrew Burgess <aburgess@broadcom.com>

Add language specific flag to control casting from scalar to
vector types. Allow scalar to vector widening during binary
operations on a scalar and a vector.
* valarith.c (vector_widen): New function for replicating a scalar
into a vector.
(value_binop): Use new function to convert scalar to vector rather
than value_cast.
* language.h (struct language_defn): Add new flag to control
behaviour of casting between scalar and vector types.
* valops.c (value_casst): Update logic for casting between vector
types, and for casting from scalar to vector including a check of
the new language flag.
* ada-lang.c (ada_language_defn): Initialise new flag.
* c-lang.c (c_language_defn): Initialise new flag.
(cplus_language_defn): Initialise new flag.
(asm_language_defn): Initialise new flag.
(minimal_language_defn): Initialise new flag.
* d-lang.c (d_language_defn): Initialise new flag.
* f-lang.c (f_language_defn): Initialise new flag.
* go-lang.c (go_language_defn): Initialise new flag.
* jv-lang.c (java_language_defn): Initialise new flag.
* language.c (unknown_language_defn): Initialise new flag.
(auto_language_defn): Initialise new flag.
(local_language_defn): Initialise new flag.
* m2-lang.c (m2_language_defn): Initialise new flag.
* objc-lang.c (objc_language_defn): Initialise new flag.
* opencl-lang.c (opencl_language_defn): Initialise new flag.
* p-lang.c (pascal_language_defn): Initialise new flag.

diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index e1dced5..75207b0 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -12616,6 +12616,7 @@ const struct language_defn ada_language_defn = {
class_name_from_physname */
ada_op_print_tab, /* expression operators for printing */
0, /* c-style arrays */
+ 1, /* scalar to vector casting strategy */
1, /* String lower bound */
ada_get_gdb_completer_word_break_characters,
ada_make_symbol_completion_list,
diff --git a/gdb/c-lang.c b/gdb/c-lang.c
index 84830be..91dd8c5 100644
--- a/gdb/c-lang.c
+++ b/gdb/c-lang.c
@@ -855,6 +855,7 @@ const struct language_defn c_language_defn =
class_name_from_physname */
c_op_print_tab, /* expression operators for printing */
1, /* c-style arrays */
+ 0, /* scalar to vector casting strategy */
0, /* String lower bound */
default_word_break_characters,
default_make_symbol_completion_list,
@@ -978,6 +979,7 @@ const struct language_defn cplus_language_defn =
class_name_from_physname */
c_op_print_tab, /* expression operators for printing */
1, /* c-style arrays */
+ 0, /* scalar to vector casting strategy */
0, /* String lower bound */
default_word_break_characters,
default_make_symbol_completion_list,
@@ -1019,6 +1021,7 @@ const struct language_defn asm_language_defn =
class_name_from_physname */
c_op_print_tab, /* expression operators for printing */
1, /* c-style arrays */
+ 0, /* scalar to vector casting strategy */
0, /* String lower bound */
default_word_break_characters,
default_make_symbol_completion_list,
@@ -1065,6 +1068,7 @@ const struct language_defn minimal_language_defn =
class_name_from_physname */
c_op_print_tab, /* expression operators for printing */
1, /* c-style arrays */
+ 0, /* scalar to vector casting strategy */
0, /* String lower bound */
default_word_break_characters,
default_make_symbol_completion_list,
diff --git a/gdb/d-lang.c b/gdb/d-lang.c
index 7b2c322..b7cb1b7 100644
--- a/gdb/d-lang.c
+++ b/gdb/d-lang.c
@@ -265,6 +265,7 @@ static const struct language_defn d_language_defn =
class_name_from_physname. */
d_op_print_tab, /* Expression operators for printing. */
1, /* C-style arrays. */
+ 1, /* scalar to vector casting strategy */
0, /* String lower bound. */
default_word_break_characters,
default_make_symbol_completion_list,
diff --git a/gdb/f-lang.c b/gdb/f-lang.c
index 0b3645f..4c01976 100644
--- a/gdb/f-lang.c
+++ b/gdb/f-lang.c
@@ -264,6 +264,7 @@ const struct language_defn f_language_defn =
class_name_from_physname */
f_op_print_tab, /* expression operators for printing */
0, /* arrays are first-class (not c-style) */
+ 1, /* scalar to vector casting strategy */
1, /* String lower bound */
f_word_break_characters,
f_make_symbol_completion_list,
diff --git a/gdb/go-lang.c b/gdb/go-lang.c
index 21f2427..194ee28 100644
--- a/gdb/go-lang.c
+++ b/gdb/go-lang.c
@@ -587,6 +587,7 @@ static const struct language_defn go_language_defn =
class_name_from_physname. */
go_op_print_tab, /* Expression operators for printing. */
1, /* C-style arrays. */
+ 1, /* scalar to vector casting strategy */
0, /* String lower bound. */
default_word_break_characters,
default_make_symbol_completion_list,
diff --git a/gdb/jv-lang.c b/gdb/jv-lang.c
index 6b865dc..fa193d2 100644
--- a/gdb/jv-lang.c
+++ b/gdb/jv-lang.c
@@ -1190,6 +1190,7 @@ const struct language_defn java_language_defn =
java_class_name_from_physname,/* Language specific class name */
java_op_print_tab, /* expression operators for printing */
0, /* not c-style arrays */
+ 1, /* scalar to vector casting strategy */
0, /* String lower bound */
default_word_break_characters,
default_make_symbol_completion_list,
diff --git a/gdb/language.c b/gdb/language.c
index 5693419..6c0298b 100644
--- a/gdb/language.c
+++ b/gdb/language.c
@@ -817,6 +817,7 @@ const struct language_defn unknown_language_defn =
class_name_from_physname */
unk_op_print_tab, /* expression operators for printing */
1, /* c-style arrays */
+ 0, /* scalar to vector casting strategy */
0, /* String lower bound */
default_word_break_characters,
default_make_symbol_completion_list,
@@ -860,6 +861,7 @@ const struct language_defn auto_language_defn =
class_name_from_physname */
unk_op_print_tab, /* expression operators for printing */
1, /* c-style arrays */
+ 0, /* scalar to vector casting strategy */
0, /* String lower bound */
default_word_break_characters,
default_make_symbol_completion_list,
@@ -901,6 +903,7 @@ const struct language_defn local_language_defn =
class_name_from_physname */
unk_op_print_tab, /* expression operators for printing */
1, /* c-style arrays */
+ 0, /* scalar to vector casting strategy */
0, /* String lower bound */
default_word_break_characters,
default_make_symbol_completion_list,
diff --git a/gdb/language.h b/gdb/language.h
index 3a1e390..01f3da4 100644
--- a/gdb/language.h
+++ b/gdb/language.h
@@ -276,6 +276,11 @@ struct language_defn

char c_style_arrays;

+ /* When casting from scalar to vector do we first cast scalar to
+ element type then replicate, or only allow casting when scalar and
+ vector of the same size, with no replication. */
+ char opencl_style_vector_casting;
+
/* Index to use for extracting the first element of a string. */
char string_lower_bound;

diff --git a/gdb/m2-lang.c b/gdb/m2-lang.c
index a87039c..0169035 100644
--- a/gdb/m2-lang.c
+++ b/gdb/m2-lang.c
@@ -394,6 +394,7 @@ const struct language_defn m2_language_defn =
class_name_from_physname */
m2_op_print_tab, /* expression operators for printing */
0, /* arrays are first-class (not c-style) */
+ 1, /* scalar to vector casting strategy */
0, /* String lower bound */
default_word_break_characters,
default_make_symbol_completion_list,
diff --git a/gdb/objc-lang.c b/gdb/objc-lang.c
index e42a03c..9fbb0a2 100644
--- a/gdb/objc-lang.c
+++ b/gdb/objc-lang.c
@@ -533,6 +533,7 @@ const struct language_defn objc_language_defn = {
class_name_from_physname */
objc_op_print_tab, /* Expression operators for printing */
1, /* C-style arrays */
+ 1, /* scalar to vector casting strategy */
0, /* String lower bound */
default_word_break_characters,
default_make_symbol_completion_list,
diff --git a/gdb/opencl-lang.c b/gdb/opencl-lang.c
index b8fd9b7..7702151 100644
--- a/gdb/opencl-lang.c
+++ b/gdb/opencl-lang.c
@@ -1017,6 +1017,7 @@ const struct language_defn opencl_language_defn =
class_name_from_physname */
c_op_print_tab, /* expression operators for printing */
1, /* c-style arrays */
+ 1, /* scalar to vector casting strategy */
0, /* String lower bound */
default_word_break_characters,
default_make_symbol_completion_list,
diff --git a/gdb/p-lang.c b/gdb/p-lang.c
index 114efbc..5e96049 100644
--- a/gdb/p-lang.c
+++ b/gdb/p-lang.c
@@ -452,6 +452,7 @@ const struct language_defn pascal_language_defn =
NULL, /* Language specific class_name_from_physname */
pascal_op_print_tab, /* expression operators for printing */
1, /* c-style arrays */
+ 1, /* scalar to vector casting strategy */
0, /* String lower bound */
default_word_break_characters,
default_make_symbol_completion_list,
diff --git a/gdb/valarith.c b/gdb/valarith.c
index c457f4a..afb45e2 100644
--- a/gdb/valarith.c
+++ b/gdb/valarith.c
@@ -1347,6 +1347,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. */

@@ -1426,7 +1469,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 502fb0d..7ade503 100644
--- a/gdb/valops.c
+++ b/gdb/valops.c
@@ -546,29 +546,33 @@ 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)
+ else if (code1 == TYPE_CODE_ARRAY && TYPE_VECTOR (type)
+ && code2 == TYPE_CODE_ARRAY && TYPE_VECTOR (type2)
+ && (current_language->opencl_style_vector_casting
+ || TYPE_LENGTH (type) != TYPE_LENGTH (type2)))
+ {
+ if (current_language->opencl_style_vector_casting)
+ error (_("Casting between vector types is not allowed"));
+ else
+ error (_("Cannot convert between vector values of different sizes"));
+ }
+ else if (code1 == TYPE_CODE_ARRAY && TYPE_VECTOR (type) && scalar
+ && current_language->opencl_style_vector_casting)
{
- /* 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"));
-
+
+ /* 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 (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;
+ return value_vector_widen (arg2, type);
}
+ else if (code1 == TYPE_CODE_ARRAY && TYPE_VECTOR (type) && scalar
+ && (!current_language->opencl_style_vector_casting
+ && TYPE_LENGTH (type) != TYPE_LENGTH (type2)))
+ error (_("can only cast scalar to vector of same size"));
else if (TYPE_LENGTH (type) == TYPE_LENGTH (type2))
{
if (code1 == TYPE_CODE_PTR && code2 == TYPE_CODE_PTR)
diff --git a/gdb/value.h b/gdb/value.h
index 3685935..f8438dc 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);
+
\f

#include "symtab.h"

gdb/testsuite/ChangeLog

2012-11-23 Andrew Burgess <aburgess@broadcom.com>

* 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.

diff --git a/gdb/testsuite/gdb.base/gnu_vector.c b/gdb/testsuite/gdb.base/gnu_vector.c
index a2a218f..07bc529 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 baba119..b6a1afb 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 bf39443..3412078 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 5009135..c3d0e1e 100644
--- a/gdb/testsuite/gdb.python/py-type.exp
+++ b/gdb/testsuite/gdb.python/py-type.exp
@@ -109,8 +109,8 @@ proc test_fields {lang} {
gdb_test "python print not not st.type\['a'\].type" "True"

# Test regression PR python/10805
- gdb_py_test_silent_cmd "print ar" "print value (ar)" 1
- gdb_py_test_silent_cmd "python ar = gdb.history (0)" "get value (ar) from history" 1
+ gdb_py_test_silent_cmd "print ar" "print value" 1
+ gdb_py_test_silent_cmd "python ar = gdb.history (0)" "get value from history" 1
gdb_test "python fields = ar.type.fields()"
gdb_test "python print len(fields)" "1" "Check the number of fields"
gdb_test "python print fields\[0\].type" "<range type>" "Check array field type"
@@ -119,22 +119,25 @@ proc test_fields {lang} {
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))" \
- ".1, 2." "cast to array with two arguments"
+ ".1, 2." "cast to array with two arguments"

gdb_test "python print ar\[0\].type == ar\[0\].type" "True"

# 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_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 = ar\[0\].cast(ar\[0\].type.vector(0, 1))" "set vec2" 1
+ 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 = ar\[1\].cast(ar\[1\].type.vector(1))" "set vec3" 1
+ 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"
}
}