#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
/****************************************************************************
* private variables
****************************************************************************/
-static struct set *tarvals; /* container for tarval structs */
-static struct set *values; /* container for values */
+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;
/****************************************************************************
}
#endif /* NDEBUG */
-static int hash_tv(tarval *tv)
-{
+/** Hash a tarval. */
+static int hash_tv(tarval *tv) {
return (PTR_TO_INT(tv->value) ^ PTR_TO_INT(tv->mode)) + tv->length;
}
-static int hash_val(const void *value, unsigned int length)
-{
+/** Hash a value. Treat it as a byte array. */
+static int hash_val(const void *value, unsigned int length) {
unsigned int i;
unsigned int hash = 0;
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);
+ /* the sc_ module expects that all bits are set ... */
+ sign_extend(temp, mode);
return get_tarval(temp, length, mode);
}
case TV_OVERFLOW_BAD:
case TV_OVERFLOW_WRAP:
{
char *temp = alloca(sc_get_buffer_length());
- char *diff = alloca(sc_get_buffer_length());
- sc_sub(get_mode_max(mode)->value, get_mode_min(mode)->value, diff);
- sc_val_from_ulong(1, temp);
- sc_add(diff, temp, diff);
- sc_add(value, diff, temp);
- while (sc_comp(temp, get_mode_max(mode)->value) == 1)
- sc_add(temp, diff, temp);
+ sc_val_from_ulong(-1, temp);
+ sc_and(temp, value, temp);
return get_tarval(temp, length, mode);
}
case TV_OVERFLOW_BAD:
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
}
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? */
/* 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);
case irms_float_number:
return new_tarval_from_double((long double)l, mode);
- case irms_reference:
- return l ? tarval_bad : get_tarval(NULL, 0, mode); /* null pointer or tarval_bad */
-
default:
assert(0 && "unsupported mode sort");
}
return _get_tarval_b_true();
}
-tarval *(get_tarval_P_void)(void) {
- return _get_tarval_P_void();
-}
-
tarval *get_tarval_max(ir_mode *mode)
{
ANNOUNCE();
return tarval_bad;
}
+static long _null_value;
+
tarval *get_tarval_null(ir_mode *mode)
{
ANNOUNCE();
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;
}
switch (get_mode_sort(m)) {
case irms_int_number:
case irms_character:
- return get_tarval_overflow(src->value, src->length, m);
+ 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);
case irms_internal_boolean:
/* XXX C semantics */
/* 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));
+ sc_print(src->value, get_mode_size_bits(src->mode), SC_DEC, mode_is_signed(src->mode)));
+ buffer[100 - 1] = '\0';
switch (get_mode_size_bits(m))
{
case 32:
}
return get_tarval(fc_get_buffer(), fc_get_buffer_length(), m);
-#if 0
case irms_reference:
/* allow 0 to be casted */
if (src == get_mode_null(src->mode))
return get_mode_null(m);
break;
-#endif
+
default:
break;
}
switch (get_mode_sort(tv->mode))
{
+ case irms_reference:
+ 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:
- str = sc_print(tv->value, get_mode_size_bits(tv->mode), SC_DEC);
- break;
+ str = sc_print(tv->value, get_mode_size_bits(tv->mode), SC_DEC, mode_is_signed(tv->mode));
+ break;
case TVO_OCTAL:
- str = sc_print(tv->value, get_mode_size_bits(tv->mode), SC_OCT);
- break;
+ str = sc_print(tv->value, get_mode_size_bits(tv->mode), SC_OCT, 0);
+ break;
case TVO_HEX:
case TVO_NATIVE:
default:
- str = sc_print(tv->value, get_mode_size_bits(tv->mode), SC_HEX);
- break;
+ str = sc_print(tv->value, get_mode_size_bits(tv->mode), SC_HEX, 0);
+ break;
}
return snprintf(buf, len, "%s%s%s", prefix, str, 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 snprintf(buf, len, "void");
-
case irms_internal_boolean:
switch (mode_info->mode_output) {
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));
+ char *res = xmalloc((n + 1) * sizeof(char));
unsigned char byte;
for(i = 0; i < bytes; i++) {
* 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
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) {
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)
+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);
{
ANNOUNCE();
- tarval_bad->kind = k_tarval;
- tarval_bad->mode = mode_BAD;
-
- tarval_undefined->kind = k_tarval;
- tarval_undefined->mode = mode_ANY;
+ tarval_bad->kind = k_tarval;
+ tarval_bad->mode = mode_BAD;
+ tarval_bad->value = INT_TO_PTR(resid_tarval_bad);
- tarval_b_true->kind = k_tarval;
- tarval_b_true->mode = mode_b;
+ tarval_undefined->kind = k_tarval;
+ tarval_undefined->mode = mode_ANY;
+ tarval_undefined->value = INT_TO_PTR(resid_tarval_undefined);
- tarval_b_false->kind = k_tarval;
- tarval_b_false->mode = mode_b;
+ tarval_b_true->kind = k_tarval;
+ tarval_b_true->mode = mode_b;
+ tarval_b_true->value = INT_TO_PTR(resid_tarval_b_true);
- tarval_P_void->kind = k_tarval;
- tarval_P_void->mode = mode_P;
+ 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
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);
+ set_tarval_mode_output_option(mode_P, &hex_output);
}
/* free all memory occupied by tarval. */