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]

patch: Sign-extension bug (?) in immed_double_const


Firstly, thanks to Geoff for ample guidance whilst I've been trying to
find this.  It takes absolutely ages to figure out what's going on
when it's your first foray into the compiler.

I thought I'd try to track down and fix the following bug.  It is
similar to several bugs in GNATs and recent gcc-bugs mails, so I
suspect they have a common cause:-

int main(void)
{
  unsigned char sign;
  unsigned char integer[2] = {255 };

  sign = integer[0];

  printf ( "sign == 255: %d\n", sign == 255);

  return 0;
}

This program prints 1 for the equality test when unoptimized, and 0
when optimized with recent CVS snapshots.  Moreover, "unsigned char"
can be replaced with "unsigned short" with constant 65535 (or any
other with the sign bit set for that mode).  I imagine on an 64-bit
machine it would fail with "unsigned int" too.

It appears that unsigned constants are held as unsigned quantities in
trees, but that during RTL conversion they must be sign-extended if
their binary representation within their mode has the sign bit set.
This isn't happening, and appears to be the cause of the bug.

Does the patch below look like a plausible fix?  I'm just putting out
feelers at the moment, at least until I see how it affects the
testsuites.  My first attempt at a full, enable-checking all
front-ends bootstrap failed owing to a segfault, which I suspect is
unrelated.  I can say that it cures the bug in the test case above.

If it is a good fix, I'll add something to the comment, too.

Neil.

	* varasm.c (immed_double_const):  Sign extend constants that
	would be signed in their mode.

Index: varasm.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/varasm.c,v
retrieving revision 1.129
diff -u -p -r1.129 varasm.c
--- varasm.c	2000/08/24 20:31:34	1.129
+++ varasm.c	2000/08/30 22:04:54
@@ -2071,7 +2071,8 @@ immed_double_const (i0, i1, mode)
 	 represented as a 64 bit value -1, and not as 0x00000000ffffffff.
 	 The later confuses the sparc backend.  */
 
-      if (BITS_PER_WORD < HOST_BITS_PER_WIDE_INT && BITS_PER_WORD == width
+      if (((BITS_PER_WORD < HOST_BITS_PER_WIDE_INT && BITS_PER_WORD == width)
+	   || i1 == 0)
 	  && (i0 & ((HOST_WIDE_INT) 1 << (width - 1))))
 	i0 |= ((HOST_WIDE_INT) (-1) << width);
 

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