aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog17
-rw-r--r--gdb/arch-utils.c28
-rw-r--r--gdb/arch-utils.h5
-rw-r--r--gdb/doublest.c55
-rw-r--r--gdb/dwarf2read.c25
-rw-r--r--gdb/gdbarch.c23
-rw-r--r--gdb/gdbarch.h8
-rwxr-xr-xgdb/gdbarch.sh5
-rw-r--r--gdb/gdbtypes.c19
-rw-r--r--gdb/stabsread.c24
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);