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
23de0b55
Commit
23de0b55
authored
Aug 06, 2007
by
Michael Beck
Browse files
indentation changed
[r15480]
parent
75bfbe5c
Changes
1
Hide whitespace changes
Inline
Side-by-side
ir/ana/cgana.c
View file @
23de0b55
...
...
@@ -83,12 +83,12 @@ static eset *entities = NULL;
/** Returns the entity that contains the implementation of the inherited
* entity if available, else returns the entity passed. */
static
ir_entity
*
get_inherited_methods_implementation
(
ir_entity
*
inh_meth
)
{
assert
(
get_atomic_ent_value
(
inh_meth
)
&&
"constant entity without value"
);
assert
((
get_irn_op
(
get_atomic_ent_value
(
inh_meth
))
==
op_SymConst
)
&&
(
get_SymConst_kind
(
get_atomic_ent_value
(
inh_meth
))
==
symconst_addr_ent
)
&&
"Complex constant values not supported -- address of method should be straight constant!"
);
assert
(
get_atomic_ent_value
(
inh_meth
)
&&
"constant entity without value"
);
assert
((
get_irn_op
(
get_atomic_ent_value
(
inh_meth
))
==
op_SymConst
)
&&
(
get_SymConst_kind
(
get_atomic_ent_value
(
inh_meth
))
==
symconst_addr_ent
)
&&
"Complex constant values not supported -- address of method should be straight constant!"
);
return
get_SymConst_entity
(
get_atomic_ent_value
(
inh_meth
));
return
get_SymConst_entity
(
get_atomic_ent_value
(
inh_meth
));
}
/** Collect the entity representing the implementation of this
...
...
@@ -105,23 +105,23 @@ static ir_entity *get_inherited_methods_implementation(ir_entity *inh_meth) {
* @param open
*/
static
void
collect_impls
(
ir_entity
*
method
,
eset
*
set
,
int
*
size
,
int
*
open
)
{
int
i
;
ir_entity
*
impl
;
/* Add the implementation to the set if it contains an irg, else
remember that there are more methods called. */
impl
=
method
;
if
(
get_entity_peculiarity
(
method
)
==
peculiarity_inherited
)
impl
=
get_inherited_methods_implementation
(
method
);
if
(
get_entity_peculiarity
(
method
)
!=
peculiarity_description
)
{
eset_insert
(
set
,
impl
);
++
(
*
size
);
}
/*- recursive descent -*/
for
(
i
=
get_entity_n_overwrittenby
(
method
)
-
1
;
i
>=
0
;
--
i
)
collect_impls
(
get_entity_overwrittenby
(
method
,
i
),
set
,
size
,
open
);
int
i
;
ir_entity
*
impl
;
/* Add the implementation to the set if it contains an irg, else
remember that there are more methods called. */
impl
=
method
;
if
(
get_entity_peculiarity
(
method
)
==
peculiarity_inherited
)
impl
=
get_inherited_methods_implementation
(
method
);
if
(
get_entity_peculiarity
(
method
)
!=
peculiarity_description
)
{
eset_insert
(
set
,
impl
);
++
(
*
size
);
}
/*- recursive descent -*/
for
(
i
=
get_entity_n_overwrittenby
(
method
)
-
1
;
i
>=
0
;
--
i
)
collect_impls
(
get_entity_overwrittenby
(
method
,
i
),
set
,
size
,
open
);
}
/** Alle Methoden bestimmen, die die übergebene Methode überschreiben
...
...
@@ -135,32 +135,32 @@ static void collect_impls(ir_entity *method, eset *set, int *size, int *open) {
* @param method
*/
static
ir_entity
**
get_impl_methods
(
ir_entity
*
method
)
{
eset
*
set
=
eset_create
();
int
size
=
0
;
ir_entity
**
arr
;
int
open
=
0
;
/* Collect all method entities that can be called here */
collect_impls
(
method
,
set
,
&
size
,
&
open
);
/* Vorgaenger einfuegen. */
if
(
size
==
0
&&
!
open
)
{
/* keine implementierte überschriebene Methode */
arr
=
NULL
;
}
else
if
(
open
)
{
ir_entity
*
ent
;
arr
=
NEW_ARR_F
(
ir_entity
*
,
size
+
1
);
arr
[
0
]
=
NULL
;
/* Represents open method */
for
(
ent
=
eset_first
(
set
);
size
>
0
;
ent
=
eset_next
(
set
),
--
size
)
arr
[
size
]
=
ent
;
}
else
{
ir_entity
*
ent
;
arr
=
NEW_ARR_F
(
ir_entity
*
,
size
);
for
(
size
-=
1
,
ent
=
eset_first
(
set
);
size
>=
0
;
ent
=
eset_next
(
set
),
--
size
)
arr
[
size
]
=
ent
;
}
eset_destroy
(
set
);
return
arr
;
eset
*
set
=
eset_create
();
int
size
=
0
;
ir_entity
**
arr
;
int
open
=
0
;
/* Collect all method entities that can be called here */
collect_impls
(
method
,
set
,
&
size
,
&
open
);
/* Vorgaenger einfuegen. */
if
(
size
==
0
&&
!
open
)
{
/* keine implementierte überschriebene Methode */
arr
=
NULL
;
}
else
if
(
open
)
{
ir_entity
*
ent
;
arr
=
NEW_ARR_F
(
ir_entity
*
,
size
+
1
);
arr
[
0
]
=
NULL
;
/* Represents open method */
for
(
ent
=
eset_first
(
set
);
size
>
0
;
ent
=
eset_next
(
set
),
--
size
)
arr
[
size
]
=
ent
;
}
else
{
ir_entity
*
ent
;
arr
=
NEW_ARR_F
(
ir_entity
*
,
size
);
for
(
size
-=
1
,
ent
=
eset_first
(
set
);
size
>=
0
;
ent
=
eset_next
(
set
),
--
size
)
arr
[
size
]
=
ent
;
}
eset_destroy
(
set
);
return
arr
;
}
/** Analyze address computations.
...
...
@@ -184,67 +184,67 @@ static ir_entity ** get_impl_methods(ir_entity * method) {
* @param env A map that maps names of entities to the entities.
*/
static
void
sel_methods_walker
(
ir_node
*
node
,
void
*
env
)
{
pmap
*
ldname_map
=
env
;
ir_entity
**
arr
;
/* Call standard optimizations */
if
(
is_Sel
(
node
))
{
ir_node
*
new_node
=
optimize_in_place
(
node
);
if
(
node
!=
new_node
)
exchange
(
node
,
new_node
);
}
/* replace SymConst(name)-operations by SymConst(ent) */
if
(
get_irn_op
(
node
)
==
op_SymConst
)
{
if
(
get_SymConst_kind
(
node
)
==
symconst_addr_name
)
{
pmap_entry
*
entry
=
pmap_find
(
ldname_map
,
(
void
*
)
get_SymConst_name
(
node
));
if
(
entry
!=
NULL
)
{
/* Method is declared in the compiled code */
assert
(
0
&&
"There should not be a SymConst[addr_name] addressing a method with an implementation"
"in this compilation unit. Use a SymConst[addr_ent]."
);
}
}
}
else
if
(
get_irn_op
(
node
)
==
op_Sel
&&
is_Method_type
(
get_entity_type
(
get_Sel_entity
(
node
))))
{
ir_entity
*
ent
=
get_SymConst_entity
(
get_atomic_ent_value
(
get_Sel_entity
(
node
)));
assert
(
get_entity_peculiarity
(
ent
)
!=
peculiarity_inherited
);
if
(
!
eset_contains
(
entities
,
ent
))
{
/* Entity not yet handled. Find all (internal or external)
* implemented methods that overwrites this entity.
* This set is stored in the entity link. */
set_entity_link
(
ent
,
get_impl_methods
(
ent
));
eset_insert
(
entities
,
ent
);
}
/* -- As an add on we get an optimization that removes polymorphic calls.
This optimization is more powerful than that in transform_node_Sel(). -- */
arr
=
get_entity_link
(
ent
);
if
(
arr
==
NULL
)
{
/*
* The Sel node never returns a pointer to a usable method.
* We could not call it, but it may be description:
* We call a method in a dead part of the program.
*/
assert
(
get_entity_peculiarity
(
ent
)
==
peculiarity_description
);
}
else
if
(
get_opt_optimize
()
&&
get_opt_closed_world
()
&&
get_opt_dyn_meth_dispatch
()
&&
(
ARR_LEN
(
arr
)
==
1
&&
arr
[
0
]
!=
NULL
))
{
ir_node
*
new_node
;
/*
* The Sel node returns only one possible method.
* So we could replace the Sel node by a SymConst.
* This method must exists.
*/
set_irg_current_block
(
current_ir_graph
,
get_nodes_block
(
node
));
assert
(
get_entity_peculiarity
(
get_SymConst_entity
(
get_atomic_ent_value
(
arr
[
0
])))
==
peculiarity_existent
);
new_node
=
copy_const_value
(
get_irn_dbg_info
(
node
),
get_atomic_ent_value
(
arr
[
0
]));
DBG_OPT_POLY
(
node
,
new_node
);
exchange
(
node
,
new_node
);
}
}
pmap
*
ldname_map
=
env
;
ir_entity
**
arr
;
/* Call standard optimizations */
if
(
is_Sel
(
node
))
{
ir_node
*
new_node
=
optimize_in_place
(
node
);
if
(
node
!=
new_node
)
exchange
(
node
,
new_node
);
}
/* replace SymConst(name)-operations by SymConst(ent) */
if
(
get_irn_op
(
node
)
==
op_SymConst
)
{
if
(
get_SymConst_kind
(
node
)
==
symconst_addr_name
)
{
pmap_entry
*
entry
=
pmap_find
(
ldname_map
,
(
void
*
)
get_SymConst_name
(
node
));
if
(
entry
!=
NULL
)
{
/* Method is declared in the compiled code */
assert
(
0
&&
"There should not be a SymConst[addr_name] addressing a method with an implementation"
"in this compilation unit. Use a SymConst[addr_ent]."
);
}
}
}
else
if
(
get_irn_op
(
node
)
==
op_Sel
&&
is_Method_type
(
get_entity_type
(
get_Sel_entity
(
node
))))
{
ir_entity
*
ent
=
get_SymConst_entity
(
get_atomic_ent_value
(
get_Sel_entity
(
node
)));
assert
(
get_entity_peculiarity
(
ent
)
!=
peculiarity_inherited
);
if
(
!
eset_contains
(
entities
,
ent
))
{
/* Entity not yet handled. Find all (internal or external)
* implemented methods that overwrites this entity.
* This set is stored in the entity link. */
set_entity_link
(
ent
,
get_impl_methods
(
ent
));
eset_insert
(
entities
,
ent
);
}
/* -- As an add on we get an optimization that removes polymorphic calls.
This optimization is more powerful than that in transform_node_Sel(). -- */
arr
=
get_entity_link
(
ent
);
if
(
arr
==
NULL
)
{
/*
* The Sel node never returns a pointer to a usable method.
* We could not call it, but it may be description:
* We call a method in a dead part of the program.
*/
assert
(
get_entity_peculiarity
(
ent
)
==
peculiarity_description
);
}
else
if
(
get_opt_optimize
()
&&
get_opt_closed_world
()
&&
get_opt_dyn_meth_dispatch
()
&&
(
ARR_LEN
(
arr
)
==
1
&&
arr
[
0
]
!=
NULL
))
{
ir_node
*
new_node
;
/*
* The Sel node returns only one possible method.
* So we could replace the Sel node by a SymConst.
* This method must exists.
*/
set_irg_current_block
(
current_ir_graph
,
get_nodes_block
(
node
));
assert
(
get_entity_peculiarity
(
get_SymConst_entity
(
get_atomic_ent_value
(
arr
[
0
])))
==
peculiarity_existent
);
new_node
=
copy_const_value
(
get_irn_dbg_info
(
node
),
get_atomic_ent_value
(
arr
[
0
]));
DBG_OPT_POLY
(
node
,
new_node
);
exchange
(
node
,
new_node
);
}
}
}
/** Initialize auxiliary data structures.
...
...
@@ -257,21 +257,21 @@ static void sel_methods_walker(ir_node * node, void *env) {
* Finally asserts if there is a SymConst(name) if there could be a
* SymConst(ent). */
static
void
sel_methods_init
(
void
)
{
int
i
;
pmap
*
ldname_map
=
pmap_create
();
/* Map entity names to entities: to replace
SymConst(name) by SymConst(ent). */
assert
(
entities
==
NULL
);
entities
=
eset_create
();
for
(
i
=
get_irp_n_irgs
()
-
1
;
i
>=
0
;
--
i
)
{
ir_entity
*
ent
=
get_irg_entity
(
get_irp_irg
(
i
));
/* only external visible methods are allowed to call by a SymConst_ptr_name */
if
(
get_entity_visibility
(
ent
)
!=
visibility_local
)
{
pmap_insert
(
ldname_map
,
(
void
*
)
get_entity_ld_ident
(
ent
),
ent
);
}
}
all_irg_walk
(
sel_methods_walker
,
NULL
,
ldname_map
);
pmap_destroy
(
ldname_map
);
int
i
;
pmap
*
ldname_map
=
pmap_create
();
/* Map entity names to entities: to replace
SymConst(name) by SymConst(ent). */
assert
(
entities
==
NULL
);
entities
=
eset_create
();
for
(
i
=
get_irp_n_irgs
()
-
1
;
i
>=
0
;
--
i
)
{
ir_entity
*
ent
=
get_irg_entity
(
get_irp_irg
(
i
));
/* only external visible methods are allowed to call by a SymConst_ptr_name */
if
(
get_entity_visibility
(
ent
)
!=
visibility_local
)
{
pmap_insert
(
ldname_map
,
(
void
*
)
get_entity_ld_ident
(
ent
),
ent
);
}
}
all_irg_walk
(
sel_methods_walker
,
NULL
,
ldname_map
);
pmap_destroy
(
ldname_map
);
}
/*--------------------------------------------------------------------------*/
...
...
@@ -288,26 +288,26 @@ static void sel_methods_init(void) {
* @param sel the Sel node
*/
static
ir_entity
**
get_Sel_arr
(
ir_node
*
sel
)
{
static
ir_entity
**
NULL_ARRAY
=
NULL
;
ir_entity
*
ent
;
ir_entity
**
arr
;
assert
(
is_Sel
(
sel
));
ent
=
get_Sel_entity
(
sel
);
ent
=
get_inherited_methods_implementation
(
ent
);
assert
(
is_Method_type
(
get_entity_type
(
ent
)));
/* what else? */
arr
=
get_entity_link
(
ent
);
if
(
arr
)
{
return
arr
;
}
else
{
/* "NULL" zeigt an, dass keine Implementierung existiert. Dies
* kann für polymorphe (abstrakte) Methoden passieren. */
if
(
!
NULL_ARRAY
)
{
NULL_ARRAY
=
NEW_ARR_F
(
ir_entity
*
,
0
);
}
return
NULL_ARRAY
;
}
static
ir_entity
**
NULL_ARRAY
=
NULL
;
ir_entity
*
ent
;
ir_entity
**
arr
;
assert
(
is_Sel
(
sel
));
ent
=
get_Sel_entity
(
sel
);
ent
=
get_inherited_methods_implementation
(
ent
);
assert
(
is_Method_type
(
get_entity_type
(
ent
)));
/* what else? */
arr
=
get_entity_link
(
ent
);
if
(
arr
)
{
return
arr
;
}
else
{
/* "NULL" zeigt an, dass keine Implementierung existiert. Dies
* kann für polymorphe (abstrakte) Methoden passieren. */
if
(
!
NULL_ARRAY
)
{
NULL_ARRAY
=
NEW_ARR_F
(
ir_entity
*
,
0
);
}
return
NULL_ARRAY
;
}
}
/**
...
...
@@ -316,61 +316,61 @@ static ir_entity ** get_Sel_arr(ir_node * sel) {
* @param sel the Sel node
*/
static
int
get_Sel_n_methods
(
ir_node
*
sel
)
{
return
ARR_LEN
(
get_Sel_arr
(
sel
));
return
ARR_LEN
(
get_Sel_arr
(
sel
));
}
/**
* Returns the ith possible called method entity at a Sel node.
*/
static
ir_entity
*
get_Sel_method
(
ir_node
*
sel
,
int
pos
)
{
ir_entity
**
arr
=
get_Sel_arr
(
sel
);
assert
(
pos
>=
0
&&
pos
<
ARR_LEN
(
arr
));
return
arr
[
pos
];
ir_entity
**
arr
=
get_Sel_arr
(
sel
);
assert
(
pos
>=
0
&&
pos
<
ARR_LEN
(
arr
));
return
arr
[
pos
];
}
static
void
free_mark
(
ir_node
*
node
,
eset
*
set
);
static
void
free_mark_proj
(
ir_node
*
node
,
long
n
,
eset
*
set
)
{
assert
(
get_irn_mode
(
node
)
==
mode_T
);
if
(
get_irn_link
(
node
)
==
MARK
)
{
/* already visited */
return
;
}
set_irn_link
(
node
,
MARK
);
switch
(
get_irn_opcode
(
node
))
{
case
iro_Proj
:
{
/* proj_proj: in einem "sinnvollen" Graphen kommt jetzt ein
* op_Tuple oder ein Knoten, der in "free_ana_walker" behandelt
* wird. */
ir_node
*
pred
=
get_Proj_pred
(
node
);
if
(
get_irn_link
(
pred
)
!=
MARK
&&
get_irn_op
(
pred
)
==
op_Tuple
)
{
free_mark_proj
(
get_Tuple_pred
(
pred
,
get_Proj_proj
(
node
)),
n
,
set
);
}
else
{
/* nothing: da in "free_ana_walker" behandelt. */
}
break
;
}
case
iro_Tuple
:
free_mark
(
get_Tuple_pred
(
node
,
n
),
set
);
break
;
case
iro_Id
:
free_mark_proj
(
get_Id_pred
(
node
),
n
,
set
);
break
;
case
iro_Start
:
case
iro_Alloc
:
case
iro_Load
:
/* nothing: Die Operationen werden in free_ana_walker() selbst
* behandelt. */
break
;
default:
assert
(
0
&&
"unexpected opcode or opcode not implemented"
);
break
;
}
set_irn_link
(
node
,
NULL
);
assert
(
get_irn_mode
(
node
)
==
mode_T
);
if
(
get_irn_link
(
node
)
==
MARK
)
{
/* already visited */
return
;
}
set_irn_link
(
node
,
MARK
);
switch
(
get_irn_opcode
(
node
))
{
case
iro_Proj
:
{
/* proj_proj: in einem "sinnvollen" Graphen kommt jetzt ein
* op_Tuple oder ein Knoten, der in "free_ana_walker" behandelt
* wird. */
ir_node
*
pred
=
get_Proj_pred
(
node
);
if
(
get_irn_link
(
pred
)
!=
MARK
&&
get_irn_op
(
pred
)
==
op_Tuple
)
{
free_mark_proj
(
get_Tuple_pred
(
pred
,
get_Proj_proj
(
node
)),
n
,
set
);
}
else
{
/* nothing: da in "free_ana_walker" behandelt. */
}
break
;
}
case
iro_Tuple
:
free_mark
(
get_Tuple_pred
(
node
,
n
),
set
);
break
;
case
iro_Id
:
free_mark_proj
(
get_Id_pred
(
node
),
n
,
set
);
break
;
case
iro_Start
:
case
iro_Alloc
:
case
iro_Load
:
/* nothing: Die Operationen werden in free_ana_walker() selbst
* behandelt. */
break
;
default:
assert
(
0
&&
"unexpected opcode or opcode not implemented"
);
break
;
}
set_irn_link
(
node
,
NULL
);
}
/**
...
...
@@ -385,99 +385,99 @@ static void free_mark_proj(ir_node * node, long n, eset * set) {
* @param set the set of all free methods
*/
static
void
free_mark
(
ir_node
*
node
,
eset
*
set
)
{
int
i
;
if
(
get_irn_link
(
node
)
==
MARK
)
return
;
/* already visited */
set_irn_link
(
node
,
MARK
);
switch
(
get_irn_opcode
(
node
))
{
case
iro_Sel
:
{
ir_entity
*
ent
=
get_Sel_entity
(
node
);
if
(
is_Method_type
(
get_entity_type
(
ent
)))
{
for
(
i
=
get_Sel_n_methods
(
node
)
-
1
;
i
>=
0
;
--
i
)
{
eset_insert
(
set
,
get_Sel_method
(
node
,
i
));
}
}
break
;
}
case
iro_SymConst
:
if
(
get_SymConst_kind
(
node
)
==
symconst_addr_ent
)
{
ir_entity
*
ent
=
get_SymConst_entity
(
node
);
if
(
is_Method_type
(
get_entity_type
(
ent
)))
{
eset_insert
(
set
,
ent
);
}
}
else
{
assert
(
get_SymConst_kind
(
node
)
==
symconst_addr_name
);
/* nothing: SymConst points to extern method */
}
break
;
case
iro_Phi
:
for
(
i
=
get_Phi_n_preds
(
node
)
-
1
;
i
>=
0
;
--
i
)
{
free_mark
(
get_Phi_pred
(
node
,
i
),
set
);
}
break
;
case
iro_Id
:
free_mark
(
get_Id_pred
(
node
),
set
);
break
;
case
iro_Proj
:
free_mark_proj
(
get_Proj_pred
(
node
),
get_Proj_proj
(
node
),
set
);
break
;
default:
/* nothing: Wird unten behandelt! */
break
;
}
set_irn_link
(
node
,
NULL
);
int
i
;
if
(
get_irn_link
(
node
)
==
MARK
)
return
;
/* already visited */
set_irn_link
(
node
,
MARK
);
switch
(
get_irn_opcode
(
node
))
{
case
iro_Sel
:
{
ir_entity
*
ent
=
get_Sel_entity
(
node
);
if
(
is_Method_type
(
get_entity_type
(
ent
)))
{
for
(
i
=
get_Sel_n_methods
(
node
)
-
1
;
i
>=
0
;
--
i
)
{
eset_insert
(
set
,
get_Sel_method
(
node
,
i
));
}
}
break
;
}
case
iro_SymConst
:
if
(
get_SymConst_kind
(
node
)
==
symconst_addr_ent
)
{
ir_entity
*
ent
=
get_SymConst_entity
(
node
);
if
(
is_Method_type
(
get_entity_type
(
ent
)))
{
eset_insert
(
set
,
ent
);
}
}
else
{
assert
(
get_SymConst_kind
(
node
)
==
symconst_addr_name
);
/* nothing: SymConst points to extern method */
}
break
;
case
iro_Phi
:
for
(
i
=
get_Phi_n_preds
(
node
)
-
1
;
i
>=
0
;
--
i
)
{
free_mark
(
get_Phi_pred
(
node
,
i
),
set
);
}
break
;
case
iro_Id
:
free_mark
(
get_Id_pred
(
node
),
set
);
break
;
case
iro_Proj
:
free_mark_proj
(
get_Proj_pred
(
node
),
get_Proj_proj
(
node
),
set
);
break
;
default:
/* nothing: Wird unten behandelt! */
break
;
}
set_irn_link
(
node
,
NULL
);
}
/**
* post-walker. Find method addresses.
*/
static
void
free_ana_walker
(
ir_node
*
node
,
void
*
env
)
{
eset
*
set
=
env
;
int
i
;
if
(
get_irn_link
(
node
)
==
MARK
)
{
/* already visited */
return
;
}
switch
(
get_irn_opcode
(
node
))
{
/* special nodes */
case
iro_Sel
:
case
iro_SymConst
:
case
iro_Const
:
case
iro_Phi
:
case
iro_Id
:
case
iro_Proj
:
case
iro_Tuple
:
/* nothing */
break
;
/* Sonderbehandlung, da der Funktionszeigereingang natürlich kein
* Verräter ist. */
case
iro_Call
:
set_irn_link
(
node
,
MARK
);
for
(
i
=
get_Call_n_params
(
node
)
-
1
;
i
>=
0
;
--
i
)
{
ir_node
*
pred
=
get_Call_param
(
node
,
i
);
if
(
mode_is_reference
(
get_irn_mode
(
pred
)))
{
free_mark
(
pred
,
set
);
}
}
break
;
/* other nodes: Alle anderen Knoten nehmen wir als Verräter an, bis
* jemand das Gegenteil implementiert. */
default:
set_irn_link
(
node
,
MARK
);
for
(
i
=
get_irn_arity
(
node
)
-
1
;
i
>=
0
;
--
i
)
{
ir_node
*
pred
=
get_irn_n
(
node
,
i
);
if
(
mode_is_reference
(
get_irn_mode
(
pred
)))
{
free_mark
(
pred
,
set
);
}
}
break
;
}
set_irn_link
(
node
,
NULL
);
eset
*
set
=
env
;
int
i
;
if
(
get_irn_link
(
node
)
==
MARK
)
{
/* already visited */
return
;
}
switch
(
get_irn_opcode
(
node
))
{
/* special nodes */
case
iro_Sel
:
case
iro_SymConst
:
case
iro_Const
:
case
iro_Phi
:
case
iro_Id
:
case
iro_Proj
:
case
iro_Tuple
:
/* nothing */
break
;
/* Sonderbehandlung, da der Funktionszeigereingang natürlich kein
* Verräter ist. */
case
iro_Call
:
set_irn_link
(
node
,
MARK
);
for
(
i
=
get_Call_n_params
(
node
)
-
1
;
i
>=
0
;
--
i
)
{
ir_node
*
pred
=
get_Call_param
(
node
,
i
);
if
(
mode_is_reference
(
get_irn_mode
(
pred
)))
{
free_mark
(
pred
,
set
);
}
}
break
;
/* other nodes: Alle anderen Knoten nehmen wir als Verräter an, bis
* jemand das Gegenteil implementiert. */
default:
set_irn_link
(
node
,
MARK
);
for
(
i
=
get_irn_arity
(
node
)
-
1
;
i
>=
0
;
--
i
)
{