*
*/
#ifdef HAVE_CONFIG_H
-# include <config.h>
+# include "config.h"
+#endif
+
+#ifdef HAVE_STRING_H
+# include <string.h>
#endif
-#include <stdlib.h>
#include "cgana.h"
#include "rta.h"
+#include "xmalloc.h"
#include "irnode_t.h"
#include "irmode_t.h"
#include "irprog_t.h"
/** 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) {
+ 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));
+
+#if 0 // this stuff is outdated, I think. GL 10.11.04
entity *impl_meth = NULL;
ir_node *addr = get_atomic_ent_value(inh_meth);
- assert(addr && "constant entity without value");
+ assert(get_atomic_ent_value(inh_meth) && "constant entity without value");
if ((get_irn_op(addr) == op_SymConst) &&
(get_SymConst_kind(addr) == symconst_addr_ent)) {
printf("impl meth: "); DDMEO(impl_meth);
assert(!impl_meth || get_entity_peculiarity(impl_meth) == peculiarity_existent);
*/
+ assert(0);
impl_meth = NULL;
}
+ assert((impl_meth || inh_meth) && "no implementation for inherited entity");
return impl_meth? impl_meth : inh_meth;
+#endif
}
*/
static void collect_impls(entity *method, eset *set, int *size, bool *open) {
int i;
+ entity *impl;
+#if 0
if (get_entity_peculiarity(method) == peculiarity_existent) {
if ((get_entity_visibility(method) == visibility_external_allocated)
&& (NULL == get_entity_irg(method))) {
+ /* We could also add these entities to the callees, but right now we
+ subsume them by unknown_entity. */
*open = true;
} else {
assert(get_entity_irg(method) != NULL);
if (get_entity_peculiarity(method) == peculiarity_inherited) {
entity *impl_ent = get_inherited_methods_implementation(method);
- assert(impl_ent && "no implementation for inherited entity");
if (get_entity_visibility(impl_ent) == visibility_external_allocated) {
assert(get_entity_irg(impl_ent) == NULL);
*open = true;
}
}
}
+#endif
+ /* Only the assertions: */
+ if (get_entity_peculiarity(method) == peculiarity_existent) {
+ if ((get_entity_visibility(method) == visibility_external_allocated)
+ && (NULL == get_entity_irg(method))) {
+ } else {
+ assert(get_entity_irg(method) != NULL);
+ }
+ }
+ if (get_entity_peculiarity(method) == peculiarity_inherited) {
+ entity *impl_ent = get_inherited_methods_implementation(method);
+ if (get_entity_visibility(impl_ent) == visibility_external_allocated) {
+ assert(get_entity_irg(impl_ent) == NULL);
+ } else {
+ assert(get_entity_irg(impl_ent) != NULL);
+ }
+ }
+
+ /* Add the implementation to the set if it contains an irg, else
+ remember that there are more methods called. */
+ /* @@@ We could also add unknown_entity, or the entities with the
+ unknown irgs. The first case would result in the exact same
+ behavior: all unknown irgs are represented by the one and only
+ unknown entity. If we add all entities, we known the number of
+ entities possibly called, and whether there are real unknown
+ entities, i.e, such not represented in the type description.
+ This would be better for an analysis: it could rule out more
+ cases. */
+ impl = method;
+ if (get_entity_peculiarity(method) == peculiarity_inherited)
+ impl = get_inherited_methods_implementation(method);
+
+ if (get_entity_peculiarity(method) != peculiarity_description) {
+ //if (get_entity_irg(impl)) {
+ eset_insert(set, impl);
+ ++(*size);
+ //} else {
+ /* GL: better: eset_insert(set, unknown_entity); */
+ //*open = true;
+ //}
+ }
+
/*- recursive descent -*/
for (i = get_entity_n_overwrittenby(method) - 1; i >= 0; --i)
collect_impls(get_entity_overwrittenby(method, i), set, size, open);
return arr;
}
-/** Analyse address computations.
+/** Analyze address computations.
*
* - If the node is a SymConst(name) replace it by SymConst(ent) if possible.
* - If the node is a Sel:
*
*
* @param node The node to analyze
- * @param ldname_map A map that mapps names of entities to the entities.
+ * @param env A map that maps names of entities to the entities.
*/
-static void sel_methods_walker(ir_node * node, pmap * ldname_map) {
+static void sel_methods_walker(ir_node * node, void *env) {
+ pmap *ldname_map = env;
/* 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 */
- entity * ent = entry->value;
- if (get_opt_normalize() && (get_entity_visibility(ent) != visibility_external_allocated)) { /* Meth. is defined */
- set_irg_current_block(current_ir_graph, get_nodes_block(node));
- ir_node *new_node = copy_const_value(get_atomic_ent_value(ent));
+ entity * ent = entry->value;
+ if (get_opt_normalize() && (get_entity_visibility(ent) != visibility_external_allocated)) { /* Meth. is defined */
+ ir_node *new_node;
- DBG_OPT_CSTEVAL(node, new_node);
+ set_irg_current_block(current_ir_graph, get_nodes_block(node));
+ new_node = copy_const_value(get_atomic_ent_value(ent));
- assert(get_entity_irg(ent));
- DDMN(new_node);
- exchange(node, new_node);
- }
+ DBG_OPT_CSTEVAL(node, new_node);
+
+ assert(get_entity_irg(ent));
+ DDMN(new_node);
+ exchange(node, new_node);
+ }
}
}
}
-
else if (get_irn_op(node) == op_Sel &&
is_method_type(get_entity_type(get_Sel_entity(node)))) {
entity * ent = get_Sel_entity(node);
(get_irn_op(skip_Proj(get_Sel_ptr(node))) == op_Alloc)) {
ir_node *new_node;
entity *called_ent;
+
/* We know which method will be called, no dispatch necessary. */
called_ent = resolve_ent_polymorphy(get_Alloc_type(skip_Proj(get_Sel_ptr(node))), ent);
set_irg_current_block(current_ir_graph, get_nodes_block(node));
+
/* called_ent may not be description: has no Address/Const to Call! */
assert(get_entity_peculiarity(called_ent) != peculiarity_description);
new_node = copy_const_value(get_atomic_ent_value(called_ent));
DBG_OPT_POLY_ALLOC(node, new_node);
exchange(node, new_node);
}
-
else {
assert(get_entity_peculiarity(ent) != peculiarity_inherited);
if (!eset_contains(entities, ent)) {
/* Gib eine Warnung aus wenn die Entitaet eine Beschreibung ist
fuer die es keine Implementierung gibt. */
if (get_entity_peculiarity(ent) == peculiarity_description) {
- /* This is possible: We call a method in a dead part of the program. */
+ /* This is possible: We call a method in a dead part of the program. */
} else {
- DDMN(node);
- assert(0); /* Why should this happen ??? */
+ DDMN(node);
+ assert(0); /* Why should this happen ??? */
//exchange(node, new_Bad());
}
} else {
* SymConst(entity)-Operationen ersetzt. */
static void sel_methods_init(void) {
int i;
- pmap * ldname_map = pmap_create(); /* Map entitiy names to entities: to replace SymConst(name) by SymConst(ent). */
+ 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) {
- entity * ent = get_irg_entity(get_irp_irg(i));
- /* Nur extern sichtbare Methode können überhaupt mit SymConst
+ ir_graph *irg = get_irp_irg(i);
+ entity * ent = get_irg_entity(irg);
+ /* Nur extern sichtbare Methoden können überhaupt mit SymConst
* aufgerufen werden. */
if (get_entity_visibility(ent) != visibility_local) {
pmap_insert(ldname_map, (void *) get_entity_ld_ident(ent), ent);
}
}
- all_irg_walk((irg_walk_func *) sel_methods_walker, NULL, ldname_map);
+ all_irg_walk(sel_methods_walker, NULL, ldname_map);
pmap_destroy(ldname_map);
}
/*****************************************************************************/
-/* Datenstruktur freigeben. */
+/** Frees the allocated entity map */
static void sel_methods_dispose(void) {
entity * ent;
assert(entities);
}
-/* Gibt die Menge aller Methoden zurück, die an diesem Sel-Knoten
- * zurückgegeben werden können. Die Liste enthält keine doppelten
- * Einträge. */
+/**
+ * Returns an array of all methods that could be called at a Sel node.
+ * This array contains every entry only once.
+ */
static entity ** get_Sel_arr(ir_node * sel) {
static entity ** NULL_ARRAY = NULL;
entity * ent;
entity ** arr;
+
assert(sel && get_irn_op(sel) == op_Sel);
ent = get_Sel_entity(sel);
assert(is_method_type(get_entity_type(ent))); /* what else? */
}
}
-
+/**
+ * Returns the number of possible called methods at a Sel node.
+ */
static int get_Sel_n_methods(ir_node * sel) {
return ARR_LEN(get_Sel_arr(sel));
}
-
+/**
+ * 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);
assert(pos >= 0 && pos < ARR_LEN(arr));
ir_node * pred = get_Proj_pred(node);
if (get_irn_link(pred) != MARK) {
if (get_irn_op(pred) == op_Tuple) {
- callee_ana_proj(get_Tuple_pred(pred, get_Proj_proj(node)), n, methods);
+ callee_ana_proj(get_Tuple_pred(pred, get_Proj_proj(node)), n, methods);
} else {
- eset_insert(methods, MARK); /* free method -> unknown */
+ eset_insert(methods, MARK); /* free method -> unknown */
}
}
break;
if (get_SymConst_kind(node) == symconst_addr_ent) {
entity * ent = get_SymConst_entity(node);
assert(ent && is_method_type(get_entity_type(ent)));
- if (get_entity_visibility(ent) != visibility_external_allocated) {
- assert(get_entity_irg(ent));
- eset_insert(methods, ent);
- } else {
- eset_insert(methods, MARK); /* free method -> unknown */
- }
+ eset_insert(methods, ent);
} else {
assert(get_SymConst_kind(node) == symconst_addr_name);
/* externe Methode (wegen fix_symconst!) */
eset * methods = eset_create();
entity * ent;
entity ** arr = NEW_ARR_F(entity *, 0);
- callee_ana_node(skip_Id(get_Call_ptr(call)), methods);
+ 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);
}
static void free_mark(ir_node * node, eset * set) {
int i;
-// assert(mode_is_reference(get_irn_mode(node)));
+
if (get_irn_link(node) == MARK) {
return; /* already visited */
}
/* Convert the flexible array to an array that can be handled
by standard C. */
- p = (entity **)malloc(sizeof(*p) * ARR_LEN(free_meths));
+ p = xmalloc(sizeof(*p) * ARR_LEN(free_meths));
memcpy(p, free_meths, ARR_LEN(free_meths) * sizeof(*p));
*length = ARR_LEN(free_meths);
void opt_call_addrs(void) {
sel_methods_init();
sel_methods_dispose();
-#if 0
- int i;
- pmap * ldname_map = pmap_create();
- 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));
- /* Nur extern sichtbare Methoden können überhaupt mit SymConst
- * aufgerufen werden. */
- if (get_entity_visibility(ent) != local) {
- pmap_insert(ldname_map, (void *) get_entity_ld_ident(ent), ent);
- }
- }
- all_irg_walk((irg_walk_func *) sel_methods_walker, NULL, ldname_map);
- pmap_destroy(ldname_map);
-#endif
}