cleanups and bugfixes in the tarval module and a new lower-level tarval interface...
authorMatthias Braun <matze@braunis.de>
Wed, 24 Feb 2010 15:04:40 +0000 (15:04 +0000)
committerMatthias Braun <matze@braunis.de>
Wed, 24 Feb 2010 15:04:40 +0000 (15:04 +0000)
[r27211]

include/libfirm/tv.h
ir/tv/fltcalc.c
ir/tv/strcalc.c
ir/tv/tv.c

index 5b3cdda..aba6bcc 100644 (file)
  */
 tarval *new_tarval_from_str(const char *str, size_t len, ir_mode *mode);
 
+/**
+ * Construct a new tarval from a given string.
+ *
+ * @param str   The string representing the target value
+ * @param len   The length of the string
+ * @param sign  is -1 or 1 depending on the numbers sign
+ * @param base  number system base.
+ *              binary(2), octal(8), decimal(10) and hexadecimal(16) numbers
+ *              are supported.
+ * @param mode  The mode requested for the result tarval
+ *
+ * @return
+ *   A tarval with the given mode. If overflow settings are set to
+ *   TV_OVERFLOW_BAD then a tarval_bad is returned if the number can't be
+ *   represented in the given mode.
+ *   Return bad if the number couldn't successfully be parsed.
+ */
+tarval *new_integer_tarval_from_str(const char *str, size_t len, char sign,
+                                    unsigned char base, ir_mode *mode);
+
 /**
  * Constructor function for new tarvals
  *
index f72d1c5..4480a26 100644 (file)
 
 #include "xmalloc.h"
 
+#if defined(HAVE_LONG_DOUBLE) && !defined(__CYGWIN__)
+/* No strtold on windows and no replacement yet */
+#define strtold(s, e) strtod(s, e)
+#endif
+
 /** The number of extra precision rounding bits */
 #define ROUNDING_BITS 2
 
