Target FP: Handle interfaces to scripting languages
authorUlrich Weigand <ulrich.weigand@de.ibm.com>
Mon, 6 Nov 2017 15:00:47 +0000 (16:00 +0100)
committerUlrich Weigand <ulrich.weigand@de.ibm.com>
Mon, 6 Nov 2017 15:00:47 +0000 (16:00 +0100)
The last remaing use for DOUBLEST is in the code that interfaces to the
scripting languages (Python and Guile).  The problem here is that we
expose interfaces to convert a GDB value to and from native values of
floating-point type in those languages, and those by definition use
the host floating-point format.

While we cannot completely eliminate conversions to/from the host
floating-point format here, we still need to get rid of the uses
of value_as_double / value_from_double, since those will go away.

This patch implements two new target-float.c routine:
 - target_float_to_host_double
 - target_float_from_host_double
which convert to/from a host "double".  Those should only ever be
used where a host "double" is mandated by an external interface.

gdb/ChangeLog:
2017-11-06  Ulrich Weigand  <uweigand@de.ibm.com>

* target-float.c (floatformat_to_host_double): New function.
(floatformat_from_host_double): Likewise.
(target_float_to_host_double): Likewise.
(target_float_from_host_double): Likewise.
* target-float.h (target_float_to_host_double): Add prototype.
(target_float_from_host_double): Likewise.

* guile/scm-value.c: Include "target-float.h".
(gdbscm_value_to_real): Use target_float_to_host_double.
Handle integer source values via value_as_long.
* guile/scm-math.c: Include "target-float.h".  Do not include
"doublest.h", "dfp.h", and "expression.h".
(vlscm_convert_typed_number): Use target_float_from_host_double.
(vlscm_convert_number): Likewise.

* python/py-value.c (valpy_float): Use target_float_to_host_double.
(convert_value_from_python): Use target_float_from_host_double.

gdb/ChangeLog
gdb/guile/scm-math.c
gdb/guile/scm-value.c
gdb/python/py-value.c
gdb/target-float.c
gdb/target-float.h

index ad8e0297610548d67d7720a9582739c43a37746c..8f0432aed104db215a039d2aeb310b7ec87bda62 100644 (file)
@@ -1,3 +1,23 @@
+2017-11-06  Ulrich Weigand  <uweigand@de.ibm.com>
+
+       * target-float.c (floatformat_to_host_double): New function.
+       (floatformat_from_host_double): Likewise.
+       (target_float_to_host_double): Likewise.
+       (target_float_from_host_double): Likewise.
+       * target-float.h (target_float_to_host_double): Add prototype.
+       (target_float_from_host_double): Likewise.
+
+       * guile/scm-value.c: Include "target-float.h".
+       (gdbscm_value_to_real): Use target_float_to_host_double.
+       Handle integer source values via value_as_long.
+       * guile/scm-math.c: Include "target-float.h".  Do not include
+       "doublest.h", "dfp.h", and "expression.h".
+       (vlscm_convert_typed_number): Use target_float_from_host_double.
+       (vlscm_convert_number): Likewise.
+
+       * python/py-value.c (valpy_float): Use target_float_to_host_double.
+       (convert_value_from_python): Use target_float_from_host_double.
+
 2017-11-06  Ulrich Weigand  <uweigand@de.ibm.com>
 
        * ada-lang.c (cast_to_fixed): Reimplement in target arithmetic.
index c4dfe71f54e41eb4da6aa83bb3753d239bd66ad2..ef27d6859d8b30de0ed1b877475d5259be35c152 100644 (file)
@@ -24,9 +24,7 @@
 #include "arch-utils.h"
 #include "charset.h"
 #include "cp-abi.h"
-#include "doublest.h" /* Needed by dfp.h.  */
-#include "expression.h" /* Needed by dfp.h.  */
-#include "dfp.h"
+#include "target-float.h"
 #include "symtab.h" /* Needed by language.h.  */
 #include "language.h"
 #include "valprint.h"
