[Issue 2746] New: Make float.init signalling NaN by default
d-bugmail at puremagic.com
d-bugmail at puremagic.com
Thu Mar 19 05:00:59 PDT 2009
http://d.puremagic.com/issues/show_bug.cgi?id=2746
Summary: Make float.init signalling NaN by default
Product: D
Version: 2.025
Platform: PC
OS/Version: Windows
Status: NEW
Keywords: patch
Severity: enhancement
Priority: P2
Component: DMD
AssignedTo: bugzilla at digitalmars.com
ReportedBy: clugdbug at yahoo.com.au
The patch below changes the init values for
float, double, real, ifloat, idouble, ireal, cfloat, cdouble, and creal
from a quiet NaN into a signalling NaN.
Thus, use of uninitialized variables can be detected simply by enabling the
"invalid" floating-point exception.
------
It involves adding one short function (isSignallingNaN), and modifying 3
others.
(Note: compared to the version I posted on the newgroup, this uses a payload
which is different to the machine NaN, so that uninitialised variables can be
detected even if exceptions are disabled).
=================================
mtype.c line 2150
=================================
Expression *TypeBasic::defaultInit(Loc loc)
{ integer_t value = 0;
#if __DMC__
// Note: could be up to 16 bytes long.
unsigned short snan[8] = { 0, 0, 0, 0xA000, 0x7FFF, 0 };
d_float80 fvalue = *(long double*)snan;
#endif
#if LOGDEFAULTINIT
printf("TypeBasic::defaultInit() '%s'\n", toChars());
#endif
switch (ty)
{
case Tchar:
value = 0xFF;
break;
case Twchar:
case Tdchar:
value = 0xFFFF;
break;
case Timaginary32:
case Timaginary64:
case Timaginary80:
case Tfloat32:
case Tfloat64:
case Tfloat80:
#if __DMC__
return new RealExp(loc, fvalue, this);
#else
return getProperty(loc, Id::nan);
#endif
case Tcomplex32:
case Tcomplex64:
case Tcomplex80:
#if __DMC__
{ // Can't use fvalue + I*fvalue (the im part becomes a quiet
NaN).
complex_t cvalue;
((real_t *)&cvalue)[0] = fvalue;
((real_t *)&cvalue)[1] = fvalue;
return new ComplexExp(loc, cvalue, this);
}
#else
return getProperty(loc, Id::nan);
#endif
case Tvoid:
error(loc, "void does not have a default initializer");
}
return new IntegerExp(loc, value, this);
}
=================================
e2ir.c line 1182.
=================================
bool isSignallingNaN(real_t x)
{
#if __DMC__
if (x>=0 || x<0) return false;
return !((((unsigned short*)&x)[3])&0x4000);
#else
return false;
#endif
}
elem *RealExp::toElem(IRState *irs)
{ union eve c;
tym_t ty;
//printf("RealExp::toElem(%p)\n", this);
memset(&c, 0, sizeof(c));
ty = type->toBasetype()->totym();
switch (tybasic(ty))
{
case TYfloat:
case TYifloat:
c.Vfloat = value;
if (isSignallingNaN(value) ) {
((unsigned int*)&c.Vfloat)[0] &= 0xFFBFFFFFL;
}
break;
case TYdouble:
case TYidouble:
c.Vdouble = value; // this unfortunately converts SNAN to QNAN.
if ( isSignallingNaN(value) ) {
((unsigned int*)&c.Vdouble)[1] &= 0xFFF7FFFFL;
}
break;
case TYldouble:
case TYildouble:
c.Vldouble = value;
break;
default:
print();
type->print();
type->toBasetype()->print();
printf("ty = %d, tym = %x\n", type->ty, ty);
assert(0);
}
return el_const(ty, &c);
}
elem *ComplexExp::toElem(IRState *irs)
{ union eve c;
tym_t ty;
real_t re;
real_t im;
re = creall(value);
im = cimagl(value);
memset(&c, 0, sizeof(c));
ty = type->totym();
switch (tybasic(ty))
{
case TYcfloat:
c.Vcfloat.re = (float) re;
c.Vcfloat.im = (float) im;
if ( isSignallingNaN(re) && isSignallingNaN(im)) {
((unsigned int*)&c.Vcfloat.re)[0] &= 0xFFBFFFFFL;
((unsigned int*)&c.Vcfloat.im)[0] &= 0xFFBFFFFFL;
}
break;
case TYcdouble:
c.Vcdouble.re = (double) re;
c.Vcdouble.im = (double) im;
if ( isSignallingNaN(re) && isSignallingNaN(im)) {
((unsigned int*)&c.Vcdouble.re)[1] &= 0xFFF7FFFFL;
((unsigned int*)&c.Vcdouble.im)[1] &= 0xFFF7FFFFL;
}
break;
case TYcldouble:
c.Vcldouble.re = re;
c.Vcldouble.im = im;
break;
default:
assert(0);
}
return el_const(ty, &c);
}
--
More information about the Digitalmars-d-bugs
mailing list