This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Improve debug info for Ada (1/4)
- From: Eric Botcazou <ebotcazou at adacore dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Mon, 12 Feb 2007 20:27:05 +0100
- Subject: [PATCH] Improve debug info for Ada (1/4)
Hi,
The Ada compiler uses a special encoding to describe record types with variant
parts in the debug info (see exp_dbg.ads); in particular, it builds auxiliary
record types which can contain fields with relative (negative) offsets and
asks the debug back-end to output info for them.
This works fine, except for the following glitch in the DWARF-2 back-end:
field_byte_offset uses the traditional rounding scheme
u += align - 1;
u /= align;
u *= align;
to round the offset up to the alignment. It's essentially an "unsigned"
rounding scheme. Now, depending on the host, the multiplication and division
are either unsigned (32-bit host) or signed (64-bit host), leading to the
following discrepancy in the debug info
.ascii "family___XVN___XVL4\0" ! DW_AT_name
.byte 0x2 ! DW_AT_decl_file (p.ads)
.byte 0x12 ! DW_AT_decl_line
.uaword 0x601 ! DW_AT_type
.byte 0xb ! DW_AT_data_member_location
.byte 0x23 ! DW_OP_plus_uconst
.uleb128 0xfffffffffffffffc
.ascii "family___XVN___XVL4\0" ! DW_AT_name
.byte 0x2 ! DW_AT_decl_file (p.ads)
.byte 0x12 ! DW_AT_decl_line
.uaword 0x5f8 ! DW_AT_type
.byte 0x2 ! DW_AT_data_member_location
.byte 0x23 ! DW_OP_plus_uconst
.uleb128 0x0
for the same field with offset -4 (see attached testcase). It stems from the
relative position of HOST_WIDE_INT and "unsigned int" for type promotion.
The attached patch simply makes sure everything is always done in unsigned
types. Bootstrapped/regtested on i586-suse-linux, OK for mainline?
2007-02-12 Eric Botcazou <ebotcazou@adacore.com>
* dwarf2out.c (round_up_to_align): New static function.
(field_byte_offset): Use it to round the offset.
:ADDPATCH debug:
--
Eric Botcazou
Index: dwarf2out.c
===================================================================
--- dwarf2out.c (revision 121686)
+++ dwarf2out.c (working copy)
@@ -9656,6 +9656,24 @@ simple_decl_align_in_bits (tree decl)
return (TREE_CODE (decl) != ERROR_MARK) ? DECL_ALIGN (decl) : BITS_PER_WORD;
}
+/* Return the result of rounding T up to ALIGN. */
+
+static inline HOST_WIDE_INT
+round_up_to_align (HOST_WIDE_INT t, unsigned int align)
+{
+ /* We must be careful if T is negative because HOST_WIDE_INT can be
+ either "above" or "below" unsigned int as per the C promotion
+ rules, depending on the host, thus making the signedness of the
+ direct multiplication and division unpredictable. */
+ unsigned HOST_WIDE_INT u = (unsigned HOST_WIDE_INT) t;
+
+ u += align - 1;
+ u /= align;
+ u *= align;
+
+ return (HOST_WIDE_INT) u;
+}
+
/* Given a pointer to a FIELD_DECL, compute and return the byte offset of the
lowest addressed byte of the "containing object" for the given FIELD_DECL,
or return 0 if we are unable to determine what that offset is, either
@@ -9755,9 +9773,8 @@ field_byte_offset (tree decl)
object_offset_in_bits = deepest_bitpos - type_size_in_bits;
/* Round up to type_align by default. This works best for bitfields. */
- object_offset_in_bits += type_align_in_bits - 1;
- object_offset_in_bits /= type_align_in_bits;
- object_offset_in_bits *= type_align_in_bits;
+ object_offset_in_bits
+ = round_up_to_align (object_offset_in_bits, type_align_in_bits);
if (object_offset_in_bits > bitpos_int)
{
@@ -9765,9 +9782,8 @@ field_byte_offset (tree decl)
object_offset_in_bits = deepest_bitpos - type_size_in_bits;
/* Round up to decl_align instead. */
- object_offset_in_bits += decl_align_in_bits - 1;
- object_offset_in_bits /= decl_align_in_bits;
- object_offset_in_bits *= decl_align_in_bits;
+ object_offset_in_bits
+ = round_up_to_align (object_offset_in_bits, decl_align_in_bits);
}
return object_offset_in_bits / BITS_PER_UNIT;
with Interfaces.C;
package P is
type UNSIGNED_SHORT_INT is new Interfaces.C.Unsigned_Short;
type UNSIGNED_INT is new Interfaces.C.Unsigned;
type Domain_Type is (One, Two, Three);
subtype Sockaddr_Data is String (1..14);
subtype Sockaddr_Path is String (1..104);
type Sockaddr(Family : Domain_Type) is
record
case Family is
when One =>
Path : Sockaddr_Path;
when Two =>
Port : Unsigned_Short_Int;
Addr : Unsigned_Int;
when others =>
Data : Sockaddr_Data;
end case;
end record;
for Sockaddr use
record
Family at 0 range 0..15;
Path at 2 range 0..831;
Port at 2 range 0..15;
Addr at 4 range 0..31;
Data at 2 range 0..111;
end record;
end P;