This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch] Scalar to vector widening


Hi,

This patch adds support for widening scalars to vectors to allow binary 
operations with mixed operand types. It mainly extends the binop_promote 
function to call widen_scalar_to_vector if required. No regressions on i686-*-
linux-gnu.

Regards
Ken Werner
ChangeLog:

2010-09-17  Ken Werner  <ken.werner@de.ibm.com>

	* value.h (widen_scalar_to_vector): Declare.
	* valops.c (widen_scalar_to_vector): New function.
	(value_assign): Add call to widen_scalar_to_vector.
	* eval.c (binop_promote, evaluate_subexp_standard)
	<BINOP_ASSIGN_MODIFY, BINOP_LSH, BINOP_RSH>: Likewise.

testsuite/ChangeLog:

2010-09-17  Ken Werner  <ken.werner@de.ibm.com>

	* gdb.base/gnu_vector.c (ia, ib, fa, fb): New variables.
	* gdb.base/gnu_vector.exp: Add tests for scalar to vector widening.

Index: gdb/eval.c
===================================================================
RCS file: /cvs/src/src/gdb/eval.c,v
retrieving revision 1.139
diff -p -u -r1.139 eval.c
--- gdb/eval.c	11 Aug 2010 16:48:26 -0000	1.139
+++ gdb/eval.c	17 Sep 2010 10:56:28 -0000
@@ -574,6 +574,7 @@ binop_promote (const struct language_def
   struct type *promoted_type = NULL;
   struct type *type1;
   struct type *type2;
+  int t1_is_vec, t2_is_vec;
 
   *arg1 = coerce_ref (*arg1);
   *arg2 = coerce_ref (*arg2);
@@ -581,15 +582,26 @@ binop_promote (const struct language_def
   type1 = check_typedef (value_type (*arg1));
   type2 = check_typedef (value_type (*arg2));
 
-  if ((TYPE_CODE (type1) != TYPE_CODE_FLT
-       && TYPE_CODE (type1) != TYPE_CODE_DECFLOAT
-       && !is_integral_type (type1))
-      || (TYPE_CODE (type2) != TYPE_CODE_FLT
-	  && TYPE_CODE (type2) != TYPE_CODE_DECFLOAT
-	  && !is_integral_type (type2)))
+  t1_is_vec = (TYPE_CODE (type1) == TYPE_CODE_ARRAY && TYPE_VECTOR (type1));
+  t2_is_vec = (TYPE_CODE (type2) == TYPE_CODE_ARRAY && TYPE_VECTOR (type2));
+
+  if (((TYPE_CODE (type1) != TYPE_CODE_FLT
+	&& TYPE_CODE (type1) != TYPE_CODE_DECFLOAT
+	&& !is_integral_type (type1))
+       || (TYPE_CODE (type2) != TYPE_CODE_FLT
+	   && TYPE_CODE (type2) != TYPE_CODE_DECFLOAT
+	   && !is_integral_type (type2)))
+      && t1_is_vec == t2_is_vec)
     return;
 
-  if (TYPE_CODE (type1) == TYPE_CODE_DECFLOAT
+  if (t1_is_vec != t2_is_vec)
+    {
+      /* Wide the scalar operand to vector.  */
+      struct value **v = t1_is_vec ? arg2 : arg1;
+      struct type *t = t1_is_vec ? type1 : type2;
+      *v = widen_scalar_to_vector (t, *v);
+    }
+  else if (TYPE_CODE (type1) == TYPE_CODE_DECFLOAT
       || TYPE_CODE (type2) == TYPE_CODE_DECFLOAT)
     {
       /* No promotion required.  */
@@ -2035,8 +2047,13 @@ evaluate_subexp_standard (struct type *e
 
 	  /* For shift and integer exponentiation operations,
 	     only promote the first argument.  */
-	  if ((op == BINOP_LSH || op == BINOP_RSH || op == BINOP_EXP)
-	      && is_integral_type (value_type (arg2)))
+	  if (op == BINOP_LSH || op == BINOP_RSH)
+	    {
+	      arg2 = widen_scalar_to_vector (check_typedef (value_type (arg1)),
+					     arg2);
+	      unop_promote (exp->language_defn, exp->gdbarch, &tmp);
+	    }
+	  else if (op == BINOP_EXP && is_integral_type (value_type (arg2)))
 	    unop_promote (exp->language_defn, exp->gdbarch, &tmp);
 	  else
 	    binop_promote (exp->language_defn, exp->gdbarch, &tmp, &arg2);
@@ -2130,8 +2147,14 @@ evaluate_subexp_standard (struct type *e
 	    {
 	      /* For shift and integer exponentiation operations,
 		 only promote the first argument.  */
-	      if ((op == BINOP_LSH || op == BINOP_RSH || op == BINOP_EXP)
-		  && is_integral_type (value_type (arg2)))
+	      if (op == BINOP_LSH || op == BINOP_RSH)
+		{
+		  arg2 =
+		    widen_scalar_to_vector (check_typedef (value_type (arg1)),
+					    arg2);
+		  unop_promote (exp->language_defn, exp->gdbarch, &arg1);
+		}
+	      else if (op == BINOP_EXP && is_integral_type (value_type (arg2)))
 		unop_promote (exp->language_defn, exp->gdbarch, &arg1);
 	      else
 		binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2);
Index: gdb/valops.c
===================================================================
RCS file: /cvs/src/src/gdb/valops.c,v
retrieving revision 1.249
diff -p -u -r1.249 valops.c
--- gdb/valops.c	14 Jul 2010 14:54:58 -0000	1.249
+++ gdb/valops.c	17 Sep 2010 10:56:29 -0000
@@ -1079,7 +1079,15 @@ value_assign (struct value *toval, struc
 
   type = value_type (toval);
   if (VALUE_LVAL (toval) != lval_internalvar)
-    fromval = value_cast (type, fromval);
+    {
+      struct type *fromtype = check_typedef (value_type (fromval));
+      struct type *totype = check_typedef (type);
+      if (!(TYPE_CODE (fromtype) == TYPE_CODE_ARRAY && TYPE_VECTOR (fromtype))
+	  && (TYPE_CODE (totype) == TYPE_CODE_ARRAY && TYPE_VECTOR (totype)))
+	fromval = widen_scalar_to_vector (type, fromval);
+      else
+	fromval = value_cast (type, fromval);
+    }
   else
     {
       /* Coerce arrays and functions to pointers, except for arrays
@@ -3607,6 +3615,37 @@ cast_into_complex (struct type *type, st
     error (_("cannot cast non-number to complex"));
 }
 
+/* Widens the scalar val to a vector of type dst_type.  */
+
+struct value *
+widen_scalar_to_vector (struct type *dst_type, struct value *val)
+{
+  struct type *val_type, *eltype;
+  struct value *ret;
+  int i, n;
+
+  val_type = check_typedef (value_type (val));
+
+  if ((TYPE_CODE (val_type) == TYPE_CODE_ARRAY && TYPE_VECTOR (val_type))
+      || !(TYPE_CODE (dst_type) == TYPE_CODE_ARRAY && TYPE_VECTOR (dst_type)))
+    return val;
+
+  eltype = check_typedef (TYPE_TARGET_TYPE (dst_type));
+  val = value_cast (eltype, val);
+
+  ret = allocate_value (dst_type);
+
+  n = TYPE_LENGTH (dst_type) / TYPE_LENGTH (eltype);
+  for (i = 0; i < n; i++)
+    {
+      /* Duplicate the contents of val into the destination vector.  */
+      memcpy (value_contents_writeable (ret) + (i * TYPE_LENGTH (eltype)),
+	      value_contents_all (val),
+	      TYPE_LENGTH (eltype));
+    }
+  return ret;
+}
+
 void
 _initialize_valops (void)
 {
Index: gdb/value.h
===================================================================
RCS file: /cvs/src/src/gdb/value.h,v
retrieving revision 1.161
diff -p -u -r1.161 value.h
--- gdb/value.h	7 Jul 2010 16:15:18 -0000	1.161
+++ gdb/value.h	17 Sep 2010 10:56:29 -0000
@@ -721,6 +721,9 @@ extern struct value *value_slice (struct
 extern struct value *value_literal_complex (struct value *, struct value *,
 					    struct type *);
 
+extern struct value *widen_scalar_to_vector (struct type *dst_type,
+					     struct value *val);
+
 extern struct value *find_function_in_inferior (const char *,
 						struct objfile **);
 
Index: gdb/testsuite/gdb.base/gnu_vector.c
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.base/gnu_vector.c,v
retrieving revision 1.1
diff -p -u -r1.1 gnu_vector.c
--- gdb/testsuite/gdb.base/gnu_vector.c	11 Aug 2010 16:48:26 -0000	1.1
+++ gdb/testsuite/gdb.base/gnu_vector.c	17 Sep 2010 10:56:29 -0000
@@ -17,10 +17,16 @@
 
    Contributed by Ken Werner <ken.werner@de.ibm.com>  */
 
+int ia = 2;
+int ib = 1;
 int __attribute__ ((vector_size (4 * sizeof(int)))) i4a = {2, 4, 8, 16};
 int __attribute__ ((vector_size (4 * sizeof(int)))) i4b = {1, 2, 8, 4};
+
+float fa = 2;
+float fb = 1;
 float __attribute__ ((vector_size (4 * sizeof(float)))) f4a = {2, 4, 8, 16};
 float __attribute__ ((vector_size (4 * sizeof(float)))) f4b = {1, 2, 8, 4};
+
 unsigned int __attribute__ ((vector_size (4 * sizeof(unsigned int)))) ui4 = {2, 4, 8, 16};
 int __attribute__ ((vector_size (2 * sizeof(int)))) i2 = {1, 2};
 long long __attribute__ ((vector_size (2 * sizeof(long long)))) ll2 = {1, 2};
Index: gdb/testsuite/gdb.base/gnu_vector.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.base/gnu_vector.exp,v
retrieving revision 1.1
diff -p -u -r1.1 gnu_vector.exp
--- gdb/testsuite/gdb.base/gnu_vector.exp	11 Aug 2010 16:48:26 -0000	1.1
+++ gdb/testsuite/gdb.base/gnu_vector.exp	17 Sep 2010 10:56:29 -0000
@@ -72,9 +72,28 @@ gdb_test "print f4a - f4b" "\\\$$decimal
 gdb_test "print f4a * f4b" "\\\$$decimal = \\{2, 8, 64, 64\\}"
 gdb_test "print f4a / f4b" "\\\$$decimal = \\{2, 2, 1, 4\\}"
 
-# Test error conditions
-gdb_test "print i4a + 1" "Vector operations are only supported among vectors"
-gdb_test "print 1 + f4a" "Vector operations are only supported among vectors"
+# Test scalar to vector widening
+gdb_test "print i4a + ib" "\\\$$decimal = \\{3, 5, 9, 17\\}"
+gdb_test "print fa - f4b" "\\\$$decimal = \\{1, 0, -6, -2\\}"
+gdb_test "print f4a * fb" "\\\$$decimal = \\{2, 4, 8, 16\\}"
+gdb_test "print ia / i4b" "\\\$$decimal = \\{2, 1, 0, 0\\}"
+gdb_test "print i4a % ib" "\\\$$decimal = \\{0, 0, 0, 0\\}"
+
+gdb_test "print ia & i4b" "\\\$$decimal = \\{0, 2, 0, 0\\}"
+gdb_test "print i4a | ib" "\\\$$decimal = \\{3, 5, 9, 17\\}"
+gdb_test "print ia ^ i4b" "\\\$$decimal = \\{3, 0, 10, 6\\}"
+gdb_test "print i4a << ib" "\\\$$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 = \{2, 4, 8, 16\}" "\\\$$decimal = \\{2, 4, 8, 16\\}"
+gdb_test "print i4a <<= ib" "\\\$$decimal = \\{4, 8, 16, 32\\}"
+
+# Test some error scenarios
 gdb_test "print i4a + d2" "Cannot perform operation on vectors with different types"
 gdb_test "print d2 + i4a" "Cannot perform operation on vectors with different types"
 gdb_test "print f4a + ll2" "Cannot perform operation on vectors with different types"

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]