@@ -837,211 +842,26 @@ int fc_get_buffer_length(void)
 
 void *fc_val_from_str(const char *str, unsigned int len, const ieee_descriptor_t *desc, void *result)
 {
-#if 0
-       enum {
-               START,
-               LEFT_OF_DOT,
-               RIGHT_OF_DOT,
-               EXP_START,
-               EXPONENT,
-               END
-       };
-
-       char exp_sign;
-       int exp_int, hsb, state;
-
-       const char *old_str;
-
-       int pos;
-       char *mant_str, *exp_val, *power_val;
-
-       (void) len;
-       if (result == NULL) result = calc_buffer;
-
-       exp_val = alloca(value_size);
-       power_val = alloca(calc_buffer_size);
-       mant_str = alloca((len)?(len):(strlen(str)));
-
-       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;
-       exp_int = 0;
-       state = START;
-
-       while (len == 0 || str-old_str < len) {
-               switch (state) {
-               case START:
-                       switch (*str) {
-                       case '+':
-                               result->sign = 0;
-                               state = LEFT_OF_DOT;
-                               str++;
-                               break;
-
-                       case '-':
-                               result->sign = 1;
-                               state = LEFT_OF_DOT;
-                               str++;
-                               break;
-
-                       case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
-                               result->sign = 0;
-                               state = LEFT_OF_DOT;
-                               break;
-
-                       case '.':
-                               result->sign = 0;
-                               state = RIGHT_OF_DOT;
-                               str++;
-                               break;
-
-                       case 'n':
-                       case 'N':
-                       case 'i':
-                       case 'I':
-                               break;
-
-                       default:
-                               fail_char(old_str, len, str - old_str);
-                       }
-                       break;
-
-               case LEFT_OF_DOT:
-                       switch (*str) {
-                       case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
-                               mant_str[pos++] = *(str++);
-                               break;
-
-                       case '.':
-                               state = RIGHT_OF_DOT;
-                               str++;
-                               break;
-
-                       case 'e':
-                       case 'E':
-                               state = EXP_START;
-                               str++;
-                               break;
-
-                       case '\0':
-                               mant_str[pos] = '\0';
-                               goto done;
-
-                       default:
-                               fail_char(old_str, len, str - old_str);
-                       }
-                       break;
-
-               case RIGHT_OF_DOT:
-                       switch (*str) {
-                       case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
-                               mant_str[pos++] = *(str++);
-                               exp_int++;
-                               break;
-
-                       case 'e':
-                       case 'E':
-                               state = EXP_START;
-                               str++;
-                               break;
-
-                       case '\0':
-                               mant_str[pos] = '\0';
-                               goto done;
-
-                       default:
-                               fail_char(old_str, len, str - old_str);
-                       }
-                       break;
-
-               case EXP_START:
-                       switch (*str) {
-                       case '-':
-                               exp_sign = 1;
-                               /* fall through */
-                       case '+':
-                               if (*(str-1) != 'e' && *(str-1) != 'E') fail_char(old_str, len, str - old_str);
-                               str++;
-                               break;
-
-                       case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
-                               mant_str[pos] = '\0';
-                               pos = 1;
-                               str++;
-                               state = EXPONENT;
-                               break;
-
-                       default:
-                               fail_char(old_str, len, str - old_str);
-                       }
-                       break;
-
-               case EXPONENT:
-                       switch (*str) {
-                       case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
-                               pos++;
-                               str++;
-                               break;
-
-                       case '\0': goto done;
-
-                       default:
-                               fail_char(old_str, len, str - old_str);
-                       }
-               }
-       } /*  switch (state) */
+       char *buffer;
 
-done:
-       sc_val_from_str(mant_str, strlen(mant_str), _mant(result));
-
-       /* shift to put value left of radix point */
-       sc_val_from_ulong(mant_size + ROUNDING_BITS, exp_val);
-
-       _shift_left(_mant(result), exp_val, _mant(result));
-
-       sc_val_from_ulong((1 << (exp_size - 1)) - 1, _exp(result));
-
-       _normalize(result, result, 0);
-
-       if (state == EXPONENT) {
-               exp_int -= atoi(str-pos);
-       }
-
-       _power_of_ten(exp_int, &result->desc, power_val);
-
-       _fdiv(result, power_val, result);
-
-       return result;
-#else
        /* XXX excuse of an implementation to make things work */
        LLDBL             val;
        fp_value          *tmp = alloca(calc_buffer_size);
        ieee_descriptor_t tmp_desc;
-       (void) len;
 
-#if defined(HAVE_LONG_DOUBLE) && !defined(__CYGWIN__)
-       val = strtold(str, NULL);
+       buffer = alloca(len+1);
+       memcpy(buffer, str, len);
+       buffer[len] = '\0';
+       val = strtold(buffer, NULL);
+
        DEBUGPRINTF(("val_from_str(%s)\n", str));
        tmp_desc.exponent_size = 15;
        tmp_desc.mantissa_size = 63;
        tmp_desc.explicit_one  = 1;
        tmp_desc.clss          = NORMAL;
        fc_val_from_ieee754(val, &tmp_desc, tmp);
-#else
-       val = strtod(str, NULL);
-       DEBUGPRINTF(("val_from_str(%s)\n", str));
-       tmp_desc.exponent_size = 11;
-       tmp_desc.mantissa_size = 52;
-       tmp_desc.explicit_one  = 0;
-       tmp_desc.clss          = NORMAL;
-       fc_val_from_ieee754(val, &tmp_desc, tmp);
-#endif /* HAVE_LONG_DOUBLE */
+
        return fc_cast(tmp, desc, result);
-#endif
 }
 
 fp_value *fc_val_from_ieee754(LLDBL l, const ieee_descriptor_t *desc, fp_value *result)
