+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.
tracepoint.c \
trad-frame.c \
tramp-frame.c \
+ target-float.c \
typeprint.c \
ui-file.c \
ui-file.h \
tracefile.h \
tracepoint.h \
trad-frame.h \
+ target-float.h \
tramp-frame.h \
typeprint.h \
ui-file.h \
top.o \
trad-frame.o \
tramp-frame.o \
+ target-float.o \
typeprint.o \
ui-file.o \
ui-out.o \
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)
{
return float_nan;
}
- if (mant_zero)
- return float_zero;
-
return float_normal;
}
|| (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
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 *);
#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"
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;
--- /dev/null
+/* 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");
+}
+
--- /dev/null
+/* 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
#include "language.h"
#include "doublest.h"
#include "dfp.h"
+#include "target-float.h"
#include <math.h>
#include "infcall.h"
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);
#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"
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;
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;
+}
+
\f
/* Get the value of the FIELDNO'th field (which must be static) of
TYPE. */
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);