diff options
-rw-r--r-- | gdb/ChangeLog | 20 | ||||
-rw-r--r-- | gdb/guile/scm-math.c | 20 | ||||
-rw-r--r-- | gdb/guile/scm-value.c | 23 | ||||
-rw-r--r-- | gdb/python/py-value.c | 10 | ||||
-rw-r--r-- | gdb/target-float.c | 57 | ||||
-rw-r--r-- | gdb/target-float.h | 5 |
6 files changed, 124 insertions, 11 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index ad8e029..8f0432a 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,25 @@ 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. (cast_from_fixed): Likewise. (ada_scaling_type): New function. diff --git a/gdb/guile/scm-math.c b/gdb/guile/scm-math.c index c4dfe71..ef27d68 100644 --- a/gdb/guile/scm-math.c +++ b/gdb/guile/scm-math.c @@ -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")); diff --git a/gdb/guile/scm-value.c b/gdb/guile/scm-value.c index 3732666..0cf7547 100644 --- a/gdb/guile/scm-value.c +++ b/gdb/guile/scm-value.c @@ -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")); diff --git a/gdb/python/py-value.c b/gdb/python/py-value.c index 16c7650..11f1fc9 100644 --- a/gdb/python/py-value.c +++ b/gdb/python/py-value.c @@ -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)) { diff --git a/gdb/target-float.c b/gdb/target-float.c index ad04f8f..d2c1064 100644 --- a/gdb/target-float.c +++ b/gdb/target-float.c @@ -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. */ diff --git a/gdb/target-float.h b/gdb/target-float.h index 466dd1b..4ac88ef 100644 --- a/gdb/target-float.h +++ b/gdb/target-float.h @@ -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); |