[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