2 * Copyright (C) 1995-2011 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 Functionality to modify the type graph.
23 * @author Goetz Lindenmaier
26 * Traverse the type information. The walker walks the whole ir graph
27 * to find the distinct type trees in the type graph forest.
28 * - execute the pre function before recursion
29 * - execute the post function after recursion
40 #include "irgraph_t.h"
47 * The walker environment
49 typedef struct type_walk_env {
50 type_walk_func *pre; /**< Pre-walker function */
51 type_walk_func *post; /**< Post-walker function */
52 void *env; /**< environment for walker functions */
55 /* a walker for irn's */
56 static void irn_type_walker(
57 ir_node *node, type_walk_func *pre, type_walk_func *post, void *env);
59 static void walk_initializer(ir_initializer_t *initializer,
60 type_walk_func *pre, type_walk_func *post,
63 switch (initializer->kind) {
64 case IR_INITIALIZER_CONST:
65 irn_type_walker(initializer->consti.value, pre, post, env);
67 case IR_INITIALIZER_TARVAL:
68 case IR_INITIALIZER_NULL:
71 case IR_INITIALIZER_COMPOUND: {
73 for (i = 0; i < initializer->compound.n_initializers; ++i) {
74 ir_initializer_t *subinitializer
75 = initializer->compound.initializers[i];
76 walk_initializer(subinitializer, pre, post, env);
81 panic("invalid initializer found");
85 * Main walker: walks over all used types/entities of a
88 static void do_type_walk(type_or_ent tore,
93 size_t i, n_types, n_mem;
94 ir_entity *ent = NULL;
99 switch (get_kind(tore.ent)) {
102 if (entity_visited(ent))
104 mark_entity_visited(ent);
108 if (type_visited(tp))
110 mark_type_visited(tp);
116 /* execute pre method */
121 switch (get_kind(tore.ent)) {
123 cont.typ = get_entity_owner(ent);
124 do_type_walk(cont, pre, post, env);
125 cont.typ = get_entity_type(ent);
126 do_type_walk(cont, pre, post, env);
128 /* walk over the value types */
129 if (ent->initializer != NULL) {
130 walk_initializer(ent->initializer, pre, post, env);
134 switch (get_type_tpop_code(tp)) {
136 n_types = get_class_n_supertypes(tp);
137 for (i = 0; i < n_types; ++i) {
138 cont.typ = get_class_supertype(tp, i);
139 do_type_walk(cont, pre, post, env);
141 n_mem = get_class_n_members(tp);
142 for (i = 0; i < n_mem; ++i) {
143 cont.ent = get_class_member(tp, i);
144 do_type_walk(cont, pre, post, env);
146 n_types = get_class_n_subtypes(tp);
147 for (i = 0; i < n_types; ++i) {
148 cont.typ = get_class_subtype(tp, i);
149 do_type_walk(cont, pre, post, env);
154 n_mem = get_struct_n_members(tp);
155 for (i = 0; i < n_mem; ++i) {
156 cont.ent = get_struct_member(tp, i);
157 do_type_walk(cont, pre, post, env);
162 n_mem = get_method_n_params(tp);
163 for (i = 0; i < n_mem; ++i) {
164 cont.typ = get_method_param_type(tp, i);
165 do_type_walk(cont, pre, post, env);
167 n_mem = get_method_n_ress(tp);
168 for (i = 0; i < n_mem; ++i) {
169 cont.typ = get_method_res_type(tp, i);
170 do_type_walk(cont, pre, post, env);
175 n_mem = get_union_n_members(tp);
176 for (i = 0; i < n_mem; ++i) {
177 cont.ent = get_union_member(tp, i);
178 do_type_walk(cont, pre, post, env);
183 cont.typ = get_array_element_type(tp);
184 do_type_walk(cont, pre, post, env);
185 cont.ent = get_array_element_entity(tp);
186 do_type_walk(cont, pre, post, env);
189 case tpo_enumeration:
194 cont.typ = get_pointer_points_to_type(tp);
195 do_type_walk(cont, pre, post, env);
204 case tpo_uninitialized:
205 assert(0 && "Faulty type");
208 break; /* end case k_type */
211 printf(" *** Faulty type or entity! \n");
215 /* execute post method */
220 /** Check whether node contains types or entities as an attribute.
221 If so start a walk over that information. */
222 static void irn_type_walker(
223 ir_node *node, type_walk_func *pre, type_walk_func *post, void *env)
229 cont.ent = get_irn_entity_attr(node);
231 do_type_walk(cont, pre, post, env);
232 cont.typ = get_irn_type_attr(node);
234 do_type_walk(cont, pre, post, env);
237 /** Check whether node contains types or entities as an attribute.
238 If so start a walk over that information. */
239 static void start_type_walk(ir_node *node, void *ctx)
241 type_walk_env *env = (type_walk_env*)ctx;
243 type_walk_func *post;
250 irn_type_walker(node, pre, post, envi);
253 void type_walk(type_walk_func *pre, type_walk_func *post, void *env)
255 size_t i, n_types = get_irp_n_types();
258 irp_reserve_resources(irp, IRP_RESOURCE_TYPE_VISITED);
259 inc_master_type_visited();
260 for (i = 0; i < n_types; ++i) {
261 cont.typ = get_irp_type(i);
262 do_type_walk(cont, pre, post, env);
264 cont.typ = get_glob_type();
265 do_type_walk(cont, pre, post, env);
266 irp_free_resources(irp, IRP_RESOURCE_TYPE_VISITED);
269 void type_walk_irg(ir_graph *irg,
271 type_walk_func *post,
274 ir_graph *rem = current_ir_graph;
275 /* this is needed to pass the parameters to the walker that actually
276 walks the type information */
277 type_walk_env type_env;
281 type_env.post = post;
284 current_ir_graph = irg;
286 /* We walk over the irg to find all IR-nodes that contain an attribute
287 with type information. If we find one we call a type walker to
288 touch the reachable type information.
289 The same type can be referenced by several IR-nodes. To avoid
290 repeated visits of the same type node we must decrease the
291 type visited flag for each walk. This is done in start_type_walk().
292 Here we initially increase the flag. We only call do_type_walk that does
293 not increase the flag.
295 irp_reserve_resources(irp, IRP_RESOURCE_TYPE_VISITED);
296 inc_master_type_visited();
297 irg_walk(get_irg_end(irg), start_type_walk, NULL, &type_env);
299 cont.ent = get_irg_entity(irg);
300 do_type_walk(cont, pre, post, env);
302 cont.typ = get_irg_frame_type(irg);
303 do_type_walk(cont, pre, post, env);
305 current_ir_graph = rem;
306 irp_free_resources(irp, IRP_RESOURCE_TYPE_VISITED);
309 static void type_walk_s2s_2(type_or_ent tore,
311 type_walk_func *post,
317 switch (get_kind(tore.ent)) {
319 if (entity_visited(tore.ent)) return;
322 if (type_visited(tore.typ)) return;
329 switch (get_kind(tore.typ)) {
332 ir_type *tp = tore.typ;
333 mark_type_visited(tp);
334 switch (get_type_tpop_code(tp)) {
339 n = get_class_n_supertypes(tp);
340 for (i = 0; i < n; ++i) {
341 cont.typ = get_class_supertype(tp, i);
342 type_walk_s2s_2(cont, pre, post, env);
344 /* execute pre method */
348 n = get_class_n_subtypes(tp);
349 for (i = 0; i < n; ++i) {
350 cont.typ = get_class_subtype(tp, i);
351 type_walk_s2s_2(cont, pre, post, env);
354 /* execute post method */
363 case tpo_enumeration:
369 printf(" *** Faulty type! \n");
372 } break; /* end case k_type */
377 printf(" *** Faulty type or entity! \n");
382 void type_walk_super2sub(type_walk_func *pre,
383 type_walk_func *post,
387 size_t i, n_types = get_irp_n_types();
389 irp_reserve_resources(irp, IRP_RESOURCE_TYPE_VISITED);
390 inc_master_type_visited();
391 cont.typ = get_glob_type();
392 type_walk_s2s_2(cont, pre, post, env);
393 for (i = 0; i < n_types; ++i) {
394 cont.typ = get_irp_type(i);
395 type_walk_s2s_2(cont, pre, post, env);
397 irp_free_resources(irp, IRP_RESOURCE_TYPE_VISITED);
400 /*****************************************************************************/
402 static void type_walk_super_2(type_or_ent tore, type_walk_func *pre,
403 type_walk_func *post, void *env)
408 switch (get_kind(tore.ent)) {
410 if (entity_visited(tore.ent))
414 if (type_visited(tore.typ))
422 switch (get_kind(tore.typ)) {
425 ir_type *tp = tore.typ;
426 mark_type_visited(tp);
427 switch (get_type_tpop_code(tp)) {
432 /* execute pre method */
436 n = get_class_n_supertypes(tp);
437 for (i = 0; i < n; ++i) {
438 cont.typ = get_class_supertype(tp, i);
439 type_walk_super_2(cont, pre, post, env);
442 /* execute post method */
451 case tpo_enumeration:
457 printf(" *** Faulty type! \n");
460 } break; /* end case k_type */
465 printf(" *** Faulty type or entity! \n");
470 void type_walk_super(type_walk_func *pre, type_walk_func *post, void *env)
472 size_t i, n_types = get_irp_n_types();
475 irp_reserve_resources(irp, IRP_RESOURCE_TYPE_VISITED);
476 inc_master_type_visited();
477 cont.typ = get_glob_type();
478 type_walk_super_2(cont, pre, post, env);
479 for (i = 0; i < n_types; ++i) {
480 cont.typ = get_irp_type(i);
481 type_walk_super_2(cont, pre, post, env);
483 irp_free_resources(irp, IRP_RESOURCE_TYPE_VISITED);
486 /*****************************************************************************/
489 static void class_walk_s2s_2(ir_type *tp, class_walk_func *pre,
490 class_walk_func *post, void *env)
495 if (type_visited(tp)) return;
497 assert(is_Class_type(tp));
498 /* Assure all supertypes are visited before */
499 n = get_class_n_supertypes(tp);
500 for (i = 0; i < n; ++i) {
501 if (type_not_visited(get_class_supertype(tp, i)))
505 mark_type_visited(tp);
507 /* execute pre method */
511 n = get_class_n_subtypes(tp);
512 for (i = 0; i < n; ++i) {
513 class_walk_s2s_2(get_class_subtype(tp, i), pre, post, env);
515 /* execute post method */
520 void class_walk_super2sub(class_walk_func *pre,
521 class_walk_func *post,
524 size_t i, n_types = get_irp_n_types();
527 irp_reserve_resources(irp, IRP_RESOURCE_TYPE_VISITED);
528 inc_master_type_visited();
529 for (i = 0; i < n_types; i++) {
530 tp = get_irp_type(i);
531 if (is_Class_type(tp) &&
532 (get_class_n_supertypes(tp) == 0) &&
533 type_not_visited(tp) &&
534 (! is_frame_type(tp)) &&
535 (tp != get_glob_type())) {
536 class_walk_s2s_2(tp, pre, post, env);
539 irp_free_resources(irp, IRP_RESOURCE_TYPE_VISITED);
543 void walk_types_entities(ir_type *tp,
544 entity_walk_func *doit,
549 switch (get_type_tpop_code(tp)) {
551 n = get_class_n_members(tp);
552 for (i = 0; i < n; ++i)
553 doit(get_class_member(tp, i), env);
556 n = get_struct_n_members(tp);
557 for (i = 0; i < n; ++i)
558 doit(get_struct_member(tp, i), env);
561 n = get_union_n_members(tp);
562 for (i = 0; i < n; ++i)
563 doit(get_union_member(tp, i), env);
566 doit(get_array_element_entity(tp), env);
569 case tpo_enumeration: