Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
Zwinkau
libfirm
Commits
e18eba3e
Commit
e18eba3e
authored
Mar 14, 2005
by
Götz Lindenmaier
Browse files
moved stuff handling inheritance to an own file
Added algorithm to compute transitive closure of inheritance [r5368]
parent
4842e339
Changes
8
Hide whitespace changes
Inline
Side-by-side
ir/ir/irprog_t.h
View file @
e18eba3e
...
...
@@ -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
...
...
ir/tr/Makefile.in
View file @
e18eba3e
...
...
@@ -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
...
...
ir/tr/entity.c
View file @
e18eba3e
...
...
@@ -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
;
}
ir/tr/entity.h
View file @
e18eba3e
...
...
@@ -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
*
...
...
ir/tr/tr_inheritance.c
0 → 100644
View file @
e18eba3e
/**
*
* @file tp_inheritance.c
*
* Project: libFIRM <br>
* File name: ir/tr/tp_inheritance.c <br>
* Purpose: Utility routines for inheritance representation <br>
* Author: Goetz Lindenmaier <br>
* Modified by: <br>
* Created: <br>
* Copyright: (c) 2001-2005 Universität Karlsruhe <br>
* Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE. <br>
* 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
;