diff options
-rw-r--r-- | gdb/ChangeLog | 17 | ||||
-rw-r--r-- | gdb/arch-utils.c | 28 | ||||
-rw-r--r-- | gdb/arch-utils.h | 5 | ||||
-rw-r--r-- | gdb/doublest.c | 55 | ||||
-rw-r--r-- | gdb/dwarf2read.c | 25 | ||||
-rw-r--r-- | gdb/gdbarch.c | 23 | ||||
-rw-r--r-- | gdb/gdbarch.h | 8 | ||||
-rwxr-xr-x | gdb/gdbarch.sh | 5 | ||||
-rw-r--r-- | gdb/gdbtypes.c | 19 | ||||
-rw-r--r-- | gdb/stabsread.c | 24 |
10 files changed, 141 insertions, 68 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 1dbddac..f269c3c 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,22 @@ 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 platform ABI floating-point formats for built-in types. * d-lang.c (build_d_types): Likewise. diff --git a/gdb/arch-utils.c b/gdb/arch-utils.c index 53121bc..776dabc 100644 --- a/gdb/arch-utils.c +++ b/gdb/arch-utils.c @@ -241,6 +241,34 @@ legacy_virtual_frame_pointer (struct gdbarch *gdbarch, *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; +} int generic_convert_register_p (struct gdbarch *gdbarch, int regnum, diff --git a/gdb/arch-utils.h b/gdb/arch-utils.h index ad3f126..bbb0878 100644 --- a/gdb/arch-utils.h +++ b/gdb/arch-utils.h @@ -95,6 +95,11 @@ int cannot_register_not (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); diff --git a/gdb/doublest.c b/gdb/doublest.c index 088037e..943a9f6 100644 --- a/gdb/doublest.c +++ b/gdb/doublest.c @@ -770,52 +770,8 @@ floatformat_from_doublest (const struct floatformat *fmt, } -/* 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) @@ -824,11 +780,8 @@ 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; } diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index 746290e..40ee66d 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -14757,6 +14757,27 @@ read_typedef (struct die_info *die, struct dwarf2_cu *cu) 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. */ @@ -14797,14 +14818,14 @@ read_base_type (struct die_info *die, struct dwarf2_cu *cu) 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); diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c index af7359e..4d8ef18 100644 --- a/gdb/gdbarch.c +++ b/gdb/gdbarch.c @@ -176,6 +176,7 @@ struct gdbarch 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; @@ -376,6 +377,7 @@ gdbarch_alloc (const struct gdbarch_info *info, 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; @@ -522,6 +524,7 @@ verify_gdbarch (struct gdbarch *gdbarch) /* 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); @@ -973,6 +976,9 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *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)); fprintf_unfiltered (file, @@ -1729,6 +1735,23 @@ set_gdbarch_long_double_format (struct gdbarch *gdbarch, 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) { diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h index bc0f692..cd01718 100644 --- a/gdb/gdbarch.h +++ b/gdb/gdbarch.h @@ -187,6 +187,14 @@ extern void set_gdbarch_long_double_bit (struct gdbarch *gdbarch, int long_doubl 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 diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh index d8e0eeb..1663156 100755 --- a/gdb/gdbarch.sh +++ b/gdb/gdbarch.sh @@ -383,6 +383,11 @@ v:const struct floatformat **:double_format:::::floatformats_ieee_double::pforma 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 diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c index b7b638e..ad890ca 100644 --- a/gdb/gdbtypes.c +++ b/gdb/gdbtypes.c @@ -2712,21 +2712,16 @@ set_type_code (struct type *type, enum type_code code) 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; } diff --git a/gdb/stabsread.c b/gdb/stabsread.c index 3bad6ac..e8ebadd 100644 --- a/gdb/stabsread.c +++ b/gdb/stabsread.c @@ -353,6 +353,24 @@ dbx_alloc_type (int typenums[2], struct objfile *objfile) 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. */ @@ -3847,11 +3865,11 @@ read_sun_floating_type (char **pp, int typenums[2], struct objfile *objfile) 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. @@ -4138,7 +4156,7 @@ read_range_type (char **pp, int typenums[2], int type_size, 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); |