index d57f0f1..50aaf56 100644 (file)
@@ -817,15 +817,7 @@ void sign_extend(void *buffer, ir_mode *mode)
  * The C-standard does theoretically allow otherwise. */
 static inline void check_ascii(void)
 {
-       assert('1'-'0' == 1
-               && '2'-'0' == 2
-               && '3'-'0' == 3
-               && '4'-'0' == 4
-               && '5'-'0' == 5
-               && '6'-'0' == 6
-               && '7'-'0' == 7
-               && '8'-'0' == 8
-               && '9'-'0' == 9);
+       /* C standard guarantees that '0'-'9' is a range */
        assert('b'-'a' == 1
                && 'c'-'a' == 2
                && 'd'-'a' == 3
@@ -865,10 +857,10 @@ int sc_val_from_str(char sign, unsigned base, const char *str,
                unsigned v;
                if (c >= '0' && c <= '9')
                        v = c - '0';
-               else if (c >= 'A' && c <= 'Z')
-                       v = c - 'A';
-               else if (c >= 'a' && c <= 'z')
-                       v = c - 'z';
+               else if (c >= 'A' && c <= 'F')
+                       v = c - 'A' + 10;
+               else if (c >= 'a' && c <= 'f')
+                       v = c - 'a' + 10;
                else
                        return 0;
 
index 44119bd..afb06da 100644 (file)
@@ -58,9 +58,6 @@
     target values */
 #define N_CONSTANTS 2048
 
-/* get the integer overflow mode */
-#define GET_OVERFLOW_MODE() int_overflow_mode
-
 /* unused, float to int doesn't work yet */
 enum float_to_int_mode {
        TRUNCATE,
@@ -236,7 +233,7 @@ static tarval *get_tarval_overflow(const void *value, int length, ir_mode *mode)
 
        case irms_int_number:
                if (sc_comp(value, get_mode_max(mode)->value) == 1) {
-                       switch (GET_OVERFLOW_MODE()) {
+                       switch (tarval_get_integer_overflow_mode()) {
                        case TV_OVERFLOW_SATURATE:
                                return get_mode_max(mode);
                        case TV_OVERFLOW_WRAP:
@@ -253,7 +250,7 @@ static tarval *get_tarval_overflow(const void *value, int length, ir_mode *mode)
                        }
                }
                if (sc_comp(value, get_mode_min(mode)->value) == -1) {
-                       switch (GET_OVERFLOW_MODE()) {
+                       switch (tarval_get_integer_overflow_mode()) {
                        case TV_OVERFLOW_SATURATE:
                                return get_mode_min(mode);
                        case TV_OVERFLOW_WRAP: {
@@ -321,9 +318,20 @@ static const ieee_descriptor_t *get_descriptor(const ir_mode *mode)
        }
 }
 
-/*
- *   public functions declared in tv.h
- */
+tarval *new_integer_tarval_from_str(const char *str, size_t len, char sign,
+                                    unsigned char base, ir_mode *mode)
+{
+       void *buffer;
+       int   ok;
+
+       buffer = alloca(sc_get_buffer_length());
+
+       ok = sc_val_from_str(sign, base, str, len, buffer);
+       if (!ok)
+               return tarval_bad;
+
+       return get_tarval_overflow(buffer, sc_get_buffer_length(), mode);
+}
 
 static tarval *new_tarval_from_str_int(const char *str, size_t len,
                                        ir_mode *mode)
@@ -372,7 +380,6 @@ static tarval *new_tarval_from_str_int(const char *str, size_t len,
        ok = sc_val_from_str(sign, base, str, len, buffer);
        if (!ok)
                return tarval_bad;
-       sign_extend(buffer, mode);
 
        return get_tarval_overflow(buffer, sc_get_buffer_length(), mode);
 }
@@ -905,6 +912,7 @@ tarval *tarval_convert_to(tarval *src, ir_mode *dst_mode)
        char                    *buffer;
        fp_value                *res;
        const ieee_descriptor_t *desc;
+       int                      len;
 
        carry_flag = -1;
 
@@ -979,11 +987,11 @@ tarval *tarval_convert_to(tarval *src, ir_mode *dst_mode)
                        buffer = alloca(100);
                        /* decimal string representation because hexadecimal output is
                         * interpreted unsigned by fc_val_from_str, so this is a HACK */
-                       snprintf(buffer, 100, "%s",
+                       len = snprintf(buffer, 100, "%s",
                                sc_print(src->value, get_mode_size_bits(src->mode), SC_DEC, mode_is_signed(src->mode)));
                        buffer[100 - 1] = '\0';
                        desc = get_descriptor(dst_mode);
-                       fc_val_from_str(buffer, 0, desc, NULL);
+                       fc_val_from_str(buffer, len, desc, NULL);
                        return get_tarval(fc_get_buffer(), fc_get_buffer_length(), dst_mode);
 
                default: