X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Ftv%2Ftv.c;h=6c50d1dd69a703ea73defbbfbea836e00df8acad;hb=9d1fda9a8933dda2c16e90f1528b68d6d8c34685;hp=7b633ed17926dc096df364ecfbda13b7a4e7e223;hpb=493a2be714558086f03e0e2d17285e039c83a011;p=libfirm diff --git a/ir/tv/tv.c b/ir/tv/tv.c index 7b633ed17..6c50d1dd6 100644 --- a/ir/tv/tv.c +++ b/ir/tv/tv.c @@ -28,11 +28,15 @@ #include /* assertions */ #include /* atoi() */ -#include /* nice things for strings */ +#ifdef HAVE_STRING_H +# include /* nice things for strings */ +#endif #ifdef HAVE_STRINGS_H #include /* strings.h also includes bsd only function strcasecmp */ #endif -#include +#ifdef HAVE_STDLIB_H +# include +#endif #ifdef HAVE_ALLOCA_H # include #endif @@ -42,28 +46,28 @@ #include "tv_t.h" #include "set.h" /* to store tarvals in */ -/* #include "tune.h" */ /* some constants */ #include "entity_t.h" /* needed to store pointers to entities */ -#include "irmode.h" /* defines modes etc */ #include "irmode_t.h" #include "irnode.h" /* defines boolean return values (pnc_number)*/ -#include "host.h" #include "strcalc.h" #include "fltcalc.h" +#include "irtools.h" +#include "xmalloc.h" +#include "firm_common.h" /** Size of hash tables. Should correspond to average number of distinct constant target values */ #define N_CONSTANTS 2048 -/* XXX hack until theres's a proper interface */ -#define BAD 1 -#define SATURATE 2 -#define WRAP 3 -#define GET_OVERFLOW_MODE() BAD +/* get the integer overflow mode */ +#define GET_OVERFLOW_MODE() int_overflow_mode /* unused, float to int doesn't work yet */ -#define TRUNCATE 1 -#define ROUND 2 +enum float_to_int_mode { + TRUNCATE, + ROUND +}; + #define GET_FLOAT_TO_INT_MODE() TRUNCATE #define SWITCH_NOINFINITY 0 @@ -96,6 +100,7 @@ static long long count = 0; ****************************************************************************/ static struct set *tarvals; /* container for tarval structs */ static struct set *values; /* container for values */ +static tarval_int_overflow_mode_t int_overflow_mode = TV_OVERFLOW_WRAP; /**************************************************************************** * private functions @@ -134,7 +139,7 @@ INLINE static void tarval_verify(tarval *tv) static int hash_tv(tarval *tv) { - return ((unsigned int)tv->value ^ (unsigned int)tv->mode) + tv->length; + return (PTR_TO_INT(tv->value) ^ PTR_TO_INT(tv->mode)) + tv->length; } static int hash_val(const void *value, unsigned int length) @@ -152,12 +157,13 @@ static int hash_val(const void *value, unsigned int length) return hash; } -/* finds tarval with value/mode or creates new tarval */ +/** finds tarval with value/mode or creates new tarval */ static tarval *get_tarval(const void *value, int length, ir_mode *mode) { tarval tv; - tv.mode = mode; + tv.kind = k_tarval; + tv.mode = mode; tv.length = length; if (length > 0) { /* if there already is such a value, it is returned, else value @@ -171,6 +177,9 @@ static tarval *get_tarval(const void *value, int length, ir_mode *mode) return (tarval *)INSERT_TARVAL(&tv); } +/** + * handle overflow + */ static tarval *get_tarval_overflow(const void *value, int length, ir_mode *mode) { switch (get_mode_sort(mode)) @@ -178,21 +187,16 @@ 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()) { - case SATURATE: + case TV_OVERFLOW_SATURATE: return get_mode_max(mode); - case WRAP: + 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 BAD: + case TV_OVERFLOW_BAD: return tarval_bad; default: return get_tarval(value, length, mode); @@ -200,21 +204,16 @@ 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()) { - case SATURATE: + case TV_OVERFLOW_SATURATE: return get_mode_min(mode); - case WRAP: + 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 BAD: + case TV_OVERFLOW_BAD: return tarval_bad; default: return get_tarval(value, length, mode); @@ -233,23 +232,22 @@ static tarval *get_tarval_overflow(const void *value, int length, ir_mode *mode) return get_mode_null(mode); } break; + default: break; } return get_tarval(value, length, 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 @@ -295,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); + 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? */ @@ -314,7 +311,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) { ANNOUNCE(); - assert(mode && !((get_mode_sort(mode) == irms_memory)||(get_mode_sort(mode)==irms_control_flow)||(get_mode_sort(mode)==irms_auxiliary))); + assert(mode); switch(get_mode_sort(mode)) { @@ -322,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); @@ -330,11 +329,8 @@ 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); + assert(0 && "unsupported mode sort"); } return NULL; } @@ -342,8 +338,10 @@ 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); + ANNOUNCE(); - if (get_mode_sort(tv->mode) != irms_int_number) return 0; + if (sort != irms_int_number && sort != irms_character) return 0; if (get_mode_size_bits(tv->mode) > sizeof(long)<<3) { @@ -359,7 +357,7 @@ int tarval_is_long(tarval *tv) } /* this might overflow the machine's long, so use only with small values */ -long tarval_to_long(tarval* tv) +long get_tarval_long(tarval* tv) { ANNOUNCE(); assert(tarval_is_long(tv) && "tarval too big to fit in long"); @@ -395,7 +393,7 @@ int tarval_is_double(tarval *tv) return (get_mode_sort(tv->mode) == irms_float_number); } -long double tarval_to_double(tarval *tv) +long double get_tarval_double(tarval *tv) { ANNOUNCE(); assert(tarval_is_double(tv)); @@ -403,61 +401,14 @@ long double tarval_to_double(tarval *tv) return fc_val_to_float(tv->value); } -/* The tarval represents the address of the entity. As the address must - be constant the entity must have as owner the global type. */ -tarval *new_tarval_from_entity (entity *ent, ir_mode *mode) -{ - ANNOUNCE(); - assert(ent); - assert(mode && (get_mode_sort(mode) == irms_reference)); - - return get_tarval((void *)ent, 0, mode); -} -int tarval_is_entity(tarval *tv) -{ - ANNOUNCE(); - assert(tv); - /* tv->value == NULL means dereferencing a null pointer */ - return ((get_mode_sort(tv->mode) == irms_reference) && (tv->value != NULL) && (tv->length == 0) - && (tv != tarval_P_void)); -} - -entity *tarval_to_entity(tarval *tv) -{ - ANNOUNCE(); - assert(tv); - - if (tarval_is_entity(tv)) - return (entity *)tv->value; - else { - assert(0 && "tarval did not represent an entity"); - return NULL; - } -} - -void free_tarval_entity(entity *ent) { - /* There can be a tarval referencing this entity. Even if the - tarval is not used by the code any more, it can still reference - the entity as tarvals live indepently of the entity referenced. - Further the tarval is hashed into a set. If a hash function - evaluation happens to collide with this tarval, we will vrfy that - it contains a proper entity and we will crash if the entity is - freed. - - Unluckily, tarvals can neither be changed nor deleted, and to find - one, all existing reference modes have to be tried -> a facility - to retrieve all modes of a kind is needed. */ - ANNOUNCE(); -} /* * Access routines for tarval fields ======================================== */ -ir_mode *get_tarval_mode (tarval *tv) /* get the mode of the tarval */ -{ - ANNOUNCE(); - assert(tv); - return tv->mode; + +/* get the mode of the tarval */ +ir_mode *(get_tarval_mode)(const tarval *tv) { + return _get_tarval_mode(tv); } /* @@ -470,30 +421,20 @@ ir_mode *get_tarval_mode (tarval *tv) /* get the mode of the tarval */ * therefore the irmode functions should be prefered to the functions below. */ -tarval *get_tarval_bad(void) -{ - ANNOUNCE(); - return tarval_bad; -} -tarval *get_tarval_undefined(void) -{ - ANNOUNCE(); - return tarval_undefined; +tarval *(get_tarval_bad)(void) { + return _get_tarval_bad(); } -tarval *get_tarval_b_false(void) -{ - ANNOUNCE(); - return tarval_b_false; + +tarval *(get_tarval_undefined)(void) { + return _get_tarval_undefined(); } -tarval *get_tarval_b_true(void) -{ - ANNOUNCE(); - return tarval_b_true; + +tarval *(get_tarval_b_false)(void) { + return _get_tarval_b_false(); } -tarval *get_tarval_P_void(void) -{ - ANNOUNCE(); - return tarval_P_void; + +tarval *(get_tarval_b_true)(void) { + return _get_tarval_b_true(); } tarval *get_tarval_max(ir_mode *mode) @@ -501,7 +442,7 @@ tarval *get_tarval_max(ir_mode *mode) ANNOUNCE(); assert(mode); - if (get_mode_vector_elems(mode) > 1) { + if (get_mode_n_vector_elems(mode) > 1) { /* vector arithmetic not implemented yet */ return tarval_bad; } @@ -546,7 +487,7 @@ tarval *get_tarval_min(ir_mode *mode) ANNOUNCE(); assert(mode); - if (get_mode_vector_elems(mode) > 1) { + if (get_mode_n_vector_elems(mode) > 1) { /* vector arithmetic not implemented yet */ return tarval_bad; } @@ -586,12 +527,14 @@ tarval *get_tarval_min(ir_mode *mode) return tarval_bad; } +static long _null_value; + tarval *get_tarval_null(ir_mode *mode) { ANNOUNCE(); assert(mode); - if (get_mode_vector_elems(mode) > 1) { + if (get_mode_n_vector_elems(mode) > 1) { /* vector arithmetic not implemented yet */ return tarval_bad; } @@ -613,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; } @@ -623,7 +566,7 @@ tarval *get_tarval_one(ir_mode *mode) ANNOUNCE(); assert(mode); - if (get_mode_vector_elems(mode) > 1) { + if (get_mode_n_vector_elems(mode) > 1) { /* vector arithmetic not implemented yet */ return tarval_bad; } @@ -649,12 +592,42 @@ tarval *get_tarval_one(ir_mode *mode) return tarval_bad; } +tarval *get_tarval_minus_one(ir_mode *mode) +{ + ANNOUNCE(); + assert(mode); + + if (get_mode_n_vector_elems(mode) > 1) { + /* vector arithmetic not implemented yet */ + return tarval_bad; + } + + switch(get_mode_sort(mode)) + { + case irms_control_flow: + case irms_memory: + case irms_auxiliary: + case irms_internal_boolean: + case irms_reference: + assert(0); + break; + + case irms_float_number: + 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 tarval_bad; +} + tarval *get_tarval_nan(ir_mode *mode) { ANNOUNCE(); assert(mode); - if (get_mode_vector_elems(mode) > 1) { + if (get_mode_n_vector_elems(mode) > 1) { /* vector arithmetic not implemented yet */ return tarval_bad; } @@ -680,12 +653,12 @@ tarval *get_tarval_nan(ir_mode *mode) } } -tarval *get_tarval_inf(ir_mode *mode) +tarval *get_tarval_plus_inf(ir_mode *mode) { ANNOUNCE(); assert(mode); - if (get_mode_vector_elems(mode) > 1) { + if (get_mode_n_vector_elems(mode) > 1) { /* vector arithmetic not implemented yet */ return tarval_bad; } @@ -711,6 +684,37 @@ tarval *get_tarval_inf(ir_mode *mode) } } +tarval *get_tarval_minus_inf(ir_mode *mode) +{ + ANNOUNCE(); + assert(mode); + + if (get_mode_n_vector_elems(mode) > 1) { + /* vector arithmetic not implemented yet */ + return tarval_bad; + } + + if (get_mode_sort(mode) == irms_float_number) { + switch(get_mode_size_bits(mode)) + { + case 32: + fc_get_minusinf(8, 23, NULL); + break; + case 64: + fc_get_minusinf(11, 52, NULL); + break; + case 80: + fc_get_minusinf(15, 64, NULL); + break; + } + return get_tarval(fc_get_buffer(), fc_get_buffer_length(), mode); + } + else { + assert(0 && "tarval is not floating point"); + return tarval_bad; + } +} + /* * Arithmethic operations on tarvals ======================================== */ @@ -723,7 +727,7 @@ int tarval_is_negative(tarval *a) ANNOUNCE(); assert(a); - if (get_mode_vector_elems(a->mode) > 1) { + if (get_mode_n_vector_elems(a->mode) > 1) { /* vector arithmetic not implemented yet */ assert(0 && "tarval_is_negative is not allowed for vector modes"); return 0; @@ -768,18 +772,24 @@ int tarval_is_one(tarval *a) /* * comparison */ -pnc_number tarval_cmp(tarval *a, tarval *b) +pn_Cmp tarval_cmp(tarval *a, tarval *b) { ANNOUNCE(); assert(a); assert(b); - if (a == tarval_bad || b == tarval_bad) assert(0 && "Comparison with tarval_bad"); - if (a == tarval_undefined || b == tarval_undefined) return False; - if (a == b) return Eq; - if (a->mode != b->mode) return False; + if (a == tarval_bad || b == tarval_bad) { + assert(0 && "Comparison with tarval_bad"); + return pn_Cmp_False; + } + + if (a == tarval_undefined || b == tarval_undefined) + return pn_Cmp_False; + + if (a->mode != b->mode) + return pn_Cmp_False; - if (get_mode_vector_elems(a->mode) > 1) { + if (get_mode_n_vector_elems(a->mode) > 1) { /* vector arithmetic not implemented yet */ assert(0 && "cmp not implemented for vector modes"); } @@ -791,24 +801,34 @@ pnc_number tarval_cmp(tarval *a, tarval *b) case irms_memory: case irms_auxiliary: case irms_reference: - return False; + if (a == b) + return pn_Cmp_Eq; + return pn_Cmp_False; case irms_float_number: + /* + * BEWARE: we cannot compare a == b here, because + * a NaN is always Unordered to any other value, even to itself! + */ switch (fc_comp(a->value, b->value)) { - case -1: return Lt; - case 0: assert(0 && "different tarvals compare equal"); return Eq; - case 1: return Gt; - case 2: return Uo; - default: return False; + case -1: return pn_Cmp_Lt; + case 0: return pn_Cmp_Eq; + case 1: return pn_Cmp_Gt; + case 2: return pn_Cmp_Uo; + default: return pn_Cmp_False; } case irms_int_number: case irms_character: - return (sc_comp(a->value, b->value)==1)?(Gt):(Lt); + if (a == b) + return pn_Cmp_Eq; + return sc_comp(a->value, b->value) == 1 ? pn_Cmp_Gt : pn_Cmp_Lt; case irms_internal_boolean: - return (a == tarval_b_true)?(Gt):(Lt); + if (a == b) + return pn_Cmp_Eq; + return a == tarval_b_true ? pn_Cmp_Gt : pn_Cmp_Lt; } - return False; + return pn_Cmp_False; } /* @@ -824,7 +844,7 @@ tarval *tarval_convert_to(tarval *src, ir_mode *m) if (src->mode == m) return src; - if (get_mode_vector_elems(src->mode) > 1) { + if (get_mode_n_vector_elems(src->mode) > 1) { /* vector arithmetic not implemented yet */ return tarval_bad; } @@ -839,7 +859,7 @@ tarval *tarval_convert_to(tarval *src, ir_mode *m) /* cast float to something */ case irms_float_number: switch (get_mode_sort(m)) { - case irms_float_number: + case irms_float_number: switch (get_mode_size_bits(m)) { case 32: @@ -855,7 +875,6 @@ tarval *tarval_convert_to(tarval *src, ir_mode *m) break; } return get_tarval(fc_get_buffer(), fc_get_buffer_length(), m); - break; case irms_int_number: switch (GET_FLOAT_TO_INT_MODE()) @@ -867,14 +886,14 @@ tarval *tarval_convert_to(tarval *src, ir_mode *m) fc_rnd(src->value, NULL); break; default: + assert(0); break; } - /* XXX floating point unit can't produce a value in integer + /* FIXME: floating point unit can't produce a value in integer * representation * an intermediate representation is needed here first. */ /* return get_tarval(); */ return tarval_bad; - break; default: /* the rest can't be converted */ @@ -917,6 +936,12 @@ 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; } @@ -952,7 +977,6 @@ tarval *tarval_not(tarval *a) ANNOUNCE(); assert(a); - assert(mode_is_int(a->mode)); /* bitwise negation is only allowed for integer */ /* works for vector mode without changes */ @@ -963,7 +987,15 @@ tarval *tarval_not(tarval *a) sc_not(a->value, buffer); return get_tarval(buffer, a->length, a->mode); + case irms_internal_boolean: + if (a == tarval_b_true) + return tarval_b_false; + if (a == tarval_b_false) + return tarval_b_true; + return tarval_bad; + default: + assert(0 && "bitwise negation is only allowed for integer and boolean"); return tarval_bad; } } @@ -978,9 +1010,10 @@ tarval *tarval_neg(tarval *a) ANNOUNCE(); assert(a); assert(mode_is_num(a->mode)); /* negation only for numerical values */ - assert(mode_is_signed(a->mode)); /* negation is difficult without negative numbers, isn't it */ - if (get_mode_vector_elems(a->mode) > 1) { + /* note: negation is allowed even for unsigned modes. */ + + if (get_mode_n_vector_elems(a->mode) > 1) { /* vector arithmetic not implemented yet */ return tarval_bad; } @@ -1011,9 +1044,9 @@ tarval *tarval_add(tarval *a, tarval *b) ANNOUNCE(); assert(a); assert(b); - assert((a->mode == b->mode) || (get_mode_sort(a->mode) == irms_character && mode_is_int(b->mode))); + assert(a->mode == b->mode); - if (get_mode_vector_elems(a->mode) > 1 || get_mode_vector_elems(b->mode) > 1) { + if (get_mode_n_vector_elems(a->mode) > 1 || get_mode_n_vector_elems(b->mode) > 1) { /* vector arithmetic not implemented yet */ return tarval_bad; } @@ -1046,9 +1079,9 @@ tarval *tarval_sub(tarval *a, tarval *b) ANNOUNCE(); assert(a); assert(b); - assert((a->mode == b->mode) || (get_mode_sort(a->mode) == irms_character && mode_is_int(b->mode))); + assert(a->mode == b->mode); - if (get_mode_vector_elems(a->mode) > 1 || get_mode_vector_elems(b->mode) > 1) { + if (get_mode_n_vector_elems(a->mode) > 1 || get_mode_n_vector_elems(b->mode) > 1) { /* vector arithmetic not implemented yet */ return tarval_bad; } @@ -1080,9 +1113,9 @@ tarval *tarval_mul(tarval *a, tarval *b) ANNOUNCE(); assert(a); assert(b); - assert((a->mode == b->mode) && mode_is_num(a->mode)); + assert(a->mode == b->mode); - if (get_mode_vector_elems(a->mode) > 1) { + if (get_mode_n_vector_elems(a->mode) > 1) { /* vector arithmetic not implemented yet */ return tarval_bad; } @@ -1114,7 +1147,7 @@ tarval *tarval_quo(tarval *a, tarval *b) assert(b); assert((a->mode == b->mode) && mode_is_float(a->mode)); - if (get_mode_vector_elems(a->mode) > 1) { + if (get_mode_n_vector_elems(a->mode) > 1) { /* vector arithmetic not implemented yet */ return tarval_bad; } @@ -1134,7 +1167,7 @@ tarval *tarval_div(tarval *a, tarval *b) assert(b); assert((a->mode == b->mode) && mode_is_int(a->mode)); - if (get_mode_vector_elems(a->mode) > 1) { + if (get_mode_n_vector_elems(a->mode) > 1) { /* vector arithmetic not implemented yet */ return tarval_bad; } @@ -1157,7 +1190,7 @@ tarval *tarval_mod(tarval *a, tarval *b) assert(b); assert((a->mode == b->mode) && mode_is_int(a->mode)); - if (get_mode_vector_elems(a->mode) > 1) { + if (get_mode_n_vector_elems(a->mode) > 1) { /* vector arithmetic not implemented yet */ return tarval_bad; } @@ -1180,7 +1213,7 @@ tarval *tarval_abs(tarval *a) assert(a); assert(mode_is_num(a->mode)); - if (get_mode_vector_elems(a->mode) > 1) { + if (get_mode_n_vector_elems(a->mode) > 1) { /* vector arithmetic not implemented yet */ return tarval_bad; } @@ -1302,7 +1335,7 @@ tarval *tarval_shl(tarval *a, tarval *b) assert(b); assert(mode_is_int(a->mode) && mode_is_int(b->mode)); - if (get_mode_vector_elems(a->mode) > 1 || get_mode_vector_elems(a->mode) > 1) { + if (get_mode_n_vector_elems(a->mode) > 1 || get_mode_n_vector_elems(a->mode) > 1) { /* vector arithmetic not implemented yet */ return tarval_bad; } @@ -1332,7 +1365,7 @@ tarval *tarval_shr(tarval *a, tarval *b) assert(b); assert(mode_is_int(a->mode) && mode_is_int(b->mode)); - if (get_mode_vector_elems(a->mode) > 1 || get_mode_vector_elems(a->mode) > 1) { + if (get_mode_n_vector_elems(a->mode) > 1 || get_mode_n_vector_elems(a->mode) > 1) { /* vector arithmetic not implemented yet */ return tarval_bad; } @@ -1362,7 +1395,7 @@ tarval *tarval_shrs(tarval *a, tarval *b) assert(b); assert(mode_is_int(a->mode) && mode_is_int(b->mode)); - if (get_mode_vector_elems(a->mode) > 1 || get_mode_vector_elems(a->mode) > 1) { + if (get_mode_n_vector_elems(a->mode) > 1 || get_mode_n_vector_elems(a->mode) > 1) { /* vector arithmetic not implemented yet */ return tarval_bad; } @@ -1392,7 +1425,7 @@ tarval *tarval_rot(tarval *a, tarval *b) assert(b); assert(mode_is_int(a->mode) && mode_is_int(b->mode)); - if (get_mode_vector_elems(a->mode) > 1 || get_mode_vector_elems(a->mode) > 1) { + if (get_mode_n_vector_elems(a->mode) > 1 || get_mode_n_vector_elems(a->mode) > 1) { /* vector arithmetic not implemented yet */ return tarval_bad; } @@ -1411,6 +1444,13 @@ tarval *tarval_rot(tarval *a, tarval *b) return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode); } +/* + * carry flag of the last operation + */ +int tarval_carry(void) +{ + return sc_had_carry(); +} /* * Output of tarvals @@ -1470,30 +1510,19 @@ 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 (tarval_is_entity(tv)) { - if (get_entity_peculiarity((entity *)tv->value) != peculiarity_description) - return snprintf(buf, len, "%s%s%s", prefix, get_entity_ld_name((entity *)tv->value), suffix); - else { - if (mode_info->mode_output == TVO_NATIVE) - return snprintf(buf, len, "NULL"); - else - return snprintf(buf, len, "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 { - if (size > tv->length) { - memcpy(buf, tv->value, tv->length); - buf[tv->length] = '\0'; - } - else { - /* truncated */ - memcpy(buf, tv->value, size-1); - buf[size-1] = '\0'; + /* truncated */ + memcpy(buf, tv->value, len-1); + buf[len-1] = '\0'; + } + return tv->length; } - return tv->length; - } else return snprintf(buf, len, "void"); @@ -1514,7 +1543,7 @@ int tarval_snprintf(char *buf, size_t len, tarval *tv) case irms_control_flow: case irms_memory: case irms_auxiliary: - return snprintf(buf, len, ""); + return snprintf(buf, len, ""); } return 0; @@ -1535,15 +1564,30 @@ int tarval_printf(tarval *tv) { } -char *tarval_bitpattern(tarval *tv) +char *get_tarval_bitpattern(tarval *tv) { - return NULL; + int i, j, pos = 0; + int n = get_mode_size_bits(tv->mode); + int bytes = (n + 7) / 8; + char *res = xmalloc((n + 1) * sizeof(char)); + unsigned char byte; + + for(i = 0; i < bytes; i++) { + byte = get_tarval_sub_bits(tv, i); + for(j = 1; j < 256; j <<= 1) + if(pos < n) + res[pos++] = j & byte ? '1' : '0'; + } + + res[n] = '\0'; + + return res; } /* * access to the bitpattern */ -unsigned char tarval_sub_bits(tarval *tv, unsigned byte_ofs) +unsigned char get_tarval_sub_bits(tarval *tv, unsigned byte_ofs) { switch (get_mode_sort(tv->mode)) { case irms_int_number: @@ -1565,7 +1609,7 @@ unsigned char tarval_sub_bits(tarval *tv, unsigned byte_ofs) * * Returns zero on success. */ -int tarval_set_mode_output_option(ir_mode *mode, const tarval_mode_info *modeinfo) +int set_tarval_mode_output_option(ir_mode *mode, const tarval_mode_info *modeinfo) { assert(mode); @@ -1576,9 +1620,9 @@ int tarval_set_mode_output_option(ir_mode *mode, const tarval_mode_info *modeinf /* * Returns the output options of one mode. * - * This functions returns the modinfo of a given mode. + * This functions returns the mode info of a given mode. */ -const tarval_mode_info *tarval_get_mode_output_option(ir_mode *mode) +const tarval_mode_info *get_tarval_mode_output_option(ir_mode *mode) { assert(mode); @@ -1589,12 +1633,12 @@ const tarval_mode_info *tarval_get_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 */ -tarval_classification_t tarval_classify(tarval *tv) +tarval_classification_t classify_tarval(tarval *tv) { ANNOUNCE(); if (!tv || tv == tarval_bad) return TV_CLASSIFY_OTHER; @@ -1610,6 +1654,46 @@ tarval_classification_t tarval_classify(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) { + int_overflow_mode = ov_mode; +} + +/** + * Get the overflow mode for integer operations. + */ +tarval_int_overflow_mode_t tarval_get_integer_overflow_mode(void) { + return int_overflow_mode; +} + /** * default mode_info for output as HEX */ @@ -1628,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); @@ -1652,27 +1737,37 @@ void init_tarval_2(void) { ANNOUNCE(); - tarval_bad->mode = mode_BAD; - tarval_undefined->mode = mode_ANY; - tarval_b_true->mode = mode_b; - tarval_b_false->mode = mode_b; - tarval_P_void->mode = mode_P; + tarval_bad->kind = k_tarval; + tarval_bad->mode = mode_BAD; + tarval_bad->value = INT_TO_PTR(resid_tarval_bad); + + tarval_undefined->kind = k_tarval; + tarval_undefined->mode = mode_ANY; + tarval_undefined->value = INT_TO_PTR(resid_tarval_undefined); + + tarval_b_true->kind = k_tarval; + tarval_b_true->mode = mode_b; + tarval_b_true->value = INT_TO_PTR(resid_tarval_b_true); + + tarval_b_false->kind = k_tarval; + tarval_b_false->mode = mode_b; + tarval_b_false->value = INT_TO_PTR(resid_tarval_b_false); /* * assign output modes that are compatible with the * old implementation: Hex output */ - tarval_set_mode_output_option(mode_U, &hex_output); - tarval_set_mode_output_option(mode_C, &hex_output); - tarval_set_mode_output_option(mode_Bs, &hex_output); - tarval_set_mode_output_option(mode_Bu, &hex_output); - tarval_set_mode_output_option(mode_Hs, &hex_output); - tarval_set_mode_output_option(mode_Hu, &hex_output); - tarval_set_mode_output_option(mode_Is, &hex_output); - tarval_set_mode_output_option(mode_Iu, &hex_output); - tarval_set_mode_output_option(mode_Ls, &hex_output); - tarval_set_mode_output_option(mode_Lu, &hex_output); - tarval_set_mode_output_option(mode_P, &reference_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); + set_tarval_mode_output_option(mode_Hu, &hex_output); + set_tarval_mode_output_option(mode_Is, &hex_output); + set_tarval_mode_output_option(mode_Iu, &hex_output); + 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, &reference_output); } /* free all memory occupied by tarval. */