irop_flag_highlevel flag added to Confirm and Cast
[libfirm] / ir / tr / tr_inheritance.c
index e79aa84..ea2c044 100644 (file)
 #include "type.h"
 #include "entity.h"
 #include "typewalk.h"
+#include "irgraph_t.h"
 #include "irprog_t.h"
 #include "pset.h"
 #include "set.h"
 #include "mangle.h"
+#include "irgwalk.h"
+#include "irflag.h"
 //#include ".h"
 
 
-
 /* ----------------------------------------------------------------------- */
 /* Resolve implicit inheritance.                                           */
 /* ----------------------------------------------------------------------- */
 
 ident *default_mangle_inherited_name(entity *super, type *clss) {
-  return mangle_u(get_type_ident(clss), get_entity_ident(super));
+  return mangle_u(new_id_from_str("inh"), mangle_u(get_type_ident(clss), get_entity_ident(super)));
 }
 
-/* Replicates all entities in all super classes that are not overwritten
+/** Replicates all entities in all super classes that are not overwritten
    by an entity of this class. */
 static void copy_entities_from_superclass(type *clss, void *env)
 {
@@ -55,27 +57,27 @@ static void copy_entities_from_superclass(type *clss, void *env)
       /* check whether inhent is already overwritten */
       overwritten = 0;
       for (k = 0; (k < get_class_n_members(clss)) && (overwritten == 0); k++) {
-       thisent = get_class_member(clss, k);
-       for(l = 0; l < get_entity_n_overwrites(thisent); l++) {
-         if(inhent == get_entity_overwrites(thisent, l)) {
-           /* overwritten - do not copy */
-           overwritten = 1;
-           break;
-         }
-       }
+             thisent = get_class_member(clss, k);
+             for(l = 0; l < get_entity_n_overwrites(thisent); l++) {
+               if(inhent == get_entity_overwrites(thisent, l)) {
+                 /* overwritten - do not copy */
+                 overwritten = 1;
+                 break;
+               }
+             }
       }
       /* Inherit entity */
       if (!overwritten) {
-       thisent = copy_entity_own(inhent, clss);
-       add_entity_overwrites(thisent, inhent);
-       set_entity_peculiarity(thisent, peculiarity_inherited);
-       set_entity_ld_ident(thisent, mfunc(inhent, clss));
-       if (get_entity_variability(inhent) == variability_constant) {
-         assert(is_atomic_entity(inhent) &&  /* @@@ */
-                "Inheritance of constant, compound entities not implemented");
-         set_entity_variability(thisent, variability_constant);
-         set_atomic_ent_value(thisent, get_atomic_ent_value(inhent));
-       }
+             thisent = copy_entity_own(inhent, clss);
+             add_entity_overwrites(thisent, inhent);
+             set_entity_peculiarity(thisent, peculiarity_inherited);
+             set_entity_ld_ident(thisent, mfunc(inhent, clss));
+             if (get_entity_variability(inhent) == variability_constant) {
+               assert(is_atomic_entity(inhent) &&  /* @@@ */
+                      "Inheritance of constant, compound entities not implemented");
+               set_entity_variability(thisent, variability_constant);
+               set_atomic_ent_value(thisent, get_atomic_ent_value(inhent));
+             }
       }
     }
   }
