2 * Copyright (C) 1995-2008 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
27 * Traverse the type information. The walker walks the whole ir graph
28 * to find the distinct type trees in the type graph forest.
29 * - execute the pre function before recursion
30 * - execute the post function after recursion
44 #include "irgraph_t.h"
50 * The walker environment
52 typedef struct type_walk_env {
53 type_walk_func *pre; /**< Pre-walker function */
54 type_walk_func *post; /**< Post-walker function */
55 void *env; /**< environment for walker functions */
58 /* a walker for irn's */
59 static void irn_type_walker(
60 ir_node *node, type_walk_func *pre, type_walk_func *post, void *env);
62 static void walk_initializer(ir_initializer_t *initializer,
63 type_walk_func *pre, type_walk_func *post,
66 switch(initializer->kind) {
67 case IR_INITIALIZER_CONST:
68 irn_type_walker(initializer->consti.value, pre, post, env);
70 case IR_INITIALIZER_TARVAL:
71 case IR_INITIALIZER_NULL:
74 case IR_INITIALIZER_COMPOUND: {
76 for(i = 0; i < initializer->compound.n_initializers; ++i) {
77 ir_initializer_t *subinitializer
78 = initializer->compound.initializers[i];
79 walk_initializer(subinitializer, pre, post, env);
84 panic("invalid initializer found");
88 * Main walker: walks over all used types/entities of a
91 static void do_type_walk(type_or_ent tore,
96 int i, n_types, n_mem;
97 ir_entity *ent = NULL;
103 switch (get_kind(tore.ent)) {
106 if (entity_visited(ent))
110 tp = skip_tid(tore.typ);
111 if (type_visited(tp))
118 /* execute pre method */
123 switch (get_kind(tore.ent)) {
125 mark_entity_visited(ent);
126 cont.typ = get_entity_owner(ent);
127 do_type_walk(cont, pre, post, env);
128 cont.typ = get_entity_type(ent);
129 do_type_walk(cont, pre, post, env);
131 if (get_entity_variability(ent) != variability_uninitialized) {
132 /* walk over the value types */
133 if (ent->has_initializer) {
134 walk_initializer(ent->attr.initializer, pre, post, env);
135 } else if (is_atomic_entity(ent)) {
136 n = get_atomic_ent_value(ent);
137 irn_type_walker(n, pre, post, env);
139 n_mem = get_compound_ent_n_values(ent);
140 for (i = 0; i < n_mem; ++i) {
141 n = get_compound_ent_value(ent, i);
142 irn_type_walker(n, pre, post, env);
148 mark_type_visited(tp);
149 switch (get_type_tpop_code(tp)) {
152 n_types = get_class_n_supertypes(tp);
153 for (i = 0; i < n_types; ++i) {
154 cont.typ = get_class_supertype(tp, i);
155 do_type_walk(cont, pre, post, env);
157 n_mem = get_class_n_members(tp);
158 for (i = 0; i < n_mem; ++i) {
159 cont.ent = get_class_member(tp, i);
160 do_type_walk(cont, pre, post, env);
162 n_types = get_class_n_subtypes(tp);
163 for (i = 0; i < n_types; ++i) {
164 cont.typ = get_class_subtype(tp, i);
165 do_type_walk(cont, pre, post, env);
170 n_mem = get_struct_n_members(tp);
171 for (i = 0; i < n_mem; ++i) {
172 cont.ent = get_struct_member(tp, i);
173 do_type_walk(cont, pre, post, env);
178 n_mem = get_method_n_params(tp);
179 for (i = 0; i < n_mem; ++i) {
180 cont.typ = get_method_param_type(tp, i);
181 do_type_walk(cont, pre, post, env);
183 n_mem = get_method_n_ress(tp);
184 for (i = 0; i < n_mem; ++i) {
185 cont.typ = get_method_res_type(tp, i);
186 do_type_walk(cont, pre, post, env);
191 n_mem = get_union_n_members(tp);
192 for (i = 0; i < n_mem; ++i) {
193 cont.ent = get_union_member(tp, i);
194 do_type_walk(cont, pre, post, env);
199 cont.typ = get_array_element_type(tp);
200 do_type_walk(cont, pre, post, env);
201 cont.ent = get_array_element_entity(tp);
202 do_type_walk(cont, pre, post, env);
205 case tpo_enumeration:
210 cont.typ = get_pointer_points_to_type(tp);
211 do_type_walk(cont, pre, post, env);
221 assert(0 && "Faulty type");
224 break; /* end case k_type */
227 printf(" *** Faulty type or entity! \n");
231 /* execute post method */
236 /** Check whether node contains types or entities as an attribute.
237 If so start a walk over that information. */
238 static void irn_type_walker(
239 ir_node *node, type_walk_func *pre, type_walk_func *post, void *env)
245 cont.ent = get_irn_entity_attr(node);
247 do_type_walk(cont, pre, post, env);
248 cont.typ = get_irn_type_attr(node);
250 do_type_walk(cont, pre, post, env);
253 /** Check whether node contains types or entities as an attribute.
254 If so start a walk over that information. */
255 static void start_type_walk(ir_node *node, void *ctx) {
256 type_walk_env *env = ctx;
258 type_walk_func *post;
265 irn_type_walker(node, pre, post, envi);
268 /* walker: walks over all types */
269 void type_walk(type_walk_func *pre, type_walk_func *post, void *env) {
270 int i, n_types = get_irp_n_types();
273 inc_master_type_visited();
274 for (i = 0; i < n_types; ++i) {
275 cont.typ = get_irp_type(i);
276 do_type_walk(cont, pre, post, env);
278 cont.typ = get_glob_type();
279 do_type_walk(cont, pre, post, env);
282 void type_walk_irg(ir_graph *irg,
284 type_walk_func *post,
287 ir_graph *rem = current_ir_graph;
288 /* this is needed to pass the parameters to the walker that actually
289 walks the type information */
290 type_walk_env type_env;
294 type_env.post = post;
297 current_ir_graph = irg;
299 /* We walk over the irg to find all IR-nodes that contain an attribute
300 with type information. If we find one we call a type walker to
301 touch the reachable type information.
302 The same type can be referenced by several IR-nodes. To avoid
303 repeated visits of the same type node we must decrease the
304 type visited flag for each walk. This is done in start_type_walk().
305 Here we initially increase the flag. We only call do_type_walk that does
306 not increase the flag.
308 inc_master_type_visited();
309 irg_walk(get_irg_end(irg), start_type_walk, NULL, &type_env);
311 cont.ent = get_irg_entity(irg);
312 do_type_walk(cont, pre, post, env);
314 cont.typ = get_irg_frame_type(irg);
315 do_type_walk(cont, pre, post, env);
317 current_ir_graph = rem;
320 static void type_walk_s2s_2(type_or_ent tore,
322 type_walk_func *post,
329 switch (get_kind(tore.ent)) {
331 if (entity_visited(tore.ent)) return;
334 if (type_id == get_type_tpop(tore.typ)) {
335 cont.typ = skip_tid(tore.typ);
336 type_walk_s2s_2(cont, pre, post, env);
339 if (type_visited(tore.typ)) return;
346 switch (get_kind(tore.typ)) {
349 ir_type *tp = tore.typ;
350 mark_type_visited(tp);
351 switch (get_type_tpop_code(tp)) {
354 n = get_class_n_supertypes(tp);
355 for (i = 0; i < n; ++i) {
356 cont.typ = get_class_supertype(tp, i);
357 type_walk_s2s_2(cont, pre, post, env);
359 /* execute pre method */
364 n = get_class_n_subtypes(tp);
365 for (i = 0; i < n; ++i) {
366 cont.typ = get_class_subtype(tp, i);
367 type_walk_s2s_2(cont, pre, post, env);
370 /* execute post method */
379 case tpo_enumeration:
386 printf(" *** Faulty type! \n");
389 } break; /* end case k_type */
394 printf(" *** Faulty type or entity! \n");
399 void type_walk_super2sub(type_walk_func *pre,
400 type_walk_func *post,
404 int i, n_types = get_irp_n_types();
406 inc_master_type_visited();
407 cont.typ = get_glob_type();
408 type_walk_s2s_2(cont, pre, post, env);
409 for (i = 0; i < n_types; ++i) {
410 cont.typ = get_irp_type(i);
411 type_walk_s2s_2(cont, pre, post, env);
415 /*****************************************************************************/
418 type_walk_super_2(type_or_ent tore,
420 type_walk_func *post,
426 switch (get_kind(tore.ent)) {
428 if (entity_visited(tore.ent))
432 if (type_id == get_type_tpop(tore.typ)) {
433 cont.typ = skip_tid(tore.typ);
434 type_walk_super_2(cont, pre, post, env);
437 if (type_visited(tore.typ))
445 switch (get_kind(tore.typ)) {
448 ir_type *tp = tore.typ;
449 mark_type_visited(tp);
450 switch (get_type_tpop_code(tp)) {
453 /* execute pre method */
458 n = get_class_n_supertypes(tp);
459 for (i = 0; i < n; ++i) {
460 cont.typ = get_class_supertype(tp, i);
461 type_walk_super_2(cont, pre, post, env);
464 /* execute post method */
473 case tpo_enumeration:
480 printf(" *** Faulty type! \n");
483 } break; /* end case k_type */
488 printf(" *** Faulty type or entity! \n");
493 void type_walk_super(type_walk_func *pre,
494 type_walk_func *post,
496 int i, n_types = get_irp_n_types();
499 inc_master_type_visited();
500 cont.typ = get_glob_type();
501 type_walk_super_2(cont, pre, post, env);
502 for (i = 0; i < n_types; ++i) {
503 cont.typ = get_irp_type(i);
504 type_walk_super_2(cont, pre, post, env);
508 /*****************************************************************************/
512 class_walk_s2s_2(ir_type *tp,
513 class_walk_func *pre,
514 class_walk_func *post,
520 if (type_visited(tp)) return;
522 assert(is_Class_type(tp));
523 /* Assure all supertypes are visited before */
524 n = get_class_n_supertypes(tp);
525 for (i = 0; i < n; ++i) {
526 if (type_not_visited(get_class_supertype(tp, i)))
530 mark_type_visited(tp);
532 /* execute pre method */
537 n = get_class_n_subtypes(tp);
538 for (i = 0; i < n; ++i) {
539 class_walk_s2s_2(get_class_subtype(tp, i), pre, post, env);
541 /* execute post method */
546 void class_walk_super2sub(class_walk_func *pre,
547 class_walk_func *post,
550 int i, n_types = get_irp_n_types();
553 inc_master_type_visited();
554 for (i = 0; i < n_types; i++) {
555 tp = get_irp_type(i);
556 if (is_Class_type(tp) &&
557 (get_class_n_supertypes(tp) == 0) &&
558 type_not_visited(tp)) {
559 assert(! is_frame_type(tp));
560 assert(tp != get_glob_type());
561 class_walk_s2s_2(tp, pre, post, env);
567 /* Walks over all entities in the type */
568 void walk_types_entities(ir_type *tp,
569 entity_walk_func *doit,
574 switch (get_type_tpop_code(tp)) {
576 n = get_class_n_members(tp);
577 for (i = 0; i < n; ++i)
578 doit(get_class_member(tp, i), env);
581 n = get_struct_n_members(tp);
582 for (i = 0; i < n; ++i)
583 doit(get_struct_member(tp, i), env);
586 n = get_union_n_members(tp);
587 for (i = 0; i < n; ++i)
588 doit(get_union_member(tp, i), env);
591 doit(get_array_element_entity(tp), env);
594 case tpo_enumeration: