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
46 #include "irgraph_t.h"
52 * The walker environment
54 typedef struct type_walk_env {
55 type_walk_func *pre; /**< Pre-walker function */
56 type_walk_func *post; /**< Post-walker function */
57 void *env; /**< environment for walker functions */
60 /* a walker for irn's */
61 static void irn_type_walker(
62 ir_node *node, type_walk_func *pre, type_walk_func *post, void *env);
64 static void walk_initializer(ir_initializer_t *initializer,
65 type_walk_func *pre, type_walk_func *post,
68 switch(initializer->kind) {
69 case IR_INITIALIZER_CONST:
70 irn_type_walker(initializer->consti.value, pre, post, env);
72 case IR_INITIALIZER_TARVAL:
73 case IR_INITIALIZER_NULL:
76 case IR_INITIALIZER_COMPOUND: {
78 for(i = 0; i < initializer->compound.n_initializers; ++i) {
79 ir_initializer_t *subinitializer
80 = initializer->compound.initializers[i];
81 walk_initializer(subinitializer, pre, post, env);
86 panic("invalid initializer found");
90 * Main walker: walks over all used types/entities of a
93 static void do_type_walk(type_or_ent tore,
98 int i, n_types, n_mem;
99 ir_entity *ent = NULL;
105 switch (get_kind(tore.ent)) {
108 if (entity_visited(ent))
112 tp = skip_tid(tore.typ);
113 if (type_visited(tp))
120 /* execute pre method */
125 switch (get_kind(tore.ent)) {
127 mark_entity_visited(ent);
128 cont.typ = get_entity_owner(ent);
129 do_type_walk(cont, pre, post, env);
130 cont.typ = get_entity_type(ent);
131 do_type_walk(cont, pre, post, env);
133 if (get_entity_variability(ent) != variability_uninitialized) {
134 /* walk over the value types */
135 if (ent->has_initializer) {
136 walk_initializer(ent->attr.initializer, pre, post, env);
137 } else if (is_atomic_entity(ent)) {
138 n = get_atomic_ent_value(ent);
139 irn_type_walker(n, pre, post, env);
141 n_mem = get_compound_ent_n_values(ent);
142 for (i = 0; i < n_mem; ++i) {
143 n = get_compound_ent_value(ent, i);
144 irn_type_walker(n, pre, post, env);
150 mark_type_visited(tp);
151 switch (get_type_tpop_code(tp)) {
154 n_types = get_class_n_supertypes(tp);
155 for (i = 0; i < n_types; ++i) {
156 cont.typ = get_class_supertype(tp, i);
157 do_type_walk(cont, pre, post, env);
159 n_mem = get_class_n_members(tp);
160 for (i = 0; i < n_mem; ++i) {
161 cont.ent = get_class_member(tp, i);
162 do_type_walk(cont, pre, post, env);
164 n_types = get_class_n_subtypes(tp);
165 for (i = 0; i < n_types; ++i) {
166 cont.typ = get_class_subtype(tp, i);
167 do_type_walk(cont, pre, post, env);
172 n_mem = get_struct_n_members(tp);
173 for (i = 0; i < n_mem; ++i) {
174 cont.ent = get_struct_member(tp, i);
175 do_type_walk(cont, pre, post, env);
180 n_mem = get_method_n_params(tp);
181 for (i = 0; i < n_mem; ++i) {
182 cont.typ = get_method_param_type(tp, i);
183 do_type_walk(cont, pre, post, env);
185 n_mem = get_method_n_ress(tp);
186 for (i = 0; i < n_mem; ++i) {
187 cont.typ = get_method_res_type(tp, i);
188 do_type_walk(cont, pre, post, env);
193 n_mem = get_union_n_members(tp);
194 for (i = 0; i < n_mem; ++i) {
195 cont.ent = get_union_member(tp, i);
196 do_type_walk(cont, pre, post, env);
201 cont.typ = get_array_element_type(tp);
202 do_type_walk(cont, pre, post, env);
203 cont.ent = get_array_element_entity(tp);
204 do_type_walk(cont, pre, post, env);
207 case tpo_enumeration:
212 cont.typ = get_pointer_points_to_type(tp);
213 do_type_walk(cont, pre, post, env);
223 assert(0 && "Faulty type");
226 break; /* end case k_type */
229 printf(" *** Faulty type or entity! \n");
233 /* execute post method */
240 /** Check whether node contains types or entities as an attribute.
241 If so start a walk over that information. */
242 static void irn_type_walker(
243 ir_node *node, type_walk_func *pre, type_walk_func *post, void *env)
249 cont.ent = get_irn_entity_attr(node);
251 do_type_walk(cont, pre, post, env);
252 cont.typ = get_irn_type_attr(node);
254 do_type_walk(cont, pre, post, env);
257 /** Check whether node contains types or entities as an attribute.
258 If so start a walk over that information. */
259 static void start_type_walk(ir_node *node, void *ctx) {
260 type_walk_env *env = ctx;
262 type_walk_func *post;
269 irn_type_walker(node, pre, post, envi);
272 /* walker: walks over all types */
273 void type_walk(type_walk_func *pre, type_walk_func *post, void *env) {
274 int i, n_types = get_irp_n_types();
277 inc_master_type_visited();
278 for (i = 0; i < n_types; ++i) {
279 cont.typ = get_irp_type(i);
280 do_type_walk(cont, pre, post, env);
282 cont.typ = get_glob_type();
283 do_type_walk(cont, pre, post, env);
286 void type_walk_irg(ir_graph *irg,
288 type_walk_func *post,
291 ir_graph *rem = current_ir_graph;
292 /* this is needed to pass the parameters to the walker that actually
293 walks the type information */
294 type_walk_env type_env;
298 type_env.post = post;
301 current_ir_graph = irg;
303 /* We walk over the irg to find all IR-nodes that contain an attribute
304 with type information. If we find one we call a type walker to
305 touch the reachable type information.
306 The same type can be referenced by several IR-nodes. To avoid
307 repeated visits of the same type node we must decrease the
308 type visited flag for each walk. This is done in start_type_walk().
309 Here we initially increase the flag. We only call do_type_walk that does
310 not increase the flag.
312 inc_master_type_visited();
313 irg_walk(get_irg_end(irg), start_type_walk, NULL, &type_env);
315 cont.ent = get_irg_entity(irg);
316 do_type_walk(cont, pre, post, env);
318 cont.typ = get_irg_frame_type(irg);
319 do_type_walk(cont, pre, post, env);
321 current_ir_graph = rem;
325 static void type_walk_s2s_2(type_or_ent tore,
327 type_walk_func *post,
334 switch (get_kind(tore.ent)) {
336 if (entity_visited(tore.ent)) return;
339 if (type_id == get_type_tpop(tore.typ)) {
340 cont.typ = skip_tid(tore.typ);
341 type_walk_s2s_2(cont, pre, post, env);
344 if (type_visited(tore.typ)) return;
351 switch (get_kind(tore.typ)) {
354 ir_type *tp = tore.typ;
355 mark_type_visited(tp);
356 switch (get_type_tpop_code(tp)) {
359 n = get_class_n_supertypes(tp);
360 for (i = 0; i < n; ++i) {
361 cont.typ = get_class_supertype(tp, i);
362 type_walk_s2s_2(cont, pre, post, env);
364 /* execute pre method */
369 n = get_class_n_subtypes(tp);
370 for (i = 0; i < n; ++i) {
371 cont.typ = get_class_subtype(tp, i);
372 type_walk_s2s_2(cont, pre, post, env);
375 /* execute post method */
384 case tpo_enumeration:
391 printf(" *** Faulty type! \n");
394 } break; /* end case k_type */
399 printf(" *** Faulty type or entity! \n");
405 void type_walk_super2sub(type_walk_func *pre,
406 type_walk_func *post,
410 int i, n_types = get_irp_n_types();
412 inc_master_type_visited();
413 cont.typ = get_glob_type();
414 type_walk_s2s_2(cont, pre, post, env);
415 for (i = 0; i < n_types; ++i) {
416 cont.typ = get_irp_type(i);
417 type_walk_s2s_2(cont, pre, post, env);
421 /*****************************************************************************/
424 type_walk_super_2(type_or_ent tore,
426 type_walk_func *post,
432 switch (get_kind(tore.ent)) {
434 if (entity_visited(tore.ent))
438 if (type_id == get_type_tpop(tore.typ)) {
439 cont.typ = skip_tid(tore.typ);
440 type_walk_super_2(cont, pre, post, env);
443 if (type_visited(tore.typ))
451 switch (get_kind(tore.typ)) {
454 ir_type *tp = tore.typ;
455 mark_type_visited(tp);
456 switch (get_type_tpop_code(tp)) {
459 /* execute pre method */
464 n = get_class_n_supertypes(tp);
465 for (i = 0; i < n; ++i) {
466 cont.typ = get_class_supertype(tp, i);
467 type_walk_super_2(cont, pre, post, env);
470 /* execute post method */
479 case tpo_enumeration:
486 printf(" *** Faulty type! \n");
489 } break; /* end case k_type */
494 printf(" *** Faulty type or entity! \n");
500 void type_walk_super(type_walk_func *pre,
501 type_walk_func *post,
503 int i, n_types = get_irp_n_types();
506 inc_master_type_visited();
507 cont.typ = get_glob_type();
508 type_walk_super_2(cont, pre, post, env);
509 for (i = 0; i < n_types; ++i) {
510 cont.typ = get_irp_type(i);
511 type_walk_super_2(cont, pre, post, env);
515 /*****************************************************************************/
519 class_walk_s2s_2(ir_type *tp,
520 class_walk_func *pre,
521 class_walk_func *post,
527 if (type_visited(tp)) return;
529 assert(is_Class_type(tp));
530 /* Assure all supertypes are visited before */
531 n = get_class_n_supertypes(tp);
532 for (i = 0; i < n; ++i) {
533 if (type_not_visited(get_class_supertype(tp, i)))
537 mark_type_visited(tp);
539 /* execute pre method */
544 n = get_class_n_subtypes(tp);
545 for (i = 0; i < n; ++i) {
546 class_walk_s2s_2(get_class_subtype(tp, i), pre, post, env);
548 /* execute post method */
555 void class_walk_super2sub(class_walk_func *pre,
556 class_walk_func *post,
559 int i, n_types = get_irp_n_types();
562 inc_master_type_visited();
563 for (i = 0; i < n_types; i++) {
564 tp = get_irp_type(i);
565 if (is_Class_type(tp) &&
566 (get_class_n_supertypes(tp) == 0) &&
567 type_not_visited(tp)) {
568 assert(! is_frame_type(tp));
569 assert(tp != get_glob_type());
570 class_walk_s2s_2(tp, pre, post, env);
576 /* Walks over all entities in the type */
577 void walk_types_entities(ir_type *tp,
578 entity_walk_func *doit,
583 switch (get_type_tpop_code(tp)) {
585 n = get_class_n_members(tp);
586 for (i = 0; i < n; ++i)
587 doit(get_class_member(tp, i), env);
590 n = get_struct_n_members(tp);
591 for (i = 0; i < n; ++i)
592 doit(get_struct_member(tp, i), env);
595 n = get_union_n_members(tp);
596 for (i = 0; i < n; ++i)
597 doit(get_union_member(tp, i), env);
600 doit(get_array_element_entity(tp), env);
603 case tpo_enumeration: