From: Götz Lindenmaier Date: Mon, 14 Mar 2005 11:33:09 +0000 (+0000) Subject: moved stuff handling inheritance to an own file X-Git-Url: http://nsz.repo.hu/git/?a=commitdiff_plain;h=e18eba3e4511208f4eaccc1501ead35ba8c555b8;p=libfirm moved stuff handling inheritance to an own file Added algorithm to compute transitive closure of inheritance [r5368] --- diff --git a/ir/ir/irprog_t.h b/ir/ir/irprog_t.h index 7a7cbdc44..c5dadf0b6 100644 --- a/ir/ir/irprog_t.h +++ b/ir/ir/irprog_t.h @@ -28,6 +28,7 @@ #include "firm_common_t.h" #include "typegmod.h" #include "irtypeinfo.h" +#include "tr_inheritance.h" #include "callgraph.h" #include "field_temperature.h" @@ -63,6 +64,7 @@ struct ir_prog { irg_callee_info_state callee_info_state; /**< Validity of callee information. Contains the lowest value or all irgs. */ ir_typeinfo_state typeinfo_state; /**< Validity of type information. */ + inh_transitive_closure_state inh_trans_closure_state; /**< trans closure of inh relations. */ irp_callgraph_state callgraph_state; /**< State of the callgraph. */ struct ir_loop *outermost_cg_loop; /**< For callgraph analysis: entry point diff --git a/ir/tr/Makefile.in b/ir/tr/Makefile.in index c2f627196..9c7fa3736 100644 --- a/ir/tr/Makefile.in +++ b/ir/tr/Makefile.in @@ -16,13 +16,13 @@ topdir = ../.. subdir := ir/tr INSTALL_HEADERS = entity.h mangle.h tpop.h type.h typewalk.h type_or_entity.h \ - typegmod.h trvrfy.h type_identify.h + typegmod.h trvrfy.h type_identify.h tr_inheritance.h SOURCES = $(INSTALL_HEADERS) SOURCES += Makefile.in \ entity.c entity_t.h mangle.c tpop.c tpop_t.h type.c type_t.h \ - typewalk.c typegmod.c trvrfy.h trvrfy.c type_identify.c + typewalk.c typegmod.c trvrfy.h trvrfy.c type_identify.c tr_inheritance.c include $(topdir)/MakeRules diff --git a/ir/tr/entity.c b/ir/tr/entity.c index c6b1b6d0a..20b930de1 100644 --- a/ir/tr/entity.c +++ b/ir/tr/entity.c @@ -1285,44 +1285,3 @@ bool entity_not_visited(entity *ent) { assert(ent && ent->kind == k_entity); return get_entity_visited(ent) < type_visited; } - -/* 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; - - if (get_entity_owner(static_ent) == dynamic_class) return static_ent; - - n_overwrittenby = get_entity_n_overwrittenby(static_ent); - for (i = 0; i < n_overwrittenby; ++i) { - res = resolve_ent_polymorphy2(dynamic_class, get_entity_overwrittenby(static_ent, i)); - if (res) - break; - } - - return res; -} - -/** Resolve polymorphy in the inheritance relation. - * - * Returns the dynamically referenced entity if the static entity and the - * dynamic type are given. - * Search downwards in overwritten tree. */ -entity *resolve_ent_polymorphy(type *dynamic_class, entity *static_ent) { - entity *res; - assert(static_ent && static_ent->kind == k_entity); - - res = resolve_ent_polymorphy2(dynamic_class, static_ent); -#if DEBUG_libfirm - if (!res) { - printf(" Could not find entity "); DDME(static_ent); - printf(" in "); DDMT(dynamic_class); - printf("\n"); - dump_entity(static_ent); - dump_type(get_entity_owner(static_ent)); - dump_type(dynamic_class); - } -#endif - assert(res); - return res; -} diff --git a/ir/tr/entity.h b/ir/tr/entity.h index 89b549f78..e42a11dfb 100644 --- a/ir/tr/entity.h +++ b/ir/tr/entity.h @@ -49,13 +49,11 @@ * - int offset: Offset in bits for this entity. Fixed when layout * of owner is determined. * - ir_graph *irg: If (type == method_type) this is the corresponding irg. -* The ir_graph constructor automatically sets this field. +* The ir_graph constructor automatically sets this field. * If (type != method_type) access of this field will cause * an assertion. */ -/* $Id$ */ - # ifndef _ENTITY_H_ # define _ENTITY_H_ @@ -63,6 +61,8 @@ # include "type.h" # include "dbginfo.h" +# include "tr_inheritance.h" + /*-----------------------------------------------------------------*/ /* general */ /*-----------------------------------------------------------------*/ @@ -517,7 +517,6 @@ int is_compound_entity(entity *ent); */ bool equal_entity(entity *ent1, entity *ent2); - /** Outputs a unique number for this entity if libfirm is compiled for debugging, (configure with --enable-debug) else returns 0. */ long get_entity_nr(entity *ent); @@ -537,10 +536,6 @@ bool entity_visited(entity *ent); /** Returns true if this entity was not visited. */ bool entity_not_visited(entity *ent); -/** Returns the dynamically referenced entity if the static entity and the - * dynamic type are given. */ -entity *resolve_ent_polymorphy(type *dynamic_class, entity* static_ent); - /** * @page unknown_entity * diff --git a/ir/tr/tr_inheritance.c b/ir/tr/tr_inheritance.c new file mode 100644 index 000000000..e79aa84ef --- /dev/null +++ b/ir/tr/tr_inheritance.c @@ -0,0 +1,528 @@ +/** + * + * @file tp_inheritance.c + * + * Project: libFIRM
+ * File name: ir/tr/tp_inheritance.c
+ * Purpose: Utility routines for inheritance representation
+ * Author: Goetz Lindenmaier
+ * Modified by:
+ * Created:
+ * Copyright: (c) 2001-2005 Universität Karlsruhe
+ * Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE.
+ * CVS-ID: $Id$ + * + * + * + * @see type.h entity.h + */ + +#include "type.h" +#include "entity.h" +#include "typewalk.h" +#include "irprog_t.h" +#include "pset.h" +#include "set.h" +#include "mangle.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)); +} + +/* 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) +{ + int i, j, k, l; + int overwritten; + type *super, *inhenttype; + entity *inhent, *thisent; + mangle_inherited_name_func *mfunc = (mangle_inherited_name_func *)env; + + for(i = 0; i < get_class_n_supertypes(clss); i++) { + super = get_class_supertype(clss, i); + assert(is_Class_type(super) && "not a class"); + for(j = 0; j < get_class_n_members(super); j++) { + inhent = get_class_member(super, j); + inhenttype = get_entity_type(inhent); + /* 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; + } + } + } + /* 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)); + } + } + } + } +} + +/* Resolve implicit inheritance. + * + * Resolves the implicit inheritance supplied by firm. + */ +void resolve_inheritance(mangle_inherited_name_func *mfunc) { + if (!mfunc) + mfunc = default_mangle_inherited_name; + class_walk_super2sub(copy_entities_from_superclass, NULL, (void *)mfunc); +} + + +/* ----------------------------------------------------------------------- */ +/* The transitive closure of the subclass/superclass and */ +/* overwrites/overwrittenby relation. */ +/* */ +/* A walk over the ir (O(#types+#entities)) computes the transitive */ +/* closure. Adding a new type/entity or changing the basic relations in */ +/* some other way invalidates the transitive closure, i.e., it is not */ +/* updated by the basic functions. */ +/* */ +/* All functions are named as their counterparts for the basic relations, */ +/* adding the infix 'trans_'. */ +/* ----------------------------------------------------------------------- */ + +void set_irp_inh_transitive_closure_state(inh_transitive_closure_state s) { + irp->inh_trans_closure_state = s; +} +void invalidate_irp_inh_transitive_closure_state(void) { + if (irp->inh_trans_closure_state == inh_transitive_closure_valid) + irp->inh_trans_closure_state = inh_transitive_closure_invalid; +} +inh_transitive_closure_state get_irp_inh_transitive_closure_state(void) { + return irp->inh_trans_closure_state; +} + +static void assert_valid_state(void) { + assert(irp->inh_trans_closure_state == inh_transitive_closure_valid || + irp->inh_trans_closure_state == inh_transitive_closure_invalid); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +/* There is a set that extends each entity/type with two new */ +/* fields: one for the upwards directed relation: 'up' (supertype, */ +/* overwrites) and one for the downwards directed relation: 'down' (sub- */ +/* type, overwrittenby. These fields contain psets (and maybe later */ +/* arrays) listing all subtypes... */ +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +typedef struct { + firm_kind *kind; /* An entity or type. */ + pset *up; + pset *down; +} tr_inh_trans_tp; + +/* We use this set for all types and entities. */ +static set *tr_inh_trans_set = NULL; + +static int tr_inh_trans_cmp(const void *e1, const void *e2, size_t size) { + tr_inh_trans_tp *ef1 = (tr_inh_trans_tp *)e1; + tr_inh_trans_tp *ef2 = (tr_inh_trans_tp *)e2; + return (ef1->kind != ef2->kind); +} + +static INLINE unsigned int tr_inh_trans_hash(void *e) { + void *v = (void *) ((tr_inh_trans_tp *)e)->kind; + return HASH_PTR(v); +} + +typedef enum { + d_up, + d_down, +} dir; + +/* This always completes successfully. */ +static tr_inh_trans_tp* get_firm_kind_entry(firm_kind *k) { + tr_inh_trans_tp a, *found; + a.kind = k; + + if (!tr_inh_trans_set) tr_inh_trans_set = new_set(tr_inh_trans_cmp, 128); + + found = set_find(tr_inh_trans_set, &a, sizeof(a), tr_inh_trans_hash(&a)); + if (!found) { + a.up = pset_new_ptr(16); + a.down = pset_new_ptr(16); + found = set_insert(tr_inh_trans_set, &a, sizeof(a), tr_inh_trans_hash(&a)); + } + return found; +} + +static pset *get_entity_map(entity *ent, dir d) { + 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; +} +/* +static void add_entity_map(entity *ent, dir d, entity *new) { + 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); +} +*/ +static pset *get_type_map(type *tp, dir d) { + 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; +} +/* +static void add_type_map(type *tp, dir d, type *new) { + assert(is_type(tp) && is_type(new)); + tr_inh_trans_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 + * relations. + * + * The walk in the dag formed by the relation is tricky: We must visit + * all subtypes before visiting the supertypes. So we first walk down. + * Then we can compute the closure for this type. Then we walk up. + * As we call ourselves recursive, and walk in both directions, there + * can be cycles. So we have to make sure, that if we visit a node + * a second time (in a walk up) we do nothing. For this we increment + * the master visited flag twice. + * If the type is marked with master_flag_visited-1 it is on the stack. + * If it is marked with master_flag_visited it is fully processed. + * + * Well, we still miss some candidates ... */ +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(); + + assert(is_Class_type(tp)); + + set_type_visited(tp, master_visited-1); + + /* Recursive descend. */ + 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); + compute_down_closure(stp); + } + } + + /* types */ + myset = get_type_map(tp, d_down); + for (i = 0; i < n_subtypes; ++i) { + type *stp = get_class_subtype(tp, i); + subset = get_type_map(stp, d_down); + pset_insert_ptr(myset, stp); + pset_insert_pset_ptr(myset, subset); + } + + /* entities */ + n_members = get_class_n_members(tp); + for (i = 0; i < n_members; ++i) { + entity *mem = get_class_member(tp, i); + int j, n_overwrittenby = get_entity_n_overwrittenby(mem); + + myset = get_entity_map(mem, d_down); + 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); + } + } + + mark_type_visited(tp); + + /* Walk up. */ + 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) { + compute_down_closure(stp); + } + } +} + +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(); + + assert(is_Class_type(tp)); + + set_type_visited(tp, master_visited-1); + + /* Recursive descend. */ + 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); + compute_up_closure(stp); + } + } + + /* types */ + myset = get_type_map(tp, d_up); + for (i = 0; i < n_supertypes; ++i) { + type *stp = get_class_supertype(tp, i); + subset = get_type_map(stp, d_up); + pset_insert_ptr(myset, stp); + pset_insert_pset_ptr(myset, subset); + } + + /* entities */ + n_members = get_class_n_members(tp); + for (i = 0; i < n_members; ++i) { + entity *mem = get_class_member(tp, i); + int j, n_overwrites = get_entity_n_overwrites(mem); + + myset = get_entity_map(mem, d_up); + 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); + pset_insert_ptr(myset, ov); + } + } + + mark_type_visited(tp); + + /* Walk down. */ + 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) { + compute_up_closure(stp); + } + } +} + +/** Compute the transitive closure of the subclass/superclass and + * overwrites/overwrittenby relation. + * + * This function walks over the ir (O(#types+#entities)) to compute the + * transitive closure. */ +void compute_inh_transitive_closure(void) { + int i, n_types = get_irp_n_types(); + free_inh_transitive_closure(); + + /* The 'down' relation */ + inc_master_type_visited(); /* Inc twice: one if on stack, second if values computed. */ + inc_master_type_visited(); + 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; + 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; + } + + /* This is a good starting point. */ + if (!has_unmarked_subtype) + compute_down_closure(tp); + } + } + + /* The 'up' relation */ + inc_master_type_visited(); + inc_master_type_visited(); + 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; + 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; + } + + /* This is a good starting point. */ + if (!has_unmarked_supertype) + compute_up_closure(tp); + } + } + + irp->inh_trans_closure_state = inh_transitive_closure_valid; +} + +/** Free memory occupied by the transitive closure information. */ +void free_inh_transitive_closure(void) { + if (tr_inh_trans_set) { + tr_inh_trans_tp *elt; + for (elt = set_first(tr_inh_trans_set); elt; elt = set_next(tr_inh_trans_set)) { + del_pset(elt->up); + del_pset(elt->down); + } + del_set(tr_inh_trans_set); + tr_inh_trans_set = NULL; + } + irp->inh_trans_closure_state = inh_transitive_closure_none; +} + +/* - subtype ------------------------------------------------------------- */ + +type *get_class_trans_subtype_first(type *tp) { + assert_valid_state(); + return pset_first(get_type_map(tp, d_down)); +} + +type *get_class_trans_subtype_next (type *tp) { + assert_valid_state(); + return pset_next(get_type_map(tp, d_down)); +} + +/* - supertype ----------------------------------------------------------- */ + +type *get_class_trans_supertype_first(type *tp) { + assert_valid_state(); + return pset_first(get_type_map(tp, d_up)); +} + +type *get_class_trans_supertype_next (type *tp) { + assert_valid_state(); + return pset_next(get_type_map(tp, d_up)); +} + +/* - overwrittenby ------------------------------------------------------- */ + +entity *get_entity_trans_overwrittenby_first(entity *ent) { + assert_valid_state(); + return pset_first(get_entity_map(ent, d_down)); +} + +entity *get_entity_trans_overwrittenby_next (entity *ent) { + assert_valid_state(); + return pset_next(get_entity_map(ent, d_down)); +} + +/* - overwrites ---------------------------------------------------------- */ + + +/** Iterate over all transitive overwritten entities. */ +entity *get_entity_trans_overwrites_first(entity *ent) { + assert_valid_state(); + return pset_first(get_entity_map(ent, d_up)); +} + +entity *get_entity_trans_overwrites_next (entity *ent) { + assert_valid_state(); + return pset_next(get_entity_map(ent, d_up)); +} + + + + + +/* ----------------------------------------------------------------------- */ +/* Classify pairs of types/entities in the inheritance relations. */ +/* ----------------------------------------------------------------------- */ + +/* Returns true if low is subclass of high. */ +int is_subclass_of(type *low, type *high) { + int i, n_subtypes; + assert(is_Class_type(low) && is_Class_type(high)); + + if (low == high) return 1; + + 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; + } + + /* depth first search from high downwards. */ + n_subtypes = get_class_n_subtypes(high); + for (i = 0; i < n_subtypes; i++) { + type *stp = get_class_subtype(high, i); + if (low == stp) return 1; + if (is_subclass_of(low, stp)) + return 1; + } + return 0; +} + +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; + } + + /* depth first search from high downwards. */ + n_overwrittenby = get_entity_n_overwrittenby(high); + for (i = 0; i < n_overwrittenby; i++) { + entity *ov = get_entity_overwrittenby(high, i); + if (low == ov) return 1; + if (is_overwritten_by(low, ov)) + return 1; + } + return 0; +} + + +/* 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; + + if (get_entity_owner(static_ent) == dynamic_class) return static_ent; + + n_overwrittenby = get_entity_n_overwrittenby(static_ent); + for (i = 0; i < n_overwrittenby; ++i) { + res = resolve_ent_polymorphy2(dynamic_class, get_entity_overwrittenby(static_ent, i)); + if (res) + break; + } + + return res; +} + +/* Resolve polymorphy in the inheritance relation. + * + * Returns the dynamically referenced entity if the static entity and the + * dynamic type are given. + * Search downwards in overwritten tree. */ +entity *resolve_ent_polymorphy(type *dynamic_class, entity *static_ent) { + entity *res; + assert(static_ent && is_entity(static_ent)); + + res = resolve_ent_polymorphy2(dynamic_class, static_ent); + assert(res); + + return res; +} diff --git a/ir/tr/tr_inheritance.h b/ir/tr/tr_inheritance.h new file mode 100644 index 000000000..c4e47110c --- /dev/null +++ b/ir/tr/tr_inheritance.h @@ -0,0 +1,162 @@ +/** + * + * @file tp_inheritance.h + * + * Project: libFIRM
+ * File name: ir/tr/tp_inheritance.h
+ * Purpose: Utility routines for inheritance representation
+ * Author: Goetz Lindenmaier
+ * Modified by:
+ * Created:
+ * Copyright: (c) 2001-2005 Universität Karlsruhe
+ * Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE.
+ * CVS-ID: $Id$ + * + * This file supplies a set of utility routines for the inheritance + * representation. + * + * Inheritance is represented in Firm by two relations: sub/supertype + * between class types, overwrites/ovwerwrittenby between entities. + * + * - Classify pairs of types/entities in the inheritance relations. + * - Resolve implicit inheritance. + * - Compute the transitive closure of the subclass/superclass and + * overwrites/overwrittenby relation. + * + * @see type.h entity.h + */ + +#ifndef _TR_INHERITANCE_H_ +#define _TR_INHERITANCE_H_ + +#include "type.h" +/* #include "entity.h" */ +#include "ident.h" + +/* ----------------------------------------------------------------------- */ +/* Classify pairs of types/entities in the inheritance relations. */ +/* ----------------------------------------------------------------------- */ + +/** Returns true if low is subclass of high. + * + * 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_subclass_of(type *low, type *high); + +/** Returns true if high is (transitiv) overwritten by low. + * + * Returns false if high == low. */ +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. */ +entity *resolve_ent_polymorphy(type *dynamic_class, entity* static_ent); + +/* ----------------------------------------------------------------------- */ +/* Resolve implicit inheritance. */ +/* ----------------------------------------------------------------------- */ + +/** Default name mangling for inherited entities. + * + * Returns an ident that consists of the name of type followed by an + * underscore and the name (not ld_name) of the entity. */ +ident *default_mangle_inherited_name(entity *super, type *clss); + +/** Type of argument functions for inheritance resolver. + * + * @param super The entity in the super type that will be overwritten + * by the newly generated entity, for which this name is + * used. + * @param clss The class type in which the new entity will be placed. + */ +typedef ident *mangle_inherited_name_func(entity *super, type *clss); + +/** Resolve implicit inheritance. + * + * Resolves the implicit inheritance supplied by firm. Firm defines, + * that each entity that is not overwritten in a subclass is + * inherited to this subclass without change implicitly. This + * function generates entities that explicitly represent this + * inheritance. It generates for each entity overwriting entities in + * all subclasses of the owner of the entity, if the entity is not + * overwritten in that sublclass. + * + * The name of the new entity is generated with the function passed. + * If the function is NULL, the default_mangle_inherited_name() is + * used. + * + * This function was moved here from firmlower 3/2005. + */ +void resolve_inheritance(mangle_inherited_name_func *mfunc); + + +/* ----------------------------------------------------------------------- */ +/* The transitive closure of the subclass/superclass and */ +/* overwrites/overwrittenby relation. */ +/* */ +/* A walk over the ir (O(#types+#entities)) computes the transitive */ +/* closure. Adding a new type/entity or changing the basic relations in */ +/* some other way invalidates the transitive closure, i.e., it is not */ +/* updated by the basic functions. */ +/* */ +/* The transitive edges are held in a set, not in an array as the */ +/* underlying relation. */ +/* ----------------------------------------------------------------------- */ + +/** The state of the transitive closure. + * + * @TODO: we could manage the state for each relation separately. Invalidating + * the entity relations does not mean invalidating the class relation. */ +typedef enum { + inh_transitive_closure_none, /**< Closure is not computed, can not be accessed. */ + inh_transitive_closure_valid, /**< Closure computed and valid. */ + inh_transitive_closure_invalid, /**< Closure invalid, but can be accessed. */ + 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); +inh_transitive_closure_state get_irp_inh_transitive_closure_state(void); + + +/** Compute transitive closure of the subclass/superclass and +* overwrites/overwrittenby relation. +* +* This function walks over the ir (O(#types+#entities)) to compute the +* transitive closure. */ +void compute_inh_transitive_closure(void); + +/** Free memory occupied by the transitive closure information. */ +void free_inh_transitive_closure(void); + + +/* - subtype ------------------------------------------------------------- */ + +/** Iterate over all transitive subtypes. */ +type *get_class_trans_subtype_first(type *tp); +type *get_class_trans_subtype_next (type *tp); + +/* - supertype ----------------------------------------------------------- */ + +/** Iterate over all transitive supertypes. */ +type *get_class_trans_supertype_first(type *tp); +type *get_class_trans_supertype_next (type *tp); + +/* - overwrittenby ------------------------------------------------------- */ + +/** Iterate over all entities that transitive overwrite this entities. */ +entity *get_entity_trans_overwrittenby_first(entity *ent); +entity *get_entity_trans_overwrittenby_next (entity *ent); + +/* - overwrites ---------------------------------------------------------- */ + +/** Iterate over all transitive overwritten entities. */ +entity *get_entity_trans_overwrites_first(entity *ent); +entity *get_entity_trans_overwrites_next (entity *ent); + +#endif /* _TR_INHERITANCE_H_ */ diff --git a/ir/tr/type.c b/ir/tr/type.c index 5d2e4b3ee..ba28b7754 100644 --- a/ir/tr/type.c +++ b/ir/tr/type.c @@ -926,21 +926,6 @@ int (is_Class_type)(const type *clss) { return _is_class_type(clss); } -/* Returns true if low is subclass of high. */ -int is_subclass_of(type *low, type *high) { - int i; - assert(is_Class_type(low) && is_Class_type(high)); - if (low == high) return 1; - /* depth first search from high downwards. */ - for (i = 0; i < get_class_n_subtypes(high); i++) { - if (low == get_class_subtype(high, i)) - return 1; - if (is_subclass_of(low, get_class_subtype(high, i))) - return 1; - } - return 0; -} - /*----------------------------------------------------------------**/ /* TYPE_STRUCT */ /*----------------------------------------------------------------**/ diff --git a/ir/tr/type.h b/ir/tr/type.h index 1b796125f..16c1713a0 100644 --- a/ir/tr/type.h +++ b/ir/tr/type.h @@ -44,7 +44,6 @@ # include "irmode.h" # include "dbginfo.h" - /* to resolve recursion between entity.h and type.h */ #ifndef _ENTITY_TYPEDEF_ #define _ENTITY_TYPEDEF_ @@ -56,6 +55,8 @@ typedef struct entity entity; typedef struct ir_node ir_node; #endif +# include "tr_inheritance.h" + /** * An abstract data type to represent types. * @@ -208,17 +209,21 @@ void set_type_size_bytes(type *tp, int size); */ void set_type_size_bits(type *tp, int size); -/** Returns the alignment of a type in bytes, returns -1 if the alignment is NOT - * a byte size, ie not dividable by 8. Calls get_type_alignment_bits(). */ +/** Returns the alignment of a type in bytes. + * + * Returns -1 if the alignment is NOT + * a byte size, i.e. not dividable by 8. Calls get_type_alignment_bits(). */ int get_type_alignment_bytes(type *tp); -/** Returns the alignment of a type in bits. If the alignment of a type is - * not set, it is calculated here according to the following rules: - * 1.) if a type has a mode, the alignment is the mode size. - * 2.) compound types have the alignment of it's biggest member. - * 3.) array types have the alignment of its element type. - * 4.) method types return 0 here. - * 5.) all other types return 8 here (i.e. aligned at byte). +/** Returns the alignment of a type in bits. + * + * If the alignment of a type is + * not set, it is calculated here according to the following rules: + * 1.) if a type has a mode, the alignment is the mode size. + * 2.) compound types have the alignment of it's biggest member. + * 3.) array types have the alignment of its element type. + * 4.) method types return 0 here. + * 5.) all other types return 8 here (i.e. aligned at byte). */ int get_type_alignment_bits(type *tp); @@ -394,28 +399,31 @@ entity *get_class_member (const type *clss, int pos); int get_class_member_index(type *clss, entity *mem); /** Finds the member with name 'name'. If several members with the same - name returns one of them. Returns NULL if no member found. */ + * name returns one of them. Returns NULL if no member found. */ entity *get_class_member_by_name(type *clss, ident *name); /** Overwrites the member at position pos, 0 <= pos < n_member with - the passed entity. */ + * the passed entity. */ void set_class_member (type *clss, entity *member, int pos); /** Replaces complete member list in class type by the list passed. - Copies the list passed. This function is necessary to reduce the number of members. - members is an array of entities, num the size of this array. Sets all - owners of the members passed to clss. */ + * + * Copies the list passed. This function is necessary to reduce the number of members. + * members is an array of entities, num the size of this array. Sets all + * owners of the members passed to clss. */ void set_class_members (type *clss, entity *members[], int arity); /** Finds member in the list of members and removes it. - Shrinks the member list, so iterate from the end!!! - Does not deallocate the entity. */ + * + * Shrinks the member list, so iterate from the end!!! + * Does not deallocate the entity. */ void remove_class_member(type *clss, entity *member); /** Adds subtype as subtype to clss. - Checks whether clss is a supertype of subtype. If not - adds also clss as supertype to subtype. */ + * + * Checks whether clss is a supertype of subtype. If not + * adds also clss as supertype to subtype. */ void add_class_subtype (type *clss, type *subtype); /** Returns the number of subtypes */ @@ -425,8 +433,9 @@ int get_class_n_subtypes (const type *clss); type *get_class_subtype (type *clss, int pos); /** Sets the subtype at position pos, 0 <= pos < n_subtype. - Does not set the corresponding supertype relation for subtype: this might - be a different position! */ + * + * Does not set the corresponding supertype relation for subtype: this might + * be a different position! */ void set_class_subtype (type *clss, type *subtype, int pos); /** Finds subtype in the list of subtypes and removes it */ @@ -434,8 +443,9 @@ void remove_class_subtype(type *clss, type *subtype); /** Adds supertype as supertype to class. - Checks whether clss is a subtype of supertype. If not - adds also clss as subtype to supertype. */ + * + * Checks whether clss is a subtype of supertype. If not + * adds also clss as subtype to supertype. */ void add_class_supertype (type *clss, type *supertype); /** Returns the number of supertypes */ @@ -447,9 +457,10 @@ int get_class_supertype_index(type *clss, type *super_clss); /** Gets the supertype at position pos, 0 <= pos < n_supertype. */ type *get_class_supertype (type *clss, int pos); -/** Sets the supertype at position pos, 0 <= pos < n_subtype. - Does not set the corresponding subtype relation for supertype: this might - be a different position! */ +/** Sets the supertype at position pos, 0 <= pos < n_supertype. + * + * Does not set the corresponding subtype relation for supertype: this might + * be at a different position! */ void set_class_supertype (type *clss, type *supertype, int pos); /** Finds supertype in the list of supertypes and removes it */ @@ -486,9 +497,6 @@ int get_class_dfn (const type *clss); /** Returns true if a type is a class type. */ int is_Class_type(const type *clss); -/** Returns true if low is subclass of high. */ -int is_subclass_of(type *low, type *high); - /** * @page struct_type Representation of a struct type *