+2016-09-05 Ulrich Weigand <uweigand@de.ibm.com>
+
+ * gdbarch.sh (floatformat_for_type): New gdbarch callback.
+ * gdbarch.h, gdbarch.c: Re-generate.
+ * arch-utils.h (default_floatformat_for_type): New prototype.
+ * arch-utils.c (default_floatformat_for_type): New function.
+
+ * doublest.c (floatformat_from_length): Remove.
+ (floatformat_from_type): Assume TYPE_FLOATFORMAT is non-NULL.
+ * gdbtypes.c (verify_floatformat): Require non-NULL format.
+
+ * dwarf2read.c (dwarf2_init_float_type): New function.
+ (read_base_type): Use it.
+ * stabsread.c (dbx_init_float_type): New function.
+ (read_sun_floating_type): Use it.
+ (read_range_type): Likewise.
+
2016-09-05 Ulrich Weigand <uweigand@de.ibm.com>
* ada-lang.c (ada_language_arch_info): Use gdbarch-provided
*frame_offset = 0;
}
+/* Return a floating-point format for a floating-point variable of
+ length LEN in bits. If non-NULL, NAME is the name of its type.
+ If no suitable type is found, return NULL. */
+
+const struct floatformat **
+default_floatformat_for_type (struct gdbarch *gdbarch,
+ const char *name, int len)
+{
+ const struct floatformat **format = NULL;
+
+ if (len == gdbarch_half_bit (gdbarch))
+ format = gdbarch_half_format (gdbarch);
+ else if (len == gdbarch_float_bit (gdbarch))
+ format = gdbarch_float_format (gdbarch);
+ else if (len == gdbarch_double_bit (gdbarch))
+ format = gdbarch_double_format (gdbarch);
+ else if (len == gdbarch_long_double_bit (gdbarch))
+ format = gdbarch_long_double_format (gdbarch);
+ /* On i386 the 'long double' type takes 96 bits,
+ while the real number of used bits is only 80,
+ both in processor and in memory.
+ The code below accepts the real bit size. */
+ else if (gdbarch_long_double_format (gdbarch) != NULL
+ && len == gdbarch_long_double_format (gdbarch)[0]->totalsize)
+ format = gdbarch_long_double_format (gdbarch);
+
+ return format;
+}
\f
int
generic_convert_register_p (struct gdbarch *gdbarch, int regnum,
extern gdbarch_virtual_frame_pointer_ftype legacy_virtual_frame_pointer;
+/* Default implementation of gdbarch_floatformat_for_type. */
+extern const struct floatformat **
+ default_floatformat_for_type (struct gdbarch *gdbarch,
+ const char *name, int len);
+
extern CORE_ADDR generic_skip_trampoline_code (struct frame_info *frame,
CORE_ADDR pc);
}
\f
-/* Return a floating-point format for a floating-point variable of
- length LEN. If no suitable floating-point format is found, an
- error is thrown.
-
- We need this functionality since information about the
- floating-point format of a type is not always available to GDB; the
- debug information typically only tells us the size of a
- floating-point type.
-
- FIXME: kettenis/2001-10-28: In many places, particularly in
- target-dependent code, the format of floating-point types is known,
- but not passed on by GDB. This should be fixed. */
-
-static const struct floatformat *
-floatformat_from_length (struct gdbarch *gdbarch, int len)
-{
- const struct floatformat *format;
-
- if (len * TARGET_CHAR_BIT == gdbarch_half_bit (gdbarch))
- format = gdbarch_half_format (gdbarch)
- [gdbarch_byte_order (gdbarch)];
- else if (len * TARGET_CHAR_BIT == gdbarch_float_bit (gdbarch))
- format = gdbarch_float_format (gdbarch)
- [gdbarch_byte_order (gdbarch)];
- else if (len * TARGET_CHAR_BIT == gdbarch_double_bit (gdbarch))
- format = gdbarch_double_format (gdbarch)
- [gdbarch_byte_order (gdbarch)];
- else if (len * TARGET_CHAR_BIT == gdbarch_long_double_bit (gdbarch))
- format = gdbarch_long_double_format (gdbarch)
- [gdbarch_byte_order (gdbarch)];
- /* On i386 the 'long double' type takes 96 bits,
- while the real number of used bits is only 80,
- both in processor and in memory.
- The code below accepts the real bit size. */
- else if ((gdbarch_long_double_format (gdbarch) != NULL)
- && (len * TARGET_CHAR_BIT
- == gdbarch_long_double_format (gdbarch)[0]->totalsize))
- format = gdbarch_long_double_format (gdbarch)
- [gdbarch_byte_order (gdbarch)];
- else
- format = NULL;
- if (format == NULL)
- error (_("Unrecognized %d-bit floating-point type."),
- len * TARGET_CHAR_BIT);
- return format;
-}
+/* Return the floating-point format for a floating-point variable of
+ type TYPE. */
const struct floatformat *
floatformat_from_type (const struct type *type)
const struct floatformat *fmt;
gdb_assert (TYPE_CODE (type) == TYPE_CODE_FLT);
- if (TYPE_FLOATFORMAT (type) != NULL)
- fmt = TYPE_FLOATFORMAT (type)[gdbarch_byte_order (gdbarch)];
- else
- fmt = floatformat_from_length (gdbarch, TYPE_LENGTH (type));
-
+ gdb_assert (TYPE_FLOATFORMAT (type));
+ fmt = TYPE_FLOATFORMAT (type)[gdbarch_byte_order (gdbarch)];
gdb_assert (TYPE_LENGTH (type) >= floatformat_totalsize_bytes (fmt));
return fmt;
}
return this_type;
}
+/* Allocate a floating-point type of size BITS and name NAME. Pass NAME_HINT
+ (which may be different from NAME) to the architecture back-end to allow
+ it to guess the correct format if necessary. */
+
+static struct type *
+dwarf2_init_float_type (struct objfile *objfile, int bits, const char *name,
+ const char *name_hint)
+{
+ struct gdbarch *gdbarch = get_objfile_arch (objfile);
+ const struct floatformat **format;
+ struct type *type;
+
+ format = gdbarch_floatformat_for_type (gdbarch, name_hint, bits);
+ if (format)
+ type = init_float_type (objfile, bits, name, format);
+ else
+ type = init_type (objfile, TYPE_CODE_ERROR, bits / TARGET_CHAR_BIT, name);
+
+ return type;
+}
+
/* Find a representation of a given base type and install
it in the TYPE field of the die. */
type = init_boolean_type (objfile, bits, 1, name);
break;
case DW_ATE_complex_float:
- type = init_float_type (objfile, bits / 2, NULL, NULL);
+ type = dwarf2_init_float_type (objfile, bits / 2, NULL, name);
type = init_complex_type (objfile, name, type);
break;
case DW_ATE_decimal_float:
type = init_decfloat_type (objfile, bits, name);
break;
case DW_ATE_float:
- type = init_float_type (objfile, bits, name, NULL);
+ type = dwarf2_init_float_type (objfile, bits, name, name);
break;
case DW_ATE_signed:
type = init_integer_type (objfile, bits, 0, name);
const struct floatformat ** double_format;
int long_double_bit;
const struct floatformat ** long_double_format;
+ gdbarch_floatformat_for_type_ftype *floatformat_for_type;
int ptr_bit;
int addr_bit;
int dwarf2_addr_size;
gdbarch->float_bit = 4*TARGET_CHAR_BIT;
gdbarch->double_bit = 8*TARGET_CHAR_BIT;
gdbarch->long_double_bit = 8*TARGET_CHAR_BIT;
+ gdbarch->floatformat_for_type = default_floatformat_for_type;
gdbarch->ptr_bit = gdbarch->int_bit;
gdbarch->char_signed = -1;
gdbarch->virtual_frame_pointer = legacy_virtual_frame_pointer;
/* Skip verify of long_double_bit, invalid_p == 0 */
if (gdbarch->long_double_format == 0)
gdbarch->long_double_format = floatformats_ieee_double;
+ /* Skip verify of floatformat_for_type, invalid_p == 0 */
/* Skip verify of ptr_bit, invalid_p == 0 */
if (gdbarch->addr_bit == 0)
gdbarch->addr_bit = gdbarch_ptr_bit (gdbarch);
fprintf_unfiltered (file,
"gdbarch_dump: float_format = %s\n",
pformat (gdbarch->float_format));
+ fprintf_unfiltered (file,
+ "gdbarch_dump: floatformat_for_type = <%s>\n",
+ host_address_to_string (gdbarch->floatformat_for_type));
fprintf_unfiltered (file,
"gdbarch_dump: fp0_regnum = %s\n",
plongest (gdbarch->fp0_regnum));
gdbarch->long_double_format = long_double_format;
}
+const struct floatformat **
+gdbarch_floatformat_for_type (struct gdbarch *gdbarch, const char *name, int length)
+{
+ gdb_assert (gdbarch != NULL);
+ gdb_assert (gdbarch->floatformat_for_type != NULL);
+ if (gdbarch_debug >= 2)
+ fprintf_unfiltered (gdb_stdlog, "gdbarch_floatformat_for_type called\n");
+ return gdbarch->floatformat_for_type (gdbarch, name, length);
+}
+
+void
+set_gdbarch_floatformat_for_type (struct gdbarch *gdbarch,
+ gdbarch_floatformat_for_type_ftype floatformat_for_type)
+{
+ gdbarch->floatformat_for_type = floatformat_for_type;
+}
+
int
gdbarch_ptr_bit (struct gdbarch *gdbarch)
{
extern const struct floatformat ** gdbarch_long_double_format (struct gdbarch *gdbarch);
extern void set_gdbarch_long_double_format (struct gdbarch *gdbarch, const struct floatformat ** long_double_format);
+/* Returns the floating-point format to be used for values of length LENGTH.
+ NAME, if non-NULL, is the type name, which may be used to distinguish
+ different target formats of the same length. */
+
+typedef const struct floatformat ** (gdbarch_floatformat_for_type_ftype) (struct gdbarch *gdbarch, const char *name, int length);
+extern const struct floatformat ** gdbarch_floatformat_for_type (struct gdbarch *gdbarch, const char *name, int length);
+extern void set_gdbarch_floatformat_for_type (struct gdbarch *gdbarch, gdbarch_floatformat_for_type_ftype *floatformat_for_type);
+
/* For most targets, a pointer on the target and its representation as an
address in GDB have the same size and "look the same". For such a
target, you need only set gdbarch_ptr_bit and gdbarch_addr_bit
v:int:long_double_bit:::8 * sizeof (long double):8*TARGET_CHAR_BIT::0
v:const struct floatformat **:long_double_format:::::floatformats_ieee_double::pformat (gdbarch->long_double_format)
+# Returns the floating-point format to be used for values of length LENGTH.
+# NAME, if non-NULL, is the type name, which may be used to distinguish
+# different target formats of the same length.
+m:const struct floatformat **:floatformat_for_type:const char *name, int length:name, length:0:default_floatformat_for_type::0
+
# For most targets, a pointer on the target and its representation as an
# address in GDB have the same size and "look the same". For such a
# target, you need only set gdbarch_ptr_bit and gdbarch_addr_bit
static int
verify_floatformat (int bit, const struct floatformat **floatformats)
{
+ gdb_assert (floatformats != NULL);
+ gdb_assert (floatformats[0] != NULL && floatformats[1] != NULL);
+
if (bit == -1)
- {
- gdb_assert (floatformats != NULL);
- gdb_assert (floatformats[0] != NULL && floatformats[1] != NULL);
- bit = floatformats[0]->totalsize;
- }
+ bit = floatformats[0]->totalsize;
gdb_assert (bit >= 0);
- if (floatformats != NULL)
- {
- size_t len = bit / TARGET_CHAR_BIT;
-
- gdb_assert (len >= floatformat_totalsize_bytes (floatformats[0]));
- gdb_assert (len >= floatformat_totalsize_bytes (floatformats[1]));
- }
+ size_t len = bit / TARGET_CHAR_BIT;
+ gdb_assert (len >= floatformat_totalsize_bytes (floatformats[0]));
+ gdb_assert (len >= floatformat_totalsize_bytes (floatformats[1]));
return bit;
}
return (*type_addr);
}
+/* Allocate a floating-point type of size BITS. */
+
+static struct type *
+dbx_init_float_type (struct objfile *objfile, int bits)
+{
+ struct gdbarch *gdbarch = get_objfile_arch (objfile);
+ const struct floatformat **format;
+ struct type *type;
+
+ format = gdbarch_floatformat_for_type (gdbarch, NULL, bits);
+ if (format)
+ type = init_float_type (objfile, bits, NULL, format);
+ else
+ type = init_type (objfile, TYPE_CODE_ERROR, bits / TARGET_CHAR_BIT, NULL);
+
+ return type;
+}
+
/* for all the stabs in a given stab vector, build appropriate types
and fix their symbols in given symbol vector. */
if (details == NF_COMPLEX || details == NF_COMPLEX16
|| details == NF_COMPLEX32)
{
- rettype = init_float_type (objfile, nbits / 2, NULL, NULL);
+ rettype = dbx_init_float_type (objfile, nbits / 2);
return init_complex_type (objfile, NULL, rettype);
}
- return init_float_type (objfile, nbits, NULL, NULL);
+ return dbx_init_float_type (objfile, nbits);
}
/* Read a number from the string pointed to by *PP.
if (n3 == 0 && n2 > 0)
{
struct type *float_type
- = init_float_type (objfile, n2 * TARGET_CHAR_BIT, NULL, NULL);
+ = dbx_init_float_type (objfile, n2 * TARGET_CHAR_BIT);
if (self_subrange)
return init_complex_type (objfile, NULL, float_type);