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 @@ ...@@ -102,6 +102,26 @@
*/ */
tarval *new_tarval_from_str(const char *str, size_t len, ir_mode *mode); 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 * Constructor function for new tarvals
* *
......
...@@ -43,6 +43,11 @@ ...@@ -43,6 +43,11 @@
#include "xmalloc.h" #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 */ /** The number of extra precision rounding bits */
#define ROUNDING_BITS 2 #define ROUNDING_BITS 2
...@@ -837,211 +842,26 @@ int fc_get_buffer_length(void) ...@@ -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) void *fc_val_from_str(const char *str, unsigned int len, const ieee_descriptor_t *desc, void *result)
{ {
#if 0 char *buffer;
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) */
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 */ /* XXX excuse of an implementation to make things work */
LLDBL val; LLDBL val;
fp_value *tmp = alloca(calc_buffer_size); fp_value *tmp = alloca(calc_buffer_size);
ieee_descriptor_t tmp_desc; ieee_descriptor_t tmp_desc;
(void) len;
#if defined(HAVE_LONG_DOUBLE) && !defined(__CYGWIN__) buffer = alloca(len+1);
val = strtold(str, NULL); memcpy(buffer, str, len);
buffer[len] = '\0';
val = strtold(buffer, NULL);
DEBUGPRINTF(("val_from_str(%s)\n", str)); DEBUGPRINTF(("val_from_str(%s)\n", str));
tmp_desc.exponent_size = 15; tmp_desc.exponent_size = 15;
tmp_desc.mantissa_size = 63; tmp_desc.mantissa_size = 63;
tmp_desc.explicit_one = 1; tmp_desc.explicit_one = 1;
tmp_desc.clss = NORMAL; tmp_desc.clss = NORMAL;
fc_val_from_ieee754(val, &tmp_desc, tmp); 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); return fc_cast(tmp, desc, result);
#endif
} }
fp_value *fc_val_from_ieee754(LLDBL l, const ieee_descriptor_t *desc, fp_value *result) 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) ...@@ -817,15 +817,7 @@ void sign_extend(void *buffer, ir_mode *mode)
* The C-standard does theoretically allow otherwise. */ * The C-standard does theoretically allow otherwise. */
static inline void check_ascii(void) static inline void check_ascii(void)
{ {
assert('1'-'0' == 1 /* C standard guarantees that '0'-'9' is a range */
&& '2'-'0' == 2
&& '3'-'0' == 3
&& '4'-'0' == 4
&& '5'-'0' == 5
&& '6'-'0' == 6
&& '7'-'0' == 7
&& '8'-'0' == 8
&& '9'-'0' == 9);
assert('b'-'a' == 1 assert('b'-'a' == 1
&& 'c'-'a' == 2 && 'c'-'a' == 2
&& 'd'-'a' == 3 && 'd'-'a' == 3
...@@ -865,10 +857,10 @@ int sc_val_from_str(char sign, unsigned base, const char *str, ...@@ -865,10 +857,10 @@ int sc_val_from_str(char sign, unsigned base, const char *str,
unsigned v; unsigned v;
if (c >= '0' && c <= '9') if (c >= '0' && c <= '9')
v = c - '0'; v = c - '0';
else if (c >= 'A' && c <= 'Z') else if (c >= 'A' && c <= 'F')
v = c - 'A'; v = c - 'A' + 10;
else if (c >= 'a' && c <= 'z') else if (c >= 'a' && c <= 'f')
v = c - 'z'; v = c - 'a' + 10;
else else
return 0; return 0;
......
...@@ -58,9 +58,6 @@ ...@@ -58,9 +58,6 @@
target values */ target values */
#define N_CONSTANTS 2048 #define N_CONSTANTS 2048
/* get the integer overflow mode */
#define GET_OVERFLOW_MODE() int_overflow_mode
/* unused, float to int doesn't work yet */ /* unused, float to int doesn't work yet */
enum float_to_int_mode { enum float_to_int_mode {
TRUNCATE, TRUNCATE,
...@@ -236,7 +233,7 @@ static tarval *get_tarval_overflow(const void *value, int length, ir_mode *mode) ...@@ -236,7 +233,7 @@ static tarval *get_tarval_overflow(const void *value, int length, ir_mode *mode)
case irms_int_number: case irms_int_number:
if (sc_comp(value, get_mode_max(mode)->value) == 1) { if (sc_comp(value, get_mode_max(mode)->value) == 1) {
switch (GET_OVERFLOW_MODE()) { switch (tarval_get_integer_overflow_mode()) {
case TV_OVERFLOW_SATURATE: case TV_OVERFLOW_SATURATE:
return get_mode_max(mode); return get_mode_max(mode);
case TV_OVERFLOW_WRAP: case TV_OVERFLOW_WRAP:
...@@ -253,7 +250,7 @@ static tarval *get_tarval_overflow(const void *value, int length, ir_mode *mode) ...@@ -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) { if (sc_comp(value, get_mode_min(mode)->value) == -1) {
switch (GET_OVERFLOW_MODE()) { switch (tarval_get_integer_overflow_mode()) {
case TV_OVERFLOW_SATURATE: case TV_OVERFLOW_SATURATE:
return get_mode_min(mode); return get_mode_min(mode);
case TV_OVERFLOW_WRAP: { case TV_OVERFLOW_WRAP: {
...@@ -321,9 +318,20 @@ static const ieee_descriptor_t *get_descriptor(const ir_mode *mode) ...@@ -321,9 +318,20 @@ static const ieee_descriptor_t *get_descriptor(const ir_mode *mode)
} }
} }
/* tarval *new_integer_tarval_from_str(const char *str, size_t len, char sign,
* public functions declared in tv.h 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, static tarval *new_tarval_from_str_int(const char *str, size_t len,
ir_mode *mode) ir_mode *mode)
...@@ -372,7 +380,6 @@ static tarval *new_tarval_from_str_int(const char *str, size_t len, ...@@ -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); ok = sc_val_from_str(sign, base, str, len, buffer);
if (!ok) if (!ok)
return tarval_bad; return tarval_bad;
sign_extend(buffer, mode);
return get_tarval_overflow(buffer, sc_get_buffer_length(), 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) ...@@ -905,6 +912,7 @@ tarval *tarval_convert_to(tarval *src, ir_mode *dst_mode)
char *buffer; char *buffer;
fp_value *res; fp_value *res;
const ieee_descriptor_t *desc; const ieee_descriptor_t *desc;
int len;
carry_flag = -1; carry_flag = -1;
...@@ -979,11 +987,11 @@ tarval *tarval_convert_to(tarval *src, ir_mode *dst_mode) ...@@ -979,11 +987,11 @@ tarval *tarval_convert_to(tarval *src, ir_mode *dst_mode)
buffer = alloca(100); buffer = alloca(100);
/* decimal string representation because hexadecimal output is /* decimal string representation because hexadecimal output is
* interpreted unsigned by fc_val_from_str, so this is a HACK */ * 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))); sc_print(src->value, get_mode_size_bits(src->mode), SC_DEC, mode_is_signed(src->mode)));
buffer[100 - 1] = '\0'; buffer[100 - 1] = '\0';
desc = get_descriptor(dst_mode); 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); return get_tarval(fc_get_buffer(), fc_get_buffer_length(), dst_mode);
default: default:
......
Supports Markdown
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