From: Matthias Braun Date: Wed, 24 Feb 2010 15:04:40 +0000 (+0000) Subject: cleanups and bugfixes in the tarval module and a new lower-level tarval interface... X-Git-Url: http://nsz.repo.hu/git/?a=commitdiff_plain;h=7971bd301f173d9d926cf40a4bdb700f42b8c07a;p=libfirm cleanups and bugfixes in the tarval module and a new lower-level tarval interface 'new_integer_tarval_from_str' [r27211] --- diff --git a/include/libfirm/tv.h b/include/libfirm/tv.h index 5b3cdda14..aba6bcc3f 100644 --- a/include/libfirm/tv.h +++ b/include/libfirm/tv.h @@ -102,6 +102,26 @@ */ 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 * diff --git a/ir/tv/fltcalc.c b/ir/tv/fltcalc.c index f72d1c573..4480a269f 100644 --- a/ir/tv/fltcalc.c +++ b/ir/tv/fltcalc.c @@ -43,6 +43,11 @@ #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) diff --git a/ir/tv/strcalc.c b/ir/tv/strcalc.c index d57f0f168..50aaf5689 100644 --- a/ir/tv/strcalc.c +++ b/ir/tv/strcalc.c @@ -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; diff --git a/ir/tv/tv.c b/ir/tv/tv.c index 44119bd2c..afb06da9b 100644 --- a/ir/tv/tv.c +++ b/ir/tv/tv.c @@ -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: