3 * File name: ir/tr/typewalk.c
4 * Purpose: Traverse the type information.
5 * Author: Goetz Lindenmaier
9 * Copyright: (c) 1999-2003 Universität Karlsruhe
10 * Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE.
14 * traverse the type information. The walker walks the whole ir graph
15 * to find the distinct type trees in the type graph forest.
16 * - execute the pre function before recursion
17 * - execute the post function after recursion
31 #include "type_or_entity.h"
35 #include "irgraph_t.h"
39 typedef struct type_walk_env {
46 static void type_walk_2(type_or_ent *tore,
47 void (*pre) (type_or_ent*, void*),
48 void (*post)(type_or_ent*, void*),
54 switch (get_kind(tore)) {
56 if (((entity *)tore)->visit >= type_visited) return;
59 if(type_id == get_type_tpop((type*)tore)) {
60 type_walk_2((type_or_ent *)skip_tid((type *)tore), pre, post, env);
63 if (((type *)tore)->visit >= type_visited) return;
69 /* execute pre method */
74 switch (get_kind(tore)) {
78 entity *ent = (entity *)tore;
79 ent->visit = type_visited;
80 type_walk_2((type_or_ent *)get_entity_owner(ent), pre, post, env);
81 type_walk_2((type_or_ent *)get_entity_type(ent), pre, post, env);
86 type *tp = (type *)tore;
87 mark_type_visited(tp);
88 switch (get_type_tpop_code(tp)) {
91 for (i=0; i<get_class_n_supertypes(tp); i++)
92 type_walk_2((type_or_ent *)get_class_supertype(tp, i), pre, post, env);
93 for (i=0; i<get_class_n_members(tp); i++)
94 type_walk_2((type_or_ent *)get_class_member(tp, i), pre, post, env);
95 for (i=0; i<get_class_n_subtypes(tp); i++)
96 type_walk_2((type_or_ent *)get_class_subtype(tp, i), pre, post, env);
101 for (i=0; i<get_struct_n_members(tp); i++)
102 type_walk_2((type_or_ent *)get_struct_member(tp, i), pre, post, env);
107 for (i = 0; i < get_method_n_params(tp); i++)
108 type_walk_2((type_or_ent *)get_method_param_type(tp, i), pre, post, env);
109 for (i = 0; i < get_method_n_ress(tp); i++)
110 type_walk_2((type_or_ent *)get_method_res_type(tp, i), pre, post, env);
115 for (i = 0; i < get_union_n_members(tp); i++)
116 type_walk_2((type_or_ent *)get_union_member(tp, i), pre, post, env);
120 type_walk_2((type_or_ent *)get_array_element_type(tp),
122 type_walk_2((type_or_ent *)get_array_element_entity(tp),
125 case tpo_enumeration:
129 type_walk_2((type_or_ent *)get_pointer_points_to_type(tp),
139 assert(0 && "Faulty type");
142 } break; /* end case k_type */
144 printf(" *** Faulty type or entity! \n");
148 /* execute post method */
155 /** Check wether node contains types or entities as an attribute.
156 If so start a walk over that information. */
157 static void start_type_walk(ir_node *node, void *env) {
159 type_walk_func *post;
162 pre = ((type_walk_env *)env)->pre;
163 post = ((type_walk_env *)env)->post;
164 envi = ((type_walk_env *)env)->env;
168 switch (get_irn_opcode(node)) { /* node label */
170 if ( (get_SymConst_kind(node) ==symconst_type_tag)
171 || (get_SymConst_kind(node) ==symconst_size))
172 type_walk_2((type_or_ent *)get_SymConst_type(node), pre, post, envi);
175 type_walk_2((type_or_ent *)get_Sel_entity(node), pre, post, envi);
178 type_walk_2((type_or_ent *)get_Call_type(node), pre, post, envi);
181 type_walk_2((type_or_ent *)get_Alloc_type(node), pre, post, envi);
184 type_walk_2((type_or_ent *)get_Free_type(node), pre, post, envi);
187 type_walk_2((type_or_ent *)get_Cast_type(node), pre, post, envi);
194 void type_walk(type_walk_func *pre, type_walk_func *post, void *env) {
195 int i, n_types = get_irp_n_types();
198 for (i = 0; i < n_types; i++) {
199 type_walk_2((type_or_ent *)get_irp_type(i), pre, post, env);
201 type_walk_2((type_or_ent *)get_glob_type(), pre, post, env);
204 void type_walk_irg (ir_graph *irg,
205 void (*pre)(type_or_ent*, void*),
206 void (*post)(type_or_ent*, void*),
209 ir_graph *rem = current_ir_graph;
210 /* this is needed to pass the parameters to the walker that actually
211 walks the type information */
212 type_walk_env type_env;
215 type_env.post = post;
218 current_ir_graph = irg;
220 /* We walk over the irg to find all irnodes that contain an attribute
221 with type information. If we find one we call a type walker to
222 touch the reachable type information.
223 The same type can be referenced by several irnodes. To avoid
224 repeated visits of the same type node we must decrease the
225 type visited flag for each walk. This is done in start_type_walk().
226 Here we initially increase the flag. We only call type_walk_2 that does
227 not increase the flag.
230 irg_walk(get_irg_end(irg), start_type_walk, NULL, &type_env);
232 type_walk_2((type_or_ent *)get_irg_entity(irg), pre, post, env);
234 type_walk_2((type_or_ent *)get_irg_frame_type(irg), pre, post, env);
236 current_ir_graph = rem;
240 static void type_walk_s2s_2(type_or_ent *tore,
241 void (*pre)(type_or_ent*, void*),
242 void (*post)(type_or_ent*, void*),
248 switch (get_kind(tore)) {
250 if (((entity *)tore)->visit >= type_visited) return;
253 if(type_id == get_type_tpop((type*)tore)) {
254 type_walk_s2s_2((type_or_ent *)skip_tid((type *)tore), pre, post, env);
257 if (((type *)tore)->visit >= type_visited) return;
264 switch (get_kind(tore)) {
267 type *tp = (type *)tore;
268 mark_type_visited(tp);
269 switch (get_type_tpop_code(tp)) {
272 for (i = 0; i < get_class_n_supertypes(tp); i++) {
273 type_walk_s2s_2((type_or_ent *)get_class_supertype(tp, i), pre,
276 /* execute pre method */
279 tp = skip_tid((type*)tore);
281 for (i = 0; i < get_class_n_subtypes(tp); i++) {
282 type_walk_s2s_2((type_or_ent *)get_class_subtype(tp, i), pre,
286 /* execute post method */
295 case tpo_enumeration:
302 printf(" *** Faulty type! \n");
305 } break; /* end case k_type */
310 printf(" *** Faulty type or entity! \n");
316 void type_walk_super2sub(
317 void (*pre)(type_or_ent*, void*),
318 void (*post)(type_or_ent*, void*),
321 int i, n_types = get_irp_n_types();
324 type_walk_s2s_2((type_or_ent *)get_glob_type(), pre, post, env);
325 for (i = 0; i < n_types; i++) {
326 tp = get_irp_type(i);
327 type_walk_s2s_2((type_or_ent *)tp, pre, post, env);
331 /*****************************************************************************/
334 type_walk_super_2(type_or_ent *tore,
335 void (*pre)(type_or_ent*, void*),
336 void (*post)(type_or_ent*, void*),
342 switch (get_kind(tore)) {
344 if (((entity *)tore)->visit >= type_visited) return;
347 if(type_id == get_type_tpop((type*)tore)) {
348 type_walk_super_2((type_or_ent *)skip_tid((type *)tore), pre, post, env);
351 if (((type *)tore)->visit >= type_visited) return;
358 switch (get_kind(tore)) {
361 type *tp = (type *)tore;
362 mark_type_visited(tp);
363 switch (get_type_tpop_code(tp)) {
366 /* execute pre method */
369 tp = skip_tid((type*)tore);
371 for (i = 0; i < get_class_n_supertypes(tp); i++) {
372 type_walk_super_2((type_or_ent *)get_class_supertype(tp, i), pre,
376 /* execute post method */
385 case tpo_enumeration:
392 printf(" *** Faulty type! \n");
395 } break; /* end case k_type */
400 printf(" *** Faulty type or entity! \n");
406 void type_walk_super(
407 void (*pre)(type_or_ent*, void*),
408 void (*post)(type_or_ent*, void*),
410 int i, n_types = get_irp_n_types();
413 type_walk_super_2((type_or_ent *)get_glob_type(), pre, post, env);
414 for (i = 0; i < n_types; i++) {
415 tp = get_irp_type(i);
416 type_walk_super_2((type_or_ent *)tp, pre, post, env);
420 /*****************************************************************************/
424 class_walk_s2s_2(type *tp,
425 void (*pre)(type*, void*),
426 void (*post)(type*, void*),
432 if (tp->visit >= type_visited) return;
434 assert(is_class_type(tp));
435 /* Assure all supertypes are visited before */
436 for (i=0; i < get_class_n_supertypes(tp); i++) {
437 if (get_type_visited(get_class_supertype(tp, i)) < type_visited)
441 mark_type_visited(tp);
443 /* execute pre method */
447 tp = skip_tid((type*)tp);
448 for (i=0; i<get_class_n_subtypes(tp); i++) {
449 class_walk_s2s_2(get_class_subtype(tp, i), pre, post, env);
451 /* execute post method */
458 void class_walk_super2sub(
459 void (*pre)(type*, void*),
460 void (*post)(type*, void*),
463 int i, n_types = get_irp_n_types();
467 for (i = 0; i < n_types; i++) {
468 tp = get_irp_type(i);
469 if (is_class_type(tp) &&
470 (get_class_n_supertypes(tp) == 0) &&
471 (tp->visit < type_visited)) {
472 assert(!is_frame_type(tp));
473 assert(tp != get_glob_type());
474 class_walk_s2s_2(tp, pre, post, env);
480 /* Walks over all entities in the type */
481 void walk_types_entities(
483 void (*doit)(entity*, void*),
487 switch(get_type_tpop_code(tp)) {
489 for (i=0; i<get_class_n_members(tp); i++)
490 doit(get_class_member(tp, i), env);
493 for (i=0; i<get_struct_n_members(tp); i++)
494 doit(get_struct_member(tp, i), env);
497 for (i = 0; i < get_union_n_members(tp); i++)
498 doit(get_union_member(tp, i), env);
501 doit(get_array_element_entity(tp), env);
504 case tpo_enumeration: