/** Returns the entity that contains the implementation of the inherited
* entity if available, else returns the entity passed. */
-static entity *get_inherited_methods_implementation(entity *inh_meth) {
+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) &&
* @param size Number of entities in set.
* @param open
*/
-static void collect_impls(entity *method, eset *set, int *size, int *open) {
+static void collect_impls(ir_entity *method, eset *set, int *size, int *open) {
int i;
- entity *impl;
+ ir_entity *impl;
/* Add the implementation to the set if it contains an irg, else
remember that there are more methods called. */
*
* @param method
*/
-static entity ** get_impl_methods(entity * method) {
+static ir_entity ** get_impl_methods(ir_entity * method) {
eset * set = eset_create();
int size = 0;
- entity ** arr;
+ ir_entity ** arr;
int open = 0;
/* Collect all method entities that can be called here */
/* keine implementierte überschriebene Methode */
arr = NULL;
} else if (open) {
- entity * ent;
- arr = NEW_ARR_F(entity *, size + 1);
+ 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 {
- entity * ent;
- arr = NEW_ARR_F(entity *, size);
+ 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;
}
*/
static void sel_methods_walker(ir_node * node, void *env) {
pmap *ldname_map = env;
- entity **arr;
+ ir_entity **arr;
/* Call standard optimizations */
if (is_Sel(node)) {
}
else if (get_irn_op(node) == op_Sel &&
is_Method_type(get_entity_type(get_Sel_entity(node)))) {
- entity * ent = get_SymConst_entity(get_atomic_ent_value(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)) {
*/
assert (get_entity_peculiarity(ent) == peculiarity_description);
}
- else if (get_opt_optimize() && get_opt_dyn_meth_dispatch() &&
+ 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;
assert(entities == NULL);
entities = eset_create();
for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
- entity * ent = get_irg_entity(get_irp_irg(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);
*
* @param sel the Sel node
*/
-static entity ** get_Sel_arr(ir_node * sel) {
- static entity ** NULL_ARRAY = NULL;
- entity * ent;
- entity ** arr;
+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);
/* "NULL" zeigt an, dass keine Implementierung existiert. Dies
* kann für polymorphe (abstrakte) Methoden passieren. */
if (!NULL_ARRAY) {
- NULL_ARRAY = NEW_ARR_F(entity *, 0);
+ NULL_ARRAY = NEW_ARR_F(ir_entity *, 0);
}
return NULL_ARRAY;
}
/**
* Returns the ith possible called method entity at a Sel node.
*/
-static entity * get_Sel_method(ir_node * sel, int pos) {
- entity ** arr = get_Sel_arr(sel);
+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];
}
switch (get_irn_opcode(node)) {
case iro_Sel: {
- entity * ent = get_Sel_entity(node);
+ 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));
}
case iro_SymConst:
if (get_SymConst_kind(node) == symconst_addr_ent) {
- entity * ent = get_SymConst_entity(node);
+ ir_entity * ent = get_SymConst_entity(node);
if (is_Method_type(get_entity_type(ent))) {
eset_insert(set, ent);
}
*
* which is sometimes used to anchor functions.
*/
-static void add_method_address(entity *ent, eset *set)
+static void add_method_address(ir_entity *ent, eset *set)
{
ir_node *n;
ir_type *tp;
/* let's check if it's the address of a function */
if (get_irn_op(n) == op_SymConst) {
if (get_SymConst_kind(n) == symconst_addr_ent) {
- entity *ent = get_SymConst_entity(n);
+ ir_entity *ent = get_SymConst_entity(n);
if (is_Method_type(get_entity_type(ent)))
eset_insert(set, ent);
* umgewandelt worden sein, d.h. SymConst-Operationen verweisen immer
* auf eine echt externe Methode.
*/
-static entity ** get_free_methods(void)
+static ir_entity ** get_free_methods(void)
{
eset *free_set = eset_create();
int i;
- entity **arr = NEW_ARR_F(entity *, 0);
- entity *ent;
+ ir_entity **arr = NEW_ARR_F(ir_entity *, 0);
+ ir_entity *ent;
ir_graph *irg;
ir_type *glob;
/* Finally, transform the set into an array. */
for (ent = eset_first(free_set); ent; ent = eset_next(free_set)) {
- ARR_APP1(entity *, arr, ent);
+ ARR_APP1(ir_entity *, arr, ent);
}
eset_destroy(free_set);
set_irn_link(node, NULL);
}
-
-static void callee_ana_node(ir_node * node, eset * methods) {
+/**
+ * Analyse a Call address.
+ *
+ * @param node the node representing the call address
+ * @param methods after call contains the set of all possibly called entities
+ */
+static void callee_ana_node(ir_node *node, eset *methods) {
int i;
assert(mode_is_reference(get_irn_mode(node)) || is_Bad(node));
- /* rekursion verhindern */
+ /* Beware of recursion */
if (get_irn_link(node) == MARK) {
/* already visited */
return;
set_irn_link(node, MARK);
switch (get_irn_opcode(node)) {
+ case iro_Const:
+ /* A direct address call. We tread this as an external
+ call and ignore it completely. */
+ eset_insert(methods, MARK); /* free method -> unknown */
+ break;
case iro_SymConst:
if (get_SymConst_kind(node) == symconst_addr_ent) {
- entity * ent = get_SymConst_entity(node);
+ ir_entity *ent = get_SymConst_entity(node);
assert(ent && is_Method_type(get_entity_type(ent)));
eset_insert(methods, ent);
} else {
case iro_Sel:
/* polymorphe Methode */
for (i = get_Sel_n_methods(node) - 1; i >= 0; --i) {
- entity * ent = get_Sel_method(node, i);
+ ir_entity * ent = get_Sel_method(node, i);
if (ent) {
eset_insert(methods, ent);
} else {
/* nothing */
break;
- case iro_Phi: /* Vereinigung */
+ case iro_Phi:
for (i = get_Phi_n_preds(node) - 1; i >= 0; --i) {
callee_ana_node(get_Phi_pred(node, i), methods);
}
callee_ana_node(get_Mux_true(node), methods);
break;
+ case iro_Psi:
+ for (i = get_Psi_n_conds(node) - 1; i >= 0; --i) {
+ callee_ana_node(get_Psi_val(node, i), methods);
+ }
+ callee_ana_node(get_Psi_default(node), methods);
+ break;
+
case iro_Id:
callee_ana_node(get_Id_pred(node), methods);
break;
set_irn_link(node, NULL);
}
-/* */
+/**
+ * Walker: Analyses every call node and calculates an array of possible
+ * callees for that call.
+ */
static void callee_walker(ir_node * call, void * env) {
if (is_Call(call)) {
eset * methods = eset_create();
- entity * ent;
- entity ** arr = NEW_ARR_F(entity *, 0);
+ ir_entity * ent;
+ ir_entity ** arr = NEW_ARR_F(ir_entity *, 0);
assert(get_irn_op(get_Call_ptr(call)) != op_Id);
callee_ana_node(get_Call_ptr(call), methods);
if (eset_contains(methods, MARK)) { /* unknown method */
- ARR_APP1(entity *, arr, unknown_entity);
+ ARR_APP1(ir_entity *, arr, unknown_entity);
}
for (ent = eset_first(methods); ent; ent = eset_next(methods)) {
if (ent != MARK) {
- ARR_APP1(entity *, arr, ent);
+ ARR_APP1(ir_entity *, arr, ent);
}
}
#if 0 /* This generates Bad nodes when we don't want it.
Call it with a check for valid cgana information in local_optimize. */
- if (ARR_LEN(arr) == 0 && get_opt_optimize() && get_opt_dyn_meth_dispatch()) {
+ if (ARR_LEN(arr) == 0 && get_opt_optimize() && get_opt_closed_world() && get_opt_dyn_meth_dispatch()) {
/* Kann vorkommen, wenn der Vorgänger beispielsweise eine
* Sel-Operation war, die keine Methoden zurückgeben
* konnte. Wir ersetzen die Call-Operation ebenfalls durch
}
}
+/**
+ * Walker: Removes all tuple.
+ */
+static void remove_Tuples(ir_node *proj, void *env) {
+ ir_node *nn;
+ if (! is_Proj(proj)) return;
-static void remove_Tuples(ir_node * proj, void * env) {
- ir_node *new;
- if (get_irn_opcode(proj) != iro_Proj) return;
-
- new = skip_Tuple(proj);
- if (new != proj) exchange(proj, new);
+ nn = skip_Tuple(proj);
+ if (nn != proj) exchange(proj, nn);
}
int i;
/* Alle Graphen analysieren. */
for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
- irg_walk_graph(get_irp_irg(i), callee_walker, remove_Tuples, NULL);
- set_irg_callee_info_state(get_irp_irg(i), irg_callee_info_consistent);
+ ir_graph *irg = get_irp_irg(i);
+ irg_walk_graph(irg, callee_walker, remove_Tuples, NULL);
+ set_irg_callee_info_state(irg, irg_callee_info_consistent);
}
set_irp_callee_info_state(irg_callee_info_consistent);
}
/** Frees intermediate data structures. */
static void sel_methods_dispose(void) {
- entity * ent;
+ ir_entity * ent;
assert(entities);
for (ent = eset_first(entities); ent; ent = eset_next(entities)) {
- entity ** arr = get_entity_link(ent);
+ ir_entity ** arr = get_entity_link(ent);
if (arr) {
DEL_ARR_F(arr);
}
/* Main drivers. */
/*--------------------------------------------------------------------------*/
-void cgana(int *length, entity ***free_methods) {
- entity ** free_meths, **p;
+void cgana(int *length, ir_entity ***free_methods) {
+ ir_entity ** free_meths, **p;
/* Optimize Sel/SymConst nodes and compute all methods that implement an entity. */
sel_methods_init();