class cast states implemented
authorGötz Lindenmaier <goetz@ipd.info.uni-karlsruhe.de>
Fri, 29 Apr 2005 12:06:01 +0000 (12:06 +0000)
committerGötz Lindenmaier <goetz@ipd.info.uni-karlsruhe.de>
Fri, 29 Apr 2005 12:06:01 +0000 (12:06 +0000)
[r5742]

ir/tr/tr_inheritance.c
ir/tr/tr_inheritance.h

index 3712d40..c0b3b73 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"
 
 
@@ -411,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) {
@@ -480,6 +488,10 @@ 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));
@@ -532,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));
+  }
+}
index 5fe6be7..5585c25 100644 (file)
 #define _TR_INHERITANCE_H_
 
 #include "type.h"
-/* #include "entity.h" */
+/*#include "entity.h"*/
 #include "ident.h"
 
+
+/* to resolve recursion between entity.h and irgraph.h */
+#ifndef _IR_GRAPH_TYPEDEF_
+#define _IR_GRAPH_TYPEDEF_
+typedef struct ir_graph ir_graph;
+#endif
+
 /* ----------------------------------------------------------------------- */
 /* Classify pairs of types/entities in the inheritance relations.          */
 /* ----------------------------------------------------------------------- */
  *  subclasses of high.  */
 int is_subclass_of(type *low, type *high);
 
+/** Returns true if high is superclass of low.
+ *
+ *  Low is a subclass of high if low == high or if low is a subclass of
+ *  a subclass of high.  I.e, we search in all subtypes of high for low.
+ *  @@@ this can be implemented more efficient if we know the set of all
+ *  subclasses of high.  */
+int is_superclass_of(type *high, type *low);
+
 /** Returns true if high is (transitive) overwritten by low.
  *
  *  Returns false if high == low. */
@@ -52,9 +67,9 @@ int is_overwritten_by(entity *high, entity *low);
 
 /** Resolve polymorphy in the inheritance relation.
  *
- * Returns the dynamically referenced entity if the static entity and the
- * dynamic type are given.
- * Searches downwards in overwritten tree. */
+ *  Returns the dynamically referenced entity if the static entity and the
+ *  dynamic type are given.
+ *  Searches downwards in overwritten tree. */
 entity *resolve_ent_polymorphy(type *dynamic_class, entity* static_ent);
 
 /* ----------------------------------------------------------------------- */
@@ -119,8 +134,8 @@ typedef enum {
   inh_transitive_closure_max         /**<  Invalid value. */
 } inh_transitive_closure_state;
 
-void                        set_irp_inh_transitive_closure_state(inh_transitive_closure_state s);
-void                        invalidate_irp_inh_transitive_closure_state(void);
+void                         set_irp_inh_transitive_closure_state(inh_transitive_closure_state s);
+void                         invalidate_irp_inh_transitive_closure_state(void);
 inh_transitive_closure_state get_irp_inh_transitive_closure_state(void);
 
 
@@ -140,6 +155,7 @@ void free_inh_transitive_closure(void);
 /** Iterate over all transitive subtypes. */
 type *get_class_trans_subtype_first(type *tp);
 type *get_class_trans_subtype_next (type *tp);
+int   is_class_trans_subtype (type *tp, type *subtp);
 
 /* - supertype ----------------------------------------------------------- */
 
@@ -159,4 +175,54 @@ entity *get_entity_trans_overwrittenby_next (entity *ent);
 entity *get_entity_trans_overwrites_first(entity *ent);
 entity *get_entity_trans_overwrites_next (entity *ent);
 
+
+/* ----------------------------------------------------------------------- */
+/** The state of Cast operations that cast class types or pointers to class
+ *  types.
+ *
+ * The state expresses, how far Cast operations conform with the class
+ * hierarchy.
+ *
+ *   class A {}
+ *   class B1 extends A {}
+ *   class B2 extends A {}
+ *   class C  extends B1 {}
+ * normalized:  Cast operations conform with the inheritance relation.
+ *   I.e., the type of the operand of a Cast is either a super= or a sub-
+ *   type of the type casted to. Example: (A)((B2) (new C())).
+ * transitive:  Cast operations conform with the transitive inheritance
+ *   relation. Example: (A)(new C()).
+ * any:  Cast operations do not conform with the transitive inheritance
+ *   relation.  Example: (B2)(new B1())
+ *
+ *  @see: tropt.h
+ */
+/* ----------------------------------------------------------------------- */
+
+/** Flags for class cast state.
+ *
+ * The state in irp is allways smaller or equal to the state of any
+ * irg.
+ *
+ * We rely on the ordering of the enum. */
+typedef enum {
+  ir_class_casts_any        = 0, /**< There are class casts that do not cast in conformance with
+                                     the class hierarchy.  @@@ So far this does not happen in Firm. */
+  ir_class_casts_transitive = 1, /**< Class casts conform to transitive inheritance edges. Default. */
+  ir_class_casts_normalized = 2, /**< Class casts conform to inheritance edges. */
+  ir_class_casts_state_max,
+} ir_class_cast_state;
+char *get_class_cast_state_string(ir_class_cast_state s);
+
+void                set_irg_class_cast_state(ir_graph *irg, ir_class_cast_state s);
+ir_class_cast_state get_irg_class_cast_state(ir_graph *irg);
+void                set_irp_class_cast_state(ir_class_cast_state s);
+ir_class_cast_state get_irp_class_cast_state(void);
+
+/** Verify the class cast state of an irg.
+ *
+ *  Asserts if state is to high, outputs warning if state is to low
+ *  and firm verbosity is set.
+ */
+void verify_irg_class_cast_state(ir_graph *irg);
 #endif  /* _TR_INHERITANCE_H_ */