problem with long long bitfields in varasm.c

Herman ten Brugge Haj.Ten.Brugge@net.HCC.nl
Fri May 14 09:57:00 GMT 1999


Hello,

I discovered a bug in varasm.c that caused incorrect code to be
generated for long long bitfields.

I did sent this problem about 1/2 year ago but nothing happened until
now so I just resent it as a reminder.

I found a problem with long long bitfields. The problem occurred with the
following program:

struct tmp
{
  long long int pad : 12;
  long long int field : 52;
};
struct tmp tmp = {0x123LL, 0x123456789ABCDLL};

The code result for the i386 is:
tmp:
.byte 0x23
.byte 0xd1
.byte 0xbc
.byte 0x9a
.byte 0x78
.byte 0x55		<--- wrong
.byte 0x34
.byte 0x12

I found the bug in output_constructor in varasm.c. The value this_time and
shift are not calculated correctly.
I also found another bug. This bug only occures on the c4x where 
HOST_BITS_PER_WIDE_INT == 32. It is illegal to do a shift with this value
so I clamped the value of this_time to HOST_BITS_PER_WIDE_INT-1.

	Herman.

1999-05-14 Herman A.J. ten Brugge <Haj.Ten.Brugge@net.HCC.nl>

        * varasm.c (output_constructor) Fixed problem with calculating
	this_time and shift for long long bitfields. Also fixed problem
	with shiftcount equal to HOST_BITS_PER_WIDE_INT.

--- varasm.c.org	Fri May 14 18:52:55 1999
+++ varasm.c	Fri May 14 18:53:04 1999
@@ -4192,6 +4192,7 @@ output_constructor (exp, size)
 		 (all part of the same byte).  */
 	      this_time = MIN (end_offset - next_offset,
 			       BITS_PER_UNIT - next_bit);
+	      this_time = MIN (this_time, HOST_BITS_PER_WIDE_INT-1);
 	      if (BYTES_BIG_ENDIAN)
 		{
 		  /* On big-endian machine, take the most significant bits
@@ -4203,8 +4204,7 @@ output_constructor (exp, size)
 		  if (shift < HOST_BITS_PER_WIDE_INT
 		      && shift + this_time > HOST_BITS_PER_WIDE_INT)
 		    {
-		      this_time -= (HOST_BITS_PER_WIDE_INT - shift);
-		      shift = HOST_BITS_PER_WIDE_INT;
+		      this_time = (HOST_BITS_PER_WIDE_INT - shift);
 		    }
 
 		  /* Now get the bits from the appropriate constant word.  */
@@ -4236,8 +4236,7 @@ output_constructor (exp, size)
 		  if (shift < HOST_BITS_PER_WIDE_INT
 		      && shift + this_time > HOST_BITS_PER_WIDE_INT)
 		    {
-		      this_time -= (HOST_BITS_PER_WIDE_INT - shift);
-		      shift = HOST_BITS_PER_WIDE_INT;
+		      this_time = (HOST_BITS_PER_WIDE_INT - shift);
 		    }
 
 		  /* Now get the bits from the appropriate constant word.  */


More information about the Gcc-patches mailing list