@@ -171,37 +173,46 @@ static tr_inh_trans_tp* get_firm_kind_entry(firm_kind *k) {
 }
 
 static pset *get_entity_map(entity *ent, dir d) {
+  tr_inh_trans_tp *found;
+
   assert(is_entity(ent));
-  tr_inh_trans_tp *found = get_firm_kind_entry((firm_kind *)ent);
-  if (d == d_up) return found->up;
-  else           return found->down;
+  found = get_firm_kind_entry((firm_kind *)ent);
+  return (d == d_up) ? found->up : found->down;
 }
 /*
 static void  add_entity_map(entity *ent, dir d, entity *new) {
+  tr_inh_trans_tp *found;
+
   assert(is_entity(ent) && is_entity(new));
   tr_inh_trans_tp *found = get_firm_kind_entry((firm_kind *)ent);
-  if (d == d_up) pset_insert_ptr(found->up,   new);
-  else           pset_insert_ptr(found->down, new);
+  if (d == d_up)
+    pset_insert_ptr(found->up,   new);
+  else
+    pset_insert_ptr(found->down, new);
 }
 */
 static pset *get_type_map(type *tp, dir d) {
+  tr_inh_trans_tp *found;
+
   assert(is_type(tp));
-  tr_inh_trans_tp *found = get_firm_kind_entry((firm_kind *)tp);
-  if (d == d_up) return found->up;
-  else           return found->down;
+  found = get_firm_kind_entry((firm_kind *)tp);
+  return (d == d_up) ? found->up : found->down;
 }
 /*
 static void  add_type_map(type *tp, dir d, type *new) {
+  tr_inh_trans_tp *found;
+
   assert(is_type(tp) && is_type(new));
-  tr_inh_trans_tp *found = get_firm_kind_entry((firm_kind *)tp);
+  found = get_firm_kind_entry((firm_kind *)tp);
   if (d == d_up) pset_insert_ptr(found->up,   new);
   else           pset_insert_ptr(found->down, new);
 }
 */
 
 
-/* Walk over all types reachable from tp in the sub/supertype
- * retlation and compute the closure for the two downwards directed
+/**
+ * Walk over all types reachable from tp in the sub/supertype
+ * relation and compute the closure for the two downwards directed
  * relations.
  *
  * The walk in the dag formed by the relation is tricky:  We must visit
@@ -218,7 +229,7 @@ static void  add_type_map(type *tp, dir d, type *new) {
 static void compute_down_closure(type *tp) {
   pset *myset, *subset;
   int i, n_subtypes, n_members, n_supertypes;
-  int master_visited = get_master_type_visited();
+  unsigned long master_visited = get_master_type_visited();
 
   assert(is_Class_type(tp));
 
@@ -228,8 +239,7 @@ static void compute_down_closure(type *tp) {
   n_subtypes = get_class_n_subtypes(tp);
   for (i = 0; i < n_subtypes; ++i) {
     type *stp = get_class_subtype(tp, i);
-    if (type_not_visited(stp)) {
-      assert(get_type_visited(tp) < master_visited-1);
+    if (get_type_visited(stp) < master_visited-1) {
       compute_down_closure(stp);
     }
   }
@@ -250,11 +260,11 @@ static void compute_down_closure(type *tp) {
     int j, n_overwrittenby = get_entity_n_overwrittenby(mem);
 
     myset = get_entity_map(mem, d_down);
-    for (j = 0; j > n_overwrittenby; ++j) {
+    for (j = 0; j < n_overwrittenby; ++j) {
       entity *ov = get_entity_overwrittenby(mem, j);
       subset = get_entity_map(ov, d_down);
-      pset_insert_pset_ptr(myset, subset);
       pset_insert_ptr(myset, ov);
+      pset_insert_pset_ptr(myset, subset);
     }
   }
 
@@ -264,7 +274,7 @@ static void compute_down_closure(type *tp) {
   n_supertypes = get_class_n_supertypes(tp);
   for (i = 0; i < n_supertypes; ++i) {
     type *stp = get_class_supertype(tp, i);
-    if (get_type_visited(tp) < master_visited-1) {
+    if (get_type_visited(stp) < master_visited-1) {
       compute_down_closure(stp);
     }
   }
@@ -273,7 +283,7 @@ static void compute_down_closure(type *tp) {
 static void compute_up_closure(type *tp) {
   pset *myset, *subset;
   int i, n_subtypes, n_members, n_supertypes;
-  int master_visited = get_master_type_visited();
+  unsigned long master_visited = get_master_type_visited();
 
   assert(is_Class_type(tp));
 
@@ -283,8 +293,7 @@ static void compute_up_closure(type *tp) {
   n_supertypes = get_class_n_supertypes(tp);
   for (i = 0; i < n_supertypes; ++i) {
     type *stp = get_class_supertype(tp, i);
-    if (type_not_visited(stp)) {
-      assert(get_type_visited(tp) < get_master_type_visited()-1);
+    if (get_type_visited(stp) < get_master_type_visited()-1) {
       compute_up_closure(stp);
     }
   }
@@ -305,7 +314,7 @@ static void compute_up_closure(type *tp) {
     int j, n_overwrites = get_entity_n_overwrites(mem);
 
     myset = get_entity_map(mem, d_up);
-    for (j = 0; j > n_overwrites; ++j) {
+    for (j = 0; j < n_overwrites; ++j) {
       entity *ov = get_entity_overwrites(mem, j);
       subset = get_entity_map(ov, d_up);
       pset_insert_pset_ptr(myset, subset);
@@ -319,7 +328,7 @@ static void compute_up_closure(type *tp) {
   n_subtypes = get_class_n_subtypes(tp);
   for (i = 0; i < n_subtypes; ++i) {
     type *stp = get_class_subtype(tp, i);
-    if (get_type_visited(tp) < master_visited-1) {
+    if (get_type_visited(stp) < master_visited-1) {
       compute_up_closure(stp);
     }
   }
@@ -340,9 +349,10 @@ void compute_inh_transitive_closure(void) {
   for (i = 0; i < n_types; ++i) {
     type *tp = get_irp_type(i);
     if (is_Class_type(tp) && type_not_visited(tp)) { /* For others there is nothing to accumulate. */
-      assert(get_type_visited(tp) < get_master_type_visited()-1);
       int j, n_subtypes = get_class_n_subtypes(tp);
       int has_unmarked_subtype = false;
+
+      assert(get_type_visited(tp) < get_master_type_visited()-1);
       for (j = 0; j < n_subtypes && !has_unmarked_subtype; ++j) {
        type *stp = get_class_subtype(tp, j);
        if (type_not_visited(stp)) has_unmarked_subtype = true;
@@ -360,12 +370,13 @@ void compute_inh_transitive_closure(void) {
   for (i = 0; i < n_types; ++i) {
     type *tp = get_irp_type(i);
     if (is_Class_type(tp) && type_not_visited(tp)) { /* For others there is nothing to accumulate. */
-      assert(get_type_visited(tp) < get_master_type_visited()-1);
       int j, n_supertypes = get_class_n_supertypes(tp);
       int has_unmarked_supertype = false;
+
+      assert(get_type_visited(tp) < get_master_type_visited()-1);
       for (j = 0; j < n_supertypes && !has_unmarked_supertype; ++j) {
-       type *stp = get_class_supertype(tp, j);
-       if (type_not_visited(stp)) has_unmarked_supertype = true;
+             type *stp = get_class_supertype(tp, j);
+             if (type_not_visited(stp)) has_unmarked_supertype = true;
       }
 
       /* This is a good starting point. */
@@ -403,6 +414,11 @@ type *get_class_trans_subtype_next (type *tp) {
   return pset_next(get_type_map(tp, d_down));
 }
 
+int is_class_trans_subtype (type *tp, type *subtp) {
+  assert_valid_state();
+  return (pset_find_ptr(get_type_map(tp, d_down), subtp) != NULL);
+}
+
 /* - supertype ----------------------------------------------------------- */
 
 type *get_class_trans_supertype_first(type *tp) {
@@ -458,8 +474,7 @@ int is_subclass_of(type *low, type *high) {
 
   if (get_irp_inh_transitive_closure_state() == inh_transitive_closure_valid) {
     pset *m = get_type_map(high, d_down);
-    if (pset_find_ptr(m, low)) return 1;
-    else                        return 0;
+    return pset_find_ptr(m, low) ? 1 : 0;
   }
 
   /* depth first search from high downwards. */
@@ -473,14 +488,17 @@ int is_subclass_of(type *low, type *high) {
   return 0;
 }
 
+int is_superclass_of(type *high, type *low) {
+  return is_subclass_of(low, high);
+}
+
 int is_overwritten_by(entity *high, entity *low) {
   int i, n_overwrittenby;
   assert(is_entity(low) && is_entity(high));
 
   if (get_irp_inh_transitive_closure_state() == inh_transitive_closure_valid) {
     pset *m = get_entity_map(high, d_down);
-    if (pset_find_ptr(m, low)) return 1;
-    else                       return 0;
+    return pset_find_ptr(m, low) ? 1 : 0;
   }
 
   /* depth first search from high downwards. */
@@ -495,7 +513,7 @@ int is_overwritten_by(entity *high, entity *low) {
 }
 
 
-/* Need two routines because I want to assert the result. */
+/** Need two routines because I want to assert the result. */
 static entity *resolve_ent_polymorphy2 (type *dynamic_class, entity *static_ent) {
   int i, n_overwrittenby;
   entity *res = NULL;
@@ -526,3 +544,101 @@ entity *resolve_ent_polymorphy(type *dynamic_class, entity *static_ent) {
 
   return res;
 }
+
+
+
+/* ----------------------------------------------------------------------- */
+/* Class cast state handling.                                              */
+/* ----------------------------------------------------------------------- */
+
+/* - State handling. ----------------------------------------- */
+
+void set_irg_class_cast_state(ir_graph *irg, ir_class_cast_state s) {
+  if (get_irp_class_cast_state() > s) set_irp_class_cast_state(s);
+  irg->class_cast_state = s;
+}
+
+ir_class_cast_state get_irg_class_cast_state(ir_graph *irg) {
+  return irg->class_cast_state;
+}
+
+void set_irp_class_cast_state(ir_class_cast_state s) {
+  int i;
+  for (i = 0; i < get_irp_n_irgs(); ++i)
+    assert(get_irg_class_cast_state(get_irp_irg(i)) >= s);
+  irp->class_cast_state = s;
+}
+
+ir_class_cast_state get_irp_class_cast_state(void) {
+  return irp->class_cast_state;
+}
+
+char *get_class_cast_state_string(ir_class_cast_state s) {
+#define X(a)    case a: return #a
+  switch(s) {
+    X(ir_class_casts_any);
+    X(ir_class_casts_transitive);
+    X(ir_class_casts_normalized);
+    X(ir_class_casts_state_max);
+  default: return "invalid class cast state";
+  }
+#undef X
+}
+
+/* - State verification. ------------------------------------- */
+
+typedef struct ccs_env {
+  ir_class_cast_state expected_state;
+  ir_class_cast_state worst_situation;
+} ccs_env;
+
+void verify_irn_class_cast_state(ir_node *n, void *env) {
+  ccs_env *ccs = (ccs_env *)env;
+  ir_class_cast_state this_state = ir_class_casts_any;
+
+  type *fromtype = get_irn_typeinfo_type(get_Cast_op(n));
+  type *totype   = get_Cast_type(n);
+  int ref_depth = 0;
+
+  while (is_Pointer_type(totype) && is_Pointer_type(fromtype)) {
+    totype   = get_pointer_points_to_type(totype);
+    fromtype = get_pointer_points_to_type(fromtype);
+    ref_depth++;
+  }
+
+  if (!is_Class_type(totype)) return;
+
+  if (is_subclass_of(totype, fromtype) ||
+      is_subclass_of(fromtype, totype)   ) {
+    this_state = ir_class_casts_transitive;
+    if ((get_class_supertype_index(totype, fromtype) == -1) &&
+       (get_class_supertype_index(fromtype, totype) == -1) ) {
+      this_state = ir_class_casts_normalized;
+    }
+  }
+
+  assert(this_state >= ccs->expected_state &&
+        "invalid state class cast state setting in graph");
+
+  if (this_state < ccs->worst_situation)
+    ccs->worst_situation = this_state;
+}
+
+
+/** Verify that the graph meets reqirements of state set. */
+void verify_irg_class_cast_state(ir_graph *irg) {
+  ccs_env env;
+
+  env.expected_state  = get_irg_class_cast_state(irg);
+  env.worst_situation = ir_class_casts_normalized;
+
+  irg_walk_graph(irg, NULL, verify_irn_class_cast_state, &env);
+
+  if ((env.worst_situation > env.expected_state) && get_firm_verbosity()) {
+    printf("Note:  class cast state is set lower than reqired in graph\n       ");
+    DDMG(irg);
+    printf("       state is %s, reqired is %s\n",
+          get_class_cast_state_string(env.expected_state),
+          get_class_cast_state_string(env.worst_situation));
+  }
+}