Target FP: Handle interfaces to scripting languages

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.
This commit is contained in:
Ulrich Weigand 2017-11-06 16:00:47 +01:00
parent 50eff16b85
commit 14ad931172
6 changed files with 124 additions and 11 deletions

View 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> 2017-11-06 Ulrich Weigand <uweigand@de.ibm.com>
* ada-lang.c (cast_to_fixed): Reimplement in target arithmetic. * ada-lang.c (cast_to_fixed): Reimplement in target arithmetic.

View file

@ -24,9 +24,7 @@
#include "arch-utils.h" #include "arch-utils.h"
#include "charset.h" #include "charset.h"
#include "cp-abi.h" #include "cp-abi.h"
#include "doublest.h" /* Needed by dfp.h. */ #include "target-float.h"
#include "expression.h" /* Needed by dfp.h. */
#include "dfp.h"
#include "symtab.h" /* Needed by language.h. */ #include "symtab.h" /* Needed by language.h. */
#include "language.h" #include "language.h"
#include "valprint.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) 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 else
{ {
*except_scmp = gdbscm_make_type_error (func_name, obj_arg_pos, obj, *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)); gdbscm_scm_to_ulongest (obj));
} }
else if (scm_is_real (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, *except_scmp = gdbscm_make_out_of_range_error (func_name, obj_arg_pos, obj,
_("value not a number representable on the target")); _("value not a number representable on the target"));

View file

@ -24,6 +24,7 @@
#include "arch-utils.h" #include "arch-utils.h"
#include "charset.h" #include "charset.h"
#include "cp-abi.h" #include "cp-abi.h"
#include "target-float.h"
#include "infcall.h" #include "infcall.h"
#include "symtab.h" /* Needed by language.h. */ #include "symtab.h" /* Needed by language.h. */
#include "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); = vlscm_get_value_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
struct value *value = v_smob->value; struct value *value = v_smob->value;
struct type *type; struct type *type;
DOUBLEST d = 0; double d = 0;
struct value *check = nullptr;
type = value_type (value); type = value_type (value);
@ -1038,7 +1040,22 @@ gdbscm_value_to_real (SCM self)
TRY 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) CATCH (except, RETURN_MASK_ALL)
{ {
@ -1047,7 +1064,7 @@ gdbscm_value_to_real (SCM self)
END_CATCH END_CATCH
/* TODO: Is there a better way to check if the value fits? */ /* 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, gdbscm_out_of_range_error (FUNC_NAME, SCM_ARG1, self,
_("number can't be converted to a double")); _("number can't be converted to a double"));

View file

@ -1560,10 +1560,10 @@ valpy_float (PyObject *self)
{ {
type = check_typedef (type); 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.")); 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) CATCH (except, RETURN_MASK_ALL)
{ {
@ -1681,7 +1681,11 @@ convert_value_from_python (PyObject *obj)
double d = PyFloat_AsDouble (obj); double d = PyFloat_AsDouble (obj);
if (! PyErr_Occurred ()) 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)) else if (gdbpy_is_string (obj))
{ {

View file

@ -59,6 +59,27 @@ floatformat_from_ulongest (const struct floatformat *fmt, gdb_byte *addr,
floatformat_from_doublest (fmt, &d, 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 /* 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 byte-stream FROM to a floating-point number of format TO_FMT, and
store it to the target byte-stream TO. */ 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"); 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 /* 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 byte-stream FROM to a floating-point number of type TO_TYPE, and
store it to the target byte-stream TO. */ store it to the target byte-stream TO. */

View file

@ -42,6 +42,11 @@ extern void target_float_from_longest (gdb_byte *addr,
extern void target_float_from_ulongest (gdb_byte *addr, extern void target_float_from_ulongest (gdb_byte *addr,
const struct type *type, const struct type *type,
ULONGEST val); 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, extern void target_float_convert (const gdb_byte *from,
const struct type *from_type, const struct type *from_type,
gdb_byte *to, const struct type *to_type); gdb_byte *to, const struct type *to_type);