[M3devel] floats in IL
Jay
jayk123 at hotmail.com
Thu Jun 5 20:46:22 CEST 2008
Tony, the way floats/doubles are read/used by parse.c is definitely wrong.
Gcc wants an array of longs.
At the very least, the current code hits alignment faults on OpenBSD/sparc64.
32 bit architectures would be ok, as would AMD64.
As well, gcc wants 32 bits per long -- even if the longs are larger than that.
So even on AMD64 it is probably reading garbage.
So how about something like this:
static treescan_float (unsigned *fkind){ unsigned long i = get_int (); long n_bytes; long longs[(sizeof(long double) + sizeof(long) - 1) / sizeof(long)] = { 0 };
tree tipe; REAL_VALUE_TYPE val;
*fkind = i; switch (i) { case 0: tipe = t_reel; n_bytes = REEL_BYTES; break; case 1: tipe = t_lreel; n_bytes = LREEL_BYTES; break; case 2: tipe = t_xreel; n_bytes = XREEL_BYTES; break; default: fatal_error(" *** invalid floating point value, precision = 0x%lx, at m3cg_lineno %d", i, m3cg_lineno); }
/* read the value's bytes; each long holds 32 bits */ for (i = 0; i < n_bytes; i++) { longs[i / 4] |= ((0xFF & get_int ()) << ((i % 4) * 8)); }
/* finally, assemble a floating point value */ if (tipe == t_reel) { real_from_target_fmt (&val, longs, &ieee_single_format); } else { real_from_target_fmt (&val, longs, &ieee_double_format); } return build_real (tipe, val);}I'd also feel better if get_int returned an unsigned type but don't have enough evidence there yet to change it.
And this looks suspicous:
#define INTEGER(x) long x = get_int()#define UNUSED_INTEGER(x) int x ATTRIBUTE_UNUSED = get_int()static longget_int (void){ long i, n_bytes, sign, val, shift;
i = (long) get_byte (); switch (i) { case M3CG_Int1: return (long) get_byte (); case M3CG_NInt1: return - (long) get_byte (); case M3CG_Int2: n_bytes = 2; sign = 1; break; case M3CG_NInt2: n_bytes = 2; sign = -1; break; case M3CG_Int4: n_bytes = 4; sign = 1; break; case M3CG_NInt4: n_bytes = 4; sign = -1; break; case M3CG_Int8: n_bytes = 8; sign = 1; break; case M3CG_NInt8: n_bytes = 8; sign = -1; break; default: return i; }
for (val = 0, shift = 0; n_bytes > 0; n_bytes--, shift += 8) { val = val | (((long) get_byte ()) << shift); } return sign * val;}
8 bytes in a long?
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.
But I haven't debugged this either, just went groveling for "long".
Oh, scan_target_int looks better.
Probably get_int is guaranteeably only up to 32 bits and the "8" cases should fail an assertion?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?
It appears that cm3 and cm3cg must be on the same host, that the IL format is not "portable".
Because of the endianness of the float/double constants.
But I'm not 100% sure.
If you don't have time to look at, fix, test this, I will.
Just that, you know, I can be both lazy and respectful at the same time. :)
Thank, - Jay
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://m3lists.elegosoft.com/pipermail/m3devel/attachments/20080605/9be6a06a/attachment-0001.html>
More information about the M3devel
mailing list