From: Götz Lindenmaier Date: Fri, 29 Apr 2005 12:06:01 +0000 (+0000) Subject: class cast states implemented X-Git-Url: http://nsz.repo.hu/git/?a=commitdiff_plain;h=7012801102da788b13623eb0768e1acf7bf5578c;p=libfirm class cast states implemented [r5742] --- diff --git a/ir/tr/tr_inheritance.c b/ir/tr/tr_inheritance.c index 3712d40a7..c0b3b73aa 100644 --- a/ir/tr/tr_inheritance.c +++ b/ir/tr/tr_inheritance.c @@ -20,10 +20,13 @@ #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)); + } +} diff --git a/ir/tr/tr_inheritance.h b/ir/tr/tr_inheritance.h index 5fe6be7b8..5585c257c 100644 --- a/ir/tr/tr_inheritance.h +++ b/ir/tr/tr_inheritance.h @@ -30,9 +30,16 @@ #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. */ /* ----------------------------------------------------------------------- */ @@ -45,6 +52,14 @@ * 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_ */