This was fun to track down

Jim Wilson wilson@cygnus.com
Mon Sep 29 11:53:00 GMT 1997


>	An `unsigned' constant that appears negative should never be generated.

They are.  See immed_double_const in varasm.c:

      /* If MODE fits within HOST_BITS_PER_WIDE_INT, always use a CONST_INT.

	 ??? Strictly speaking, this is wrong if we create a CONST_INT
	 for a large unsigned constant with the size of MODE being
	 HOST_BITS_PER_WIDE_INT and later try to interpret that constant in a
	 wider mode.  In that case we will mis-interpret it as a negative
	 number.

	 Unfortunately, the only alternative is to make a CONST_DOUBLE
	 for any constant in any mode if it is an unsigned constant larger
	 than the maximum signed integer in an int on the host.  However,
	 doing this will break everyone that always expects to see a CONST_INT
	 for SImode and smaller.

	 We have always been making CONST_INTs in this case, so nothing new
	 is being broken.  */

>	Such constants should use const_double.

This would be nice, however, this means that every port needs to bit fixed
to handle CONST_DOUBLEs everyplace where they currently handle a CONST_INT,
and that would be a great deal of work.  It isn't clear whether fixing this
problem is worthwhile at this time.

>	Now gcc's constant representation is ambiguous.

It has always been ambiguous.  This has primarily been a problem for cross
compilers, but is now starting to affect native compilers too now that mixed
32/64 bit systems are becoming more common, because they share some of the
same traits as cross compilers.  I ran into a number of problems while doing
the irix6 port which is a mixed 32/64 bit system.

Many problems have been fixed over the years by modifying various bits of code
that create CONST_INT and CONST_DOUBLE to create them in particular ways (see
for instance what simplify_binary_operation does at the end, see also
immed_double_const).

Unfortunately there are still cases that are ambiguous.  For instance, on a
machine with a 32 bit HOST_WIDE_INT, given the number 0xffffffff80000000 it
will be represented as (CONST_INT 0x80000000).  If we then pass this to
exact_log2, it returns true, because 0x80000000 has only one bit set.
However, this answer is wrong, because the original number is clearly not
a power of two.  In order to get the right answer, we need to know the mode
of the constant, so we know how to correctly interpret the constant, or
else we need to represent any constant (signed or unsigned) as a CONST_DOUBLE
whenever the high order bit is set.

Jim



More information about the Gcc mailing list