-static void free_mark_proj(ir_node * node, long n, eset * set) {
- assert(get_irn_mode(node) == mode_T);
- if (get_irn_link(node) == MARK) {
- /* already visited */
- return;
- }
- set_irn_link(node, MARK);
- switch (get_irn_opcode(node)) {
- case iro_Proj: {
- /* proj_proj: in einem "sinnvollen" Graphen kommt jetzt ein
- * 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) {
- free_mark_proj(get_Tuple_pred(pred, get_Proj_proj(node)), n, set);
- } else {
- /* nothing: da in "free_ana_walker" behandelt. */
- }
- break;
- }
-
- case iro_Tuple:
- free_mark(get_Tuple_pred(node, n), set);
- break;
-
- case iro_Id:
- free_mark_proj(get_Id_pred(node), n, set);
- break;
-
- case iro_Start:
- case iro_Alloc:
- case iro_Load:
- /* nothing: Die Operationen werden in "free_ana_walker" selbst
- * behandelt. */
- break;
-
- default:
- assert(0 && "unexpected opcode or opcode not implemented");
- break;
- }
- set_irn_link(node, NULL);
+/**
+ * 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));
+ /* 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, unknown_entity); /* free method -> unknown */
+ break;
+ case iro_SymConst:
+ if (get_SymConst_kind(node) == symconst_addr_ent) {
+ ir_entity *ent = get_SymConst_entity(node);
+ assert(ent && is_method_entity(ent));
+ eset_insert(methods, ent);
+ } else {
+ assert(get_SymConst_kind(node) == symconst_addr_name);
+ /* external method (because fix_symconst()!) */
+ eset_insert(methods, unknown_entity); /* free method -> unknown */
+ }
+ break;
+ case iro_Sel:
+ /* polymorphic method */
+ for (i = get_Sel_n_methods(node) - 1; i >= 0; --i) {
+ ir_entity *ent = get_Sel_method(node, i);
+ if (ent != NULL) {
+ eset_insert(methods, ent);
+ } else {
+ eset_insert(methods, unknown_entity);
+ }
+ }
+ break;
+
+ case iro_Bad:
+ /* nothing */
+ break;
+
+ case iro_Phi:
+ for (i = get_Phi_n_preds(node) - 1; i >= 0; --i) {
+ callee_ana_node(get_Phi_pred(node, i), methods);
+ }
+ break;
+
+ case iro_Mux:
+ callee_ana_node(get_Mux_false(node), methods);
+ callee_ana_node(get_Mux_true(node), methods);
+ break;
+
+ case iro_Id:
+ callee_ana_node(get_Id_pred(node), methods);
+ break;
+
+ case iro_Proj:
+ callee_ana_proj(get_Proj_pred(node), get_Proj_proj(node), methods);
+ break;
+
+ case iro_Add:
+ case iro_Sub:
+ case iro_Conv:
+ /* extern */
+ eset_insert(methods, unknown_entity); /* free method -> unknown */
+ break;
+
+ default:
+ assert(0 && "invalid opcode or opcode not implemented");
+ break;
+ }