[M3devel] floats in IL

Tony Hosking hosking at cs.purdue.edu
Thu Jun 5 21:05:20 CEST 2008


Indeed there may be problems with those fragments since there were  
some changes needed there in porting forward into newer versions of  
gcc.  Feel free to fix as needs be.  That code has provenance from  
well before me so no feelings of mine will get hurt.  Go for it.

On Jun 5, 2008, at 7:46 PM, Jay wrote:

> 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 tree
> scan_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 long
> get_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




More information about the M3devel mailing list