added phase reinit data per irn
[libfirm] / ir / tr / type.c
index 29703e3..3eaedfa 100644 (file)
@@ -6,7 +6,7 @@
  * Modified by: Michael Beck
  * Created:
  * CVS-ID:      $Id$
- * Copyright:   (c) 2001-2003 Universität Karlsruhe
+ * Copyright:   (c) 2001-2006 Universität Karlsruhe
  * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
  */
 
@@ -17,8 +17,8 @@
  *  Implementation of the datastructure to hold
  *  type information.
  *
- *  (C) 2001-2005 by Universitaet Karlsruhe
- *  Goetz Lindenmaier
+ *  (C) 2001-2006 by Universitaet Karlsruhe
+ *  Goetz Lindenmaier, Michael Beck
  *
  *  This module supplies a datastructure to represent all types
  *  known in the compiled program.  This includes types specified
@@ -67,6 +67,7 @@
 # include "mangle.h"
 # include "tv_t.h"
 # include "irhooks.h"
+# include "irtools.h"
 
 # include "array.h"
 
@@ -78,11 +79,6 @@ ir_type *firm_none_type;    ir_type *get_none_type(void)    { return firm_none_t
 ir_type *firm_unknown_type; ir_type *get_unknown_type(void) { return firm_unknown_type; }
 
 
-#ifdef DEBUG_libfirm
-/* Returns a new, unique number to number nodes or the like. */
-int get_irp_new_node_nr(void);
-#endif
-
 /* Suffixes added to types used for pass-by-value representations. */
 static ident *value_params_suffix = NULL;
 static ident *value_ress_suffix = NULL;
@@ -241,7 +237,7 @@ long get_type_nr(const ir_type *tp) {
 #ifdef DEBUG_libfirm
   return tp->nr;
 #else
-  return (long)tp;
+  return (long)PTR_TO_INT(tp);
 #endif
 }
 
@@ -259,7 +255,7 @@ int (get_type_size_bits)(const ir_type *tp) {
 }
 
 
-visibility get_type_visibility (const ir_type *tp) {
+ir_visibility get_type_visibility (const ir_type *tp) {
 #if 0
   visibility res =  visibility_local;
   if (is_compound_type(tp)) {
@@ -283,7 +279,7 @@ visibility get_type_visibility (const ir_type *tp) {
   return tp->visibility;
 }
 
-void       set_type_visibility (ir_type *tp, visibility v) {
+void       set_type_visibility (ir_type *tp, ir_visibility v) {
   assert(is_type(tp));
 #if 0
   /* check for correctness */
@@ -365,6 +361,7 @@ int get_type_alignment_bits(ir_type *tp) {
 void
 set_type_alignment_bits(ir_type *tp, int align) {
   assert(tp && tp->kind == k_type);
+  assert((align == -1 || (align & (align - 1)) == 0) && "type alignment not power of two");
   /* Methods don't have an alignment. */
   if (tp->type_op != type_method) {
     tp->align = align;
@@ -373,7 +370,11 @@ set_type_alignment_bits(ir_type *tp, int align) {
 
 void
 set_type_alignment_bytes(ir_type *tp, int align) {
-  set_type_alignment_bits(tp, 8*align);
+       if (align == -1) {
+               set_type_alignment_bits(tp, -1);
+       } else {
+               set_type_alignment_bits(tp, 8*align);
+       }
 }
 
 /* Returns a human readable string for the enum entry. */
@@ -405,50 +406,50 @@ set_type_state(ir_type *tp, type_state state) {
     int i;
     switch (get_type_tpop_code(tp)) {
     case tpo_class:
-      {
-    assert(get_type_size_bits(tp) > -1);
-    if (tp != get_glob_type()) {
-      int n_mem = get_class_n_members(tp);
-      for (i = 0; i < n_mem; i++) {
-        if (get_entity_offset_bits(get_class_member(tp, i)) <= -1)
-          { DDMT(tp); DDME(get_class_member(tp, i)); }
-        assert(get_entity_offset_bits(get_class_member(tp, i)) > -1);
-            /* TR ??
-        assert(is_Method_type(get_entity_type(get_class_member(tp, i))) ||
-           (get_entity_allocation(get_class_member(tp, i)) == allocation_automatic));
-                   */
+      assert(get_type_size_bits(tp) > -1);
+      if (tp != get_glob_type()) {
+        int n_mem = get_class_n_members(tp);
+        for (i = 0; i < n_mem; i++) {
+          if (get_entity_offset_bits(get_class_member(tp, i)) <= -1)
+            { DDMT(tp); DDME(get_class_member(tp, i)); }
+          assert(get_entity_offset_bits(get_class_member(tp, i)) > -1);
+              /* TR ??
+          assert(is_Method_type(get_entity_type(get_class_member(tp, i))) ||
+             (get_entity_allocation(get_class_member(tp, i)) == allocation_automatic));
+                     */
+        }
       }
-    }
-      } break;
+      break;
     case tpo_struct:
-      {
-        assert(get_type_size_bits(tp) > -1);
-        for (i = 0; i < get_struct_n_members(tp); i++) {
-          assert(get_entity_offset_bits(get_struct_member(tp, i)) > -1);
-          assert((get_entity_allocation(get_struct_member(tp, i)) == allocation_automatic));
-        }
-      } break;
+      assert(get_type_size_bits(tp) > -1);
+      for (i = 0; i < get_struct_n_members(tp); i++) {
+        assert(get_entity_offset_bits(get_struct_member(tp, i)) > -1);
+        assert((get_entity_allocation(get_struct_member(tp, i)) == allocation_automatic));
+      }
+      break;
     case tpo_union:
-      /* ?? */
-      break;
+      /* ?? */
+      break;
     case tpo_array:
-      /* ??
+      /* ??
          Check order?
          Assure that only innermost dimension is dynamic? */
-      break;
+      break;
     case tpo_enumeration:
-      {
-        assert(get_type_mode != NULL);
-        for (i = 0; i < get_enumeration_n_enums(tp); i++)
-          assert(get_enumeration_enum(tp, i) != NULL);
-      } break;
+      assert(get_type_mode != NULL);
+      for (i = get_enumeration_n_enums(tp) - 1; i >= 0; --i) {
+        ir_enum_const *ec = get_enumeration_const(tp, i);
+        tarval        *tv = get_enumeration_value(ec);
+        assert(tv != NULL && tv != tarval_bad);
+      }
+      break;
     default: break;
     } /* switch (tp) */
   }
-  if (state = layout_fixed)
+  if (state == layout_fixed)
     tp->flags |= tf_layout_fixed;
   else
-    tp->flags &= tf_layout_fixed;
+    tp->flags &= ~tf_layout_fixed;
 }
 
 unsigned long (get_type_visited)(const ir_type *tp) {
@@ -769,7 +770,8 @@ ir_type *new_d_type_class (ident *name, dbg_info *db) {
   res->attr.ca.supertypes  = NEW_ARR_F (ir_type *, 0);
   res->attr.ca.peculiarity = peculiarity_existent;
   res->attr.ca.type_info   = NULL;
-  res->attr.ca.final       = 0;
+  res->attr.ca.vtable_size = 0;
+  res->attr.ca.clss_flags  = cf_none;
   res->attr.ca.dfn         = 0;
   hook_new_type(res);
   return res;
@@ -953,7 +955,7 @@ void set_class_type_info(ir_type *clss, entity *ent) {
   clss->attr.ca.type_info = ent;
 }
 
-const char *get_peculiarity_string(peculiarity p) {
+const char *get_peculiarity_name(ir_peculiarity p) {
 #define X(a)    case a: return #a
   switch (p) {
     X(peculiarity_description);
@@ -964,23 +966,55 @@ const char *get_peculiarity_string(peculiarity p) {
   return "invalid peculiarity";
 }
 
-peculiarity get_class_peculiarity (const ir_type *clss) {
+ir_peculiarity get_class_peculiarity (const ir_type *clss) {
   assert(clss && (clss->type_op == type_class));
   return clss->attr.ca.peculiarity;
 }
 
-void        set_class_peculiarity (ir_type *clss, peculiarity pec) {
+void        set_class_peculiarity (ir_type *clss, ir_peculiarity pec) {
   assert(clss && (clss->type_op == type_class));
   assert(pec != peculiarity_inherited);  /* There is no inheritance of types in libFirm. */
   clss->attr.ca.peculiarity = pec;
 }
 
+/* Returns the size of the virtual function table. */
+unsigned (get_class_vtable_size)(const ir_type *clss) {
+  return _get_class_vtable_size(clss);
+}
+
+/* Sets a new size of the virtual function table. */
+void (set_class_vtable_size)(ir_type *clss, unsigned size) {
+  _set_class_vtable_size(clss, size);
+}
+
+/* Returns non-zero if a class is final. */
 int (is_class_final)(const ir_type *clss) {
   return _is_class_final(clss);
 }
 
-void (set_class_final)(ir_type *clss, int final) {
-  _set_class_final(clss, final);
+/* Sets if a class is final. */
+void (set_class_final)(ir_type *clss, int flag) {
+  _set_class_final(clss, flag);
+}
+
+/* Returns non-zero if a class is an interface. */
+int (is_class_interface)(const ir_type *clss) {
+  return _is_class_interface(clss);
+}
+
+/* Sets the class interface flag. */
+void (set_class_interface)(ir_type *clss, int flag) {
+  _set_class_interface(clss, flag);
+}
+
+/* Returns non-zero if a class is abstract. */
+int (is_class_abstract)(const ir_type *clss) {
+  return _is_class_abstract(clss);
+}
+
+/* Sets the class abstract flag. */
+void (set_class_abstract)(ir_type *clss, int final) {
+  _set_class_abstract(clss, final);
 }
 
 void set_class_dfn (ir_type *clss, int dfn) {
@@ -1119,13 +1153,20 @@ static INLINE ir_type *
 build_value_type(ident *name, int len, tp_ent_pair *tps) {
   int i;
   ir_type *res = new_type_struct(name);
+  res->flags |= tf_value_param_type;
   /* Remove type from type list.  Must be treated differently than other types. */
   remove_irp_type(res);
   for (i = 0; i < len; i++) {
+    ident *id = tps[i].param_name;
+
     /* use res as default if corresponding type is not yet set. */
     ir_type *elt_type = tps[i].tp ? tps[i].tp : res;
 
-    tps[i].ent = new_entity(res, mangle_u(name, get_type_ident(elt_type)), elt_type);
+    /* use the parameter name if specified */
+    if (! id)
+      id = mangle_u(name, get_type_ident(elt_type));
+    tps[i].ent = new_entity(res, id, elt_type);
+    set_entity_allocation(tps[i].ent, allocation_parameter);
   }
   return res;
 }
@@ -1140,13 +1181,14 @@ ir_type *new_d_type_method(ident *name, int n_param, int n_res, dbg_info *db) {
   res->flags                       |= tf_layout_fixed;
   res->size                         = get_mode_size_bits(mode_P_code);
   res->attr.ma.n_params             = n_param;
-  res->attr.ma.param_type           = xcalloc(n_param, sizeof(res->attr.ma.param_type[0]));
+  res->attr.ma.params               = xcalloc(n_param, sizeof(res->attr.ma.params[0]));
   res->attr.ma.value_params         = NULL;
   res->attr.ma.n_res                = n_res;
   res->attr.ma.res_type             = xcalloc(n_res, sizeof(res->attr.ma.res_type[0]));
   res->attr.ma.value_ress           = NULL;
   res->attr.ma.variadicity          = variadicity_non_variadic;
   res->attr.ma.first_variadic_param = -1;
+  res->attr.ma.additional_properties = mtp_no_property;
   res->attr.ma.irg_calling_conv     = default_cc_mask;
   hook_new_type(res);
   return res;
@@ -1163,7 +1205,7 @@ void free_method_entities(ir_type *method) {
 /* Attention: also frees entities in value parameter subtypes! */
 void free_method_attrs(ir_type *method) {
   assert(method && (method->type_op == type_method));
-  free(method->attr.ma.param_type);
+  free(method->attr.ma.params);
   free(method->attr.ma.res_type);
   if (method->attr.ma.value_params) {
     free_type_entities(method->attr.ma.value_params);
@@ -1180,19 +1222,20 @@ int (get_method_n_params)(const ir_type *method) {
   return _get_method_n_params(method);
 }
 
+/* Returns the type of the parameter at position pos of a method. */
 ir_type *get_method_param_type(ir_type *method, int pos) {
   ir_type *res;
   assert(method && (method->type_op == type_method));
   assert(pos >= 0 && pos < get_method_n_params(method));
-  res = method->attr.ma.param_type[pos].tp;
+  res = method->attr.ma.params[pos].tp;
   assert(res != NULL && "empty method param type");
-  return method->attr.ma.param_type[pos].tp = skip_tid(res);
+  return method->attr.ma.params[pos].tp = skip_tid(res);
 }
 
 void  set_method_param_type(ir_type *method, int pos, ir_type *tp) {
   assert(method && (method->type_op == type_method));
   assert(pos >= 0 && pos < get_method_n_params(method));
-  method->attr.ma.param_type[pos].tp = tp;
+  method->attr.ma.params[pos].tp = tp;
   /* If information constructed set pass-by-value representation. */
   if (method->attr.ma.value_params) {
     assert(get_method_n_params(method) == get_struct_n_members(method->attr.ma.value_params));
@@ -1200,6 +1243,28 @@ void  set_method_param_type(ir_type *method, int pos, ir_type *tp) {
   }
 }
 
+/* Returns an ident representing the parameters name. Returns NULL if not set.
+   For debug support only. */
+ident *get_method_param_ident(ir_type *method, int pos) {
+  assert(method && (method->type_op == type_method));
+  assert(pos >= 0 && pos < get_method_n_params(method));
+  return method->attr.ma.params[pos].param_name;
+}
+
+/* Returns a string representing the parameters name. Returns NULL if not set.
+   For debug support only. */
+const char *get_method_param_name(ir_type *method, int pos) {
+  ident *id = get_method_param_ident(method, pos);
+  return id ? get_id_str(id) : NULL;
+}
+
+/* Sets an ident representing the parameters name. For debug support only. */
+void set_method_param_ident(ir_type *method, int pos, ident *id) {
+  assert(method && (method->type_op == type_method));
+  assert(pos >= 0 && pos < get_method_n_params(method));
+  method->attr.ma.params[pos].param_name = id;
+}
+
 /* Returns an entity that represents the copied value argument.  Only necessary
    for compounds passed by value. */
 entity *get_method_value_param_ent(ir_type *method, int pos) {
@@ -1210,15 +1275,15 @@ entity *get_method_value_param_ent(ir_type *method, int pos) {
     /* parameter value type not created yet, build */
     method->attr.ma.value_params
       = build_value_type(mangle_u(get_type_ident(method), value_params_suffix),
-             get_method_n_params(method), method->attr.ma.param_type);
+             get_method_n_params(method), method->attr.ma.params);
   }
   /*
    * build_value_type() sets the method->attr.ma.value_params type as default if
    * no type is set!
    */
-  assert((get_entity_type(method->attr.ma.param_type[pos].ent) != method->attr.ma.value_params)
+  assert((get_entity_type(method->attr.ma.params[pos].ent) != method->attr.ma.value_params)
      && "param type not yet set");
-  return method->attr.ma.param_type[pos].ent;
+  return method->attr.ma.params[pos].ent;
 }
 
 /*
@@ -1517,6 +1582,7 @@ void free_array_attrs (ir_type *array) {
   assert(array && (array->type_op == type_array));
   free(array->attr.aa.lower_bound);
   free(array->attr.aa.upper_bound);
+  free(array->attr.aa.order);
 }
 
 /* manipulate private fields of array ir_type */
@@ -1660,11 +1726,11 @@ void set_array_size_bits(ir_type *tp, int size) {
 
 /* create a new type enumeration -- set the enumerators independently */
 ir_type *new_d_type_enumeration(ident *name, int n_enums, dbg_info *db) {
-  ir_type *res = new_type(type_enumeration, NULL, name, db);
+  ir_type *res;
 
-  res->attr.ea.n_enums     = n_enums;
-  res->attr.ea.enumer      = xcalloc(n_enums, sizeof(res->attr.ea.enumer[0]));
-  res->attr.ea.enum_nameid = xcalloc(n_enums, sizeof(res->attr.ea.enum_nameid[0]));
+  assert(n_enums >= 0);
+  res = new_type(type_enumeration, NULL, name, db);
+  res->attr.ea.enumer = NEW_ARR_F(ir_enum_const, n_enums);
   hook_new_type(res);
   return res;
 }
@@ -1678,39 +1744,46 @@ void free_enumeration_entities(ir_type *enumeration) {
 }
 void free_enumeration_attrs(ir_type *enumeration) {
   assert(enumeration && (enumeration->type_op == type_enumeration));
-  free(enumeration->attr.ea.enumer);
-  free(enumeration->attr.ea.enum_nameid);
+  DEL_ARR_F(enumeration->attr.ea.enumer);
 }
 
 /* manipulate fields of enumeration type. */
-int     get_enumeration_n_enums (const ir_type *enumeration) {
+int     get_enumeration_n_enums(const ir_type *enumeration) {
   assert(enumeration && (enumeration->type_op == type_enumeration));
-  return enumeration->attr.ea.n_enums;
+  return ARR_LEN(enumeration->attr.ea.enumer);
 }
-void    set_enumeration_enum    (ir_type *enumeration, int pos, tarval *con) {
-  assert(enumeration && (enumeration->type_op == type_enumeration));
-  assert(pos >= 0 && pos < get_enumeration_n_enums(enumeration));
-  enumeration->attr.ea.enumer[pos] = con;
+
+/* create a new constant */
+void set_enumeration_const(ir_type *enumeration, int pos, ident *nameid, tarval *con) {
+  assert(0 <= pos && pos < ARR_LEN(enumeration->attr.ea.enumer));
+  enumeration->attr.ea.enumer[pos].nameid = nameid;
+  enumeration->attr.ea.enumer[pos].value  = con;
+  enumeration->attr.ea.enumer[pos].owner  = enumeration;
 }
-tarval *get_enumeration_enum    (const ir_type *enumeration, int pos) {
+
+ir_enum_const *get_enumeration_const(const ir_type *enumeration, int pos) {
   assert(enumeration && (enumeration->type_op == type_enumeration));
   assert(pos >= 0 && pos < get_enumeration_n_enums(enumeration));
-  return enumeration->attr.ea.enumer[pos];
+  return &enumeration->attr.ea.enumer[pos];
 }
-void    set_enumeration_nameid  (ir_type *enumeration, int pos, ident *id) {
-  assert(enumeration && (enumeration->type_op == type_enumeration));
-  assert(pos >= 0 && pos < get_enumeration_n_enums(enumeration));
-  enumeration->attr.ea.enum_nameid[pos] = id;
+
+ir_type *get_enumeration_owner(const ir_enum_const *enum_cnst) {
+  return enum_cnst->owner;
 }
-ident  *get_enumeration_nameid  (const ir_type *enumeration, int pos) {
-  assert(enumeration && (enumeration->type_op == type_enumeration));
-  assert(pos >= 0 && pos < get_enumeration_n_enums(enumeration));
-  return enumeration->attr.ea.enum_nameid[pos];
+void    set_enumeration_value(ir_enum_const *enum_cnst, tarval *con) {
+  enum_cnst->value = con;
 }
-const char *get_enumeration_name(const ir_type *enumeration, int pos) {
-  assert(enumeration && (enumeration->type_op == type_enumeration));
-  assert(pos >= 0 && pos < get_enumeration_n_enums(enumeration));
-  return get_id_str(enumeration->attr.ea.enum_nameid[pos]);
+tarval *get_enumeration_value(const ir_enum_const *enum_cnst) {
+  return enum_cnst->value;
+}
+void    set_enumeration_nameid(ir_enum_const *enum_cnst, ident *id) {
+  enum_cnst->nameid = id;
+}
+ident  *get_enumeration_nameid(const ir_enum_const *enum_cnst) {
+  return enum_cnst->nameid;
+}
+const char *get_enumeration_name(const ir_enum_const *enum_cnst) {
+  return get_id_str(enum_cnst->nameid);
 }
 
 /* typecheck */
@@ -1786,8 +1859,8 @@ void set_pointer_mode(ir_type *tp, ir_mode *mode) {
  *  Not efficient: O(#types).
  *  If not found returns firm_unknown_type. */
 ir_type *find_pointer_type_to_type (ir_type *tp) {
-  int i;
-  for (i = 0; i < get_irp_n_types(); ++i) {
+  int i, n = get_irp_n_types();
+  for (i = 0; i < n; ++i) {
     ir_type *found = get_irp_type(i);
     if (is_Pointer_type(found) && get_pointer_points_to_type(found) == tp)
       return (found);
@@ -1890,12 +1963,17 @@ int is_compound_type(const ir_type *tp) {
   return tp->type_op->flags & TP_OP_FLAG_COMPOUND;
 }
 
-/* Checks, whether a type is a frame ir_type */
+/* Checks, whether a type is a frame type */
 int is_frame_type(const ir_type *tp) {
   return tp->flags & tf_frame_type;
 }
 
-/* Checks, whether a type is a lowered ir_type */
+/* Checks, whether a type is a value parameter type */
+int is_value_param_type(const ir_type *tp) {
+  return tp->flags & tf_value_param_type;
+}
+
+/* Checks, whether a type is a lowered type */
 int is_lowered_type(const ir_type *tp) {
   return tp->flags & tf_lowered_type;
 }
@@ -1933,3 +2011,62 @@ ir_type *get_associated_type(const ir_type *tp) {
 void set_default_size_bits(ir_type *tp, int size) {
   tp->size = size;
 }
+
+/*
+ * Allocate an area of size bytes aligned at alignment
+ * at the start or the end of a frame type.
+ * The frame type must have already an fixed layout.
+ */
+entity *frame_alloc_area(ir_type *frame_type, int size, int alignment, int at_start)
+{
+  entity *area;
+  ir_type *tp;
+  ident *name;
+  char buf[32];
+  int frame_align, i, offset, frame_size;
+  static unsigned area_cnt = 0;
+  static ir_type *a_byte = NULL;
+
+  assert(is_frame_type(frame_type));
+  assert(get_type_state(frame_type) == layout_fixed);
+
+  if (! a_byte)
+    a_byte = new_type_primitive(new_id_from_chars("byte", 4), mode_Bu);
+
+  snprintf(buf, sizeof(buf), "area%u", area_cnt++);
+  name = new_id_from_str(buf);
+
+  /* align the size */
+  frame_align = get_type_alignment_bytes(frame_type);
+  size = (size + frame_align - 1) & -frame_align;
+
+  tp = new_type_array(mangle_u(get_type_ident(frame_type), name), 1, a_byte);
+  set_array_bounds_int(tp, 0, 0, size);
+  set_type_alignment_bytes(tp, alignment);
+
+  frame_size = get_type_size_bytes(frame_type);
+  if (at_start) {
+    /* fix all offsets so far */
+    for (i = get_class_n_members(frame_type) - 1; i >= 0; --i) {
+      entity *ent = get_class_member(frame_type, i);
+
+      set_entity_offset_bytes(ent, get_entity_offset_bytes(ent) + size);
+    }
+    /* calculate offset and new type size */
+    offset = 0;
+    frame_size += size;
+  }
+  else {
+    /* calculate offset and new type size */
+    offset = (frame_size + alignment - 1) & -alignment;
+    frame_size = offset + size;
+  }
+
+  area = new_entity(frame_type, name, tp);
+  set_entity_offset_bytes(area, offset);
+  set_type_size_bytes(frame_type, frame_size);
+
+  /* mark this entity as compiler generated */
+  set_entity_compiler_generated(area, 1);
+  return area;
+}