This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[Patch] Emit 64-bit bounds on 32-bit hosts with DWARF
- From: Eric Botcazou <ebotcazou at adacore dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Sat, 11 Jul 2009 13:48:10 +0200
- Subject: [Patch] Emit 64-bit bounds on 32-bit hosts with DWARF
Hi,
the compiler doesn't properly represent 64-bit range types on 32-bit hosts:
package P is
type T is range -2**63 .. 2**63-1;
end P;
yields
.uleb128 0x5 # (DIE (0x40) DW_TAG_subrange_type)
.long .LASF4 # DW_AT_name: "p__t"
.long 0x2e # DW_AT_type
.uleb128 0x3 # (DIE (0x2e) DW_TAG_base_type)
.byte 0x8 # DW_AT_byte_size
.byte 0x5 # DW_AT_encoding
so GDB has to bridge the gap with some kludges. The attached patch adds the
missing support by fully using "double integers" when needed and gets rid of a
couple of ??? comments in the process, yielding:
.uleb128 0x5 # (DIE (0x40) DW_TAG_subrange_type)
.long 0x0 # DW_AT_lower_bound
.long 0x80000000
.long 0xffffffff # DW_AT_upper_bound
.long 0x7fffffff
.long .LASF4 # DW_AT_name: "p__t"
.long 0x2e # DW_AT_type
It also emits the bounds with the precision of their type so as to shield the
debug info from the variations of the host as much as possible.
This should affect only Ada in practice and the necessary GDB adjustments are
about to be submitted as well. Tested GCC/GDB on i586-suse-linux with no
regressions, OK for mainline?
2009-07-11 Eric Botcazou <ebotcazou@adacore.com>
* dwarf2out.c (enum dw_val_class): Replace dw_val_class_long_long
with dw_val_class_const_double.
(struct dw_long_long_struct): Delete.
(struct dw_val_struct): Adjust for above change.
(add_AT_long_long): Rename into...
(add_AT_double): ...this.
(print_die): Replace dw_val_class_long_long case with
dw_val_class_const_double case.
(attr_checksum): Likewise.
(same_dw_val_p): Likewise.
(size_of_die): Likewise.
(value_format): Likewise.
(output_die): Likewise.
(add_const_value_attribute) <CONST_DOUBLE>: Call add_AT_double
instead of add_AT_long_long.
(add_bound_info) <INTEGER_CST>: Generate the bound as an unsigned
value with the precision of its type.
--
Eric Botcazou
Index: dwarf2out.c
===================================================================
--- dwarf2out.c (revision 149417)
+++ dwarf2out.c (working copy)
@@ -3837,7 +3837,7 @@ enum dw_val_class
dw_val_class_range_list,
dw_val_class_const,
dw_val_class_unsigned_const,
- dw_val_class_long_long,
+ dw_val_class_const_double,
dw_val_class_vec,
dw_val_class_flag,
dw_val_class_die_ref,
@@ -3849,15 +3849,6 @@ enum dw_val_class
dw_val_class_file
};
-/* Describe a double word constant value. */
-/* ??? Every instance of long_long in the code really means CONST_DOUBLE. */
-
-typedef struct GTY(()) dw_long_long_struct {
- unsigned long hi;
- unsigned long low;
-}
-dw_long_long_const;
-
/* Describe a floating point constant value, or a vector constant value. */
typedef struct GTY(()) dw_vec_struct {
@@ -3880,7 +3871,7 @@ typedef struct GTY(()) dw_val_struct {
dw_loc_descr_ref GTY ((tag ("dw_val_class_loc"))) val_loc;
HOST_WIDE_INT GTY ((default)) val_int;
unsigned HOST_WIDE_INT GTY ((tag ("dw_val_class_unsigned_const"))) val_unsigned;
- dw_long_long_const GTY ((tag ("dw_val_class_long_long"))) val_long_long;
+ double_int GTY ((tag ("dw_val_class_const_double"))) val_double;
dw_vec_const GTY ((tag ("dw_val_class_vec"))) val_vec;
struct dw_val_die_union
{
@@ -5416,8 +5407,8 @@ static void add_AT_int (dw_die_ref, enum
static inline HOST_WIDE_INT AT_int (dw_attr_ref);
static void add_AT_unsigned (dw_die_ref, enum dwarf_attribute, unsigned HOST_WIDE_INT);
static inline unsigned HOST_WIDE_INT AT_unsigned (dw_attr_ref);
-static void add_AT_long_long (dw_die_ref, enum dwarf_attribute, unsigned long,
- unsigned long);
+static void add_AT_double (dw_die_ref, enum dwarf_attribute,
+ HOST_WIDE_INT, unsigned HOST_WIDE_INT);
static inline void add_AT_vec (dw_die_ref, enum dwarf_attribute, unsigned int,
unsigned int, unsigned char *);
static hashval_t debug_str_do_hash (const void *);
@@ -6337,15 +6328,15 @@ AT_unsigned (dw_attr_ref a)
/* Add an unsigned double integer attribute value to a DIE. */
static inline void
-add_AT_long_long (dw_die_ref die, enum dwarf_attribute attr_kind,
- long unsigned int val_hi, long unsigned int val_low)
+add_AT_double (dw_die_ref die, enum dwarf_attribute attr_kind,
+ HOST_WIDE_INT high, unsigned HOST_WIDE_INT low)
{
dw_attr_node attr;
attr.dw_attr = attr_kind;
- attr.dw_attr_val.val_class = dw_val_class_long_long;
- attr.dw_attr_val.v.val_long_long.hi = val_hi;
- attr.dw_attr_val.v.val_long_long.low = val_low;
+ attr.dw_attr_val.val_class = dw_val_class_const_double;
+ attr.dw_attr_val.v.val_double.high = high;
+ attr.dw_attr_val.v.val_double.low = low;
add_dwarf_attr (die, &attr);
}
@@ -7173,10 +7164,11 @@ print_die (dw_die_ref die, FILE *outfile
case dw_val_class_unsigned_const:
fprintf (outfile, HOST_WIDE_INT_PRINT_UNSIGNED, AT_unsigned (a));
break;
- case dw_val_class_long_long:
- fprintf (outfile, "constant (%lu,%lu)",
- a->dw_attr_val.v.val_long_long.hi,
- a->dw_attr_val.v.val_long_long.low);
+ case dw_val_class_const_double:
+ fprintf (outfile, "constant ("HOST_WIDE_INT_PRINT_DEC","\
+ HOST_WIDE_INT_PRINT_UNSIGNED")",
+ a->dw_attr_val.v.val_double.high,
+ a->dw_attr_val.v.val_double.low);
break;
case dw_val_class_vec:
fprintf (outfile, "floating-point or vector constant");
@@ -7332,8 +7324,8 @@ attr_checksum (dw_attr_ref at, struct md
case dw_val_class_unsigned_const:
CHECKSUM (at->dw_attr_val.v.val_unsigned);
break;
- case dw_val_class_long_long:
- CHECKSUM (at->dw_attr_val.v.val_long_long);
+ case dw_val_class_const_double:
+ CHECKSUM (at->dw_attr_val.v.val_double);
break;
case dw_val_class_vec:
CHECKSUM (at->dw_attr_val.v.val_vec);
@@ -7432,9 +7424,9 @@ same_dw_val_p (const dw_val_node *v1, co
return v1->v.val_int == v2->v.val_int;
case dw_val_class_unsigned_const:
return v1->v.val_unsigned == v2->v.val_unsigned;
- case dw_val_class_long_long:
- return v1->v.val_long_long.hi == v2->v.val_long_long.hi
- && v1->v.val_long_long.low == v2->v.val_long_long.low;
+ case dw_val_class_const_double:
+ return v1->v.val_double.high == v2->v.val_double.high
+ && v1->v.val_double.low == v2->v.val_double.low;
case dw_val_class_vec:
if (v1->v.val_vec.length != v2->v.val_vec.length
|| v1->v.val_vec.elt_size != v2->v.val_vec.elt_size)
@@ -8042,8 +8034,10 @@ size_of_die (dw_die_ref die)
case dw_val_class_unsigned_const:
size += constant_size (AT_unsigned (a));
break;
- case dw_val_class_long_long:
- size += 1 + 2*HOST_BITS_PER_LONG/HOST_BITS_PER_CHAR; /* block */
+ case dw_val_class_const_double:
+ size += 2*HOST_BITS_PER_WIDE_INT/HOST_BITS_PER_CHAR;
+ if (HOST_BITS_PER_WIDE_INT >= 64)
+ size++; /* block */
break;
case dw_val_class_vec:
size += constant_size (a->dw_attr_val.v.val_vec.length
@@ -8247,8 +8241,19 @@ value_format (dw_attr_ref a)
default:
gcc_unreachable ();
}
- case dw_val_class_long_long:
- return DW_FORM_block1;
+ case dw_val_class_const_double:
+ switch (HOST_BITS_PER_WIDE_INT)
+ {
+ case 8:
+ return DW_FORM_data2;
+ case 16:
+ return DW_FORM_data4;
+ case 32:
+ return DW_FORM_data8;
+ case 64:
+ default:
+ return DW_FORM_block1;
+ }
case dw_val_class_vec:
switch (constant_size (a->dw_attr_val.v.val_vec.length
* a->dw_attr_val.v.val_vec.elt_size))
@@ -8520,28 +8525,29 @@ output_die (dw_die_ref die)
AT_unsigned (a), "%s", name);
break;
- case dw_val_class_long_long:
+ case dw_val_class_const_double:
{
unsigned HOST_WIDE_INT first, second;
- dw2_asm_output_data (1,
- 2 * HOST_BITS_PER_LONG / HOST_BITS_PER_CHAR,
- "%s", name);
+ if (HOST_BITS_PER_WIDE_INT >= 64)
+ dw2_asm_output_data (1,
+ 2*HOST_BITS_PER_WIDE_INT/HOST_BITS_PER_CHAR,
+ NULL);
if (WORDS_BIG_ENDIAN)
{
- first = a->dw_attr_val.v.val_long_long.hi;
- second = a->dw_attr_val.v.val_long_long.low;
+ first = a->dw_attr_val.v.val_double.high;
+ second = a->dw_attr_val.v.val_double.low;
}
else
{
- first = a->dw_attr_val.v.val_long_long.low;
- second = a->dw_attr_val.v.val_long_long.hi;
+ first = a->dw_attr_val.v.val_double.low;
+ second = a->dw_attr_val.v.val_double.high;
}
- dw2_asm_output_data (HOST_BITS_PER_LONG / HOST_BITS_PER_CHAR,
- first, "long long constant");
- dw2_asm_output_data (HOST_BITS_PER_LONG / HOST_BITS_PER_CHAR,
+ dw2_asm_output_data (HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR,
+ first, name);
+ dw2_asm_output_data (HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR,
second, NULL);
}
break;
@@ -11581,7 +11587,7 @@ add_const_value_attribute (dw_die_ref di
/* Note that a CONST_DOUBLE rtx could represent either an integer or a
floating-point constant. A CONST_DOUBLE is used whenever the
constant requires more than one word in order to be adequately
- represented. We output CONST_DOUBLEs as blocks. */
+ represented. */
{
enum machine_mode mode = GET_MODE (rtl);
@@ -11594,13 +11600,8 @@ add_const_value_attribute (dw_die_ref di
add_AT_vec (die, DW_AT_const_value, length / 4, 4, array);
}
else
- {
- /* ??? We really should be using HOST_WIDE_INT throughout. */
- gcc_assert (HOST_BITS_PER_LONG == HOST_BITS_PER_WIDE_INT);
-
- add_AT_long_long (die, DW_AT_const_value,
- CONST_DOUBLE_HIGH (rtl), CONST_DOUBLE_LOW (rtl));
- }
+ add_AT_double (die, DW_AT_const_value,
+ CONST_DOUBLE_HIGH (rtl), CONST_DOUBLE_LOW (rtl));
}
break;
@@ -12658,14 +12659,33 @@ add_bound_info (dw_die_ref subrange_die,
/* All fixed-bounds are represented by INTEGER_CST nodes. */
case INTEGER_CST:
- if (! host_integerp (bound, 0)
- || (bound_attr == DW_AT_lower_bound
- && (((is_c_family () || is_java ()) && integer_zerop (bound))
- || (is_fortran () && integer_onep (bound)))))
- /* Use the default. */
- ;
- else
- add_AT_unsigned (subrange_die, bound_attr, tree_low_cst (bound, 0));
+ {
+ unsigned int prec = simple_type_size_in_bits (TREE_TYPE (bound));
+
+ /* Use the default if possible. */
+ if (bound_attr == DW_AT_lower_bound
+ && (((is_c_family () || is_java ()) && integer_zerop (bound))
+ || (is_fortran () && integer_onep (bound))))
+ ;
+
+ /* Otherwise represent the bound as an unsigned value with the
+ precision of its type. The precision and signedness of the
+ type will be necessary to re-interpret it unambiguously. */
+ else if (prec < HOST_BITS_PER_WIDE_INT)
+ {
+ unsigned HOST_WIDE_INT mask
+ = ((unsigned HOST_WIDE_INT) 1 << prec) - 1;
+ add_AT_unsigned (subrange_die, bound_attr,
+ TREE_INT_CST_LOW (bound) & mask);
+ }
+ else if (prec == HOST_BITS_PER_WIDE_INT
+ || TREE_INT_CST_HIGH (bound) == 0)
+ add_AT_unsigned (subrange_die, bound_attr,
+ TREE_INT_CST_LOW (bound));
+ else
+ add_AT_double (subrange_die, bound_attr, TREE_INT_CST_HIGH (bound),
+ TREE_INT_CST_LOW (bound));
+ }
break;
CASE_CONVERT: