This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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;

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]