@@ -599,7 +597,13 @@ vlscm_convert_typed_number (const char *func_name, int obj_arg_pos, SCM obj,
        }
     }
   else if (TYPE_CODE (type) == TYPE_CODE_FLT)
-    return value_from_double (type, scm_to_double (obj));
+    {
+      struct value *value = allocate_value (type);
+      target_float_from_host_double (value_contents_raw (value),
+                                    value_type (value),
+                                    scm_to_double (obj));
+      return value;
+    }
   else
     {
       *except_scmp = gdbscm_make_type_error (func_name, obj_arg_pos, obj,
@@ -679,7 +683,13 @@ vlscm_convert_number (const char *func_name, int obj_arg_pos, SCM obj,
                                   gdbscm_scm_to_ulongest (obj));
     }
   else if (scm_is_real (obj))
-    return value_from_double (bt->builtin_double, scm_to_double (obj));
+    {
+      struct value *value = allocate_value (bt->builtin_double);
+      target_float_from_host_double (value_contents_raw (value),
+                                    value_type (value),
+                                    scm_to_double (obj));
+      return value;
+    }
 
   *except_scmp = gdbscm_make_out_of_range_error (func_name, obj_arg_pos, obj,
                        _("value not a number representable on the target"));
index 3732666a8897a64e9c9af6b1c46e0398f0b16971..0cf75472a1261f9f3f167ec197656c9e151030b0 100644 (file)
@@ -24,6 +24,7 @@
 #include "arch-utils.h"
 #include "charset.h"
 #include "cp-abi.h"
+#include "target-float.h"
 #include "infcall.h"
 #include "symtab.h" /* Needed by language.h.  */
 #include "language.h"
@@ -1019,7 +1020,8 @@ gdbscm_value_to_real (SCM self)
     = vlscm_get_value_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
   struct value *value = v_smob->value;
   struct type *type;
-  DOUBLEST d = 0;
+  double d = 0;
+  struct value *check = nullptr;
 
   type = value_type (value);
 
@@ -1038,7 +1040,22 @@ gdbscm_value_to_real (SCM self)
 
   TRY
     {
-      d = value_as_double (value);
+      if (is_floating_value (value))
+       {
+         d = target_float_to_host_double (value_contents (value), type);
+         check = allocate_value (type);
+         target_float_from_host_double (value_contents_raw (check), type, d);
+       }
+      else if (TYPE_UNSIGNED (type))
+       {
+         d = (ULONGEST) value_as_long (value);
+         check = value_from_ulongest (type, (ULONGEST) d);
+       }
+      else
+       {
+         d = value_as_long (value);
+         check = value_from_longest (type, (LONGEST) d);
+       }
     }
   CATCH (except, RETURN_MASK_ALL)
     {
@@ -1047,7 +1064,7 @@ gdbscm_value_to_real (SCM self)
   END_CATCH
 
   /* TODO: Is there a better way to check if the value fits?  */
-  if (d != (double) d)
+  if (!value_equal (value, check))
     gdbscm_out_of_range_error (FUNC_NAME, SCM_ARG1, self,
                               _("number can't be converted to a double"));
 
index 16c765094a090c37464f96242ba10bf70cd6b17d..11f1fc978f60b939cde52f07352a9056d15bd015 100644 (file)
@@ -1560,10 +1560,10 @@ valpy_float (PyObject *self)
     {
       type = check_typedef (type);
 
-      if (TYPE_CODE (type) != TYPE_CODE_FLT)
+      if (TYPE_CODE (type) != TYPE_CODE_FLT || !is_floating_value (value))
        error (_("Cannot convert value to float."));
 
-      d = value_as_double (value);
+      d = target_float_to_host_double (value_contents (value), type);
     }
   CATCH (except, RETURN_MASK_ALL)
     {
@@ -1681,7 +1681,11 @@ convert_value_from_python (PyObject *obj)
          double d = PyFloat_AsDouble (obj);
 
          if (! PyErr_Occurred ())
-           value = value_from_double (builtin_type_pyfloat, d);
+           {
+             value = allocate_value (builtin_type_pyfloat);
+             target_float_from_host_double (value_contents_raw (value),
+                                            value_type (value), d);
+           }
        }
       else if (gdbpy_is_string (obj))
        {
index ad04f8fb4a195f77572ba2702f6868d3451be11f..d2c1064bb3acd2537def1a2b3c25cb46f4a171a6 100644 (file)
@@ -59,6 +59,27 @@ floatformat_from_ulongest (const struct floatformat *fmt, gdb_byte *addr,
   floatformat_from_doublest (fmt, &d, addr);
 }
 
+/* Convert the byte-stream ADDR, interpreted as floating-point format FMT,
+   to a floating-point value in the host "double" format.  */
+static double
+floatformat_to_host_double (const struct floatformat *fmt,
+                           const gdb_byte *addr)
+{
+  DOUBLEST d;
+  floatformat_to_doublest (fmt, addr, &d);
+  return (double) d;
+}
+
+/* Convert floating-point value VAL in the host "double" format to a target
+   floating-number of format FMT and store it as byte-stream ADDR.  */
+static void
+floatformat_from_host_double (const struct floatformat *fmt, gdb_byte *addr,
+                             double val)
+{
+  DOUBLEST d = (DOUBLEST) val;
+  floatformat_from_doublest (fmt, &d, addr);
+}
+
 /* Convert a floating-point number of format FROM_FMT from the target
    byte-stream FROM to a floating-point number of format TO_FMT, and
    store it to the target byte-stream TO.  */
@@ -299,6 +320,42 @@ target_float_from_ulongest (gdb_byte *addr, const struct type *type,
   gdb_assert_not_reached ("unexpected type code");
 }
 
+/* Convert the byte-stream ADDR, interpreted as floating-point type TYPE,
+   to a floating-point value in the host "double" format.  */
+double
+target_float_to_host_double (const gdb_byte *addr,
+                            const struct type *type)
+{
+  if (TYPE_CODE (type) == TYPE_CODE_FLT)
+    return floatformat_to_host_double (floatformat_from_type (type), addr);
+
+  /* We don't support conversions between target decimal floating-point
+     types and the host double type here.  */
+
+  gdb_assert_not_reached ("unexpected type code");
+}
+
+/* Convert floating-point value VAL in the host "double" format to a target
+   floating-number of type TYPE and store it as byte-stream ADDR.  */
+void
+target_float_from_host_double (gdb_byte *addr, const struct type *type,
+                              double val)
+{
+  /* Ensure possible padding bytes in the target buffer are zeroed out.  */
+  memset (addr, 0, TYPE_LENGTH (type));
+
+  if (TYPE_CODE (type) == TYPE_CODE_FLT)
+    {
+      floatformat_from_host_double (floatformat_from_type (type), addr, val);
+      return;
+    }
+
+  /* We don't support conversions between target decimal floating-point
+     types and the host double type here.  */
+
+  gdb_assert_not_reached ("unexpected type code");
+}
+
 /* Convert a floating-point number of type FROM_TYPE from the target
    byte-stream FROM to a floating-point number of type TO_TYPE, and
    store it to the target byte-stream TO.  */
index 466dd1b5c854d4c8ac93fa649a5fe7a12273c0bf..4ac88efb261f9696c086e878d4d15df3e8749125 100644 (file)
@@ -42,6 +42,11 @@ extern void target_float_from_longest (gdb_byte *addr,
 extern void target_float_from_ulongest (gdb_byte *addr,
                                        const struct type *type,
                                        ULONGEST val);
+extern double target_float_to_host_double (const gdb_byte *addr,
+                                          const struct type *type);
+extern void target_float_from_host_double (gdb_byte *addr,
+                                          const struct type *type,
+                                          double val);
 extern void target_float_convert (const gdb_byte *from,
                                  const struct type *from_type,
                                  gdb_byte *to, const struct type *to_type);