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
34 #include "type_or_entity.h"
38 #include "irgraph_t.h"
42 typedef struct type_walk_env {
49 static void type_walk_2(type_or_ent *tore,
50 void (*pre) (type_or_ent*, void*),
51 void (*post)(type_or_ent*, void*),
57 switch (get_kind(tore)) {
59 if (((entity *)tore)->visit >= type_visited) return;
62 if(type_id == get_type_tpop((type*)tore)) {
63 type_walk_2((type_or_ent *)skip_tid((type *)tore), pre, post, env);
66 if (((type *)tore)->visit >= type_visited) return;
72 /* execute pre method */
77 switch (get_kind(tore)) {
81 entity *ent = (entity *)tore;
82 ent->visit = type_visited;
83 type_walk_2((type_or_ent *)get_entity_owner(ent), pre, post, env);
84 type_walk_2((type_or_ent *)get_entity_type(ent), pre, post, env);
89 type *tp = (type *)tore;
90 mark_type_visited(tp);
91 switch (get_type_tpop_code(tp)) {
94 for (i=0; i<get_class_n_supertypes(tp); i++)
95 type_walk_2((type_or_ent *)get_class_supertype(tp, i), pre, post, env);
96 for (i=0; i<get_class_n_members(tp); i++)
97 type_walk_2((type_or_ent *)get_class_member(tp, i), pre, post, env);
98 for (i=0; i<get_class_n_subtypes(tp); i++)
99 type_walk_2((type_or_ent *)get_class_subtype(tp, i), pre, post, env);
104 for (i=0; i<get_struct_n_members(tp); i++)
105 type_walk_2((type_or_ent *)get_struct_member(tp, i), pre, post, env);
110 for (i = 0; i < get_method_n_params(tp); i++)
111 type_walk_2((type_or_ent *)get_method_param_type(tp, i), pre, post, env);
112 for (i = 0; i < get_method_n_ress(tp); i++)
113 type_walk_2((type_or_ent *)get_method_res_type(tp, i), pre, post, env);
118 for (i = 0; i < get_union_n_members(tp); i++)
119 type_walk_2((type_or_ent *)get_union_member(tp, i), pre, post, env);
123 type_walk_2((type_or_ent *)get_array_element_type(tp),
125 type_walk_2((type_or_ent *)get_array_element_entity(tp),
128 case tpo_enumeration:
132 type_walk_2((type_or_ent *)get_pointer_points_to_type(tp),
142 assert(0 && "Faulty type");
145 } break; /* end case k_type */
147 printf(" *** Faulty type or entity! \n");
151 /* execute post method */
158 /** Check wether node contains types or entities as an attribute.
159 If so start a walk over that information. */
160 static void start_type_walk(ir_node *node, void *env) {
162 type_walk_func *post;
165 pre = ((type_walk_env *)env)->pre;
166 post = ((type_walk_env *)env)->post;
167 envi = ((type_walk_env *)env)->env;
171 switch (get_irn_opcode(node)) { /* node label */
173 if ( (get_SymConst_kind(node) ==symconst_type_tag)
174 || (get_SymConst_kind(node) ==symconst_size))
175 type_walk_2((type_or_ent *)get_SymConst_type(node), pre, post, envi);
178 type_walk_2((type_or_ent *)get_Sel_entity(node), pre, post, envi);
181 type_walk_2((type_or_ent *)get_Call_type(node), pre, post, envi);
184 type_walk_2((type_or_ent *)get_Alloc_type(node), pre, post, envi);
187 type_walk_2((type_or_ent *)get_Free_type(node), pre, post, envi);
190 type_walk_2((type_or_ent *)get_Cast_type(node), pre, post, envi);
197 void type_walk(type_walk_func *pre, type_walk_func *post, void *env) {
198 int i, n_types = get_irp_n_types();
201 for (i = 0; i < n_types; i++) {
202 type_walk_2((type_or_ent *)get_irp_type(i), pre, post, env);
204 type_walk_2((type_or_ent *)get_glob_type(), pre, post, env);
207 void type_walk_irg (ir_graph *irg,
208 void (*pre)(type_or_ent*, void*),
209 void (*post)(type_or_ent*, void*),
212 ir_graph *rem = current_ir_graph;
213 /* this is needed to pass the parameters to the walker that actually
214 walks the type information */
215 type_walk_env type_env;
218 type_env.post = post;
221 current_ir_graph = irg;
223 /* We walk over the irg to find all irnodes that contain an attribute
224 with type information. If we find one we call a type walker to
225 touch the reachable type information.
226 The same type can be referenced by several irnodes. To avoid
227 repeated visits of the same type node we must decrease the
228 type visited flag for each walk. This is done in start_type_walk().
229 Here we initially increase the flag. We only call type_walk_2 that does
230 not increase the flag.
233 irg_walk(get_irg_end(irg), start_type_walk, NULL, &type_env);
235 type_walk_2((type_or_ent *)get_irg_entity(irg), pre, post, env);
237 type_walk_2((type_or_ent *)get_irg_frame_type(irg), pre, post, env);
239 current_ir_graph = rem;
243 static void type_walk_s2s_2(type_or_ent *tore,
244 void (*pre)(type_or_ent*, void*),
245 void (*post)(type_or_ent*, void*),
251 switch (get_kind(tore)) {
253 if (((entity *)tore)->visit >= type_visited) return;
256 if(type_id == get_type_tpop((type*)tore)) {
257 type_walk_s2s_2((type_or_ent *)skip_tid((type *)tore), pre, post, env);
260 if (((type *)tore)->visit >= type_visited) return;
267 switch (get_kind(tore)) {
270 type *tp = (type *)tore;
271 mark_type_visited(tp);
272 switch (get_type_tpop_code(tp)) {
275 for (i = 0; i < get_class_n_supertypes(tp); i++) {
276 type_walk_s2s_2((type_or_ent *)get_class_supertype(tp, i), pre,
279 /* execute pre method */
282 tp = skip_tid((type*)tore);
284 for (i = 0; i < get_class_n_subtypes(tp); i++) {
285 type_walk_s2s_2((type_or_ent *)get_class_subtype(tp, i), pre,
289 /* execute post method */
298 case tpo_enumeration:
305 printf(" *** Faulty type! \n");
308 } break; /* end case k_type */
313 printf(" *** Faulty type or entity! \n");
319 void type_walk_super2sub(
320 void (*pre)(type_or_ent*, void*),
321 void (*post)(type_or_ent*, void*),
324 int i, n_types = get_irp_n_types();
327 type_walk_s2s_2((type_or_ent *)get_glob_type(), pre, post, env);
328 for (i = 0; i < n_types; i++) {
329 tp = get_irp_type(i);
330 type_walk_s2s_2((type_or_ent *)tp, pre, post, env);
334 /*****************************************************************************/
337 type_walk_super_2(type_or_ent *tore,
338 void (*pre)(type_or_ent*, void*),
339 void (*post)(type_or_ent*, void*),
345 switch (get_kind(tore)) {
347 if (((entity *)tore)->visit >= type_visited) return;
350 if(type_id == get_type_tpop((type*)tore)) {
351 type_walk_super_2((type_or_ent *)skip_tid((type *)tore), pre, post, env);
354 if (((type *)tore)->visit >= type_visited) return;
361 switch (get_kind(tore)) {
364 type *tp = (type *)tore;
365 mark_type_visited(tp);
366 switch (get_type_tpop_code(tp)) {
369 /* execute pre method */
372 tp = skip_tid((type*)tore);
374 for (i = 0; i < get_class_n_supertypes(tp); i++) {
375 type_walk_super_2((type_or_ent *)get_class_supertype(tp, i), pre,
379 /* execute post method */
388 case tpo_enumeration:
395 printf(" *** Faulty type! \n");
398 } break; /* end case k_type */
403 printf(" *** Faulty type or entity! \n");
409 void type_walk_super(
410 void (*pre)(type_or_ent*, void*),
411 void (*post)(type_or_ent*, void*),
413 int i, n_types = get_irp_n_types();
416 type_walk_super_2((type_or_ent *)get_glob_type(), pre, post, env);
417 for (i = 0; i < n_types; i++) {
418 tp = get_irp_type(i);
419 type_walk_super_2((type_or_ent *)tp, pre, post, env);
423 /*****************************************************************************/
427 class_walk_s2s_2(type *tp,
428 void (*pre)(type*, void*),
429 void (*post)(type*, void*),
435 if (tp->visit >= type_visited) return;
437 assert(is_Class_type(tp));
438 /* Assure all supertypes are visited before */
439 for (i=0; i < get_class_n_supertypes(tp); i++) {
440 if (get_type_visited(get_class_supertype(tp, i)) < type_visited)
444 mark_type_visited(tp);
446 /* execute pre method */
450 tp = skip_tid((type*)tp);
451 for (i=0; i<get_class_n_subtypes(tp); i++) {
452 class_walk_s2s_2(get_class_subtype(tp, i), pre, post, env);
454 /* execute post method */
461 void class_walk_super2sub(
462 void (*pre)(type*, void*),
463 void (*post)(type*, void*),
466 int i, n_types = get_irp_n_types();
470 for (i = 0; i < n_types; i++) {
471 tp = get_irp_type(i);
472 if (is_Class_type(tp) &&
473 (get_class_n_supertypes(tp) == 0) &&
474 (tp->visit < type_visited)) {
475 assert(!is_frame_type(tp));
476 assert(tp != get_glob_type());
477 class_walk_s2s_2(tp, pre, post, env);
483 /* Walks over all entities in the type */
484 void walk_types_entities(
486 void (*doit)(entity*, void*),
490 switch(get_type_tpop_code(tp)) {
492 for (i=0; i<get_class_n_members(tp); i++)
493 doit(get_class_member(tp, i), env);
496 for (i=0; i<get_struct_n_members(tp); i++)
497 doit(get_struct_member(tp, i), env);
500 for (i = 0; i < get_union_n_members(tp); i++)
501 doit(get_union_member(tp, i), env);
504 doit(get_array_element_entity(tp), env);
507 case tpo_enumeration: