Floating-point warning fixes; fix round-to-overflow

Actually generate the appropriate floating-point warnings, and only
one per assembly, pretty please.

Correct the round-to-overflow condition; as written all numbers with a
positive exponent were considered overflows!
This commit is contained in:
H. Peter Anvin 2007-10-16 11:48:07 -07:00
parent 125c878e96
commit fab3a6c9de
3 changed files with 40 additions and 13 deletions

47
float.c
View File

@ -128,7 +128,8 @@ static bool ieee_flconvert(const char *string, uint16_t * mant,
bool started, seendot, warned;
p = digits;
tenpwr = 0;
started = seendot = warned = false;
started = seendot = false;
warned = (pass0 != 1);
while (*string && *string != 'E' && *string != 'e') {
if (*string == '.') {
if (!seendot) {
@ -541,11 +542,23 @@ static void set_bit(uint16_t *mant, int bit)
}
/* Test a single bit */
static int test_bit(uint16_t *mant, int bit)
static int test_bit(const uint16_t *mant, int bit)
{
return (mant[bit >> 4] >> (~bit & 15)) & 1;
}
/* Report if the mantissa value is all zero */
static bool is_zero(const uint16_t *mant)
{
int i;
for (i = 0; i < MANT_WORDS; i++)
if (mant[i])
return false;
return true;
}
/* Produce standard IEEE formats, with implicit or explicit integer
bit; this makes the following assumptions:
@ -643,11 +656,15 @@ static int to_float(const char *str, int sign, uint8_t * result,
exponent >= 2 - expmax - fmt->mantissa) {
type = FL_DENORMAL;
} else if (exponent > 0) {
error(ERR_WARNING|ERR_WARN_FL_OVERFLOW,
"overflow in floating-point constant");
if (pass0 == 1)
error(ERR_WARNING|ERR_WARN_FL_OVERFLOW,
"overflow in floating-point constant");
type = FL_INFINITY;
} else {
/* underflow */
if (pass0 == 1)
error(ERR_WARNING|ERR_WARN_FL_UNDERFLOW,
"underflow in floating-point constant");
type = FL_ZERO;
}
} else {
@ -674,9 +691,18 @@ static int to_float(const char *str, int sign, uint8_t * result,
if (!fmt->explicit)
mant[one_pos] &= ~one_mask; /* remove explicit one */
mant[0] |= exponent << (15 - fmt->exponent);
} else if (daz) {
/* Flush denormals to zero */
goto zero;
} else {
if (daz || is_zero(mant)) {
/* Flush denormals to zero */
if (pass0 == 1)
error(ERR_WARNING|ERR_WARN_FL_UNDERFLOW,
"underflow in floating-point constant");
goto zero;
} else {
if (pass0 == 1)
error(ERR_WARNING|ERR_WARN_FL_DENORM,
"denormal floating-point constant");
}
}
break;
}
@ -689,9 +715,10 @@ static int to_float(const char *str, int sign, uint8_t * result,
if (test_bit(mant, fmt->exponent+fmt->explicit-1)) {
ieee_shr(mant, 1);
exponent++;
if (exponent >= expmax) {
error(ERR_WARNING|ERR_WARN_FL_OVERFLOW,
"overflow in floating-point constant");
if (exponent >= (expmax << 1)-1) {
if (pass0 == 1)
error(ERR_WARNING|ERR_WARN_FL_OVERFLOW,
"overflow in floating-point constant");
type = FL_INFINITY;
goto overflow;
}

4
nasm.c
View File

@ -116,11 +116,11 @@ static const char *suppressed_what[1 + ERR_WARN_MAX] = {
"cyclic macro self-references",
"labels alone on lines without trailing `:'",
"numeric constants do not fit in 32 bits",
"using 8- or 16-bit relocation in ELF32, a GNU extension"
"using 8- or 16-bit relocation in ELF32, a GNU extension",
"floating point overflow",
"floating point denormal",
"floating point underflow",
"too many digits in floating-point number",
"too many digits in floating-point number"
};
/*

View File

@ -73,7 +73,7 @@ typedef void (*efunc) (int severity, const char *fmt, ...);
#define ERR_WARN_FL_DENORM WARN(7) /* FP denormal */
#define ERR_WARN_FL_UNDERFLOW WARN(8) /* FP underflow */
#define ERR_WARN_FL_TOOLONG WARN(9) /* FP too many digits */
#define ERR_WARN_MAX 8 /* the highest numbered one */
#define ERR_WARN_MAX 9 /* the highest numbered one */
/*
* Wrappers around malloc, realloc and free. nasm_malloc will