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
41 #include "irgraph_t.h"
47 * The walker environment
49 typedef struct type_walk_env {
50 type_walk_func *pre; /**< Pre-walker function */
51 type_walk_func *post; /**< Post-walker function */
52 void *env; /**< environment for walker functions */
55 /* a walker for irn's */
56 static void irn_type_walker(
57 ir_node *node, type_walk_func *pre, type_walk_func *post, void *env);
59 static void walk_initializer(ir_initializer_t *initializer,
60 type_walk_func *pre, type_walk_func *post,
63 switch(initializer->kind) {
64 case IR_INITIALIZER_CONST:
65 irn_type_walker(initializer->consti.value, pre, post, env);
67 case IR_INITIALIZER_TARVAL:
68 case IR_INITIALIZER_NULL:
71 case IR_INITIALIZER_COMPOUND: {
73 for(i = 0; i < initializer->compound.n_initializers; ++i) {
74 ir_initializer_t *subinitializer
75 = initializer->compound.initializers[i];
76 walk_initializer(subinitializer, pre, post, env);
81 panic("invalid initializer found");
85 * Main walker: walks over all used types/entities of a
88 static void do_type_walk(type_or_ent tore,
93 int i, n_types, n_mem;
94 ir_entity *ent = NULL;
100 switch (get_kind(tore.ent)) {
103 if (entity_visited(ent))
105 mark_entity_visited(ent);
109 if (type_visited(tp))
111 mark_type_visited(tp);
117 /* execute pre method */
122 switch (get_kind(tore.ent)) {
124 cont.typ = get_entity_owner(ent);
125 do_type_walk(cont, pre, post, env);
126 cont.typ = get_entity_type(ent);
127 do_type_walk(cont, pre, post, env);
129 /* walk over the value types */
130 if (ent->initializer != NULL) {
131 walk_initializer(ent->initializer, pre, post, env);
132 } else if (entity_has_compound_ent_values(ent)) {
133 n_mem = get_compound_ent_n_values(ent);
134 for (i = 0; i < n_mem; ++i) {
135 n = get_compound_ent_value(ent, i);
136 irn_type_walker(n, pre, post, env);
141 switch (get_type_tpop_code(tp)) {
143 n_types = get_class_n_supertypes(tp);
144 for (i = 0; i < n_types; ++i) {
145 cont.typ = get_class_supertype(tp, i);
146 do_type_walk(cont, pre, post, env);
148 n_mem = get_class_n_members(tp);
149 for (i = 0; i < n_mem; ++i) {
150 cont.ent = get_class_member(tp, i);
151 do_type_walk(cont, pre, post, env);
153 n_types = get_class_n_subtypes(tp);
154 for (i = 0; i < n_types; ++i) {
155 cont.typ = get_class_subtype(tp, i);
156 do_type_walk(cont, pre, post, env);
161 n_mem = get_struct_n_members(tp);
162 for (i = 0; i < n_mem; ++i) {
163 cont.ent = get_struct_member(tp, i);
164 do_type_walk(cont, pre, post, env);
169 n_mem = get_method_n_params(tp);
170 for (i = 0; i < n_mem; ++i) {
171 cont.typ = get_method_param_type(tp, i);
172 do_type_walk(cont, pre, post, env);
174 n_mem = get_method_n_ress(tp);
175 for (i = 0; i < n_mem; ++i) {
176 cont.typ = get_method_res_type(tp, i);
177 do_type_walk(cont, pre, post, env);
182 n_mem = get_union_n_members(tp);
183 for (i = 0; i < n_mem; ++i) {
184 cont.ent = get_union_member(tp, i);
185 do_type_walk(cont, pre, post, env);
190 cont.typ = get_array_element_type(tp);
191 do_type_walk(cont, pre, post, env);
192 cont.ent = get_array_element_entity(tp);
193 do_type_walk(cont, pre, post, env);
196 case tpo_enumeration:
201 cont.typ = get_pointer_points_to_type(tp);
202 do_type_walk(cont, pre, post, env);
211 case tpo_uninitialized:
212 assert(0 && "Faulty type");
215 break; /* end case k_type */
218 printf(" *** Faulty type or entity! \n");
222 /* execute post method */
227 /** Check whether node contains types or entities as an attribute.
228 If so start a walk over that information. */
229 static void irn_type_walker(
230 ir_node *node, type_walk_func *pre, type_walk_func *post, void *env)
236 cont.ent = get_irn_entity_attr(node);
238 do_type_walk(cont, pre, post, env);
239 cont.typ = get_irn_type_attr(node);
241 do_type_walk(cont, pre, post, env);
244 /** Check whether node contains types or entities as an attribute.
245 If so start a walk over that information. */
246 static void start_type_walk(ir_node *node, void *ctx) {
247 type_walk_env *env = ctx;
249 type_walk_func *post;
256 irn_type_walker(node, pre, post, envi);
259 /* walker: walks over all types */
260 void type_walk(type_walk_func *pre, type_walk_func *post, void *env) {
261 int i, n_types = get_irp_n_types();
264 irp_reserve_resources(irp, IR_RESOURCE_TYPE_VISITED);
265 inc_master_type_visited();
266 for (i = 0; i < n_types; ++i) {
267 cont.typ = get_irp_type(i);
268 do_type_walk(cont, pre, post, env);
270 cont.typ = get_glob_type();
271 do_type_walk(cont, pre, post, env);
272 irp_free_resources(irp, IR_RESOURCE_TYPE_VISITED);
275 void type_walk_prog(type_walk_func *pre, type_walk_func *post, void *env) {
276 int i, n_irgs = get_irp_n_irgs();
279 type_walk(pre, post, env);
281 for (i = 0; i < n_irgs; ++i) {
282 ir_graph *irg = get_irp_irg(i);
283 cont.typ = get_irg_frame_type(irg);
284 do_type_walk(cont, pre, post, env);
286 cont.typ = get_method_value_param_type(get_entity_type(get_irg_entity(irg)));
288 do_type_walk(cont, pre, post, env);
291 for (i = IR_SEGMENT_FIRST; i <= IR_SEGMENT_LAST; ++i) {
292 cont.typ = get_segment_type((ir_segment_t) i);
294 do_type_walk(cont, pre, post, env);
298 void type_walk_irg(ir_graph *irg,
300 type_walk_func *post,
303 ir_graph *rem = current_ir_graph;
304 /* this is needed to pass the parameters to the walker that actually
305 walks the type information */
306 type_walk_env type_env;
310 type_env.post = post;
313 current_ir_graph = irg;
315 /* We walk over the irg to find all IR-nodes that contain an attribute
316 with type information. If we find one we call a type walker to
317 touch the reachable type information.
318 The same type can be referenced by several IR-nodes. To avoid
319 repeated visits of the same type node we must decrease the
320 type visited flag for each walk. This is done in start_type_walk().
321 Here we initially increase the flag. We only call do_type_walk that does
322 not increase the flag.
324 irp_reserve_resources(irp, IR_RESOURCE_TYPE_VISITED);
325 inc_master_type_visited();
326 irg_walk(get_irg_end(irg), start_type_walk, NULL, &type_env);
328 cont.ent = get_irg_entity(irg);
329 do_type_walk(cont, pre, post, env);
331 cont.typ = get_irg_frame_type(irg);
332 do_type_walk(cont, pre, post, env);
334 current_ir_graph = rem;
335 irp_free_resources(irp, IR_RESOURCE_TYPE_VISITED);
338 static void type_walk_s2s_2(type_or_ent tore,
340 type_walk_func *post,
347 switch (get_kind(tore.ent)) {
349 if (entity_visited(tore.ent)) return;
352 if (type_visited(tore.typ)) return;
359 switch (get_kind(tore.typ)) {
362 ir_type *tp = tore.typ;
363 mark_type_visited(tp);
364 switch (get_type_tpop_code(tp)) {
367 n = get_class_n_supertypes(tp);
368 for (i = 0; i < n; ++i) {
369 cont.typ = get_class_supertype(tp, i);
370 type_walk_s2s_2(cont, pre, post, env);
372 /* execute pre method */
376 n = get_class_n_subtypes(tp);
377 for (i = 0; i < n; ++i) {
378 cont.typ = get_class_subtype(tp, i);
379 type_walk_s2s_2(cont, pre, post, env);
382 /* execute post method */
391 case tpo_enumeration:
397 printf(" *** Faulty type! \n");
400 } break; /* end case k_type */
405 printf(" *** Faulty type or entity! \n");
410 void type_walk_super2sub(type_walk_func *pre,
411 type_walk_func *post,
415 int i, n_types = get_irp_n_types();
417 irp_reserve_resources(irp, IR_RESOURCE_TYPE_VISITED);
418 inc_master_type_visited();
419 cont.typ = get_glob_type();
420 type_walk_s2s_2(cont, pre, post, env);
421 for (i = 0; i < n_types; ++i) {
422 cont.typ = get_irp_type(i);
423 type_walk_s2s_2(cont, pre, post, env);
425 irp_free_resources(irp, IR_RESOURCE_TYPE_VISITED);
428 /*****************************************************************************/
431 type_walk_super_2(type_or_ent tore,
433 type_walk_func *post,
439 switch (get_kind(tore.ent)) {
441 if (entity_visited(tore.ent))
445 if (type_visited(tore.typ))
453 switch (get_kind(tore.typ)) {
456 ir_type *tp = tore.typ;
457 mark_type_visited(tp);
458 switch (get_type_tpop_code(tp)) {
461 /* execute pre method */
465 n = get_class_n_supertypes(tp);
466 for (i = 0; i < n; ++i) {
467 cont.typ = get_class_supertype(tp, i);
468 type_walk_super_2(cont, pre, post, env);
471 /* execute post method */
480 case tpo_enumeration:
486 printf(" *** Faulty type! \n");
489 } break; /* end case k_type */
494 printf(" *** Faulty type or entity! \n");
499 void type_walk_super(type_walk_func *pre,
500 type_walk_func *post,
502 int i, n_types = get_irp_n_types();
505 irp_reserve_resources(irp, IR_RESOURCE_TYPE_VISITED);
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);
513 irp_free_resources(irp, IR_RESOURCE_TYPE_VISITED);
516 /*****************************************************************************/
520 class_walk_s2s_2(ir_type *tp,
521 class_walk_func *pre,
522 class_walk_func *post,
528 if (type_visited(tp)) return;
530 assert(is_Class_type(tp));
531 /* Assure all supertypes are visited before */
532 n = get_class_n_supertypes(tp);
533 for (i = 0; i < n; ++i) {
534 if (type_not_visited(get_class_supertype(tp, i)))
538 mark_type_visited(tp);
540 /* 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 */
553 void class_walk_super2sub(class_walk_func *pre,
554 class_walk_func *post,
557 int i, n_types = get_irp_n_types();
560 irp_reserve_resources(irp, IR_RESOURCE_TYPE_VISITED);
561 inc_master_type_visited();
562 for (i = 0; i < n_types; i++) {
563 tp = get_irp_type(i);
564 if (is_Class_type(tp) &&
565 (get_class_n_supertypes(tp) == 0) &&
566 type_not_visited(tp)) {
567 assert(! is_frame_type(tp));
568 assert(tp != get_glob_type());
569 class_walk_s2s_2(tp, pre, post, env);
572 irp_free_resources(irp, IR_RESOURCE_TYPE_VISITED);
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: