some fixes for xml dumper / still buggy.
[libfirm] / ir / tv / tv.c
index 65c8f63..954d37d 100644 (file)
@@ -41,6 +41,7 @@
 #include <assert.h>         /* assertions */
 #include <stdlib.h>         /* atoi() */
 #include <string.h>         /* nice things for strings */
+#include <strings.h>         /* nice things for strings */
 
 #include <stdlib.h>
 #include "tv_t.h"
@@ -97,8 +98,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
 
-inline static void tarval_verify(tarval *tv)
+INLINE static void tarval_verify(tarval *tv)
 {
   assert(tv);
   assert(tv->mode);
@@ -162,7 +166,6 @@ static int overflows(tarval *tv)
 {
   switch (get_mode_sort(tv->mode))
   {
-    case irms_character:
     case irms_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;
@@ -208,6 +211,8 @@ tarval *new_tarval_from_str(const char *str, size_t len, ir_mode *mode)
 
   switch (get_mode_sort(mode))
   {
+    case irms_control_flow:
+    case irms_memory:
     case irms_auxiliary:
       assert(0);
       break;
@@ -253,12 +258,12 @@ char *tarval_to_str(tarval *tv)
 #endif
 
 /*
- * helper function, creta a tarval from long
+ * helper function, create a tarval from long
  */
 tarval *new_tarval_from_long(long l, ir_mode *mode)
 {
   ANNOUNCE();
-  assert(mode && !(get_mode_sort(mode) == irms_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))
   {
@@ -287,16 +292,28 @@ tarval *new_tarval_from_long(long l, ir_mode *mode)
 int tarval_is_long(tarval *tv)
 {
   ANNOUNCE();
-  return ((get_mode_sort(tv->mode) == irms_int_number) || (get_mode_sort(tv->mode) == irms_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);
+    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)
 {
   ANNOUNCE();
-  assert(tv && get_mode_sort(tv->mode) == irms_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)
@@ -340,7 +357,8 @@ 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));
+  return ((get_mode_sort(tv->mode) == irms_reference) && (tv->value != NULL) && (tv->length == 0)
+         && (tv != tarval_P_void));
 }
 
 entity *tarval_to_entity(tarval *tv)
@@ -425,6 +443,8 @@ tarval *get_tarval_max(ir_mode *mode)
   switch(get_mode_sort(mode))
   {
     case irms_reference:
+    case irms_control_flow:
+    case irms_memory:
     case irms_auxiliary:
       assert(0);
       break;
@@ -452,6 +472,8 @@ tarval *get_tarval_min(ir_mode *mode)
   switch(get_mode_sort(mode))
   {
     case irms_reference:
+    case irms_control_flow:
+    case irms_memory:
     case irms_auxiliary:
       assert(0);
       break;
@@ -478,6 +500,8 @@ tarval *get_tarval_null(ir_mode *mode)
 
   switch(get_mode_sort(mode))
   {
+    case irms_control_flow:
+    case irms_memory:
     case irms_auxiliary:
     case irms_internal_boolean:
       assert(0);
@@ -503,6 +527,8 @@ tarval *get_tarval_one(ir_mode *mode)
 
   switch(get_mode_sort(mode))
   {
+    case irms_control_flow:
+    case irms_memory:
     case irms_auxiliary:
     case irms_internal_boolean:
     case irms_reference:
@@ -578,6 +604,16 @@ int tarval_is_negative(tarval *a)
   }
 }
 
+/*
+ * 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);
+}
+
 /*
  * comparison
  */
@@ -595,6 +631,8 @@ pnc_number tarval_cmp(tarval *a, tarval *b)
   /* Here the two tarvals are unequal and of the same mode */
   switch (get_mode_sort(a->mode))
   {
+    case irms_control_flow:
+    case irms_memory:
     case irms_auxiliary:
       return False;
 
@@ -619,9 +657,9 @@ pnc_number tarval_cmp(tarval *a, tarval *b)
  */
 tarval *tarval_convert_to(tarval *src, ir_mode *m)
 {
-  ANNOUNCE();
   tarval tv;
 
+  ANNOUNCE();
   assert(src);
   assert(m);
 
@@ -629,6 +667,8 @@ tarval *tarval_convert_to(tarval *src, ir_mode *m)
 
   switch (get_mode_sort(src->mode))
   {
+    case irms_control_flow:
+    case irms_memory:
     case irms_auxiliary:
       break;
 
@@ -884,7 +924,12 @@ 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);
+
+  /* GL: needed for easy optimization. */
+  if (a->mode == mode_b) return (a == tarval_b_false) ? a : b;
+
+  assert(mode_is_int(a->mode));
 
   sc_and(a->value, b->value);
   return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode);
@@ -898,7 +943,13 @@ 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);
+
+  /* GL: needed for easy optimization. */
+  if (a->mode == mode_b) return (a == tarval_b_true) ? a : b;
+
+
+  assert(mode_is_int(a->mode));
 
   sc_or(a->value, b->value);
   return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode);
@@ -1021,12 +1072,18 @@ int tarval_snprintf(char *buf, size_t len, tarval *tv)
       return snprintf(buf, len, "%s%s%s", prefix, fc_print_dec(tv->value, tv_buf, sizeof(tv_buf)), suffix);
 
     case irms_reference:
+      if (tv==tarval_P_void) return snprintf(buf, len, "NULL");
       if (tv->value != NULL)
-        if (tarval_is_entity(tv))
+        if (tarval_is_entity(tv)) {
           if (get_entity_peculiarity((entity *)tv->value) == existent)
-            return snprintf(buf, len, "&(%s)", get_entity_ld_name((entity *)tv->value));
-          else
-            return snprintf(buf, len, "NULL");
+            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");
+         }
+       }
         else {
          if (size > tv->length) {
            memcpy(buf, tv->value, tv->length);
@@ -1056,6 +1113,8 @@ int tarval_snprintf(char *buf, size_t len, tarval *tv)
         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, "<BAD>");
   }
@@ -1063,6 +1122,21 @@ int tarval_snprintf(char *buf, size_t len, tarval *tv)
   return 0;
 }
 
+
+/**
+ * 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 *tarval_bitpattern(tarval *tv)
 {
   return NULL;
@@ -1101,6 +1175,19 @@ int tarval_set_mode_output_option(ir_mode *mode, const tarval_mode_info *modeinf
   return 0;
 }
 
+/*
+ * Returns the output options of one mode.
+ *
+ * This functions returns the modinfo of a given mode.
+ */
+const tarval_mode_info *tarval_get_mode_output_option(ir_mode *mode)
+{
+  assert(mode);
+
+  return mode->tv_priv;
+}
+
+
 /* Identifying some tarvals ??? */
 /* Implemented in old tv.c as such:
  *   return 0 for additive neutral,
@@ -1135,6 +1222,11 @@ void init_tarval_1(void)
   /* init with default precision */
   init_strcalc(0);
   /* init_fltcalc(0); not yet*/
+  tarval_bad       = (tarval*)malloc(sizeof(tarval));
+  tarval_undefined = (tarval*)malloc(sizeof(tarval));
+  tarval_b_true    = (tarval*)malloc(sizeof(tarval));
+  tarval_b_false   = (tarval*)malloc(sizeof(tarval));
+  tarval_P_void    = (tarval*)malloc(sizeof(tarval));
 }
 
 /**
@@ -1146,6 +1238,16 @@ static const tarval_mode_info hex_output = {
   NULL,
 };
 
+/**
+ * default mode_info for output as reference
+ */
+static const tarval_mode_info reference_output = {
+  TVO_NATIVE,
+  "&(",
+  ")",
+};
+
+
 /*
  * Initialization of the tarval module: called after init_mode()
  */
@@ -1153,20 +1255,11 @@ 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_P_void = (tarval*)malloc(sizeof(tarval));
-  tarval_P_void->mode = mode_P;
+  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
@@ -1184,6 +1277,7 @@ void init_tarval_2(void)
   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);
 }
 
 /****************************************************************************