2 * Copyright (C) 2010 University of Karlsruhe. All right reserved.
4 * This file is part of libFirm.
6 * This file may be distributed and/or modified under the terms of the
7 * GNU General Public License version 2 as published by the Free Software
8 * Foundation and appearing in the file LICENSE.GPL included in the
9 * packaging of this file.
11 * Licensees holding valid libFirm Professional Edition licenses may use
12 * this file in accordance with the libFirm Commercial License.
13 * Agreement provided with the Software.
15 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * @brief Removal of unreachable methods.
23 * @author Matthias Braun
28 #include "iroptimize.h"
39 DEBUG_ONLY(static firm_dbg_module_t *dbg);
41 static void visit_entity(ir_entity *entity);
43 static void visit_node(ir_node *node, void *env)
48 if (is_SymConst(node)) {
49 if (!SYMCONST_HAS_ENT(get_SymConst_kind(node)))
51 entity = get_SymConst_entity(node);
52 } else if (is_Sel(node)) {
53 entity = get_Sel_entity(node);
61 static void start_visit_node(ir_node *node)
63 ir_graph *irg = get_irn_irg(node);
65 if (get_irg_visited(irg) < get_max_irg_visited()) {
66 set_irg_visited(irg, get_max_irg_visited());
68 current_ir_graph = irg;
69 irg_walk_2(node, visit_node, NULL, NULL);
72 static void visit_initializer(ir_initializer_t *initializer)
74 switch (initializer->kind) {
75 case IR_INITIALIZER_CONST:
76 start_visit_node(initializer->consti.value);
78 case IR_INITIALIZER_TARVAL:
79 case IR_INITIALIZER_NULL:
82 case IR_INITIALIZER_COMPOUND: {
84 for (i = 0; i < initializer->compound.n_initializers; ++i) {
85 ir_initializer_t *subinitializer
86 = initializer->compound.initializers[i];
87 visit_initializer(subinitializer);
92 panic("invalid initializer found");
95 static void visit_entity(ir_entity *entity)
99 if (entity_visited(entity))
101 mark_entity_visited(entity);
103 if (entity->initializer != NULL) {
104 visit_initializer(entity->initializer);
105 } else if (entity_has_compound_ent_values(entity)) {
107 int n_members = get_compound_ent_n_values(entity);
108 for (i = 0; i < n_members; ++i) {
109 ir_node *node = get_compound_ent_value(entity, i);
110 start_visit_node(node);
114 irg = get_entity_irg(entity);
116 start_visit_node(get_irg_end(irg));
120 static void visit_segment(ir_type *segment)
122 int n_entities = get_compound_n_members(segment);
125 for (i = 0; i < n_entities; ++i) {
126 ir_entity *entity = get_compound_member(segment, i);
127 if (get_entity_visibility(entity) != ir_visibility_default
128 && !(get_entity_linkage(entity) & IR_LINKAGE_HIDDEN_USER))
131 visit_entity(entity);
135 static void garbage_collect_in_segment(ir_type *segment)
139 for (i = get_compound_n_members(segment)-1; i >= 0; --i) {
140 ir_entity *entity = get_compound_member(segment, i);
142 if (entity_visited(entity))
145 DB((dbg, LEVEL_1, " removing entity %+F\n", entity));
147 /* TODO: this is O(n^2) improve our interfaces! */
148 remove_class_member(get_entity_owner(entity), entity);
152 void garbage_collect_entities(void)
157 FIRM_DBG_REGISTER(dbg, "firm.opt.garbagecollect");
159 /* start a type walk for all externally visible entities */
160 irp_reserve_resources(irp, IR_RESOURCE_TYPE_VISITED);
161 inc_master_type_visited();
162 inc_max_irg_visited();
164 for (s = IR_SEGMENT_FIRST; s <= IR_SEGMENT_LAST; ++s) {
165 ir_type *type = get_segment_type(s);
166 mark_type_visited(type);
171 /* remove graphs of non-visited functions
172 * (we have to count backwards so we can safely call remove_irp_irg
173 * while iterating) */
174 for (i = get_irp_n_irgs()-1; i >= 0; --i) {
175 ir_graph *irg = get_irp_irg(i);
176 ir_entity *entity = get_irg_entity(irg);
178 if (entity_visited(entity))
181 DB((dbg, LEVEL_1, " freeing method %+F\n", entity));
185 /* we can now remove all non-visited (global) entities */
186 for (s = IR_SEGMENT_FIRST; s <= IR_SEGMENT_LAST; ++s) {
187 ir_type *type = get_segment_type(s);
188 garbage_collect_in_segment(type);
190 irp_free_resources(irp, IR_RESOURCE_TYPE_VISITED);
193 ir_prog_pass_t *garbage_collect_entities_pass(const char *name)
195 return def_prog_pass(name ? name : "garbage_collect",
196 garbage_collect_entities);