X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Ftv%2Ftv.c;h=90d24bb7ad3bd40faa932986cb3544f0d5de6553;hb=464132f4d8840f7bb4228bfeef5484331bf50835;hp=5015ad2d648290a183d62ddbeb788eb6e57ebffe;hpb=1231c62d9c8be4cd4929dbcc2f8e4e6a218ad062;p=libfirm diff --git a/ir/tv/tv.c b/ir/tv/tv.c index 5015ad2d6..90d24bb7a 100644 --- a/ir/tv/tv.c +++ b/ir/tv/tv.c @@ -191,13 +191,8 @@ static tarval *get_tarval_overflow(const void *value, int length, ir_mode *mode) case TV_OVERFLOW_WRAP: { char *temp = alloca(sc_get_buffer_length()); - char *diff = alloca(sc_get_buffer_length()); - sc_sub(get_mode_max(mode)->value, get_mode_min(mode)->value, diff); - sc_val_from_ulong(1, temp); - sc_add(diff, temp, diff); - sc_sub(value, diff, temp); - while (sc_comp(temp, get_mode_max(mode)->value) == 1) - sc_sub(temp, diff, temp); + sc_val_from_ulong(-1, temp); + sc_and(temp, value, temp); return get_tarval(temp, length, mode); } case TV_OVERFLOW_BAD: @@ -213,13 +208,8 @@ static tarval *get_tarval_overflow(const void *value, int length, ir_mode *mode) case TV_OVERFLOW_WRAP: { char *temp = alloca(sc_get_buffer_length()); - char *diff = alloca(sc_get_buffer_length()); - sc_sub(get_mode_max(mode)->value, get_mode_min(mode)->value, diff); - sc_val_from_ulong(1, temp); - sc_add(diff, temp, diff); - sc_add(value, diff, temp); - while (sc_comp(temp, get_mode_max(mode)->value) == 1) - sc_add(temp, diff, temp); + sc_val_from_ulong(-1, temp); + sc_and(temp, value, temp); return get_tarval(temp, length, mode); } case TV_OVERFLOW_BAD: @@ -241,6 +231,7 @@ static tarval *get_tarval_overflow(const void *value, int length, ir_mode *mode) return get_mode_null(mode); } break; + default: break; } @@ -251,13 +242,12 @@ static tarval *get_tarval_overflow(const void *value, int length, ir_mode *mode) /* * public variables declared in tv.h */ -static tarval reserved_tv[5]; +static tarval reserved_tv[4]; tarval *tarval_bad = &reserved_tv[0]; tarval *tarval_undefined = &reserved_tv[1]; tarval *tarval_b_false = &reserved_tv[2]; tarval *tarval_b_true = &reserved_tv[3]; -tarval *tarval_P_void = &reserved_tv[4]; /* * public functions declared in tv.h @@ -303,13 +293,12 @@ tarval *new_tarval_from_str(const char *str, size_t len, ir_mode *mode) } return get_tarval(fc_get_buffer(), fc_get_buffer_length(), mode); + case irms_reference: + /* same as integer modes */ case irms_int_number: case irms_character: sc_val_from_str(str, len, NULL, mode); return get_tarval(sc_get_buffer(), sc_get_buffer_length(), mode); - - case irms_reference: - return get_tarval(str, len, mode); } assert(0); /* can't be reached, can it? */ @@ -330,6 +319,8 @@ tarval *new_tarval_from_long(long l, ir_mode *mode) /* XXX C semantics ! */ return l ? tarval_b_true : tarval_b_false ; + case irms_reference: + /* same as integer modes */ case irms_int_number: case irms_character: sc_val_from_long(l, NULL); @@ -338,9 +329,6 @@ tarval *new_tarval_from_long(long l, ir_mode *mode) case irms_float_number: return new_tarval_from_double((long double)l, mode); - case irms_reference: - return l ? tarval_bad : get_tarval(NULL, 0, mode); /* null pointer or tarval_bad */ - default: assert(0 && "unsupported mode sort"); } @@ -449,10 +437,6 @@ tarval *(get_tarval_b_true)(void) { return _get_tarval_b_true(); } -tarval *(get_tarval_P_void)(void) { - return _get_tarval_P_void(); -} - tarval *get_tarval_max(ir_mode *mode) { ANNOUNCE(); @@ -543,6 +527,8 @@ tarval *get_tarval_min(ir_mode *mode) return tarval_bad; } +static long _null_value; + tarval *get_tarval_null(ir_mode *mode) { ANNOUNCE(); @@ -570,7 +556,7 @@ tarval *get_tarval_null(ir_mode *mode) return new_tarval_from_long(0l, mode); case irms_reference: - return tarval_P_void; + return new_tarval_from_long(_null_value, mode); } return tarval_bad; } @@ -949,13 +935,13 @@ tarval *tarval_convert_to(tarval *src, ir_mode *m) break; } return get_tarval(fc_get_buffer(), fc_get_buffer_length(), m); -#if 0 + case irms_reference: /* allow 0 to be casted */ if (src == get_mode_null(src->mode)) return get_mode_null(m); break; -#endif + default: break; } @@ -1524,21 +1510,21 @@ int tarval_snprintf(char *buf, size_t len, tarval *tv) break; case irms_reference: - if (tv == tarval_P_void) return snprintf(buf, len, "NULL"); - if (tv->value != NULL){ - if (len > tv->length) { - memcpy(buf, tv->value, tv->length); - buf[tv->length] = '\0'; - } - else { - /* truncated */ - memcpy(buf, tv->value, len-1); - buf[len-1] = '\0'; + if (tv == tv->mode->null) return snprintf(buf, len, "NULL"); + if (tv->value != NULL) { + if (len > tv->length) { + memcpy(buf, tv->value, tv->length); + buf[tv->length] = '\0'; + } + else { + /* truncated */ + memcpy(buf, tv->value, len-1); + buf[len-1] = '\0'; + } + return tv->length; } - return tv->length; - } else - return snprintf(buf, len, "void"); + return snprintf(buf, len, "void"); case irms_internal_boolean: switch (mode_info->mode_output) { @@ -1647,7 +1633,7 @@ const tarval_mode_info *get_tarval_mode_output_option(ir_mode *mode) * Identifying tarvals values for algebraic simplifications. * * Returns: - * - TV_CLASSIFY_NULL for additive neutral, + * - TV_CLASSIFY_NULL for additive neutral or the NULL tarval for reference modes, * - TV_CLASSIFY_ONE for multiplicative neutral, * - TV_CLASSIFY_ALL_ONE for bitwise-and neutral * - TV_CLASSIFY_OTHER else @@ -1668,7 +1654,33 @@ tarval_classification_t classify_tarval(tarval *tv) return TV_CLASSIFY_OTHER; } -/** +/* + * Returns non-zero if a given (integer) tarval has only one single bit + * set. + */ +int is_single_bit_tarval(tarval *tv) { + int i, l; + int bits; + + if (!tv || tv == tarval_bad) return 0; + if (! mode_is_int(tv->mode)) return 0; + + l = get_mode_size_bytes(tv->mode); + for (bits = 0, i = l - 1; i >= 0; --i) { + unsigned char v = get_tarval_sub_bits(tv, (unsigned)i); + + /* check for more than one bit in these */ + if (v) { + if (v & (v-1)) + return 0; + if (++bits > 1) + return 0; + } + } + return bits; +} + +/* * Sets the overflow mode for integer operations. */ void tarval_set_integer_overflow_mode(tarval_int_overflow_mode_t ov_mode) { @@ -1700,13 +1712,14 @@ static const tarval_mode_info reference_output = { ")", }; - /* * Initialization of the tarval module: called before init_mode() */ -void init_tarval_1(void) +void init_tarval_1(long null_value) { ANNOUNCE(); + _null_value = null_value; + /* initialize the sets holding the tarvals with a comparison function and * an initial size, which is the expected number of constants */ tarvals = new_set(memcmp, N_CONSTANTS); @@ -1736,9 +1749,6 @@ void init_tarval_2(void) tarval_b_false->kind = k_tarval; tarval_b_false->mode = mode_b; - tarval_P_void->kind = k_tarval; - tarval_P_void->mode = mode_P; - /* * assign output modes that are compatible with the * old implementation: Hex output