-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: {
- 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) {
- 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);
+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_entity(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_entity(ent)) {
+ eset_insert(set, ent);
+ }
+ }
+ 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_Proj:
+ free_mark_proj(get_Proj_pred(node), get_Proj_proj(node), set);
+ break;
+ default:
+ /* nothing: */
+ break;
+ }
+}
+
+/**
+ * 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;
+ 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");