Prevent beuses from choking on basic blocks without control flow successors.
[libfirm] / ir / tv / fltcalc.c
index 3ebc8e3..5e2fc0a 100644 (file)
@@ -52,7 +52,7 @@
 
 #include "xmalloc.h"
 
-/** The number of extra precesion rounding bits */
+/** The number of extra precision rounding bits */
 #define ROUNDING_BITS 2
 
 typedef uint32_t UINT32;
@@ -841,9 +841,10 @@ void *fc_val_from_str(const char *str, unsigned int len, const ieee_descriptor_t
        power_val = alloca(calc_buffer_size);
        mant_str = alloca((len)?(len):(strlen(str)));
 
-       result->desc.exponent_size = exp_size;
-       result->desc.mantissa_size = mant_size;
-       result->desc.clss = NORMAL;
+       result->desc.exponent_size = desc->exponent_size;
+       result->desc.mantissa_size = desc->mantissa_size;
+       result->desc.explicit_one  = desc->explicit_one;
+       result->desc.clss          = NORMAL;
 
        old_str = str;
        pos = 0;
@@ -1018,7 +1019,7 @@ done:
        tmp_desc.clss          = NORMAL;
        fc_val_from_ieee754(val, &tmp_desc, tmp);
 #endif /* HAVE_LONG_DOUBLE */
-       return fc_cast(tmp, &tmp_desc, result);
+       return fc_cast(tmp, desc, result);
 #endif
 }
 
@@ -1032,7 +1033,7 @@ fp_value *fc_val_from_ieee754(LLDBL l, const ieee_descriptor_t *desc, fp_value *
        bias_res = ((1 << (desc->exponent_size - 1)) - 1);
 
 #ifdef HAVE_LONG_DOUBLE
-       mant_val  = 64;
+       mant_val  = 63;
        bias_val  = 0x3fff;
        sign      = (srcval.val.high & 0x00008000) != 0;
        exponent  = (srcval.val.high & 0x00007FFF) ;
@@ -1139,6 +1140,7 @@ LLDBL fc_val_to_ieee754(const fp_value *val) {
 
        value_t           buildval;
        ieee_descriptor_t desc;
+       unsigned          mantissa_size;
 
 #ifdef HAVE_LONG_DOUBLE
        desc.exponent_size = 15;
@@ -1151,6 +1153,7 @@ LLDBL fc_val_to_ieee754(const fp_value *val) {
        desc.explicit_one  = 0;
        desc.clss          = NORMAL;
 #endif
+       mantissa_size = desc.mantissa_size + desc.explicit_one;
 
        temp = alloca(calc_buffer_size);
        value = fc_cast(val, &desc, temp);
@@ -1168,10 +1171,10 @@ LLDBL fc_val_to_ieee754(const fp_value *val) {
        mantissa1 = 0;
 
        for (byte_offset = 0; byte_offset < 4; byte_offset++)
-               mantissa1 |= sc_sub_bits(_mant(value), desc.mantissa_size, byte_offset) << (byte_offset<<3);
+               mantissa1 |= sc_sub_bits(_mant(value), mantissa_size, byte_offset) << (byte_offset << 3);
 
        for (; (byte_offset<<3) < desc.mantissa_size; byte_offset++)
-               mantissa0 |= sc_sub_bits(_mant(value), desc.mantissa_size, byte_offset) << ((byte_offset-4)<<3);
+               mantissa0 |= sc_sub_bits(_mant(value), mantissa_size, byte_offset) << ((byte_offset - 4) << 3);
 
 #ifdef HAVE_LONG_DOUBLE
        buildval.val.high = sign << 15;
@@ -1407,6 +1410,7 @@ int fc_is_subnormal(const fp_value *a) {
 
 char *fc_print(const fp_value *val, char *buf, int buflen, unsigned base) {
        char *mul_1;
+       LLDBL flt_val;
 
        mul_1 = alloca(calc_buffer_size);
 
@@ -1424,12 +1428,12 @@ char *fc_print(const fp_value *val, char *buf, int buflen, unsigned base) {
                        snprintf(buf, buflen, "0.0");
                        break;
                default:
-                       /* XXX to be implemented */
+                       flt_val = fc_val_to_ieee754(val);
 #ifdef HAVE_LONG_DOUBLE
                        /* XXX 30 is arbitrary */
-                       snprintf(buf, buflen, "%.30LE", fc_val_to_ieee754(val));
+                       snprintf(buf, buflen, "%.30LE", flt_val);
 #else
-                       snprintf(buf, buflen, "%.18E", fc_val_to_ieee754(val));
+                       snprintf(buf, buflen, "%.18E", flt_val);
 #endif
                }
                break;
@@ -1447,10 +1451,11 @@ char *fc_print(const fp_value *val, char *buf, int buflen, unsigned base) {
                        snprintf(buf, buflen, "0.0");
                        break;
                default:
+                       flt_val = fc_val_to_ieee754(val);
 #ifdef HAVE_LONG_DOUBLE
-                       snprintf(buf, buflen, "%LA", fc_val_to_ieee754(val));
+                       snprintf(buf, buflen, "%LA", flt_val);
 #else
-                       snprintf(buf, buflen, "%A", fc_val_to_ieee754(val));
+                       snprintf(buf, buflen, "%A", flt_val);
 #endif
                }
                break;
@@ -1488,7 +1493,7 @@ int fc_get_exponent(const fp_value *value) {
 }
 
 /* Return non-zero if a given value can be converted lossless into another precision */
-int fc_can_lossless_conv_to(const fp_value *value, char exp_size, char mant_size) {
+int fc_can_lossless_conv_to(const fp_value *value, const ieee_descriptor_t *desc) {
        int v;
        int exp_bias;
 
@@ -1503,12 +1508,12 @@ int fc_can_lossless_conv_to(const fp_value *value, char exp_size, char mant_size
        }
 
        /* check if the exponent can be encoded: note, 0 and all ones are reserved for the exponent */
-       exp_bias = (1 << (exp_size - 1)) - 1;
+       exp_bias = (1 << (desc->exponent_size - 1)) - 1;
        v = fc_get_exponent(value) + exp_bias;
-       if (0 < v && v < (1 << exp_size) - 1) {
-               /* check the mantissa */
+       if (0 < v && v < (1 << desc->exponent_size) - 1) {
+               /* exponent can be encoded, now check the mantissa */
                v = value->desc.mantissa_size + ROUNDING_BITS - sc_get_lowest_set_bit(_mant(value));
-               return v < mant_size;
+               return v < desc->mantissa_size;
        }
        return 0;
 }
@@ -1530,11 +1535,11 @@ void init_fltcalc(int precision) {
                /* does nothing if already init */
                if (precision == 0) precision = FC_DEFAULT_PRECISION;
 
-               init_strcalc(precision + 4);
+               init_strcalc(precision + 2 + ROUNDING_BITS);
 
-               /* needs additionally two bits to round, a bit as explicit 1., and one for
+               /* needs additionally rounding bits, one bit as explicit 1., and one for
                 * addition overflow */
-               max_precision = sc_get_precision() - 4;
+               max_precision = sc_get_precision() - (2 + ROUNDING_BITS);
                if (max_precision < precision)
                        printf("WARNING: not enough precision available, using %d\n", max_precision);