fix another illegal usage of compound_graph_path stuff
[libfirm] / ir / tv / tv.c
index e0b51c1..3648712 100644 (file)
  * @date     2003
  * @author   Mathias Heil
  * @version  $Id$
- * @summary
+ * @brief
  *
  * Values are stored in a format depending upon chosen arithmetic
  * module. Default uses strcalc and fltcalc.
  * This implementation assumes:
  *  - target has IEEE-754 floating-point arithmetic.
  */
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
+#include "config.h"
 
-#include <assert.h>         /* assertions */
-#include <stdlib.h>         /* atoi() */
-#ifdef HAVE_STRING_H
-# include <string.h>         /* nice things for strings */
-#endif
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
 #ifdef HAVE_STRINGS_H
-#include <strings.h>        /* strings.h also includes bsd only function strcasecmp */
-#endif
-#ifdef HAVE_STDLIB_H
-# include <stdlib.h>
+#include <strings.h>
 #endif
+#include <stdlib.h>
 
 #include "tv_t.h"
-#include "set.h"            /* to store tarvals in */
-#include "entity_t.h"       /* needed to store pointers to entities */
+#include "set.h"
+#include "entity_t.h"
 #include "irmode_t.h"
-#include "irnode.h"         /* defines boolean return values (pnc_number)*/
+#include "irnode.h"
 #include "strcalc.h"
 #include "fltcalc.h"
 #include "irtools.h"
@@ -99,6 +93,9 @@ static struct set *tarvals = NULL;
 /** A set containing all existing values. */
 static struct set *values = NULL;
 
+/** The carry flag for SOME operations. -1 means UNDEFINED here */
+static int carry_flag = -1;
+
 /** The integer overflow mode. */
 static tarval_int_overflow_mode_t int_overflow_mode = TV_OVERFLOW_WRAP;
 
@@ -132,10 +129,10 @@ static void _fail_verify(tarval *tv, const char* file, int line)
                panic("%s:%d: Invalid tarval (null)", file, line);
 }
 #ifdef __GNUC__
-INLINE static void tarval_verify(tarval *tv) __attribute__ ((unused));
+inline static void tarval_verify(tarval *tv) __attribute__ ((unused));
 #endif
 
