-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);
+static void free_ana_walker(ir_node *node, void *env)
+{
+ eset *set = (eset*) 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;
+ case iro_Call:
+ /* we must handle Call nodes specially, because their call address input
+ do not expose a method address. */
+ 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;
+ default:
+ /* other nodes: Alle anderen Knoten nehmen wir als Verr�ter an, bis
+ * jemand das Gegenteil implementiert. */
+ 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;
+ }
+}
+
+/**
+ * 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)
+{
+ 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)) {
+ ir_entity *ent = get_Global_entity(n);
+
+ if (is_Method_type(get_entity_type(ent)))
+ eset_insert(set, ent);
+ }
+ return;
+ case IR_INITIALIZER_TARVAL:
+ case IR_INITIALIZER_NULL:
+ return;
+ 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_inititializer(sub_initializer, set);
+ }
+ return;
+ }
+ panic("invalid initializer found");
+}
+
+/**
+ * Add all method addresses in global 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(ir_entity *ent, eset *set)
+{
+ ir_type *tp;
+
+ /* ignore methods: these of course reference it's address
+ * TODO: remove this later once this incorrect self-initialisation is gone
+ */
+ tp = get_entity_type(ent);
+ if (is_Method_type(tp))
+ return;
+
+ if (ent->initializer != NULL) {
+ add_method_address_inititializer(get_entity_initializer(ent), set);
+ } else if (entity_has_compound_ent_values(ent)) {
+ size_t i, n;
+ for (i = 0, n = get_compound_ent_n_values(ent); i < n; ++i) {
+ ir_node *irn = get_compound_ent_value(ent, i);
+
+ /* let's check if it's the address of a function */
+ if (is_Global(irn)) {
+ ir_entity *ent = get_Global_entity(irn);
+
+ if (is_Method_type(get_entity_type(ent)))
+ eset_insert(set, ent);
+ }
+ }
+ }