X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Ftv%2Ftv.c;h=7af7434e5bafb849e7a75004bef963059cf799d6;hb=f73f5c542edb2e4ff58a4bdc4f9d53415a14c4a1;hp=88fea2e7e3987112800d7871ac18023b85a57022;hpb=1e59380bf916bbdd3bed881ec0d07acbf3769ec5;p=libfirm diff --git a/ir/tv/tv.c b/ir/tv/tv.c index 88fea2e7e..7af7434e5 100644 --- a/ir/tv/tv.c +++ b/ir/tv/tv.c @@ -1,60 +1,71 @@ -/* TV --- Target Values, aka Constant Table. - Copyright (C) 1995, 1996 Christian von Roques */ - -/* $Id$ */ +/* + * Project: libFIRM + * File name: ir/tv/tv.c + * Purpose: Representation of and static computations on target machine + * values. + * Author: Mathias Heil + * Modified by: + * Created: + * CVS-ID: $Id$ + * Copyright: (c) 2003 Universität Karlsruhe + * Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE. + */ -/****i* tv/implementation - * - * AUTHORS - * Christian von Roques - * Matthias Heil - * - * NOTES - * Internal storage for tarvals, 1st draft: - * Integers as well as pointers are stored in a hex formatted string holding - * 16 characters. Booleans are not stored as there are only two of them. +/* + * Values are stored in a format depending upon chosen arithmetic + * module. Default uses strcalc and fltcalc. * - * Floats are just reinterpreted as byte strings, because I am not sure if - * there is loss if I convert float to long double and back and furthermore - * the implementation of a fully ieee compatible floating point emulation - * is not sensible for now - * With this information it is easy to decide the kind of stored value: - * Integers have size 16, floats 4, doubles 8, long doubles 12. - ******/ + */ /* This implementation assumes: - * both host and target have IEEE-754 floating-point arithmetic. */ + * - target has IEEE-754 floating-point arithmetic. */ -/* !!! float and double divides MUST NOT SIGNAL !!! */ -/* @@@ query the floating-point expception status flags */ - -/* @@@ Problem: All Values are stored twice, once as Univ_*s and a 2nd - time in their real target mode. :-( */ - -#define MAX_INT_LENGTH 8 -#define CHAR_BUFFER_SIZE ((MAX_INT_LENGTH) * 2) #ifdef HAVE_CONFIG_H -# include +# include "config.h" #endif + #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_ALLOCA_H +# include +#endif +#ifdef HAVE_MALLOC_H +# include +#endif -#include #include "tv_t.h" #include "set.h" /* to store tarvals in */ -#include "tune.h" /* some constants */ +/* #include "tune.h" */ /* some constants */ #include "entity_t.h" /* needed to store pointers to entities */ -#include "irmode.h" /* defines modes etc */ -#include "irnode.h" /* defines boolean return values */ -#include "xprintf.h" -#include "xp_help.h" -#include "host.h" +#include "irmode_t.h" +#include "irnode.h" /* defines boolean return values (pnc_number)*/ #include "strcalc.h" #include "fltcalc.h" +/** Size of hash tables. Should correspond to average number of distinct constant + 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 */ +#define TRUNCATE 1 +#define ROUND 2 +#define GET_FLOAT_TO_INT_MODE() TRUNCATE + +#define SWITCH_NOINFINITY 0 +#define SWITCH_NODENORMALS 0 + /**************************************************************************** * local definitions and macros ****************************************************************************/ @@ -82,6 +93,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 @@ -98,8 +110,11 @@ static void _fail_verify(tarval *tv, const char* file, int line) printf("%s:%d: Invalid tarval (null)", file, line); assert(0); } +#ifdef __GNUC__ +INLINE static void tarval_verify(tarval *tv) __attribute__ ((unused)); +#endif -static void tarval_verify(tarval *tv) +INLINE static void tarval_verify(tarval *tv) { assert(tv); assert(tv->mode); @@ -135,64 +150,112 @@ 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.length = length; - if (length > 0) + if (length > 0) { /* if there already is such a value, it is returned, else value * is copied into the set */ tv.value = INSERT_VALUE(value, length); - else + } else { tv.value = value; - + } /* if there is such a tarval, it is returned, else tv is copied * into the set */ return (tarval *)INSERT_TARVAL(&tv); } /** - * Returns non-zero if a tarval overflows. - * - * @todo Implementation did not work on all modes + * handle overflow */ -static int overflows(tarval *tv) +static tarval *get_tarval_overflow(const void *value, int length, ir_mode *mode) { - switch (get_mode_sort(tv->mode)) + switch (get_mode_sort(mode)) { - case character: - case int_number: - if (sc_comp(tv->value, get_mode_max(tv->mode)->value) == 1) return 1; - if (sc_comp(tv->value, get_mode_min(tv->mode)->value) == -1) return 1; + 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()); + 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); + return get_tarval(temp, length, mode); + } + case TV_OVERFLOW_BAD: + return tarval_bad; + default: + return get_tarval(value, length, mode); + } + } + if (sc_comp(value, get_mode_min(mode)->value) == -1) { + switch (GET_OVERFLOW_MODE()) { + case TV_OVERFLOW_SATURATE: + return get_mode_min(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); + return get_tarval(temp, length, mode); + } + case TV_OVERFLOW_BAD: + return tarval_bad; + default: + return get_tarval(value, length, mode); + } + } break; - case float_number: - if (fc_comp(tv->value, get_mode_max(tv->mode)->value) == 1) return 1; - if (fc_comp(tv->value, get_mode_min(tv->mode)->value) == -1) return 1; - break; + case irms_float_number: + if (SWITCH_NOINFINITY && fc_is_inf(value)) + { + return fc_is_negative(value)?get_mode_min(mode):get_mode_max(mode); + } + if (SWITCH_NODENORMALS && fc_is_subnormal(value)) + { + return get_mode_null(mode); + } + break; default: break; } - - return 0; + return get_tarval(value, length, mode); } -/**************************************************************************** + +/* * public variables declared in tv.h - ****************************************************************************/ -tarval *tarval_bad; -tarval *tarval_undefined; -tarval *tarval_b_false; -tarval *tarval_b_true; -tarval *tarval_P_void; + */ +static tarval reserved_tv[5]; -/**************************************************************************** +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 - ****************************************************************************/ + */ + /* * Constructors ============================================================= */ @@ -205,27 +268,40 @@ tarval *new_tarval_from_str(const char *str, size_t len, ir_mode *mode) switch (get_mode_sort(mode)) { - case auxiliary: + case irms_control_flow: + case irms_memory: + case irms_auxiliary: assert(0); break; - case internal_boolean: - /* match tTrRuUeE/fFaAlLsSeE */ + case irms_internal_boolean: + /* match [tT][rR][uU][eE]|[fF][aA][lL][sS][eE] */ if (strcasecmp(str, "true")) return tarval_b_true; else if (strcasecmp(str, "false")) return tarval_b_true; else - return atoi(str) ? tarval_b_true : tarval_b_false; + /* XXX This is C semantics */ + return atoi(str) ? tarval_b_true : tarval_b_false; - case float_number: - fc_val_from_str(str, len); + case irms_float_number: + switch(get_mode_size_bits(mode)) { + case 32: + fc_val_from_str(str, len, 8, 23, NULL); + break; + case 64: + fc_val_from_str(str, len, 11, 52, NULL); + break; + case 80: + fc_val_from_str(str, len, 15, 64, NULL); + break; + } return get_tarval(fc_get_buffer(), fc_get_buffer_length(), mode); - case int_number: - case character: - sc_val_from_str(str, len); + case irms_int_number: + case irms_character: + sc_val_from_str(str, len, NULL); return get_tarval(sc_get_buffer(), sc_get_buffer_length(), mode); - case reference: + case irms_reference: return get_tarval(str, len, mode); } @@ -233,42 +309,29 @@ tarval *new_tarval_from_str(const char *str, size_t len, ir_mode *mode) return NULL; } -#if 0 -int tarval_is_str(tarval *tv) -{ - ANNOUNCE(); - assert(tv); - - return ((get_mode_sort(tv->mode) == reference) && (tv->value != NULL) && (tv->length > 0)); -} -char *tarval_to_str(tarval *tv) -{ - ANNOUNCE(); - assert(tarval_is_str(tv)); - return (char *)tv->value; -} -#endif - +/* + * helper function, create a tarval from long + */ tarval *new_tarval_from_long(long l, ir_mode *mode) { ANNOUNCE(); - assert(mode && !(get_mode_sort(mode) == auxiliary)); + assert(mode && !((get_mode_sort(mode) == irms_memory)||(get_mode_sort(mode)==irms_control_flow)||(get_mode_sort(mode)==irms_auxiliary))); switch(get_mode_sort(mode)) { - case internal_boolean: - /* XXX C-Semantics ! */ + case irms_internal_boolean: + /* XXX C semantics ! */ return l ? tarval_b_true : tarval_b_false ; - case int_number: - case character: - sc_val_from_long(l); + case irms_int_number: + case irms_character: + sc_val_from_long(l, NULL); return get_tarval(sc_get_buffer(), sc_get_buffer_length(), mode); - case float_number: + case irms_float_number: return new_tarval_from_double((long double)l, mode); - case reference: + case irms_reference: return l ? tarval_bad : get_tarval(NULL, 0, mode); /* null pointer or tarval_bad */ default: @@ -277,39 +340,63 @@ tarval *new_tarval_from_long(long l, ir_mode *mode) return NULL; } +/* returns non-zero if can be converted to long */ int tarval_is_long(tarval *tv) { ANNOUNCE(); - return ((get_mode_sort(tv->mode) == int_number) || (get_mode_sort(tv->mode) == character)); + if (get_mode_sort(tv->mode) != irms_int_number) return 0; + + if (get_mode_size_bits(tv->mode) > sizeof(long)<<3) + { + /* the value might be too big to fit in a long */ + sc_max_from_bits(sizeof(long)<<3, 0, NULL); + if (sc_comp(sc_get_buffer(), tv->value) == -1) + { + /* really doesn't fit */ + return 0; + } + } + return 1; } /* 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(tv && get_mode_sort(tv->mode) == int_number); + assert(tarval_is_long(tv) && "tarval too big to fit in long"); - return sc_val_to_long(tv->value); /* might overflow */ + return sc_val_to_long(tv->value); } tarval *new_tarval_from_double(long double d, ir_mode *mode) { ANNOUNCE(); - assert(mode && (get_mode_sort(mode) == float_number)); + assert(mode && (get_mode_sort(mode) == irms_float_number)); - fc_val_from_float(d); + switch (get_mode_size_bits(mode)) { + case 32: + fc_val_from_float(d, 8, 23, NULL); + break; + case 64: + fc_val_from_float(d, 11, 52, NULL); + break; + case 80: + fc_val_from_float(d, 15, 64, NULL); + break; + } return get_tarval(fc_get_buffer(), fc_get_buffer_length(), mode); } +/* returns non-zero if can be converted to double */ int tarval_is_double(tarval *tv) { ANNOUNCE(); assert(tv); - return (get_mode_sort(tv->mode) == float_number); + 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)); @@ -317,52 +404,25 @@ 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) == 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) == reference) && (tv->value != NULL) && (tv->length == 0)); -} - -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; - } -} /* * Access routines for tarval fields ======================================== */ -#ifdef TARVAL_ACCESS_DEFINES -# undef get_tarval_mode -#endif ir_mode *get_tarval_mode (tarval *tv) /* get the mode of the tarval */ { ANNOUNCE(); assert(tv); return tv->mode; } -#ifdef TARVAL_ACCESS_DEFINES -# define get_tarval_mode(tv) (tv)->mode -#endif + +/* +void *get_tarval_link (tarval *tv) +{ + ANNOUNCE (); + assert (tv); + return (tv->link); +} +*/ /* * Special value query functions ============================================ @@ -405,23 +465,41 @@ tarval *get_tarval_max(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 reference: - case auxiliary: + case irms_reference: + case irms_control_flow: + case irms_memory: + case irms_auxiliary: assert(0); break; - case internal_boolean: + case irms_internal_boolean: return tarval_b_true; - case float_number: - fc_get_max(get_mode_size_bits(mode)); + case irms_float_number: + switch(get_mode_size_bits(mode)) + { + case 32: + fc_get_max(8, 23, NULL); + break; + case 64: + fc_get_max(11, 52, NULL); + break; + case 80: + fc_get_max(15, 64, NULL); + break; + } return get_tarval(fc_get_buffer(), fc_get_buffer_length(), mode); - case int_number: - case character: - sc_max_from_bits(get_mode_size_bits(mode), mode_is_signed(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); } return tarval_bad; @@ -432,23 +510,41 @@ tarval *get_tarval_min(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 reference: - case auxiliary: + case irms_reference: + case irms_control_flow: + case irms_memory: + case irms_auxiliary: assert(0); break; - case internal_boolean: + case irms_internal_boolean: return tarval_b_false; - case float_number: - fc_get_min(get_mode_size_bits(mode)); + case irms_float_number: + switch(get_mode_size_bits(mode)) + { + case 32: + fc_get_min(8, 23, NULL); + break; + case 64: + fc_get_min(11, 52, NULL); + break; + case 80: + fc_get_min(15, 64, NULL); + break; + } return get_tarval(fc_get_buffer(), fc_get_buffer_length(), mode); - case int_number: - case character: - sc_min_from_bits(get_mode_size_bits(mode), mode_is_signed(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); } return tarval_bad; @@ -459,21 +555,28 @@ tarval *get_tarval_null(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 auxiliary: - case internal_boolean: + case irms_control_flow: + case irms_memory: + case irms_auxiliary: + case irms_internal_boolean: assert(0); break; - case float_number: + case irms_float_number: return new_tarval_from_double(0.0, mode); - case int_number: - case character: + case irms_int_number: + case irms_character: return new_tarval_from_long(0l, mode); - case reference: + case irms_reference: return tarval_P_void; } return tarval_bad; @@ -484,19 +587,26 @@ tarval *get_tarval_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 auxiliary: - case internal_boolean: - case reference: + case irms_control_flow: + case irms_memory: + case irms_auxiliary: + case irms_internal_boolean: + case irms_reference: assert(0); break; - case float_number: + case irms_float_number: return new_tarval_from_double(1.0, mode); - case int_number: - case character: + case irms_int_number: + case irms_character: return new_tarval_from_long(1l, mode); break; } @@ -507,47 +617,121 @@ tarval *get_tarval_nan(ir_mode *mode) { ANNOUNCE(); assert(mode); - assert(get_mode_sort(mode) == float_number); - fc_get_nan(); - return get_tarval(fc_get_buffer(), fc_get_buffer_length(), 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_qnan(8, 23, NULL); + break; + case 64: + fc_get_qnan(11, 52, NULL); + break; + case 80: + fc_get_qnan(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; + } } tarval *get_tarval_inf(ir_mode *mode) { ANNOUNCE(); assert(mode); - assert(get_mode_sort(mode) == float_number); - fc_get_inf(); - return get_tarval(fc_get_buffer(), fc_get_buffer_length(), 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_plusinf(8, 23, NULL); + break; + case 64: + fc_get_plusinf(11, 52, NULL); + break; + case 80: + fc_get_plusinf(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 ======================================== */ -/* test if negative number, 1 means 'yes' */ +/* + * test if negative number, 1 means 'yes' + */ int tarval_is_negative(tarval *a) { ANNOUNCE(); assert(a); + 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; + } + switch (get_mode_sort(a->mode)) { - case int_number: + case irms_int_number: if (!mode_is_signed(a->mode)) return 0; - else return sc_comp(a->value, get_mode_null(a->mode)->value); + else + return sc_comp(a->value, get_mode_null(a->mode)->value) == -1 ? 1 : 0; - case float_number: - return fc_comp(a->value, get_mode_null(a->mode)->value); + case irms_float_number: + return fc_comp(a->value, get_mode_null(a->mode)->value) == -1 ? 1 : 0; default: assert(0 && "not implemented"); + return 0; } } -/* comparison */ +/* + * test if null, 1 means 'yes' + */ +int tarval_is_null(tarval *a) +{ + ir_mode *m = get_tarval_mode(a); + + return a == get_tarval_null(m); +} + +/* + * test if one, 1 means 'yes' + */ +int tarval_is_one(tarval *a) +{ + ir_mode *m = get_tarval_mode(a); + + return a == get_tarval_one(m); +} + +/* + * comparison + */ pnc_number tarval_cmp(tarval *a, tarval *b) { ANNOUNCE(); @@ -557,76 +741,153 @@ pnc_number tarval_cmp(tarval *a, tarval *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 (get_tarval_mode(a) != get_tarval_mode(b)) return Uo; + if (a->mode != b->mode) return False; + + if (get_mode_n_vector_elems(a->mode) > 1) { + /* vector arithmetic not implemented yet */ + assert(0 && "cmp not implemented for vector modes"); + } /* Here the two tarvals are unequal and of the same mode */ switch (get_mode_sort(a->mode)) { - case auxiliary: + case irms_control_flow: + case irms_memory: + case irms_auxiliary: + case irms_reference: return False; - case float_number: - return (fc_comp(a->value, b->value)==1)?(Gt):(Lt); - - case int_number: - case character: + case irms_float_number: + 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 irms_int_number: + case irms_character: return (sc_comp(a->value, b->value)==1)?(Gt):(Lt); - case internal_boolean: + case irms_internal_boolean: return (a == tarval_b_true)?(Gt):(Lt); - - case reference: - return Uo; } return False; } +/* + * convert to other mode + */ tarval *tarval_convert_to(tarval *src, ir_mode *m) { - ANNOUNCE(); - tarval tv; + char *buffer; + ANNOUNCE(); assert(src); assert(m); if (src->mode == m) return src; + if (get_mode_n_vector_elems(src->mode) > 1) { + /* vector arithmetic not implemented yet */ + return tarval_bad; + } + switch (get_mode_sort(src->mode)) { - case auxiliary: + case irms_control_flow: + case irms_memory: + case irms_auxiliary: break; - case float_number: - break; + /* cast float to something */ + case irms_float_number: + switch (get_mode_sort(m)) { + case irms_float_number: + switch (get_mode_size_bits(m)) + { + case 32: + fc_cast(src->value, 8, 23, NULL); + break; + case 64: + fc_cast(src->value, 11, 52, NULL); + break; + case 80: + fc_cast(src->value, 15, 64, NULL); + break; + default: + break; + } + return get_tarval(fc_get_buffer(), fc_get_buffer_length(), m); - case int_number: - switch (get_mode_sort(m)) - { - case int_number: - case character: - tv.mode = m; - tv.length = src->length; - tv.value = src->value; - if (overflows(&tv)) + case irms_int_number: + switch (GET_FLOAT_TO_INT_MODE()) { - return tarval_bad; + case TRUNCATE: + fc_int(src->value, NULL); + break; + case ROUND: + fc_rnd(src->value, NULL); + break; + default: + break; } - return INSERT_TARVAL(&tv); + /* XXX floating point unit can't produce a value in integer + * representation + * an intermediate representation is needed here first. */ + /* return get_tarval(); */ + return tarval_bad; - case internal_boolean: + default: + /* the rest can't be converted */ + return tarval_bad; + } + break; + + /* cast int to something */ + case irms_int_number: + switch (get_mode_sort(m)) { + case irms_int_number: + case irms_character: + return get_tarval_overflow(src->value, src->length, m); + + case irms_internal_boolean: /* XXX C semantics */ if (src == get_mode_null(src->mode)) return tarval_b_false; else return tarval_b_true; + case irms_float_number: + /* XXX floating point unit does not understand internal integer + * representation, convert to string first, then create float from + * string */ + 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", + sc_print(src->value, get_mode_size_bits(src->mode), SC_DEC)); + switch (get_mode_size_bits(m)) + { + case 32: + fc_val_from_str(buffer, 0, 8, 23, NULL); + break; + case 64: + fc_val_from_str(buffer, 0, 11, 52, NULL); + break; + case 80: + fc_val_from_str(buffer, 0, 15, 64, NULL); + break; + } + return get_tarval(fc_get_buffer(), fc_get_buffer_length(), m); + default: break; } break; - case internal_boolean: + case irms_internal_boolean: switch (get_mode_sort(m)) { - case int_number: + case irms_int_number: if (src == tarval_b_true) return get_mode_one(m); else return get_mode_null(m); @@ -635,168 +896,276 @@ tarval *tarval_convert_to(tarval *src, ir_mode *m) } break; - case character: + case irms_character: break; - case reference: + case irms_reference: break; } return tarval_bad; } -tarval *tarval_neg(tarval *a) /* negation */ +/* + * bitwise negation + */ +tarval *tarval_not(tarval *a) { + char *buffer; + + ANNOUNCE(); + assert(a); + assert(mode_is_int(a->mode)); /* bitwise negation is only allowed for integer */ + + /* works for vector mode without changes */ + + switch (get_mode_sort(a->mode)) + { + case irms_int_number: + buffer = alloca(sc_get_buffer_length()); + sc_not(a->value, buffer); + return get_tarval(buffer, a->length, a->mode); + + default: + return tarval_bad; + } +} + +/* + * arithmetic negation + */ +tarval *tarval_neg(tarval *a) +{ + char *buffer; + 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 */ + + /* 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; + } switch (get_mode_sort(a->mode)) { - case int_number: - sc_neg(a->value); - return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode); + case irms_int_number: + buffer = alloca(sc_get_buffer_length()); + sc_neg(a->value, buffer); + return get_tarval_overflow(buffer, a->length, a->mode); - case float_number: - fc_neg(a->value); - return get_tarval(fc_get_buffer(), fc_get_buffer_length(), a->mode); + case irms_float_number: + fc_neg(a->value, NULL); + return get_tarval_overflow(fc_get_buffer(), fc_get_buffer_length(), a->mode); default: return tarval_bad; } } -tarval *tarval_add(tarval *a, tarval *b) /* addition */ +/* + * addition + */ +tarval *tarval_add(tarval *a, tarval *b) { + char *buffer; + ANNOUNCE(); assert(a); assert(b); - assert((a->mode == b->mode) || (get_mode_sort(a->mode) == character && mode_is_int(b->mode))); + assert(a->mode == b->mode); + + 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; + } switch (get_mode_sort(a->mode)) { - case character: - case int_number: + 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 */ - sc_add(a->value, b->value); - /* FIXME: Check for overflow */ - return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode); + buffer = alloca(sc_get_buffer_length()); + sc_add(a->value, b->value, buffer); + return get_tarval_overflow(buffer, a->length, a->mode); - case float_number: - /* FIXME: Overflow/Underflow/transition to inf when mode < 80bit */ - fc_add(a->value, b->value); - return get_tarval(fc_get_buffer(), fc_get_buffer_length(), a->mode); + case irms_float_number: + fc_add(a->value, b->value, NULL); + return get_tarval_overflow(fc_get_buffer(), fc_get_buffer_length(), a->mode); default: return tarval_bad; } } -tarval *tarval_sub(tarval *a, tarval *b) /* subtraction */ +/* + * subtraction + */ +tarval *tarval_sub(tarval *a, tarval *b) { + char *buffer; + ANNOUNCE(); assert(a); assert(b); - assert((a->mode == b->mode) || (get_mode_sort(a->mode) == character && mode_is_int(b->mode))); + assert(a->mode == b->mode); + 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; + } switch (get_mode_sort(a->mode)) { - case character: - case int_number: + 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 */ - sc_sub(a->value, b->value); - /* FIXME: check for overflow */ - return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode); + buffer = alloca(sc_get_buffer_length()); + sc_sub(a->value, b->value, buffer); + return get_tarval_overflow(buffer, a->length, a->mode); - case float_number: - /* FIXME: Overflow/Underflow/transition to inf when mode < 80bit */ - fc_add(a->value, b->value); - return get_tarval(fc_get_buffer(), fc_get_buffer_length(), a->mode); + case irms_float_number: + fc_sub(a->value, b->value, NULL); + return get_tarval_overflow(fc_get_buffer(), fc_get_buffer_length(), a->mode); default: return tarval_bad; } } -tarval *tarval_mul(tarval *a, tarval *b) /* multiplication */ +/* + * multiplication + */ +tarval *tarval_mul(tarval *a, tarval *b) { + char *buffer; + ANNOUNCE(); assert(a); assert(b); - assert((a->mode == b->mode) && mode_is_num(a->mode)); + assert(a->mode == b->mode); + + if (get_mode_n_vector_elems(a->mode) > 1) { + /* vector arithmetic not implemented yet */ + return tarval_bad; + } switch (get_mode_sort(a->mode)) { - case int_number: + case irms_int_number: /* modes of a,b are equal */ - sc_mul(a->value, b->value); - /* FIXME: check for overflow */ - return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode); + buffer = alloca(sc_get_buffer_length()); + sc_mul(a->value, b->value, buffer); + return get_tarval_overflow(buffer, a->length, a->mode); - case float_number: - /* FIXME: Overflow/Underflow/transition to inf when mode < 80bit */ - fc_add(a->value, b->value); - return get_tarval(fc_get_buffer(), fc_get_buffer_length(), a->mode); + case irms_float_number: + fc_mul(a->value, b->value, NULL); + return get_tarval_overflow(fc_get_buffer(), fc_get_buffer_length(), a->mode); default: return tarval_bad; } } -tarval *tarval_quo(tarval *a, tarval *b) /* floating point division */ +/* + * floating point division + */ +tarval *tarval_quo(tarval *a, tarval *b) { ANNOUNCE(); assert(a); assert(b); assert((a->mode == b->mode) && mode_is_float(a->mode)); - /* FIXME: Overflow/Underflow/transition to inf when mode < 80bit */ - fc_div(a->value, b->value); - return get_tarval(fc_get_buffer(), fc_get_buffer_length(), a->mode); + if (get_mode_n_vector_elems(a->mode) > 1) { + /* vector arithmetic not implemented yet */ + return tarval_bad; + } + + fc_div(a->value, b->value, NULL); + return get_tarval_overflow(fc_get_buffer(), fc_get_buffer_length(), a->mode); } -tarval *tarval_div(tarval *a, tarval *b) /* integer division */ +/* + * integer division + * overflow is impossible, but look out for division by zero + */ +tarval *tarval_div(tarval *a, tarval *b) { ANNOUNCE(); 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_div(a->value, b->value); + sc_div(a->value, b->value, NULL); return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode); } -tarval *tarval_mod(tarval *a, tarval *b) /* remainder */ +/* + * remainder + * overflow is impossible, but look out for division by zero + */ +tarval *tarval_mod(tarval *a, tarval *b) { ANNOUNCE(); 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_mod(a->value, b->value); + sc_mod(a->value, b->value, NULL); return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode); } -tarval *tarval_abs(tarval *a) /* absolute value */ +/* + * absolute value + */ +tarval *tarval_abs(tarval *a) { + char *buffer; + ANNOUNCE(); assert(a); assert(mode_is_num(a->mode)); + if (get_mode_n_vector_elems(a->mode) > 1) { + /* vector arithmetic not implemented yet */ + return tarval_bad; + } + switch (get_mode_sort(a->mode)) { - case int_number: + case irms_int_number: if (sc_comp(a->value, get_mode_null(a->mode)->value) == -1) { - sc_neg(a->value); - return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode); + buffer = alloca(sc_get_buffer_length()); + sc_neg(a->value, buffer); + return get_tarval_overflow(buffer, a->length, a->mode); } return a; - case float_number: - break; + case irms_float_number: + if (fc_comp(a->value, get_mode_null(a->mode)->value) == -1) + { + fc_neg(a->value, NULL); + return get_tarval_overflow(fc_get_buffer(), fc_get_buffer_length(), a->mode); + } + return a; default: return tarval_bad; @@ -804,193 +1173,504 @@ tarval *tarval_abs(tarval *a) /* absolute value */ return tarval_bad; } -tarval *tarval_and(tarval *a, tarval *b) /* bitwise and */ +/* + * bitwise and + */ +tarval *tarval_and(tarval *a, tarval *b) { ANNOUNCE(); assert(a); assert(b); - assert((a->mode == b->mode) && mode_is_int(a->mode)); + assert(a->mode == b->mode); - sc_and(a->value, b->value); - return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode); + /* works even for vector modes */ + + switch(get_mode_sort(a->mode)) + { + case irms_internal_boolean: + return (a == tarval_b_false) ? a : b; + + case irms_int_number: + sc_and(a->value, b->value, NULL); + return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode); + + default: + assert(0 && "operation not defined on mode"); + return tarval_bad; + } } -tarval *tarval_or (tarval *a, tarval *b) /* bitwise or */ + +/* + * bitwise or + */ +tarval *tarval_or (tarval *a, tarval *b) { ANNOUNCE(); assert(a); assert(b); - assert((a->mode == b->mode) && mode_is_int(a->mode)); + assert(a->mode == b->mode); - sc_or(a->value, b->value); - return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode); + /* works even for vector modes */ + + switch (get_mode_sort(a->mode)) + { + case irms_internal_boolean: + return (a == tarval_b_true) ? a : b; + + case irms_int_number: + sc_or(a->value, b->value, NULL); + return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode); + + default: + assert(0 && "operation not defined on mode"); + return tarval_bad;; + } } -tarval *tarval_eor(tarval *a, tarval *b) /* bitwise exclusive or (xor) */ + +/* + * bitwise exclusive or (xor) + */ +tarval *tarval_eor(tarval *a, tarval *b) { ANNOUNCE(); assert(a); assert(b); - assert((a->mode == b->mode) && mode_is_int(a->mode)); + assert((a->mode == b->mode)); - sc_or(a->value, b->value); - return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode); + /* works even for vector modes */ + + switch (get_mode_sort(a->mode)) + { + case irms_internal_boolean: + return (a == b)? tarval_b_false : tarval_b_true; + + case irms_int_number: + sc_xor(a->value, b->value, NULL); + return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode); + + default: + assert(0 && "operation not defined on mode"); + return tarval_bad;; + } } -tarval *tarval_shl(tarval *a, tarval *b) /* bitwise left shift */ +/* + * bitwise left shift + */ +tarval *tarval_shl(tarval *a, tarval *b) { + char *temp_val = NULL; ANNOUNCE(); assert(a); assert(b); assert(mode_is_int(a->mode) && mode_is_int(b->mode)); - sc_shl(a->value, b->value, get_mode_size_bits(a->mode), mode_is_signed(a->mode)); + 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; + } + + if (get_mode_modulo_shift(a->mode) != 0) + { + temp_val = alloca(sc_get_buffer_length()); + + sc_val_from_ulong(get_mode_modulo_shift(a->mode), temp_val); + sc_mod(b->value, temp_val, temp_val); + } + else + temp_val = (char*)b->value; + + sc_shl(a->value, temp_val, get_mode_size_bits(a->mode), mode_is_signed(a->mode), NULL); return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode); } -tarval *tarval_shr(tarval *a, tarval *b) /* bitwise unsigned right shift */ + +/* + * bitwise unsigned right shift + */ +tarval *tarval_shr(tarval *a, tarval *b) { + char *temp_val = NULL; ANNOUNCE(); assert(a); assert(b); assert(mode_is_int(a->mode) && mode_is_int(b->mode)); - sc_shr(a->value, b->value, get_mode_size_bits(a->mode), mode_is_signed(a->mode)); + 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; + } + + if (get_mode_modulo_shift(a->mode) != 0) + { + temp_val = alloca(sc_get_buffer_length()); + + sc_val_from_ulong(get_mode_modulo_shift(a->mode), temp_val); + sc_mod(b->value, temp_val, temp_val); + } + else + temp_val = (char*)b->value; + + sc_shr(a->value, temp_val, get_mode_size_bits(a->mode), mode_is_signed(a->mode), NULL); return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode); } -tarval *tarval_shrs(tarval *a, tarval *b) /* bitwise signed right shift */ + +/* + * bitwise signed right shift + */ +tarval *tarval_shrs(tarval *a, tarval *b) { + char *temp_val = NULL; ANNOUNCE(); assert(a); assert(b); assert(mode_is_int(a->mode) && mode_is_int(b->mode)); - sc_shrs(a->value, b->value, get_mode_size_bits(a->mode), mode_is_signed(a->mode)); + 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; + } + + if (get_mode_modulo_shift(a->mode) != 0) + { + temp_val = alloca(sc_get_buffer_length()); + + sc_val_from_ulong(get_mode_modulo_shift(a->mode), temp_val); + sc_mod(b->value, temp_val, temp_val); + } + else + temp_val = (char*)b->value; + + sc_shrs(a->value, temp_val, get_mode_size_bits(a->mode), mode_is_signed(a->mode), NULL); return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode); } -tarval *tarval_rot(tarval *a, tarval *b) /* bitwise rotation */ + +/* + * bitwise rotation + */ +tarval *tarval_rot(tarval *a, tarval *b) { + char *temp_val = NULL; ANNOUNCE(); assert(a); assert(b); assert(mode_is_int(a->mode) && mode_is_int(b->mode)); - sc_rot(a->value, b->value, get_mode_size_bits(a->mode), mode_is_signed(a->mode)); + 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; + } + + if (get_mode_modulo_shift(a->mode) != 0) + { + temp_val = alloca(sc_get_buffer_length()); + + sc_val_from_ulong(get_mode_modulo_shift(a->mode), temp_val); + sc_mod(b->value, temp_val, temp_val); + } + else + temp_val = (char*)b->value; + + sc_rot(a->value, temp_val, get_mode_size_bits(a->mode), mode_is_signed(a->mode), NULL); return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode); } -/** *********** Output of tarvals *********** **/ -int tarval_print(XP_PAR1, const xprintf_info *info ATTRIBUTE((unused)), XP_PARN) +/* + * carry flag of the last operation + */ +int tarval_carry(void) { + return sc_had_carry(); +} + +/* + * Output of tarvals + */ +int tarval_snprintf(char *buf, size_t len, tarval *tv) +{ + static const tarval_mode_info default_info = { TVO_NATIVE, NULL, NULL }; + + const char *str; + char tv_buf[100]; + const tarval_mode_info *mode_info; + const char *prefix, *suffix; + ANNOUNCE(); - tarval *tv; - char *str; - int offset; - char buf[100]; - tv = XP_GETARG(tarval *, 0); + mode_info = tv->mode->tv_priv; + if (! mode_info) + mode_info = &default_info; + prefix = mode_info->mode_prefix ? mode_info->mode_prefix : ""; + suffix = mode_info->mode_suffix ? mode_info->mode_suffix : ""; + switch (get_mode_sort(tv->mode)) { - case int_number: - case character: - offset = 16 - (get_mode_size_bits(tv->mode)/4); - str = sc_print_hex(tv->value); - return XPF1R("0x%s", str + offset); - - case float_number: - return XPF1R("%s", fc_print_dec(tv->value, buf, sizeof(buf))); - - case reference: - if (tv->value != NULL) - if (tarval_is_entity(tv)) - if (get_entity_peculiarity((entity *)tv->value) == existent) - return XPF1R("&(%I)", get_entity_ld_ident((entity *)tv->value)); - else - return XPSR("NULL"); - else - return XPMR((char*)tv->value, tv->length); + case irms_int_number: + case irms_character: + switch (mode_info->mode_output) { + + case TVO_DECIMAL: + str = sc_print(tv->value, get_mode_size_bits(tv->mode), SC_DEC); + break; + + case TVO_OCTAL: + str = sc_print(tv->value, get_mode_size_bits(tv->mode), SC_OCT); + break; + + case TVO_HEX: + case TVO_NATIVE: + default: + str = sc_print(tv->value, get_mode_size_bits(tv->mode), SC_HEX); + break; + } + return snprintf(buf, len, "%s%s%s", prefix, str, suffix); + + case irms_float_number: + switch (mode_info->mode_output) { + case TVO_HEX: + return snprintf(buf, len, "%s%s%s", prefix, fc_print(tv->value, tv_buf, sizeof(tv_buf), FC_PACKED), suffix); + + case TVO_HEXFLOAT: + return snprintf(buf, len, "%s%s%s", prefix, fc_print(tv->value, tv_buf, sizeof(tv_buf), FC_HEX), suffix); + + case TVO_FLOAT: + case TVO_NATIVE: + default: + return snprintf(buf, len, "%s%s%s", prefix, fc_print(tv->value, tv_buf, sizeof(tv_buf), FC_DEC), suffix); + } + 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'; + } + return tv->length; + } else - return XPSR("void"); + return snprintf(buf, len, "void"); + + case irms_internal_boolean: + switch (mode_info->mode_output) { - case internal_boolean: - if (tv == tarval_b_true) return XPSR("true"); - else return XPSR("false"); + case TVO_DECIMAL: + case TVO_OCTAL: + case TVO_HEX: + case TVO_BINARY: + return snprintf(buf, len, "%s%c%s", prefix, (tv == tarval_b_true) ? '1' : '0', suffix); - case auxiliary: - return XPSR(""); + case TVO_NATIVE: + default: + return snprintf(buf, len, "%s%s%s", prefix, (tv == tarval_b_true) ? "true" : "false", suffix); + } + + case irms_control_flow: + case irms_memory: + case irms_auxiliary: + return snprintf(buf, len, ""); } return 0; } -char *tarval_bitpattern(tarval *tv) + +/** + * Output of tarvals to stdio. + */ +int tarval_printf(tarval *tv) { + char buf[1024]; + int res; + + res = tarval_snprintf(buf, sizeof(buf), tv); + assert(res < sizeof(buf) && "buffer to small for tarval_snprintf"); + printf(buf); + return res; +} + + +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 = malloc((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 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: + return fc_sub_bits(tv->value, get_mode_size_bits(tv->mode), byte_ofs); + + default: + return 0; + } } -/* Identifying some tarvals ??? */ -/* Implemented in old tv.c as such: - * return 0 for additive neutral, - * 1 for multiplicative neutral, - * -1 for bitwise-and neutral - * 2 else +/* + * Specify the output options of one mode. * - * Implemented for completeness */ -long tarval_classify(tarval *tv) + * This functions stores the modinfo, so DO NOT DESTROY it. + * + * Returns zero on success. + */ +int set_tarval_mode_output_option(ir_mode *mode, const tarval_mode_info *modeinfo) +{ + assert(mode); + + mode->tv_priv = modeinfo; + return 0; +} + +/* + * Returns the output options of one mode. + * + * This functions returns the modinfo of a given mode. + */ +const tarval_mode_info *get_tarval_mode_output_option(ir_mode *mode) +{ + assert(mode); + + return mode->tv_priv; +} + +/* + * Identifying tarvals values for algebraic simplifications. + * + * Returns: + * - TV_CLASSIFY_NULL for additive neutral, + * - TV_CLASSIFY_ONE for multiplicative neutral, + * - TV_CLASSIFY_ALL_ONE for bitwise-and neutral + * - TV_CLASSIFY_OTHER else + */ +tarval_classification_t classify_tarval(tarval *tv) { ANNOUNCE(); - if (!tv || tv == tarval_bad) return 2; + if (!tv || tv == tarval_bad) return TV_CLASSIFY_OTHER; - if (tv == get_mode_null(tv->mode)) return 0; - else if (tv == get_mode_one(tv->mode)) return 1; - else if ((get_mode_sort(tv->mode) == int_number) - && (tv == new_tarval_from_long(-1, tv->mode))) return -1; + if (tv == get_mode_null(tv->mode)) + return TV_CLASSIFY_NULL; + 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))) + return TV_CLASSIFY_ALL_ONE; - return 2; + return TV_CLASSIFY_OTHER; } -/* Initialization of the tarval module: called before init_mode() */ +/** + * 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 + */ +static const tarval_mode_info hex_output = { + TVO_HEX, + "0x", + NULL, +}; + +/** + * default mode_info for output as reference + */ +static const tarval_mode_info reference_output = { + TVO_NATIVE, + "&(", + ")", +}; + + +/* + * Initialization of the tarval module: called before init_mode() + */ void init_tarval_1(void) { ANNOUNCE(); /* 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, TUNE_NCONSTANTS); - values = new_set(memcmp, TUNE_NCONSTANTS); + tarvals = new_set(memcmp, N_CONSTANTS); + values = new_set(memcmp, N_CONSTANTS); + /* init strcalc with precision of 68 to support floating point values with 64 + * bit mantissa (needs extra bits for rounding and overflow) */ + init_strcalc(68); + init_fltcalc(0); } -/* Initialization of the tarval module: called after init_mode() */ +/* + * Initialization of the tarval module: called after init_mode() + */ void init_tarval_2(void) { ANNOUNCE(); - tarval_bad = (tarval*)malloc(sizeof(tarval)); - tarval_bad->mode = NULL; - - tarval_undefined = (tarval*)malloc(sizeof(tarval)); - tarval_undefined->mode = NULL; - - tarval_b_true = (tarval*)malloc(sizeof(tarval)); - tarval_b_true->mode = mode_b; - - tarval_b_false = (tarval*)malloc(sizeof(tarval)); - tarval_b_false->mode = mode_b; + 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; + + /* + * 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); + 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); +} - tarval_P_void = (tarval*)malloc(sizeof(tarval)); - tarval_P_void->mode = mode_P; +/* free all memory occupied by tarval. */ +void finish_tarval(void) { + finish_strcalc (); + finish_fltcalc (); + del_set(tarvals); tarvals = NULL; + del_set(values); values = NULL; } /**************************************************************************** * end of tv.c ****************************************************************************/ - -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 forever (They live on an obstack.). - 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. We cannot remove tarvals from the obstack but we can - remove the entry in the hash table. */ - /* this will be re-implemented later */ - ANNOUNCE(); -}