X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Ftv%2Ftv.c;h=38834a2ea7ed6095b90b0af6f1d48d5544fd2f99;hb=ee4f23d216ae0b6b4cb641e67228f6605da77d2b;hp=964af5619c94d1d7c73a15e4ceee0d193e311f5c;hpb=292eaf646e5ae35f2cedb91ea854c163db80eefa;p=libfirm diff --git a/ir/tv/tv.c b/ir/tv/tv.c index 964af5619..38834a2ea 100644 --- a/ir/tv/tv.c +++ b/ir/tv/tv.c @@ -57,6 +57,7 @@ #include "irtools.h" #include "xmalloc.h" #include "firm_common.h" +#include "error.h" /** Size of hash tables. Should correspond to average number of distinct constant target values */ @@ -100,7 +101,8 @@ static struct set *tarvals = NULL; /* container for tarval structs */ static struct set *values = NULL; /* container for values */ static tarval_int_overflow_mode_t int_overflow_mode = TV_OVERFLOW_WRAP; -#define no_float 0 +/** if this is set non-zero, the constant folding for floating point is OFF */ +static int no_float = 0; /**************************************************************************** * private functions @@ -180,21 +182,30 @@ static tarval *get_tarval(const void *value, int length, ir_mode *mode) { */ static tarval *get_tarval_overflow(const void *value, int length, ir_mode *mode) { + char *temp; + switch (get_mode_sort(mode)) { + case irms_reference: + /* addresses always wrap around */ + temp = alloca(sc_get_buffer_length()); + sc_val_from_ulong(-1, temp); + sc_and(temp, value, temp); + /* the sc_ module expects that all bits are set ... */ + sign_extend(temp, mode); + return get_tarval(temp, length, mode); + case irms_int_number: if (sc_comp(value, get_mode_max(mode)->value) == 1) { switch (GET_OVERFLOW_MODE()) { case TV_OVERFLOW_SATURATE: return get_mode_max(mode); case TV_OVERFLOW_WRAP: - { - char *temp = alloca(sc_get_buffer_length()); - sc_val_from_ulong(-1, temp); - sc_and(temp, value, temp); - /* the sc_ module expects that all bits are set ... */ - sign_extend(temp, mode); - return get_tarval(temp, length, mode); - } + temp = alloca(sc_get_buffer_length()); + sc_val_from_ulong(-1, temp); + sc_and(temp, value, temp); + /* the sc_ module expects that all bits are set ... */ + sign_extend(temp, mode); + return get_tarval(temp, length, mode); case TV_OVERFLOW_BAD: return tarval_bad; default: @@ -274,7 +285,7 @@ tarval *new_tarval_from_str(const char *str, size_t len, ir_mode *mode) return atoi(str) ? tarval_b_true : tarval_b_false; case irms_float_number: - switch(get_mode_size_bits(mode)) { + switch (get_mode_size_bits(mode)) { case 32: fc_val_from_str(str, len, 8, 23, NULL); break; @@ -287,12 +298,11 @@ 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: + /* same as integer modes */ + case irms_int_number: + sc_val_from_str(str, len, NULL, mode); + return get_tarval(sc_get_buffer(), sc_get_buffer_length(), mode); } assert(0); /* can't be reached, can it? */ @@ -305,7 +315,7 @@ tarval *new_tarval_from_str(const char *str, size_t len, ir_mode *mode) tarval *new_tarval_from_long(long l, ir_mode *mode) { assert(mode); - switch(get_mode_sort(mode)) { + switch (get_mode_sort(mode)) { case irms_internal_boolean: /* XXX C semantics ! */ return l ? tarval_b_true : tarval_b_false ; @@ -313,8 +323,8 @@ tarval *new_tarval_from_long(long l, ir_mode *mode) { case irms_reference: /* same as integer modes */ case irms_int_number: - case irms_character: sc_val_from_long(l, NULL); + sign_extend(sc_get_buffer(), mode); return get_tarval(sc_get_buffer(), sc_get_buffer_length(), mode); case irms_float_number: @@ -328,9 +338,8 @@ tarval *new_tarval_from_long(long l, ir_mode *mode) { /* returns non-zero if can be converted to long */ int tarval_is_long(tarval *tv) { - mode_sort sort = get_mode_sort(tv->mode); - - if (sort != irms_int_number && sort != irms_character) return 0; + if (!mode_is_int(tv->mode) && !mode_is_reference(tv->mode)) + return 0; if (get_mode_size_bits(tv->mode) > (int) (sizeof(long) << 3)) { /* the value might be too big to fit in a long */ @@ -355,13 +364,13 @@ tarval *new_tarval_from_double(long double d, ir_mode *mode) { switch (get_mode_size_bits(mode)) { case 32: - fc_val_from_float(d, 8, 23, NULL); + fc_val_from_ieee754(d, 8, 23, NULL); break; case 64: - fc_val_from_float(d, 11, 52, NULL); + fc_val_from_ieee754(d, 11, 52, NULL); break; case 80: - fc_val_from_float(d, 15, 64, NULL); + fc_val_from_ieee754(d, 15, 64, NULL); break; } return get_tarval(fc_get_buffer(), fc_get_buffer_length(), mode); @@ -377,7 +386,7 @@ int tarval_is_double(tarval *tv) { long double get_tarval_double(tarval *tv) { assert(tarval_is_double(tv)); - return fc_val_to_float(tv->value); + return fc_val_to_ieee754(tv->value); } @@ -397,7 +406,7 @@ ir_mode *(get_tarval_mode)(const tarval *tv) { * value. * The functions get_mode_{Max,Min,...} return tarvals retrieved from these * functions, but these are stored on initialization of the irmode module and - * therefore the irmode functions should be prefered to the functions below. + * therefore the irmode functions should be preferred to the functions below. */ tarval *(get_tarval_bad)(void) { @@ -425,7 +434,6 @@ tarval *get_tarval_max(ir_mode *mode) { } switch(get_mode_sort(mode)) { - case irms_reference: case irms_control_flow: case irms_memory: case irms_auxiliary: @@ -449,10 +457,10 @@ tarval *get_tarval_max(ir_mode *mode) { } return get_tarval(fc_get_buffer(), fc_get_buffer_length(), mode); - case irms_int_number: - case irms_character: - sc_max_from_bits(get_mode_size_bits(mode), mode_is_signed(mode), NULL); - return get_tarval(sc_get_buffer(), sc_get_buffer_length(), mode); + case irms_reference: + case irms_int_number: + sc_max_from_bits(get_mode_size_bits(mode), mode_is_signed(mode), NULL); + return get_tarval(sc_get_buffer(), sc_get_buffer_length(), mode); } return tarval_bad; } @@ -466,7 +474,6 @@ tarval *get_tarval_min(ir_mode *mode) { } switch(get_mode_sort(mode)) { - case irms_reference: case irms_control_flow: case irms_memory: case irms_auxiliary: @@ -490,16 +497,16 @@ tarval *get_tarval_min(ir_mode *mode) { } return get_tarval(fc_get_buffer(), fc_get_buffer_length(), mode); - case irms_int_number: - case irms_character: - sc_min_from_bits(get_mode_size_bits(mode), mode_is_signed(mode), NULL); - return get_tarval(sc_get_buffer(), sc_get_buffer_length(), mode); + case irms_reference: + case irms_int_number: + sc_min_from_bits(get_mode_size_bits(mode), mode_is_signed(mode), NULL); + return get_tarval(sc_get_buffer(), sc_get_buffer_length(), mode); } return tarval_bad; } /** The bit pattern for the pointer NULL */ -static long _null_value; +static long _null_value = 0; tarval *get_tarval_null(ir_mode *mode) { assert(mode); @@ -521,7 +528,6 @@ tarval *get_tarval_null(ir_mode *mode) { return new_tarval_from_double(0.0, mode); case irms_int_number: - case irms_character: return new_tarval_from_long(0l, mode); case irms_reference: @@ -551,7 +557,6 @@ tarval *get_tarval_one(ir_mode *mode) { return new_tarval_from_double(1.0, mode); case irms_int_number: - case irms_character: return new_tarval_from_long(1l, mode); break; } @@ -579,8 +584,7 @@ tarval *get_tarval_minus_one(ir_mode *mode) { return mode_is_signed(mode) ? new_tarval_from_double(-1.0, mode) : tarval_bad; case irms_int_number: - case irms_character: - return mode_is_signed(mode) ? new_tarval_from_long(-1l, mode) : tarval_bad; + return new_tarval_from_long(-1l, mode); } return tarval_bad; } @@ -743,13 +747,12 @@ pn_Cmp tarval_cmp(tarval *a, tarval *b) { case irms_control_flow: case irms_memory: case irms_auxiliary: - case irms_reference: if (a == b) return pn_Cmp_Eq; return pn_Cmp_False; case irms_float_number: - if(no_float) + if (no_float) return pn_Cmp_False; /* * BEWARE: we cannot compare a == b here, because @@ -762,8 +765,8 @@ pn_Cmp tarval_cmp(tarval *a, tarval *b) { case 2: return pn_Cmp_Uo; default: return pn_Cmp_False; } + case irms_reference: case irms_int_number: - case irms_character: if (a == b) return pn_Cmp_Eq; return sc_comp(a->value, b->value) == 1 ? pn_Cmp_Gt : pn_Cmp_Lt; @@ -843,10 +846,10 @@ tarval *tarval_convert_to(tarval *src, ir_mode *m) { /* cast int/characters to something */ case irms_int_number: - case irms_character: switch (get_mode_sort(m)) { + + case irms_reference: case irms_int_number: - case irms_character: buffer = alloca(sc_get_buffer_length()); memcpy(buffer, src->value, sc_get_buffer_length()); sign_extend(buffer, m); @@ -880,39 +883,24 @@ tarval *tarval_convert_to(tarval *src, ir_mode *m) { } return get_tarval(fc_get_buffer(), fc_get_buffer_length(), m); - case irms_reference: - /* allow 0 to be casted */ - if (src == get_mode_null(src->mode)) - return get_mode_null(m); - break; - default: break; } break; case irms_internal_boolean: - switch (get_mode_sort(m)) { - case irms_int_number: - if (src == tarval_b_true) return get_mode_one(m); - else return get_mode_null(m); - - default: - break; - } + /* beware: this is C semantic for the INTERNAL boolean mode */ + if (get_mode_sort(m) == irms_int_number) + return src == tarval_b_true ? get_mode_one(m) : get_mode_null(m); break; case irms_reference: - switch(get_mode_sort(m)) { - case irms_int_number: + if (get_mode_sort(m) == irms_int_number) { buffer = alloca(sc_get_buffer_length()); memcpy(buffer, src->value, sc_get_buffer_length()); sign_extend(buffer, src->mode); return get_tarval_overflow(buffer, src->length, m); - default: - break; } - break; } @@ -998,7 +986,6 @@ tarval *tarval_add(tarval *a, tarval *b) { } switch (get_mode_sort(a->mode)) { - case irms_character: case irms_int_number: /* modes of a,b are equal, so result has mode of a as this might be the character */ buffer = alloca(sc_get_buffer_length()); @@ -1032,7 +1019,6 @@ tarval *tarval_sub(tarval *a, tarval *b) { return tarval_bad; } switch (get_mode_sort(a->mode)) { - case irms_character: case irms_int_number: /* modes of a,b are equal, so result has mode of a as this might be the character */ buffer = alloca(sc_get_buffer_length()); @@ -1147,6 +1133,33 @@ tarval *tarval_mod(tarval *a, tarval *b) { return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode); } +/* + * integer division AND remainder + * overflow is impossible, but look out for division by zero + */ +tarval *tarval_divmod(tarval *a, tarval *b, tarval **mod) { + int len = sc_get_buffer_length(); + char *div_res = alloca(len); + char *mod_res = alloca(len); + + assert(a); + assert(b); + assert((a->mode == b->mode) && mode_is_int(a->mode)); + + if (get_mode_n_vector_elems(a->mode) > 1) { + /* vector arithmetic not implemented yet */ + return tarval_bad; + } + + + /* x/0 error */ + if (b == get_mode_null(b->mode)) return tarval_bad; + /* modes of a,b are equal */ + sc_divmod(a->value, b->value, div_res, mod_res); + *mod = get_tarval(mod_res, len, a->mode); + return get_tarval(div_res, len, a->mode); +} + /* * absolute value */ @@ -1395,7 +1408,6 @@ int tarval_snprintf(char *buf, size_t len, tarval *tv) { if (tv == tv->mode->null) return snprintf(buf, len, "NULL"); /* fall through */ case irms_int_number: - case irms_character: switch (mode_info->mode_output) { case TVO_DECIMAL: @@ -1488,16 +1500,13 @@ char *get_tarval_bitpattern(tarval *tv) { * access to the bitpattern */ unsigned char get_tarval_sub_bits(tarval *tv, unsigned byte_ofs) { - switch (get_mode_sort(tv->mode)) { - case irms_int_number: - case irms_character: - return sc_sub_bits(tv->value, tv->length, byte_ofs); - - case irms_float_number: + switch (get_mode_arithmetic(tv->mode)) { + case irma_twos_complement: + return sc_sub_bits(tv->value, get_mode_size_bits(tv->mode), byte_ofs); + case irma_ieee754: return fc_sub_bits(tv->value, get_mode_size_bits(tv->mode), byte_ofs); - default: - return 0; + panic("get_tarval_sub_bits(): arithmetic mode not supported"); } } @@ -1543,7 +1552,7 @@ tarval_classification_t classify_tarval(tarval *tv) { else if (tv == get_mode_one(tv->mode)) return TV_CLASSIFY_ONE; else if ((get_mode_sort(tv->mode) == irms_int_number) - && (tv == new_tarval_from_long(-1, tv->mode))) + && (tv == get_mode_minus_one(tv->mode))) return TV_CLASSIFY_ALL_ONE; return TV_CLASSIFY_OTHER; @@ -1553,7 +1562,7 @@ tarval_classification_t classify_tarval(tarval *tv) { * Returns non-zero if a given (integer) tarval has only one single bit * set. */ -int is_single_bit_tarval(tarval *tv) { +int tarval_is_single_bit(tarval *tv) { int i, l; int bits; @@ -1575,6 +1584,31 @@ int is_single_bit_tarval(tarval *tv) { return bits; } +/* + * Returns non-zero if the mantissa of a floating point IEEE-754 + * tarval is zero (i.e. 1.0Exxx) + */ +int tarval_ieee754_zero_mantissa(tarval *tv) { + assert(get_mode_arithmetic(tv->mode) == irma_ieee754); + return fc_zero_mantissa(tv->value); +} + +/* Returns the exponent of a floating point IEEE-754 tarval. */ +int tarval_ieee754_get_exponent(tarval *tv) { + assert(get_mode_arithmetic(tv->mode) == irma_ieee754); + return fc_get_exponent(tv->value); +} + +/* Set the immediate precision for IEEE-754 results. */ +unsigned tarval_ieee754_set_immediate_precision(unsigned bits) { + return fc_set_immediate_precision(bits); +} + +/* Returns non-zero if the result of the last IEEE-754 operation was exact. */ +unsigned tarval_ieee754_get_exact(void) { + return fc_is_exact(); +} + /* * Sets the overflow mode for integer operations. */ @@ -1582,13 +1616,19 @@ void tarval_set_integer_overflow_mode(tarval_int_overflow_mode_t ov_mode) { int_overflow_mode = ov_mode; } -/** - * Get the overflow mode for integer operations. - */ +/* Get the overflow mode for integer operations. */ tarval_int_overflow_mode_t tarval_get_integer_overflow_mode(void) { return int_overflow_mode; } +/* Enable/Disable floating point constant folding. */ +int tarval_enable_fp_ops(int enable) { + int old = !no_float; + + no_float = !enable; + return old; +} + /** * default mode_info for output as HEX */ @@ -1638,8 +1678,6 @@ void init_tarval_2(void) { * assign output modes that are compatible with the * old implementation: Hex output */ - set_tarval_mode_output_option(mode_U, &hex_output); - set_tarval_mode_output_option(mode_C, &hex_output); set_tarval_mode_output_option(mode_Bs, &hex_output); set_tarval_mode_output_option(mode_Bu, &hex_output); set_tarval_mode_output_option(mode_Hs, &hex_output); @@ -1649,12 +1687,12 @@ void init_tarval_2(void) { set_tarval_mode_output_option(mode_Ls, &hex_output); set_tarval_mode_output_option(mode_Lu, &hex_output); set_tarval_mode_output_option(mode_P, &hex_output); - } +} /* free all memory occupied by tarval. */ void finish_tarval(void) { - finish_strcalc (); - finish_fltcalc (); + finish_strcalc(); + finish_fltcalc(); del_set(tarvals); tarvals = NULL; del_set(values); values = NULL; }