- add ir_bk_outport and ir_bk_inport
[libfirm] / ir / ir / irmode.c
index 71da96f..f83214e 100644 (file)
  * @author   Martin Trapp, Christian Schaefer, Goetz Lindenmaier, Mathias Heil
  * @version  $Id$
  */
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
+#include "config.h"
 
-#ifdef HAVE_STDLIB_H
-# include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-# include <string.h>
-#endif
+#include <stdlib.h>
+#include <string.h>
 
-# include <stddef.h>
+#include <stddef.h>
 
-# include "irprog_t.h"
-# include "irmode_t.h"
-# include "ident.h"
-# include "tv_t.h"
-# include "obst.h"
-# include "irhooks.h"
-# include "irtools.h"
-# include "array.h"
+#include "irprog_t.h"
+#include "irmode_t.h"
+#include "ident.h"
+#include "tv_t.h"
+#include "obst.h"
+#include "irhooks.h"
+#include "irtools.h"
+#include "array.h"
+#include "error.h"
 
 /** Obstack to hold all modes. */
 static struct obstack modes;
@@ -60,7 +55,7 @@ static ir_mode **mode_list;
  *
  * TODO: Add other fields
  **/
-static INLINE int modes_are_equal(const ir_mode *m, const ir_mode *n) {
+static inline int modes_are_equal(const ir_mode *m, const ir_mode *n) {
        if (m == n) return 1;
        if (m->sort         == n->sort &&
                m->arithmetic   == n->arithmetic &&
@@ -292,14 +287,15 @@ ir_mode *new_ir_mode(const char *name, ir_mode_sort sort, int bit_size, int sign
        case irms_control_flow:
        case irms_memory:
        case irms_internal_boolean:
-               assert(0 && "internal modes cannot be user defined");
-               break;
+               panic("internal modes cannot be user defined");
 
        case irms_float_number:
        case irms_int_number:
        case irms_reference:
                mode = register_mode(&mode_tmpl);
+               break;
        }
+       assert(mode != NULL);
        return mode;
 }
 
@@ -339,20 +335,18 @@ ir_mode *new_ir_vector_mode(const char *name, ir_mode_sort sort, int bit_size, u
        case irms_control_flow:
        case irms_memory:
        case irms_internal_boolean:
-               assert(0 && "internal modes cannot be user defined");
-               break;
+               panic("internal modes cannot be user defined");
 
        case irms_reference:
-               assert(0 && "only integer and floating point modes can be vectorized");
-               break;
+               panic("only integer and floating point modes can be vectorized");
 
        case irms_float_number:
-               assert(0 && "not yet implemented");
-               break;
+               panic("not yet implemented");
 
        case irms_int_number:
                mode = register_mode(&mode_tmpl);
        }
+       assert(mode != NULL);
        return mode;
 }
 
@@ -523,6 +517,79 @@ int (mode_is_int_vector)(const ir_mode *mode) {
 /* Returns true if sm can be converted to lm without loss. */
 int smaller_mode(const ir_mode *sm, const ir_mode *lm) {
        int sm_bits, lm_bits;
+
+       assert(sm);
+       assert(lm);
+
+       if (sm == lm) return 1;
+
+       sm_bits = get_mode_size_bits(sm);
+       lm_bits = get_mode_size_bits(lm);
+
+       switch (get_mode_sort(sm)) {
+       case irms_int_number:
+               switch (get_mode_sort(lm)) {
+               case irms_int_number:
+                       if (get_mode_arithmetic(sm) != get_mode_arithmetic(lm))
+                               return 0;
+
+                       /* only two complement implemented */
+                       assert(get_mode_arithmetic(sm) == irma_twos_complement);
+
+                       /* integers are convertable if
+                        *   - both have the same sign and lm is the larger one
+                        *   - lm is the signed one and is at least two bits larger
+                        *     (one for the sign, one for the highest bit of sm)
+                        *   - sm & lm are two_complement and lm has greater or equal number of bits
+                        */
+                       if (mode_is_signed(sm)) {
+                               if (!mode_is_signed(lm))
+                                       return 0;
+                               return sm_bits <= lm_bits;
+                       } else {
+                               if (mode_is_signed(lm)) {
+                                       return sm_bits < lm_bits;
+                               }
+                               return sm_bits <= lm_bits;
+                       }
+                       break;
+
+               case irms_float_number:
+                       /* int to float works if the float is large enough */
+                       return 0;
+
+               default:
+                       break;
+               }
+               break;
+
+       case irms_float_number:
+               if (get_mode_arithmetic(sm) == get_mode_arithmetic(lm)) {
+                       if ( (get_mode_sort(lm) == irms_float_number)
+                               && (get_mode_size_bits(lm) >= get_mode_size_bits(sm)) )
+                               return 1;
+               }
+               break;
+
+       case irms_reference:
+               /* do exist machines out there with different pointer lenghts ?*/
+               return 0;
+
+       case irms_internal_boolean:
+               return mode_is_int(lm);
+
+       default:
+               break;
+       }
+
+       /* else */
+       return 0;
+}
+
+/* Returns true if a value of mode sm can be converted into mode lm
+   and backwards without loss. */
+int values_in_mode(const ir_mode *sm, const ir_mode *lm) {
+       int sm_bits, lm_bits;
        ir_mode_arithmetic arith;
 
        assert(sm);
@@ -678,7 +745,9 @@ void init_mode(void) {
        newmode.name    = new_id_from_chars("E", 1);
        newmode.code    = irm_E;
        newmode.sign    = 1;
-       newmode.size    = 80;
+       /* note that the tarval module is calculating with 80 bits, but we use
+        * 96 bits, as that is what will be stored to memory by most hardware */
+       newmode.size    = 96;
 
        mode_E = register_mode(&newmode);