<html>
<head>
<style>
.hmmessage P
{
margin:0px;
padding:0px
}
body.hmmessage
{
FONT-SIZE: 10pt;
FONT-FAMILY:Tahoma
}
</style>
</head>
<body class='hmmessage'>
Tony, the way floats/doubles are read/used by parse.c is definitely wrong.<BR>
Gcc wants an array of longs.<BR>
At the very least, the current code hits alignment faults on OpenBSD/sparc64.<BR>
32 bit architectures would be ok, as would AMD64.<BR>
<BR>
As well, gcc wants 32 bits per long -- even if the longs are larger than that.<BR>
So even on AMD64 it is probably reading garbage.<BR>
<BR>
So how about something like this:<BR>
<BR>
static tree<BR>scan_float (unsigned *fkind)<BR>{<BR> unsigned long i = get_int ();<BR> long n_bytes;<BR> long longs[(sizeof(long double) + sizeof(long) - 1) / sizeof(long)] = { 0 };<BR>
tree tipe;<BR> REAL_VALUE_TYPE val;<BR>
<BR>
*fkind = i;<BR> switch (i) {<BR> case 0: tipe = t_reel; n_bytes = REEL_BYTES; break;<BR> case 1: tipe = t_lreel; n_bytes = LREEL_BYTES; break;<BR> case 2: tipe = t_xreel; n_bytes = XREEL_BYTES; break;<BR> default:<BR> fatal_error(" *** invalid floating point value, precision = 0x%lx, at m3cg_lineno %d",<BR> i, m3cg_lineno);<BR> }<BR>
<BR>
/* read the value's bytes; each long holds 32 bits */<BR> for (i = 0; i < n_bytes; i++)<BR> {<BR> longs[i / 4] |= ((0xFF & get_int ()) << ((i % 4) * 8));<BR> }<BR>
<BR>
/* finally, assemble a floating point value */<BR> if (tipe == t_reel) {<BR> real_from_target_fmt (&val, longs, &ieee_single_format);<BR> } else {<BR> real_from_target_fmt (&val, longs, &ieee_double_format);<BR> }<BR> return build_real (tipe, val);<BR>}<BR><BR>I'd also feel better if get_int returned an unsigned type but don't have enough evidence there yet to change it.<BR>
<BR>
And this looks suspicous:<BR>
<BR>
#define INTEGER(x) long x = get_int()<BR>#define UNUSED_INTEGER(x) int x ATTRIBUTE_UNUSED = get_int()<BR>static long<BR>get_int (void)<BR>{<BR> long i, n_bytes, sign, val, shift;<BR>
i = (long) get_byte ();<BR> switch (i) {<BR> case M3CG_Int1: return (long) get_byte ();<BR> case M3CG_NInt1: return - (long) get_byte ();<BR> case M3CG_Int2: n_bytes = 2; sign = 1; break;<BR> case M3CG_NInt2: n_bytes = 2; sign = -1; break;<BR> case M3CG_Int4: n_bytes = 4; sign = 1; break;<BR> case M3CG_NInt4: n_bytes = 4; sign = -1; break;<BR> case M3CG_Int8: n_bytes = 8; sign = 1; break;<BR> case M3CG_NInt8: n_bytes = 8; sign = -1; break;<BR> default: return i;<BR> }<BR>
for (val = 0, shift = 0; n_bytes > 0; n_bytes--, shift += 8) {<BR> val = val | (((long) get_byte ()) << shift);<BR> }<BR> return sign * val;<BR>}<BR><BR>
<BR>
8 bytes in a long?<BR>
I think it needs to be a high and low host wide int, or at least a host wide int and assume that is 64 bits.<BR>
But I haven't debugged this either, just went groveling for "long".<BR>
Oh, scan_target_int looks better.<BR>
Probably get_int is guaranteeably only up to 32 bits and the "8" cases should fail an assertion?<BR>or get_int is guaranteed to fit in a host long, so should only assert on the 8 cases if a long is smaller than 8 bytes?<BR>
<BR>
It appears that cm3 and cm3cg must be on the same host, that the IL format is not "portable".<BR>
Because of the endianness of the float/double constants.<BR>
But I'm not 100% sure.<BR>
<BR>
If you don't have time to look at, fix, test this, I will.<BR>
Just that, you know, I can be both lazy and respectful at the same time. :)<BR>
<BR>
Thank,<BR> - Jay<BR></body>
</html>