Target FP: Introduce target-float.{c,h}
This patch introduces the new set of target floating-point handling routines in target-float.{c,h}. In the end, the intention is that this file will contain support for all operations in target FP format, fully replacing both the current doublest.{c,h} and dfp.{c,h}. To begin with, this patch only adds a target_float_is_zero routine, which handles the equivalent of decimal_is_zero for both binary and decimal FP. For the binary case, to avoid conversion to DOUBLEST, this is implemented using the floatformat_classify routine. However, it turns out that floatformat_classify actually has a bug (it was not used to check for zero before), so this is fixed as well. The new routine is used in both value_logical_not and valpy_nonzero. There is one extra twist: the code previously used value_as_double to convert to DOUBLEST and then compare against zero. That routine performs an extra task: it detects invalid floating-point values and raises an error. In any place where value_as_double is removed in favor of some target-float.c routine, we need to replace that check. To keep this check centralized in one place, I've added a new routine is_floating_value, which returns a boolean determining whether a value's type is floating point (binary or decimal), and if so, also performs the validity check. Since we need to check whether a value is FP before calling any of the target-float routines anyway, this seems a good place to add the check without much code size overhead. In some places where we only want to check for floating-point types and not perform a validity check (e.g. for the *output* of an operation), we can use the new is_floating_type routine (in gdbarch) instead. The validity check itself is done by a new target_float_is_valid routine in target-float, encapsulating floatformat_is_valid. ChangeLog: 2017-11-06 Ulrich Weigand <uweigand@de.ibm.com> * Makefile.c (SFILES): Add target-float.c. (HFILES_NO_SRCDIR): Add target-float.h. (COMMON_OBS): Add target-float.o. * target-float.h: New file. * target-float.c: New file. * doublest.c (floatformat_classify): Fix detection of float_zero. * gdbtypes.c (is_floating_type): New function. * gdbtypes.h (is_floating_type): Add prototype. * value.c: Do not include "floatformat.h". (unpack_double): Use target_float_is_valid. (is_floating_value): New function. * value.h (is_floating_value): Add prototype- * valarith.c: Include "target-float.h". (value_logical_not): Use target_float_is_zero. * python/py-value.c: Include "target-float.h". (valpy_nonzero): Use target_float_is_zero.
This commit is contained in:
parent
74be0bdc3b
commit
701000146a
|
@ -1,3 +1,27 @@
|
|||
2017-11-06 Ulrich Weigand <uweigand@de.ibm.com>
|
||||
|
||||
* Makefile.c (SFILES): Add target-float.c.
|
||||
(HFILES_NO_SRCDIR): Add target-float.h.
|
||||
(COMMON_OBS): Add target-float.o.
|
||||
* target-float.h: New file.
|
||||
* target-float.c: New file.
|
||||
|
||||
* doublest.c (floatformat_classify): Fix detection of float_zero.
|
||||
|
||||
* gdbtypes.c (is_floating_type): New function.
|
||||
* gdbtypes.h (is_floating_type): Add prototype.
|
||||
|
||||
* value.c: Do not include "floatformat.h".
|
||||
(unpack_double): Use target_float_is_valid.
|
||||
(is_floating_value): New function.
|
||||
* value.h (is_floating_value): Add prototype-
|
||||
|
||||
* valarith.c: Include "target-float.h".
|
||||
(value_logical_not): Use target_float_is_zero.
|
||||
|
||||
* python/py-value.c: Include "target-float.h".
|
||||
(valpy_nonzero): Use target_float_is_zero.
|
||||
|
||||
2017-11-04 Tom Tromey <tom@tromey.com>
|
||||
|
||||
* h8300-tdep.c (h8300_push_dummy_call): Use std::vector.
|
||||
|
|
|
@ -1224,6 +1224,7 @@ SFILES = \
|
|||
tracepoint.c \
|
||||
trad-frame.c \
|
||||
tramp-frame.c \
|
||||
target-float.c \
|
||||
typeprint.c \
|
||||
ui-file.c \
|
||||
ui-file.h \
|
||||
|
@ -1492,6 +1493,7 @@ HFILES_NO_SRCDIR = \
|
|||
tracefile.h \
|
||||
tracepoint.h \
|
||||
trad-frame.h \
|
||||
target-float.h \
|
||||
tramp-frame.h \
|
||||
typeprint.h \
|
||||
ui-file.h \
|
||||
|
@ -1845,6 +1847,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
|
|||
top.o \
|
||||
trad-frame.o \
|
||||
tramp-frame.o \
|
||||
target-float.o \
|
||||
typeprint.o \
|
||||
ui-file.o \
|
||||
ui-out.o \
|
||||
|
|
|
@ -594,8 +594,13 @@ floatformat_classify (const struct floatformat *fmt,
|
|||
return float_normal;
|
||||
}
|
||||
|
||||
if (exponent == 0 && !mant_zero)
|
||||
return float_subnormal;
|
||||
if (exponent == 0)
|
||||
{
|
||||
if (mant_zero)
|
||||
return float_zero;
|
||||
else
|
||||
return float_subnormal;
|
||||
}
|
||||
|
||||
if (exponent == fmt->exp_nan)
|
||||
{
|
||||
|
@ -605,9 +610,6 @@ floatformat_classify (const struct floatformat *fmt,
|
|||
return float_nan;
|
||||
}
|
||||
|
||||
if (mant_zero)
|
||||
return float_zero;
|
||||
|
||||
return float_normal;
|
||||
}
|
||||
|
||||
|
|
|
@ -2935,6 +2935,16 @@ is_integral_type (struct type *t)
|
|||
|| (TYPE_CODE (t) == TYPE_CODE_BOOL)));
|
||||
}
|
||||
|
||||
int
|
||||
is_floating_type (struct type *t)
|
||||
{
|
||||
t = check_typedef (t);
|
||||
return
|
||||
((t != NULL)
|
||||
&& ((TYPE_CODE (t) == TYPE_CODE_FLT)
|
||||
|| (TYPE_CODE (t) == TYPE_CODE_DECFLOAT)));
|
||||
}
|
||||
|
||||
/* Return true if TYPE is scalar. */
|
||||
|
||||
int
|
||||
|
|
|
@ -1938,6 +1938,8 @@ extern int can_dereference (struct type *);
|
|||
|
||||
extern int is_integral_type (struct type *);
|
||||
|
||||
extern int is_floating_type (struct type *);
|
||||
|
||||
extern int is_scalar_type (struct type *type);
|
||||
|
||||
extern int is_scalar_type_recursive (struct type *);
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
#include "charset.h"
|
||||
#include "value.h"
|
||||
#include "language.h"
|
||||
#include "dfp.h"
|
||||
#include "target-float.h"
|
||||
#include "valprint.h"
|
||||
#include "infcall.h"
|
||||
#include "expression.h"
|
||||
|
@ -1317,12 +1317,9 @@ valpy_nonzero (PyObject *self)
|
|||
|
||||
if (is_integral_type (type) || TYPE_CODE (type) == TYPE_CODE_PTR)
|
||||
nonzero = !!value_as_long (self_value->value);
|
||||
else if (TYPE_CODE (type) == TYPE_CODE_FLT)
|
||||
nonzero = value_as_double (self_value->value) != 0;
|
||||
else if (TYPE_CODE (type) == TYPE_CODE_DECFLOAT)
|
||||
nonzero = !decimal_is_zero (value_contents (self_value->value),
|
||||
TYPE_LENGTH (type),
|
||||
gdbarch_byte_order (get_type_arch (type)));
|
||||
else if (is_floating_value (self_value->value))
|
||||
nonzero = !target_float_is_zero (value_contents (self_value->value),
|
||||
type);
|
||||
else
|
||||
/* All other values are True. */
|
||||
nonzero = 1;
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
/* Floating point routines for GDB, the GNU debugger.
|
||||
|
||||
Copyright (C) 2017 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "dfp.h"
|
||||
#include "doublest.h"
|
||||
#include "gdbtypes.h"
|
||||
#include "floatformat.h"
|
||||
#include "target-float.h"
|
||||
|
||||
|
||||
/* Typed floating-point routines. These routines operate on floating-point
|
||||
values in target format, represented by a byte buffer interpreted as a
|
||||
"struct type", which may be either a binary or decimal floating-point
|
||||
type (TYPE_CODE_FLT or TYPE_CODE_DECFLOAT). */
|
||||
|
||||
/* Return whether the byte-stream ADDR holds a valid value of
|
||||
floating-point type TYPE. */
|
||||
bool
|
||||
target_float_is_valid (const gdb_byte *addr, const struct type *type)
|
||||
{
|
||||
if (TYPE_CODE (type) == TYPE_CODE_FLT)
|
||||
return floatformat_is_valid (floatformat_from_type (type), addr);
|
||||
|
||||
if (TYPE_CODE (type) == TYPE_CODE_DECFLOAT)
|
||||
return true;
|
||||
|
||||
gdb_assert_not_reached ("unexpected type code");
|
||||
}
|
||||
|
||||
/* Return whether the byte-stream ADDR, interpreted as floating-point
|
||||
type TYPE, is numerically equal to zero (of either sign). */
|
||||
bool
|
||||
target_float_is_zero (const gdb_byte *addr, const struct type *type)
|
||||
{
|
||||
if (TYPE_CODE (type) == TYPE_CODE_FLT)
|
||||
return (floatformat_classify (floatformat_from_type (type), addr)
|
||||
== float_zero);
|
||||
|
||||
if (TYPE_CODE (type) == TYPE_CODE_DECFLOAT)
|
||||
return decimal_is_zero (addr, TYPE_LENGTH (type),
|
||||
gdbarch_byte_order (get_type_arch (type)));
|
||||
|
||||
gdb_assert_not_reached ("unexpected type code");
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
/* Floating point definitions for GDB.
|
||||
|
||||
Copyright (C) 1986-2017 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef TYPED_FLOAT_H
|
||||
#define TYPED_FLOAT_H
|
||||
|
||||
extern bool target_float_is_valid (const gdb_byte *addr,
|
||||
const struct type *type);
|
||||
extern bool target_float_is_zero (const gdb_byte *addr,
|
||||
const struct type *type);
|
||||
|
||||
#endif
|
|
@ -26,6 +26,7 @@
|
|||
#include "language.h"
|
||||
#include "doublest.h"
|
||||
#include "dfp.h"
|
||||
#include "target-float.h"
|
||||
#include <math.h>
|
||||
#include "infcall.h"
|
||||
|
||||
|
@ -1514,11 +1515,8 @@ value_logical_not (struct value *arg1)
|
|||
arg1 = coerce_array (arg1);
|
||||
type1 = check_typedef (value_type (arg1));
|
||||
|
||||
if (TYPE_CODE (type1) == TYPE_CODE_FLT)
|
||||
return 0 == value_as_double (arg1);
|
||||
else if (TYPE_CODE (type1) == TYPE_CODE_DECFLOAT)
|
||||
return decimal_is_zero (value_contents (arg1), TYPE_LENGTH (type1),
|
||||
gdbarch_byte_order (get_type_arch (type1)));
|
||||
if (is_floating_value (arg1))
|
||||
return target_float_is_zero (value_contents (arg1), type1);
|
||||
|
||||
len = TYPE_LENGTH (type1);
|
||||
p = value_contents (arg1);
|
||||
|
|
36
gdb/value.c
36
gdb/value.c
|
@ -29,10 +29,10 @@
|
|||
#include "language.h"
|
||||
#include "demangle.h"
|
||||
#include "doublest.h"
|
||||
#include "floatformat.h"
|
||||
#include "regcache.h"
|
||||
#include "block.h"
|
||||
#include "dfp.h"
|
||||
#include "target-float.h"
|
||||
#include "objfiles.h"
|
||||
#include "valprint.h"
|
||||
#include "cli/cli-decode.h"
|
||||
|
@ -2961,24 +2961,7 @@ unpack_double (struct type *type, const gdb_byte *valaddr, int *invp)
|
|||
nosign = TYPE_UNSIGNED (type);
|
||||
if (code == TYPE_CODE_FLT)
|
||||
{
|
||||
/* NOTE: cagney/2002-02-19: There was a test here to see if the
|
||||
floating-point value was valid (using the macro
|
||||
INVALID_FLOAT). That test/macro have been removed.
|
||||
|
||||
It turns out that only the VAX defined this macro and then
|
||||
only in a non-portable way. Fixing the portability problem
|
||||
wouldn't help since the VAX floating-point code is also badly
|
||||
bit-rotten. The target needs to add definitions for the
|
||||
methods gdbarch_float_format and gdbarch_double_format - these
|
||||
exactly describe the target floating-point format. The
|
||||
problem here is that the corresponding floatformat_vax_f and
|
||||
floatformat_vax_d values these methods should be set to are
|
||||
also not defined either. Oops!
|
||||
|
||||
Hopefully someone will add both the missing floatformat
|
||||
definitions and the new cases for floatformat_is_valid (). */
|
||||
|
||||
if (!floatformat_is_valid (floatformat_from_type (type), valaddr))
|
||||
if (!target_float_is_valid (valaddr, type))
|
||||
{
|
||||
*invp = 1;
|
||||
return 0.0;
|
||||
|
@ -3021,6 +3004,21 @@ unpack_pointer (struct type *type, const gdb_byte *valaddr)
|
|||
return unpack_long (type, valaddr);
|
||||
}
|
||||
|
||||
bool
|
||||
is_floating_value (struct value *val)
|
||||
{
|
||||
struct type *type = check_typedef (value_type (val));
|
||||
|
||||
if (is_floating_type (type))
|
||||
{
|
||||
if (!target_float_is_valid (value_contents (val), type))
|
||||
error (_("Invalid floating value found in program."));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/* Get the value of the FIELDNO'th field (which must be static) of
|
||||
TYPE. */
|
||||
|
|
|
@ -608,6 +608,10 @@ extern int print_address_demangle (const struct value_print_options *,
|
|||
struct gdbarch *, CORE_ADDR,
|
||||
struct ui_file *, int);
|
||||
|
||||
/* Returns true if VAL is of floating-point type. In addition,
|
||||
throws an error if the value is an invalid floating-point value. */
|
||||
extern bool is_floating_value (struct value *val);
|
||||
|
||||
extern LONGEST value_as_long (struct value *val);
|
||||
extern DOUBLEST value_as_double (struct value *val);
|
||||
extern CORE_ADDR value_as_address (struct value *val);
|
||||
|
|
Loading…
Reference in New Issue