* methods that are 'free', i.e., their adress is handled by
* the program directly, or they are visible external.
*/
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
+#include "config.h"
-#ifdef HAVE_STRING_H
# include <string.h>
-#endif
#include "cgana.h"
#include "rta.h"
#include "ircons.h"
#include "irgmod.h"
#include "iropt.h"
+#include "irtools.h"
#include "irflag_t.h"
#include "dbginfo_t.h"
#include "irdump.h"
-#include "irhooks.h"
-
-
-
/* unambiguous address used as a mark. */
static void *MARK = &MARK;
/** 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) &&
+ ir_node *value = get_atomic_ent_value(inh_meth);
+ assert(value && "constant entity without value");
+ assert(is_SymConst_addr_ent(value) &&
"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(value);
}
/** Collect the entity representing the implementation of this
/* Call standard optimizations */
if (is_Sel(node)) {
ir_node *new_node = optimize_in_place(node);
- if (node != new_node)
+ if (node != new_node) {
exchange(node, new_node);
+ node = new_node;
+ }
}
/* replace SymConst(name)-operations by SymConst(ent) */
}
}
} else if (is_Sel(node) && 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);
- }
+ 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_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);
- }
+ /* -- 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_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);
+ }
}
}
* 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) {
+ if (get_irn_link(pred) != MARK && is_Tuple(pred)) {
free_mark_proj(get_Tuple_pred(pred, get_Proj_proj(node)), n, set);
} else {
/* nothing: da in "free_ana_walker" behandelt. */
assert(0 && "unexpected opcode or opcode not implemented");
break;
}
- set_irn_link(node, NULL);
+ // set_irn_link(node, NULL);
}
/**
if (is_method_entity(ent)) {
eset_insert(set, ent);
}
- } else {
- assert(get_SymConst_kind(node) == symconst_addr_name);
- /* nothing: SymConst points to extern method */
}
break;
/* nothing: */
break;
}
- set_irn_link(node, NULL);
}
/**
}
break;
}
- set_irn_link(node, NULL);
}
-static void add_method_address_intitialzer(ir_initializer_t *initializer,
- eset *set)
+/**
+ * Add all method addresses in global new style initializers to the set.
+ *
+ * @note
+ * We do NOT check the type here, just it it's an entity address.
+ * The reason for this is code like:
+ *
+ * void *p = function;
+ *
+ * which is sometimes used to anchor functions.
+ */
+static void add_method_address_inititializer(ir_initializer_t *initializer,
+ eset *set)
{
- switch(initializer->kind) {
- case IR_INITIALIZER_CONST: {
- ir_node *n = initializer->consti.value;
+ ir_node *n;
+ size_t i;
+
+ switch (initializer->kind) {
+ case IR_INITIALIZER_CONST:
+ n = initializer->consti.value;
/* let's check if it's the address of a function */
if (is_Global(n)) {
eset_insert(set, ent);
}
return;
- }
case IR_INITIALIZER_TARVAL:
case IR_INITIALIZER_NULL:
return;
- case IR_INITIALIZER_COMPOUND: {
- size_t i;
-
- for(i = 0; i < initializer->compound.n_initializers; ++i) {
+ case IR_INITIALIZER_COMPOUND:
+ for (i = 0; i < initializer->compound.n_initializers; ++i) {
ir_initializer_t *sub_initializer
= initializer->compound.initializers[i];
- add_method_address_intitialzer(sub_initializer, set);
+ add_method_address_inititializer(sub_initializer, set);
}
return;
}
- }
panic("invalid initializer found");
}
return;
if (ent->has_initializer) {
-
+ add_method_address_inititializer(get_entity_initializer(ent), set);
} else if (is_atomic_entity(ent)) {
tp = get_entity_type(ent);
for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
irg = get_irp_irg(i);
ent = get_irg_entity(irg);
- /* insert "external visible" methods. */
if (get_entity_visibility(ent) != visibility_local) {
+ /* insert non-local (external) methods. */
eset_insert(free_set, ent);
- }
- /* insert "sticky" methods. */
- if (get_entity_stickyness(ent) == stickyness_sticky) {
+ } else if (get_entity_stickyness(ent) == stickyness_sticky) {
+ /* insert "sticky" methods. */
eset_insert(free_set, ent);
}
- /* Find all method entities that gets "visible" trough this graphs,
+ ir_reserve_resources(irg, IR_RESOURCE_IRN_LINK);
+ /* Find all method entities that gets "visible" through this graphs,
* for instance because their address is stored. */
- irg_walk_graph(irg, NULL, free_ana_walker, free_set);
+ irg_walk_graph(irg, firm_clear_link, free_ana_walker, free_set);
+ ir_free_resources(irg, IR_RESOURCE_IRN_LINK);
}
/* insert all methods that are used in global variables initializers */
/* Finally, transform the set into an array. */
*length = eset_count(free_set);
- arr = xmalloc(sizeof(ir_entity *) * (*length));
+ arr = XMALLOCN(ir_entity*, *length);
for (i = 0, ent = eset_first(free_set); ent; ent = eset_next(free_set)) {
arr[i++] = ent;
}
eset_insert(methods, unknown_entity); /* free method -> unknown */
break;
}
-
- set_irn_link(node, NULL);
}
/**
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;
assert(0 && "invalid opcode or opcode not implemented");
break;
}
-
- set_irn_link(node, NULL);
}
/**