Floating-point warning fixes; fix round-to-overflow
authorH. Peter Anvin <hpa@zytor.com>
Tue, 16 Oct 2007 18:48:07 +0000 (11:48 -0700)
committerH. Peter Anvin <hpa@zytor.com>
Tue, 16 Oct 2007 18:48:07 +0000 (11:48 -0700)
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!

float.c
nasm.c
nasmlib.h

diff --git a/float.c b/float.c
index 9230781..18156ef 100644 (file)
--- a/float.c
+++ b/float.c
@@ -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;
            }
diff --git a/nasm.c b/nasm.c
index 3045534..04f4190 100644 (file)
--- a/nasm.c
+++ b/nasm.c
@@ -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"
 };
 
 /*
index 08a68a5..30f0065 100644 (file)
--- a/nasmlib.h
+++ b/nasmlib.h
@@ -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