-INLINE static void tarval_verify(tarval *tv)
+inline static void tarval_verify(tarval *tv)
 {
        assert(tv);
        assert(tv->mode);
@@ -338,10 +335,10 @@ tarval *new_tarval_from_str(const char *str, size_t len, ir_mode *mode)
 
        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"))
+               if (!strcasecmp(str, "true"))
                        return tarval_b_true;
+               else if (!strcasecmp(str, "false"))
+                       return tarval_b_false;
                else
                        /* XXX This is C semantics */
                        return atoi(str) ? tarval_b_true : tarval_b_false;
@@ -352,7 +349,9 @@ 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 */
+               if (!strcasecmp(str, "null"))
+                       return get_tarval_null(mode);
+               /* FALLTHROUGH */
        case irms_int_number:
                sc_val_from_str(str, len, NULL, mode);
                return get_tarval(sc_get_buffer(), sc_get_buffer_length(), mode);
@@ -699,8 +698,6 @@ tarval *get_tarval_minus_inf(ir_mode *mode) {
  * test if negative number, 1 means 'yes'
  */
 int tarval_is_negative(tarval *a) {
-       assert(a);
-
        if (get_mode_n_vector_elems(a->mode) > 1)
                panic("vector arithmetic not implemented yet");
 
@@ -755,8 +752,7 @@ int tarval_is_minus_one(tarval *a) {
  * comparison
  */
 pn_Cmp tarval_cmp(tarval *a, tarval *b) {
-       assert(a);
-       assert(b);
+       carry_flag = -1;
 
        if (a == tarval_bad || b == tarval_bad) {
                panic("Comparison with tarval_bad");
@@ -820,6 +816,8 @@ tarval *tarval_convert_to(tarval *src, ir_mode *dst_mode) {
        fp_value                *res;
        const ieee_descriptor_t *desc;
 
+       carry_flag = -1;
+
        assert(src);
        assert(dst_mode);
 
@@ -928,7 +926,7 @@ tarval *tarval_convert_to(tarval *src, ir_mode *dst_mode) {
 tarval *tarval_not(tarval *a) {
        char *buffer;
 
-       assert(a);
+       carry_flag = -1;
 
        /* works for vector mode without changes */
 
@@ -958,9 +956,10 @@ tarval *tarval_not(tarval *a) {
 tarval *tarval_neg(tarval *a) {
        char *buffer;
 
-       assert(a);
        assert(mode_is_num(a->mode)); /* negation only for numerical values */
 
+       carry_flag = -1;
+
        /* note: negation is allowed even for unsigned modes. */
 
        if (get_mode_n_vector_elems(a->mode) > 1) {
@@ -993,8 +992,7 @@ tarval *tarval_neg(tarval *a) {
 tarval *tarval_add(tarval *a, tarval *b) {
        char *buffer;
 
-       assert(a);
-       assert(b);
+       carry_flag = -1;
 
        if (get_mode_n_vector_elems(a->mode) > 1 || get_mode_n_vector_elems(b->mode) > 1) {
                /* vector arithmetic not implemented yet */
@@ -1015,6 +1013,7 @@ tarval *tarval_add(tarval *a, tarval *b) {
                /* modes of a,b are equal, so result has mode of a as this might be the character */
                buffer = alloca(sc_get_buffer_length());
                sc_add(a->value, b->value, buffer);
+               carry_flag = sc_get_bit_at(buffer, get_mode_size_bits(a->mode));
                return get_tarval_overflow(buffer, a->length, a->mode);
 
        case irms_float_number:
@@ -1035,8 +1034,7 @@ tarval *tarval_add(tarval *a, tarval *b) {
 tarval *tarval_sub(tarval *a, tarval *b, ir_mode *dst_mode) {
        char    *buffer;
 
-       assert(a);
-       assert(b);
+       carry_flag = -1;
 
        if (get_mode_n_vector_elems(a->mode) > 1 || get_mode_n_vector_elems(b->mode) > 1) {
                /* vector arithmetic not implemented yet */
@@ -1057,6 +1055,7 @@ tarval *tarval_sub(tarval *a, tarval *b, ir_mode *dst_mode) {
                /* modes of a,b are equal, so result has mode of a as this might be the character */
                buffer = alloca(sc_get_buffer_length());
                sc_sub(a->value, b->value, buffer);
+               carry_flag = sc_get_bit_at(buffer, get_mode_size_bits(a->mode));
                return get_tarval_overflow(buffer, a->length, a->mode);
 
        case irms_float_number:
@@ -1077,10 +1076,10 @@ tarval *tarval_sub(tarval *a, tarval *b, ir_mode *dst_mode) {
 tarval *tarval_mul(tarval *a, tarval *b) {
        char *buffer;
 
-       assert(a);
-       assert(b);
        assert(a->mode == b->mode);
 
+       carry_flag = -1;
+
        if (get_mode_n_vector_elems(a->mode) > 1) {
                /* vector arithmetic not implemented yet */
                return tarval_bad;
@@ -1109,10 +1108,10 @@ tarval *tarval_mul(tarval *a, tarval *b) {
  * floating point division
  */
 tarval *tarval_quo(tarval *a, tarval *b) {
-       assert(a);
-       assert(b);
        assert((a->mode == b->mode) && mode_is_float(a->mode));
 
+       carry_flag = -1;
+
        if (no_float)
                return tarval_bad;
 
@@ -1130,10 +1129,10 @@ tarval *tarval_quo(tarval *a, tarval *b) {
  * overflow is impossible, but look out for division by zero
  */
 tarval *tarval_div(tarval *a, tarval *b) {
-       assert(a);
-       assert(b);
        assert((a->mode == b->mode) && mode_is_int(a->mode));
 
+       carry_flag = -1;
+
        if (get_mode_n_vector_elems(a->mode) > 1) {
                /* vector arithmetic not implemented yet */
                return tarval_bad;
@@ -1151,10 +1150,10 @@ tarval *tarval_div(tarval *a, tarval *b) {
  * overflow is impossible, but look out for division by zero
  */
 tarval *tarval_mod(tarval *a, tarval *b) {
-       assert(a);
-       assert(b);
        assert((a->mode == b->mode) && mode_is_int(a->mode));
 
+       carry_flag = -1;
+
        if (get_mode_n_vector_elems(a->mode) > 1) {
                /* vector arithmetic not implemented yet */
                return tarval_bad;
@@ -1176,10 +1175,10 @@ tarval *tarval_divmod(tarval *a, tarval *b, tarval **mod) {
        char *div_res = alloca(len);
        char *mod_res = alloca(len);
 
-       assert(a);
-       assert(b);
        assert((a->mode == b->mode) && mode_is_int(a->mode));
 
+       carry_flag = -1;
+
        if (get_mode_n_vector_elems(a->mode) > 1) {
                /* vector arithmetic not implemented yet */
                return tarval_bad;
@@ -1200,7 +1199,7 @@ tarval *tarval_divmod(tarval *a, tarval *b, tarval **mod) {
 tarval *tarval_abs(tarval *a) {
        char *buffer;
 
-       assert(a);
+       carry_flag = -1;
        assert(mode_is_num(a->mode));
 
        if (get_mode_n_vector_elems(a->mode) > 1) {
@@ -1238,11 +1237,10 @@ tarval *tarval_abs(tarval *a) {
  * bitwise and
  */
 tarval *tarval_and(tarval *a, tarval *b) {
-       assert(a);
-       assert(b);
        assert(a->mode == b->mode);
 
        /* works even for vector modes */
+       carry_flag = 0;
 
        switch (get_mode_sort(a->mode)) {
        case irms_internal_boolean:
@@ -1262,11 +1260,10 @@ tarval *tarval_and(tarval *a, tarval *b) {
  * bitwise or
  */
 tarval *tarval_or(tarval *a, tarval *b) {
-       assert(a);
-       assert(b);
        assert(a->mode == b->mode);
 
        /* works even for vector modes */
+       carry_flag = 0;
 
        switch (get_mode_sort(a->mode)) {
        case irms_internal_boolean:
@@ -1286,11 +1283,10 @@ tarval *tarval_or(tarval *a, tarval *b) {
  * bitwise exclusive or (xor)
  */
 tarval *tarval_eor(tarval *a, tarval *b) {
-       assert(a);
-       assert(b);
        assert((a->mode == b->mode));
 
        /* works even for vector modes */
+       carry_flag = 0;
 
        switch (get_mode_sort(a->mode)) {
        case irms_internal_boolean:
@@ -1312,10 +1308,10 @@ tarval *tarval_eor(tarval *a, tarval *b) {
 tarval *tarval_shl(tarval *a, tarval *b) {
        char *temp_val = NULL;
 
-       assert(a);
-       assert(b);
        assert(mode_is_int(a->mode) && mode_is_int(b->mode));
 
+       carry_flag = -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;
@@ -1339,10 +1335,10 @@ tarval *tarval_shl(tarval *a, tarval *b) {
 tarval *tarval_shr(tarval *a, tarval *b) {
        char *temp_val = NULL;
 
-       assert(a);
-       assert(b);
        assert(mode_is_int(a->mode) && mode_is_int(b->mode));
 
+       carry_flag = -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;
@@ -1366,10 +1362,10 @@ tarval *tarval_shr(tarval *a, tarval *b) {
 tarval *tarval_shrs(tarval *a, tarval *b) {
        char *temp_val = NULL;
 
-       assert(a);
-       assert(b);
        assert(mode_is_int(a->mode) && mode_is_int(b->mode));
 
+       carry_flag = -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;
@@ -1393,10 +1389,10 @@ tarval *tarval_shrs(tarval *a, tarval *b) {
 tarval *tarval_rotl(tarval *a, tarval *b) {
        char *temp_val = NULL;
 
-       assert(a);
-       assert(b);
        assert(mode_is_int(a->mode) && mode_is_int(b->mode));
 
+       carry_flag = -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;
@@ -1418,8 +1414,9 @@ tarval *tarval_rotl(tarval *a, tarval *b) {
  * carry flag of the last operation
  */
 int tarval_carry(void) {
-       panic("tarval_carry() requetsed: not implemented on all operations");
-       return sc_had_carry();
+       if (carry_flag == -1)
+               panic("Carry undefined for the last operation");
+       return carry_flag;
 }
 
 /*
@@ -1442,7 +1439,7 @@ int tarval_snprintf(char *buf, size_t len, tarval *tv) {
        switch (get_mode_sort(tv->mode)) {
        case irms_reference:
                if (tv == tv->mode->null) return snprintf(buf, len, "NULL");
-               /* fall through */
+               /* FALLTHROUGH */
        case irms_int_number:
                switch (mode_info->mode_output) {
 
@@ -1454,8 +1451,9 @@ int tarval_snprintf(char *buf, size_t len, tarval *tv) {
                        str = sc_print(tv->value, get_mode_size_bits(tv->mode), SC_OCT, 0);
                        break;
 
-               case TVO_HEX:
                case TVO_NATIVE:
+                       prefix = "0x";
+               case TVO_HEX:
                default:
                        str = sc_print(tv->value, get_mode_size_bits(tv->mode), SC_HEX, 0);
                        break;
@@ -1517,7 +1515,7 @@ int tarval_printf(tarval *tv) {
 
        res = tarval_snprintf(buf, sizeof(buf), tv);
        assert(res < (int) sizeof(buf) && "buffer to small for tarval_snprintf");
-       printf(buf);
+       printf("%s", buf);
        return res;
 }
 
@@ -1691,11 +1689,12 @@ tarval_int_overflow_mode_t tarval_get_integer_overflow_mode(void) {
 }
 
 /* Enable/Disable floating point constant folding. */
-int tarval_enable_fp_ops(int enable) {
-       int old = !no_float;
-
+void tarval_enable_fp_ops(int enable) {
        no_float = !enable;
-       return old;
+}
+
+int tarval_fp_ops_enabled(void) {
+       return !no_float;
 }
 
 /**