remove unnecessary declaration
[libfirm] / ir / opt / garbage_collect.c
1 /*
2  * Copyright (C) 1995-2011 University of Karlsruhe.  All right reserved.
3  *
4  * This file is part of libFirm.
5  *
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.
10  *
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.
14  *
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
17  * PURPOSE.
18  */
19
20 /**
21  * @file
22  * @brief    Removal of unreachable methods.
23  * @author   Matthias Braun
24  */
25 #include "config.h"
26
27 #include "iroptimize.h"
28 #include "typerep.h"
29 #include "type_t.h"
30 #include "entity_t.h"
31 #include "irprog_t.h"
32 #include "irprintf.h"
33 #include "irpass.h"
34 #include "irgwalk.h"
35 #include "error.h"
36 #include "debug.h"
37
38 DEBUG_ONLY(static firm_dbg_module_t *dbg;)
39
40 static void visit_entity(ir_entity *entity);
41
42 static void visit_node(ir_node *node, void *env)
43 {
44         ir_entity *entity;
45         (void) env;
46
47         if (is_SymConst(node)) {
48                 if (!SYMCONST_HAS_ENT(get_SymConst_kind(node)))
49                         return;
50                 entity = get_SymConst_entity(node);
51         } else if (is_Sel(node)) {
52                 entity = get_Sel_entity(node);
53         } else {
54                 return;
55         }
56
57         visit_entity(entity);
58 }
59
60 static void start_visit_node(ir_node *node)
61 {
62         ir_graph *irg = get_irn_irg(node);
63
64         if (get_irg_visited(irg) < get_max_irg_visited()) {
65                 set_irg_visited(irg, get_max_irg_visited());
66         }
67         irg_walk_2(node, visit_node, NULL, NULL);
68 }
69
70 static void visit_initializer(ir_initializer_t *initializer)
71 {
72         switch (initializer->kind) {
73         case IR_INITIALIZER_CONST:
74                 start_visit_node(initializer->consti.value);
75                 return;
76         case IR_INITIALIZER_TARVAL:
77         case IR_INITIALIZER_NULL:
78                 return;
79
80         case IR_INITIALIZER_COMPOUND: {
81                 size_t i;
82                 for (i = 0; i < initializer->compound.n_initializers; ++i) {
83                         ir_initializer_t *subinitializer
84                                 = initializer->compound.initializers[i];
85                         visit_initializer(subinitializer);
86                 }
87                 return;
88         }
89         }
90         panic("invalid initializer found");
91 }
92
93 static void visit_entity(ir_entity *entity)
94 {
95         ir_graph *irg;
96
97         if (entity_visited(entity))
98                 return;
99         mark_entity_visited(entity);
100
101         if (entity->initializer != NULL) {
102                 visit_initializer(entity->initializer);
103         }
104
105         irg = get_entity_irg(entity);
106         if (irg != NULL) {
107                 start_visit_node(get_irg_end(irg));
108         }
109 }
110
111 static void visit_segment(ir_type *segment)
112 {
113         int n_entities = get_compound_n_members(segment);
114         int i;
115
116         for (i = 0; i < n_entities; ++i) {
117                 ir_entity *entity = get_compound_member(segment, i);
118                 if (get_entity_visibility(entity) != ir_visibility_external
119                                 && !(get_entity_linkage(entity) & IR_LINKAGE_HIDDEN_USER)
120                                 && !(get_entity_linkage(entity) & IR_LINKAGE_NO_CODEGEN))
121                         continue;
122
123                 visit_entity(entity);
124         }
125 }
126
127 static void garbage_collect_in_segment(ir_type *segment)
128 {
129         int i;
130
131         for (i = get_compound_n_members(segment)-1; i >= 0; --i) {
132                 ir_entity *entity = get_compound_member(segment, i);
133
134                 if (entity_visited(entity))
135                         continue;
136
137                 DB((dbg, LEVEL_1, "  removing entity %+F\n", entity));
138
139                 free_entity(entity);
140         }
141 }
142
143 void garbage_collect_entities(void)
144 {
145         size_t       i;
146         ir_segment_t s;
147
148         FIRM_DBG_REGISTER(dbg, "firm.opt.garbagecollect");
149
150         /* start a type walk for all externally visible entities */
151         irp_reserve_resources(irp, IRP_RESOURCE_TYPE_VISITED);
152         inc_master_type_visited();
153         inc_max_irg_visited();
154
155         for (s = IR_SEGMENT_FIRST; s <= IR_SEGMENT_LAST; ++s) {
156                 ir_type *type = get_segment_type(s);
157                 mark_type_visited(type);
158
159                 visit_segment(type);
160         }
161
162         /* remove graphs of non-visited functions
163          * (we have to count backwards, because freeing the graph moves the last
164          *  graph in the list to the free position) */
165         for (i = get_irp_n_irgs(); i > 0;) {
166                 ir_graph  *irg    = get_irp_irg(--i);
167                 ir_entity *entity = get_irg_entity(irg);
168
169                 if (entity_visited(entity))
170                         continue;
171
172                 DB((dbg, LEVEL_1, "  freeing method %+F\n", entity));
173                 free_ir_graph(irg);
174         }
175
176         /* we can now remove all non-visited (global) entities */
177         for (s = IR_SEGMENT_FIRST; s <= IR_SEGMENT_LAST; ++s) {
178                 ir_type *type = get_segment_type(s);
179                 garbage_collect_in_segment(type);
180         }
181         irp_free_resources(irp, IRP_RESOURCE_TYPE_VISITED);
182 }
183
184 ir_prog_pass_t *garbage_collect_entities_pass(const char *name)
185 {
186         return def_prog_pass(name ? name : "garbage_collect",
187                              garbage_collect_entities);
188 }