2 * This file is part of libFirm.
3 * Copyright (C) 2012 University of Karlsruhe.
8 * @brief Removal of unreachable methods.
9 * @author Matthias Braun
13 #include "iroptimize.h"
24 DEBUG_ONLY(static firm_dbg_module_t *dbg;)
26 static void visit_entity(ir_entity *entity);
28 static void visit_node(ir_node *node, void *env)
33 if (is_SymConst(node)) {
34 if (!SYMCONST_HAS_ENT(get_SymConst_kind(node)))
36 entity = get_SymConst_entity(node);
37 } else if (is_Sel(node)) {
38 entity = get_Sel_entity(node);
46 static void start_visit_node(ir_node *node)
48 ir_graph *irg = get_irn_irg(node);
50 if (get_irg_visited(irg) < get_max_irg_visited()) {
51 set_irg_visited(irg, get_max_irg_visited());
53 irg_walk_2(node, visit_node, NULL, NULL);
56 static void visit_initializer(ir_initializer_t *initializer)
58 switch (initializer->kind) {
59 case IR_INITIALIZER_CONST:
60 start_visit_node(initializer->consti.value);
62 case IR_INITIALIZER_TARVAL:
63 case IR_INITIALIZER_NULL:
66 case IR_INITIALIZER_COMPOUND: {
68 for (i = 0; i < initializer->compound.n_initializers; ++i) {
69 ir_initializer_t *subinitializer
70 = initializer->compound.initializers[i];
71 visit_initializer(subinitializer);
76 panic("invalid initializer found");
79 static void visit_entity(ir_entity *entity)
83 if (entity_visited(entity))
85 mark_entity_visited(entity);
87 if (entity->initializer != NULL) {
88 visit_initializer(entity->initializer);
91 irg = get_entity_irg(entity);
93 start_visit_node(get_irg_end(irg));
97 static void visit_segment(ir_type *segment)
99 int n_entities = get_compound_n_members(segment);
102 for (i = 0; i < n_entities; ++i) {
103 ir_entity *entity = get_compound_member(segment, i);
104 if (get_entity_visibility(entity) != ir_visibility_external
105 && !(get_entity_linkage(entity) & IR_LINKAGE_HIDDEN_USER)
106 && !(get_entity_linkage(entity) & IR_LINKAGE_NO_CODEGEN))
109 visit_entity(entity);
113 static void garbage_collect_in_segment(ir_type *segment)
117 for (i = get_compound_n_members(segment)-1; i >= 0; --i) {
118 ir_entity *entity = get_compound_member(segment, i);
120 if (entity_visited(entity))
123 DB((dbg, LEVEL_1, " removing entity %+F\n", entity));
129 void garbage_collect_entities(void)
134 FIRM_DBG_REGISTER(dbg, "firm.opt.garbagecollect");
136 /* start a type walk for all externally visible entities */
137 irp_reserve_resources(irp, IRP_RESOURCE_TYPE_VISITED);
138 inc_master_type_visited();
139 inc_max_irg_visited();
141 for (s = IR_SEGMENT_FIRST; s <= IR_SEGMENT_LAST; ++s) {
142 ir_type *type = get_segment_type(s);
143 mark_type_visited(type);
148 /* remove graphs of non-visited functions
149 * (we have to count backwards, because freeing the graph moves the last
150 * graph in the list to the free position) */
151 for (i = get_irp_n_irgs(); i > 0;) {
152 ir_graph *irg = get_irp_irg(--i);
153 ir_entity *entity = get_irg_entity(irg);
155 if (entity_visited(entity))
158 DB((dbg, LEVEL_1, " freeing method %+F\n", entity));
162 /* we can now remove all non-visited (global) entities */
163 for (s = IR_SEGMENT_FIRST; s <= IR_SEGMENT_LAST; ++s) {
164 ir_type *type = get_segment_type(s);
165 garbage_collect_in_segment(type);
167 irp_free_resources(irp, IRP_RESOURCE_TYPE_VISITED);
170 ir_prog_pass_t *garbage_collect_entities_pass(const char *name)
172 return def_prog_pass(name ? name : "garbage_collect",
173 garbage_collect_entities);