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
28 #include "irgraph_t.h"
31 #include "type_or_entity.h"
35 /* Make types visible to allow most efficient access */
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),
137 printf(" *** Faulty type! \n");
140 } break; /* end case k_type */
142 printf(" *** Faulty type or entity! \n");
146 /* execute post method */
153 /** Check wether node contains types or entities as an attribute.
154 If so start a walk over that information. */
155 static void start_type_walk(ir_node *node, void *env) {
157 type_walk_func *post;
160 pre = ((type_walk_env *)env)->pre;
161 post = ((type_walk_env *)env)->post;
162 envi = ((type_walk_env *)env)->env;
166 switch (get_irn_opcode(node)) { /* node label */
168 if ( (get_SymConst_kind(node) == type_tag)
169 || (get_SymConst_kind(node) == size))
170 type_walk_2((type_or_ent *)get_SymConst_type(node), pre, post, envi);
173 type_walk_2((type_or_ent *)get_Sel_entity(node), pre, post, envi);
176 type_walk_2((type_or_ent *)get_Call_type(node), pre, post, envi);
179 type_walk_2((type_or_ent *)get_Alloc_type(node), pre, post, envi);
182 type_walk_2((type_or_ent *)get_Free_type(node), pre, post, envi);
185 type_walk_2((type_or_ent *)get_Cast_type(node), pre, post, envi);
192 void type_walk(type_walk_func *pre,
193 type_walk_func *post,
197 /*type_walk_2((type_or_ent *)get_glob_type(), pre, post, env);
198 global type is on the list visited below, too. */
199 for (i = 0; i < get_irp_n_types(); i++) {
200 type_walk_2((type_or_ent *)get_irp_type(i), pre, post, env);
202 type_walk_2((type_or_ent *)get_glob_type(), pre, post, env);
205 void type_walk_irg (ir_graph *irg,
206 void (*pre)(type_or_ent*, void*),
207 void (*post)(type_or_ent*, void*),
210 ir_graph *rem = current_ir_graph;
211 /* this is needed to pass the parameters to the walker that actually
212 walks the type information */
213 type_walk_env type_env;
216 type_env.post = post;
219 current_ir_graph = irg;
221 /* We walk over the irg to find all irnodes that contain an attribute
222 with type information. If we find one we call a type walker to
223 touch the reachable type information.
224 The same type can be referenced by several irnodes. To avoid
225 repeated visits of the same type node we must decrease the
226 type visited flag for each walk. This is done in start_type_walk().
227 Here we initially increase the flag. We only call type_walk_2 that does
228 not increase the flag.
231 irg_walk(get_irg_end(irg), start_type_walk, NULL, &type_env);
233 type_walk_2((type_or_ent *)get_irg_ent(irg), pre, post, env);
235 type_walk_2((type_or_ent *)get_irg_frame_type(irg), pre, post, env);
237 current_ir_graph = rem;
241 static void type_walk_s2s_2(type_or_ent *tore,
242 void (*pre)(type_or_ent*, void*),
243 void (*post)(type_or_ent*, void*),
249 switch (get_kind(tore)) {
251 if (((entity *)tore)->visit >= type_visited) return;
254 if(type_id == get_type_tpop((type*)tore)) {
255 type_walk_s2s_2((type_or_ent *)skip_tid((type *)tore), pre, post, env);
258 if (((type *)tore)->visit >= type_visited) return;
265 switch (get_kind(tore)) {
268 type *tp = (type *)tore;
269 mark_type_visited(tp);
270 switch (get_type_tpop_code(tp)) {
273 for (i = 0; i < get_class_n_supertypes(tp); i++) {
274 type_walk_s2s_2((type_or_ent *)get_class_supertype(tp, i), pre,
277 /* execute pre method */
280 tp = skip_tid((type*)tore);
282 for (i = 0; i < get_class_n_subtypes(tp); i++) {
283 type_walk_s2s_2((type_or_ent *)get_class_subtype(tp, i), pre,
287 /* execute post method */
296 case tpo_enumeration:
303 printf(" *** Faulty type! \n");
306 } break; /* end case k_type */
311 printf(" *** Faulty type or entity! \n");
317 void type_walk_super2sub(
318 void (*pre)(type_or_ent*, void*),
319 void (*post)(type_or_ent*, void*),
325 type_walk_s2s_2((type_or_ent *)get_glob_type(), pre, post, env);
326 for (i = 0; i < get_irp_n_types(); i++) {
327 tp = get_irp_type(i);
328 type_walk_s2s_2((type_or_ent *)tp, pre, post, env);
332 /*****************************************************************************/
335 type_walk_super_2(type_or_ent *tore,
336 void (*pre)(type_or_ent*, void*),
337 void (*post)(type_or_ent*, void*),
343 switch (get_kind(tore)) {
345 if (((entity *)tore)->visit >= type_visited) return;
348 if(type_id == get_type_tpop((type*)tore)) {
349 type_walk_super_2((type_or_ent *)skip_tid((type *)tore), pre, post, env);
352 if (((type *)tore)->visit >= type_visited) return;
359 switch (get_kind(tore)) {
362 type *tp = (type *)tore;
363 mark_type_visited(tp);
364 switch (get_type_tpop_code(tp)) {
367 /* execute pre method */
370 tp = skip_tid((type*)tore);
372 for (i = 0; i < get_class_n_supertypes(tp); i++) {
373 type_walk_super_2((type_or_ent *)get_class_supertype(tp, i), pre,
377 /* execute post method */
386 case tpo_enumeration:
393 printf(" *** Faulty type! \n");
396 } break; /* end case k_type */
401 printf(" *** Faulty type or entity! \n");
407 void type_walk_super(
408 void (*pre)(type_or_ent*, void*),
409 void (*post)(type_or_ent*, void*),
414 type_walk_super_2((type_or_ent *)get_glob_type(), pre, post, env);
415 for (i = 0; i < get_irp_n_types(); i++) {
416 tp = get_irp_type(i);
417 type_walk_super_2((type_or_ent *)tp, pre, post, env);
421 /*****************************************************************************/
425 class_walk_s2s_2(type *tp,
426 void (*pre)(type*, void*),
427 void (*post)(type*, void*),
433 if (tp->visit >= type_visited) return;
435 assert(is_class_type(tp));
436 /* Assure all supertypes are visited before */
437 for (i=0; i < get_class_n_supertypes(tp); i++) {
438 if (get_type_visited(get_class_supertype(tp, i)) < type_visited)
442 mark_type_visited(tp);
444 /* execute pre method */
448 tp = skip_tid((type*)tp);
449 for (i=0; i<get_class_n_subtypes(tp); i++) {
450 class_walk_s2s_2(get_class_subtype(tp, i), pre, post, env);
452 /* execute post method */
460 void class_walk_super2sub(
461 void (*pre)(type*, void*),
462 void (*post)(type*, void*),
469 for (i = 0; i < get_irp_n_types(); i++) {
470 tp = get_irp_type(i);
471 if (is_class_type(tp) &&
472 (get_class_n_supertypes(tp) == 0) &&
473 (tp->visit < type_visited) &&
474 (!is_frame_type(tp)) &&
475 (tp != get_glob_type())) {
476 class_walk_s2s_2(tp, pre, post, env);
481 void class_walk_super2sub(
482 void (*pre)(type*, void*),
483 void (*post)(type*, void*),
490 for (i = 0; i < get_irp_n_types(); i++) {
491 tp = get_irp_type(i);
492 if (is_class_type(tp) &&
493 (get_class_n_supertypes(tp) == 0) &&
494 (tp->visit < type_visited)) {
495 assert(!is_frame_type(tp));
496 assert(tp != get_glob_type());
497 class_walk_s2s_2(tp, pre, post, env);
503 /* Walks over all entities in the type */
504 void walk_types_entities(
506 void (*doit)(entity*, void*),
510 switch(get_type_tpop_code(tp)) {
512 for (i=0; i<get_class_n_members(tp); i++)
513 doit(get_class_member(tp, i), env);
516 for (i=0; i<get_struct_n_members(tp); i++)
517 doit(get_struct_member(tp, i), env);
520 for (i = 0; i < get_union_n_members(tp); i++)
521 doit(get_union_member(tp, i), env);
524 doit(get_array_element_entity(tp), env);
527 case tpo_enumeration: