finalize debug stuff before arch_env_done which frees be_emitter
[libfirm] / ir / opt / opt_frame.c
index 029d009..7699322 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
+ * Copyright (C) 1995-2011 University of Karlsruhe.  All right reserved.
  *
  * This file is part of libFirm.
  *
@@ -23,7 +23,7 @@
  * @date    15.03.2006
  * @author  Michael Beck
  * @version $Id$
- * @summary
+ * @brief
  *   Optimize the frame type by removing unused type members.
  */
 #include "config.h"
 #include "type_t.h"
 #include "irouts.h"
 #include "iredges.h"
+#include "irpass.h"
 
 /*
  * Optimize the frame type of an irg by removing
  * never touched entities.
  */
-void opt_frame_irg(ir_graph *irg) {
+void opt_frame_irg(ir_graph *irg)
+{
        ir_type   *frame_tp = get_irg_frame_type(irg);
        ir_entity *ent, *list;
        ir_node   *frame, *sel;
-       int       i, n = get_class_n_members(frame_tp);
+       size_t    i, n = get_class_n_members(frame_tp);
 
        if (n <= 0)
                return;
 
-       irp_reserve_resources(irp, IR_RESOURCE_ENTITY_LINK);
+       irp_reserve_resources(irp, IRP_RESOURCE_ENTITY_LINK);
 
        /* clear all entity links */
-       for (i = n - 1; i >= 0; --i) {
-               ent = get_class_member(frame_tp, i);
+       for (i = n; i > 0;) {
+               ent = get_class_member(frame_tp, --i);
                set_entity_link(ent, NULL);
        }
 
@@ -64,10 +66,14 @@ void opt_frame_irg(ir_graph *irg) {
                /* mark all used entities */
                foreach_out_edge(frame, edge) {
                        sel = get_edge_src_irn(edge);
-                       ent = get_Sel_entity(sel);
-                       set_entity_link(ent, ent);
+                       if (is_Sel(sel)) {
+                               ent = get_Sel_entity(sel);
+                               set_entity_link(ent, ent);
+                       }
                }
        } else {
+               int i;
+
                /* use traditionally out edges */
                assure_irg_outs(irg);
 
@@ -76,16 +82,19 @@ void opt_frame_irg(ir_graph *irg) {
                        sel = get_irn_out(frame, i);
                        if (is_Sel(sel)) {
                                ent = get_Sel_entity(sel);
-                               set_entity_link(ent, ent);
+                               /* only entities on the frame */
+                               if (get_entity_owner(ent) == frame_tp)
+                                       set_entity_link(ent, ent);
                        }
                }
        }
 
        /* link unused ones */
        list = NULL;
-       for (i = n - 1; i >= 0; --i) {
-               ent = get_class_member(frame_tp, i);
-               if (get_entity_link(ent) == NULL) {
+       for (i = n; i > 0;) {
+               ent = get_class_member(frame_tp, --i);
+               /* beware of inner functions: those are NOT unused */
+               if (get_entity_link(ent) == NULL && !is_method_entity(ent)) {
                        set_entity_link(ent, list);
                        list = ent;
                }
@@ -94,11 +103,16 @@ void opt_frame_irg(ir_graph *irg) {
        if (list != NULL) {
                /* delete list members */
                for (ent = list; ent; ent = list) {
-                       list = get_entity_link(ent);
-                       remove_class_member(frame_tp, ent);
+                       list = (ir_entity*)get_entity_link(ent);
+                       free_entity(ent);
                }
-               /* we changed the frame type, it's layout should be redefined */
+               /* we changed the frame type, its layout should be redefined */
                set_type_state(frame_tp, layout_undefined);
        }
-       irp_free_resources(irp, IR_RESOURCE_ENTITY_LINK);
+       irp_free_resources(irp, IRP_RESOURCE_ENTITY_LINK);
+}
+
+ir_graph_pass_t *opt_frame_irg_pass(const char *name)
+{
+       return def_graph_pass(name ? name : "opt_frame_irg", opt_frame_irg);
 }