Commit 7971bd30 authored by Matthias Braun's avatar Matthias Braun
Browse files

cleanups and bugfixes in the tarval module and a new lower-level tarval...

cleanups and bugfixes in the tarval module and a new lower-level tarval interface 'new_integer_tarval_from_str'

[r27211]
parent 7d36daa8
......@@ -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
*
......
......@@ -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)
......
......@@ -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;
......
......@@ -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:
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment