used ircons_t.h now
[libfirm] / ir / tv / tv.c
index 518bc8a..330b941 100644 (file)
@@ -1,31 +1,48 @@
-/* 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
- *    Matthias Heil
- *
- * NOTES
+/*
  *    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 <assert.h>         /* assertions */
 #include <stdlib.h>         /* atoi() */
 #include <string.h>         /* nice things for strings */
+#ifdef HAVE_STRINGS_H
 #include <strings.h>        /* strings.h also includes bsd only function strcasecmp */
+#endif
 #include <stdlib.h>
-#include <alloca.h>
+#ifdef HAVE_ALLOCA_H
+# include <alloca.h>
+#endif
+#ifdef HAVE_MALLOC_H
+# include <malloc.h>
+#endif
 
 #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 "irmode_t.h"
 #include "strcalc.h"
 #include "fltcalc.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
@@ -222,11 +243,13 @@ static tarval *get_tarval_overflow(const void *value, int length, ir_mode *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
@@ -256,7 +279,7 @@ tarval *new_tarval_from_str(const char *str, size_t len, ir_mode *mode)
       else if (strcasecmp(str, "false")) return tarval_b_true;
       else
         /* XXX This is C semantics */
-       return atoi(str) ? tarval_b_true : tarval_b_false;
+    return atoi(str) ? tarval_b_true : tarval_b_false;
 
     case irms_float_number:
       switch(get_mode_size_bits(mode)) {
@@ -381,7 +404,9 @@ long double tarval_to_double(tarval *tv)
 }
 
 /* The tarval represents the address of the entity.  As the address must
-   be constant the entity must have as owner the global type. */
+   be constant the entity must have as owner the global type.
+ * We no more support this function: Use the new SymConst instead.
+ */
 tarval *new_tarval_from_entity (entity *ent, ir_mode *mode)
 {
   ANNOUNCE();
@@ -390,13 +415,15 @@ tarval *new_tarval_from_entity (entity *ent, ir_mode *mode)
 
   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));
+      && (tv != tarval_P_void));
 }
 
 entity *tarval_to_entity(tarval *tv)
@@ -478,6 +505,11 @@ tarval *get_tarval_max(ir_mode *mode)
   ANNOUNCE();
   assert(mode);
 
+  if (get_mode_vector_elems(mode) > 1) {
+    /* vector arithmetic not implemented yet */
+    return tarval_bad;
+  }
+
   switch(get_mode_sort(mode))
   {
     case irms_reference:
@@ -518,6 +550,11 @@ tarval *get_tarval_min(ir_mode *mode)
   ANNOUNCE();
   assert(mode);
 
+  if (get_mode_vector_elems(mode) > 1) {
+    /* vector arithmetic not implemented yet */
+    return tarval_bad;
+  }
+
   switch(get_mode_sort(mode))
   {
     case irms_reference:
@@ -558,6 +595,11 @@ tarval *get_tarval_null(ir_mode *mode)
   ANNOUNCE();
   assert(mode);
 
+  if (get_mode_vector_elems(mode) > 1) {
+    /* vector arithmetic not implemented yet */
+    return tarval_bad;
+  }
+
   switch(get_mode_sort(mode))
   {
     case irms_control_flow:
@@ -585,6 +627,11 @@ tarval *get_tarval_one(ir_mode *mode)
   ANNOUNCE();
   assert(mode);
 
+  if (get_mode_vector_elems(mode) > 1) {
+    /* vector arithmetic not implemented yet */
+    return tarval_bad;
+  }
+
   switch(get_mode_sort(mode))
   {
     case irms_control_flow:
@@ -611,6 +658,11 @@ tarval *get_tarval_nan(ir_mode *mode)
   ANNOUNCE();
   assert(mode);
 
+  if (get_mode_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))
     {
@@ -637,6 +689,11 @@ tarval *get_tarval_inf(ir_mode *mode)
   ANNOUNCE();
   assert(mode);
 
+  if (get_mode_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))
     {
@@ -670,12 +727,18 @@ int tarval_is_negative(tarval *a)
   ANNOUNCE();
   assert(a);
 
+  if (get_mode_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 irms_int_number:
       if (!mode_is_signed(a->mode)) return 0;
       else
-       return sc_comp(a->value, get_mode_null(a->mode)->value) == -1 ? 1 : 0;
+    return sc_comp(a->value, get_mode_null(a->mode)->value) == -1 ? 1 : 0;
 
     case irms_float_number:
       return fc_comp(a->value, get_mode_null(a->mode)->value) == -1 ? 1 : 0;
@@ -696,6 +759,16 @@ int tarval_is_null(tarval *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
  */
@@ -708,7 +781,12 @@ 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 False;
+  if (a->mode != b->mode) return False;
+
+  if (get_mode_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))
@@ -750,6 +828,11 @@ tarval *tarval_convert_to(tarval *src, ir_mode *m)
 
   if (src->mode == m) return src;
 
+  if (get_mode_vector_elems(src->mode) > 1) {
+    /* vector arithmetic not implemented yet */
+    return tarval_bad;
+  }
+
   switch (get_mode_sort(src->mode))
   {
     case irms_control_flow:
@@ -760,7 +843,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:
@@ -776,7 +859,7 @@ tarval *tarval_convert_to(tarval *src, ir_mode *m)
               break;
           }
           return get_tarval(fc_get_buffer(), fc_get_buffer_length(), m);
-         break;
+      break;
 
         case irms_int_number:
           switch (GET_FLOAT_TO_INT_MODE())
@@ -795,7 +878,7 @@ tarval *tarval_convert_to(tarval *src, ir_mode *m)
            * an intermediate representation is needed here first. */
           /*  return get_tarval(); */
           return tarval_bad;
-         break;
+      break;
 
         default:
           /* the rest can't be converted */
@@ -865,7 +948,32 @@ tarval *tarval_convert_to(tarval *src, ir_mode *m)
 }
 
 /*
- * 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)
 {
@@ -876,6 +984,11 @@ tarval *tarval_neg(tarval *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) {
+    /* vector arithmetic not implemented yet */
+    return tarval_bad;
+  }
+
   switch (get_mode_sort(a->mode))
   {
     case irms_int_number:
@@ -904,6 +1017,11 @@ tarval *tarval_add(tarval *a, tarval *b)
   assert(b);
   assert((a->mode == b->mode) || (get_mode_sort(a->mode) == irms_character && mode_is_int(b->mode)));
 
+  if (get_mode_vector_elems(a->mode) > 1 || get_mode_vector_elems(b->mode) > 1) {
+    /* vector arithmetic not implemented yet */
+    return tarval_bad;
+  }
+
   switch (get_mode_sort(a->mode))
   {
     case irms_character:
@@ -934,6 +1052,10 @@ tarval *tarval_sub(tarval *a, tarval *b)
   assert(b);
   assert((a->mode == b->mode) || (get_mode_sort(a->mode) == irms_character && mode_is_int(b->mode)));
 
+  if (get_mode_vector_elems(a->mode) > 1 || get_mode_vector_elems(b->mode) > 1) {
+    /* vector arithmetic not implemented yet */
+    return tarval_bad;
+  }
   switch (get_mode_sort(a->mode))
   {
     case irms_character:
@@ -964,6 +1086,11 @@ tarval *tarval_mul(tarval *a, tarval *b)
   assert(b);
   assert((a->mode == b->mode) && mode_is_num(a->mode));
 
+  if (get_mode_vector_elems(a->mode) > 1) {
+    /* vector arithmetic not implemented yet */
+    return tarval_bad;
+  }
+
   switch (get_mode_sort(a->mode))
   {
     case irms_int_number:
@@ -991,6 +1118,11 @@ 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) {
+    /* 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);
 }
@@ -1006,6 +1138,11 @@ 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) {
+    /* 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 */
@@ -1024,6 +1161,11 @@ 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) {
+    /* 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 */
@@ -1042,6 +1184,11 @@ tarval *tarval_abs(tarval *a)
   assert(a);
   assert(mode_is_num(a->mode));
 
+  if (get_mode_vector_elems(a->mode) > 1) {
+    /* vector arithmetic not implemented yet */
+    return tarval_bad;
+  }
+
   switch (get_mode_sort(a->mode))
   {
     case irms_int_number:
@@ -1077,6 +1224,8 @@ tarval *tarval_and(tarval *a, tarval *b)
   assert(b);
   assert(a->mode == b->mode);
 
+  /* works even for vector modes */
+
   switch(get_mode_sort(a->mode))
   {
     case irms_internal_boolean:
@@ -1102,6 +1251,8 @@ tarval *tarval_or (tarval *a, tarval *b)
   assert(b);
   assert(a->mode == b->mode);
 
+  /* works even for vector modes */
+
   switch (get_mode_sort(a->mode))
   {
     case irms_internal_boolean:
@@ -1127,13 +1278,15 @@ tarval *tarval_eor(tarval *a, tarval *b)
   assert(b);
   assert((a->mode == b->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_or(a->value, b->value, NULL);
+      sc_xor(a->value, b->value, NULL);
       return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode);
 
     default:
@@ -1147,12 +1300,28 @@ tarval *tarval_eor(tarval *a, tarval *b)
  */
 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), NULL);
+  if (get_mode_vector_elems(a->mode) > 1 || get_mode_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);
 }
 
@@ -1161,12 +1330,28 @@ tarval *tarval_shl(tarval *a, tarval *b)
  */
 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), NULL);
+  if (get_mode_vector_elems(a->mode) > 1 || get_mode_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);
 }
 
@@ -1175,12 +1360,28 @@ tarval *tarval_shr(tarval *a, tarval *b)
  */
 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), NULL);
+  if (get_mode_vector_elems(a->mode) > 1 || get_mode_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);
 }
 
@@ -1189,12 +1390,28 @@ tarval *tarval_shrs(tarval *a, tarval *b)
  */
 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), NULL);
+  if (get_mode_vector_elems(a->mode) > 1 || get_mode_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);
 }
 
@@ -1227,17 +1444,17 @@ int tarval_snprintf(char *buf, size_t len, tarval *tv)
 
       case TVO_DECIMAL:
         str = sc_print(tv->value, get_mode_size_bits(tv->mode), SC_DEC);
-       break;
+    break;
 
       case TVO_OCTAL:
         str = sc_print(tv->value, get_mode_size_bits(tv->mode), SC_OCT);
-       break;
+    break;
 
       case TVO_HEX:
       case TVO_NATIVE:
       default:
         str = sc_print(tv->value, get_mode_size_bits(tv->mode), SC_HEX);
-       break;
+    break;
       }
       return snprintf(buf, len, "%s%s%s", prefix, str, suffix);
 
@@ -1257,32 +1474,32 @@ 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 == tarval_P_void) return snprintf(buf, len, "NULL");
       if (tv->value != NULL)
-        if (tarval_is_entity(tv)) {
-          if (get_entity_peculiarity((entity *)tv->value) == existent)
-            return snprintf(buf, len, "%s%s%s", prefix, get_entity_ld_name((entity *)tv->value), suffix);
-          else {
+       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");
+             return snprintf(buf, len, "NULL");
            else
-              return snprintf(buf, len, "0");
+             return snprintf(buf, len, "0");
          }
        }
-        else {
-         if (size > tv->length) {
+       else {
+         if (len > tv->length) {
            memcpy(buf, tv->value, tv->length);
            buf[tv->length] = '\0';
          }
          else {
            /* truncated */
-           memcpy(buf, tv->value, size-1);
-           buf[size-1] = '\0';
+           memcpy(buf, tv->value, len-1);
+           buf[len-1] = '\0';
          }
-          return tv->length;
+         return tv->length;
        }
       else
-        return snprintf(buf, len, "void");
+       return snprintf(buf, len, "void");
 
     case irms_internal_boolean:
       switch (mode_info->mode_output) {
@@ -1372,26 +1589,29 @@ const tarval_mode_info *tarval_get_mode_output_option(ir_mode *mode)
   return mode->tv_priv;
 }
 
-
-/* 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
+/*
+ * Identifying tarvals values for algebraic simplifications.
  *
- * Implemented for compatibility */
-long tarval_classify(tarval *tv)
+ * 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 tarval_classify(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;
+  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 -1;
+           && (tv == new_tarval_from_long(-1, tv->mode)))
+    return TV_CLASSIFY_ALL_ONE;
 
-  return 2;
+  return TV_CLASSIFY_OTHER;
 }
 
 /**
@@ -1421,18 +1641,12 @@ 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);
-
-  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));
 }
 
 /*
@@ -1465,6 +1679,14 @@ void init_tarval_2(void)
   tarval_set_mode_output_option(mode_P,  &reference_output);
 }
 
+/* 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
  ****************************************************************************/