Fix: stage comparison failure in bootstrap

Donn Terry donn@interix.com
Mon Feb 8 09:19:00 GMT 1999


Attached is a small patch to real.c to fix a problem that shows up
doing a make bootstrap on i386/Interix: the stage1 to stage2 binary
comparsons fail on gcov.o and a couple of other files.


Short description: when realvaluetype is represented as a pair
of long longs (128 bits) but actually only contains 80 bits
(Intel long double) the remaining bits are trash, confusing
the constant pooling code in varasm.c.


Long gory details:

The cause is an uninitialized field involved in a comparison,
which causes the compiler's constant-pooling to miss sharing.
(In the case of gcov.c, it's the two instances of 100 in
function_summary, after they have been widened to double type
by context.)

Here's the situation:

1)  The final target compiler is to use 80 bit long doubles.
2)  The initial compiler is MSVC, where "long long" is spelled
    "__int64".
3)  With at least some initial setup w.r.t. HOST_WIDE_INT,
    realvaluetype is declared to be a structure containing
    two HOST_WIDE_INTs (128 bits).
4)  In varasm.c, const_double_chain is searched, and the comparison
    is made on the high and low parts, as seen as integers.
    (Near "for (r = const_double_chain; r; r = CONST_DOUBLE_CHAIN (r))".
5)  The macro PUT_REAL is used in ereal_from_int, during the conversion
    to real.
6)  In the circumstances above, the lexically first definition
    of PUT_REAL is used in real.c.   That definition copies only
    80 bits of real (based on the sizeof() argument to bcopy()).
    That leaves 48 bits of the second word of the realvaluetype
    uninitialized.  The rest of the word should be zeroed so
    the comparisons in step 4 above actually match the constants.

Applying the patch cures the bootstrap problem.  From looking at the
problem with the debugger, it's clear that the failure was due to
random trash in the uninitialized partof the word.

Using a longer copy would probably still end up copying trash.



(Should this be recoded in terms of memcpy() or is that a separate change?)

diff -urP egcs.source.old/gcc/real.c egcs.source/gcc/real.c
--- egcs.source.old/gcc/real.c  Sun Jan 31 08:16:24 1999
+++ egcs.source/gcc/real.c      Fri Feb  5 13:03:05 1999
@@ -248,7 +248,10 @@
 #define MAXDECEXP 4932
 #define MINDECEXP -4956
 #define GET_REAL(r,e) bcopy ((char *) r, (char *) e, 2*NE)
-#define PUT_REAL(e,r) bcopy ((char *) e, (char *) r, 2*NE)
+#define PUT_REAL(e,r) { \
+               if (sizeof(*e) < sizeof(*r)) bzero((char *)r, sizeof(*r)); \
+               bcopy ((char *) e, (char *) r, 2*NE); \
+               }
 #else /* no XFmode */
 #if LONG_DOUBLE_TYPE_SIZE == 128
 #define NE 10
-- 

===================================================
Donn Terry                  mailto:donn@interix.com
Softway Systems, Inc.        http://www.interix.com
2850 McClelland Dr, Ste. 1800   Ft.Collins CO 80525
Tel: +1-970-204-9900           Fax: +1-970-204-9951
===================================================


More information about the Gcc-patches mailing list