aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog20
-rw-r--r--gdb/guile/scm-math.c20
-rw-r--r--gdb/guile/scm-value.c23
-rw-r--r--gdb/python/py-value.c10
-rw-r--r--gdb/target-float.c57
-rw-r--r--gdb/target-float.h5
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);