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))
107 tp = skip_tid(tore.typ);
108 if (type_visited(tp))
115 /* execute pre method */
120 switch (get_kind(tore.ent)) {
122 mark_entity_visited(ent);
123 cont.typ = get_entity_owner(ent);
124 do_type_walk(cont, pre, post, env);
125 cont.typ = get_entity_type(ent);
126 do_type_walk(cont, pre, post, env);
128 if (get_entity_variability(ent) != variability_uninitialized) {
129 /* walk over the value types */
130 if (ent->has_initializer) {
131 walk_initializer(ent->attr.initializer, pre, post, env);
132 } else if (is_atomic_entity(ent)) {
133 n = get_atomic_ent_value(ent);
134 irn_type_walker(n, pre, post, env);
136 n_mem = get_compound_ent_n_values(ent);
137 for (i = 0; i < n_mem; ++i) {
138 n = get_compound_ent_value(ent, i);
139 irn_type_walker(n, pre, post, env);
145 mark_type_visited(tp);
146 switch (get_type_tpop_code(tp)) {
149 n_types = get_class_n_supertypes(tp);
150 for (i = 0; i < n_types; ++i) {
151 cont.typ = get_class_supertype(tp, i);
152 do_type_walk(cont, pre, post, env);
154 n_mem = get_class_n_members(tp);
155 for (i = 0; i < n_mem; ++i) {
156 cont.ent = get_class_member(tp, i);
157 do_type_walk(cont, pre, post, env);
159 n_types = get_class_n_subtypes(tp);
160 for (i = 0; i < n_types; ++i) {
161 cont.typ = get_class_subtype(tp, i);
162 do_type_walk(cont, pre, post, env);
167 n_mem = get_struct_n_members(tp);
168 for (i = 0; i < n_mem; ++i) {
169 cont.ent = get_struct_member(tp, i);
170 do_type_walk(cont, pre, post, env);
175 n_mem = get_method_n_params(tp);
176 for (i = 0; i < n_mem; ++i) {
177 cont.typ = get_method_param_type(tp, i);
178 do_type_walk(cont, pre, post, env);
180 n_mem = get_method_n_ress(tp);
181 for (i = 0; i < n_mem; ++i) {
182 cont.typ = get_method_res_type(tp, i);
183 do_type_walk(cont, pre, post, env);
188 n_mem = get_union_n_members(tp);
189 for (i = 0; i < n_mem; ++i) {
190 cont.ent = get_union_member(tp, i);
191 do_type_walk(cont, pre, post, env);
196 cont.typ = get_array_element_type(tp);
197 do_type_walk(cont, pre, post, env);
198 cont.ent = get_array_element_entity(tp);
199 do_type_walk(cont, pre, post, env);
202 case tpo_enumeration:
207 cont.typ = get_pointer_points_to_type(tp);
208 do_type_walk(cont, pre, post, env);
218 assert(0 && "Faulty type");
221 break; /* end case k_type */
224 printf(" *** Faulty type or entity! \n");
228 /* execute post method */
233 /** Check whether node contains types or entities as an attribute.
234 If so start a walk over that information. */
235 static void irn_type_walker(
236 ir_node *node, type_walk_func *pre, type_walk_func *post, void *env)
242 cont.ent = get_irn_entity_attr(node);
244 do_type_walk(cont, pre, post, env);
245 cont.typ = get_irn_type_attr(node);
247 do_type_walk(cont, pre, post, env);
250 /** Check whether node contains types or entities as an attribute.
251 If so start a walk over that information. */
252 static void start_type_walk(ir_node *node, void *ctx) {
253 type_walk_env *env = ctx;
255 type_walk_func *post;
262 irn_type_walker(node, pre, post, envi);
265 /* walker: walks over all types */
266 void type_walk(type_walk_func *pre, type_walk_func *post, void *env) {
267 int i, n_types = get_irp_n_types();
270 inc_master_type_visited();
271 for (i = 0; i < n_types; ++i) {
272 cont.typ = get_irp_type(i);
273 do_type_walk(cont, pre, post, env);
275 cont.typ = get_glob_type();
276 do_type_walk(cont, pre, post, env);
279 void type_walk_prog(type_walk_func *pre, type_walk_func *post, void *env) {
280 int i, n_irgs = get_irp_n_irgs();
283 type_walk(pre, post, env);
285 for (i = 0; i < n_irgs; ++i) {
286 ir_graph *irg = get_irp_irg(i);
287 cont.typ = get_irg_frame_type(irg);
288 do_type_walk(cont, pre, post, env);
290 cont.typ = get_method_value_param_type(get_entity_type(get_irg_entity(irg)));
292 do_type_walk(cont, pre, post, env);
295 for (i = 0; i < IR_SEGMENT_COUNT; ++i) {
296 cont.typ = get_segment_type((ir_segment_t) i);
298 do_type_walk(cont, pre, post, env);
302 void type_walk_irg(ir_graph *irg,
304 type_walk_func *post,
307 ir_graph *rem = current_ir_graph;
308 /* this is needed to pass the parameters to the walker that actually
309 walks the type information */
310 type_walk_env type_env;
314 type_env.post = post;
317 current_ir_graph = irg;
319 /* We walk over the irg to find all IR-nodes that contain an attribute
320 with type information. If we find one we call a type walker to
321 touch the reachable type information.
322 The same type can be referenced by several IR-nodes. To avoid
323 repeated visits of the same type node we must decrease the
324 type visited flag for each walk. This is done in start_type_walk().
325 Here we initially increase the flag. We only call do_type_walk that does
326 not increase the flag.
328 inc_master_type_visited();
329 irg_walk(get_irg_end(irg), start_type_walk, NULL, &type_env);
331 cont.ent = get_irg_entity(irg);
332 do_type_walk(cont, pre, post, env);
334 cont.typ = get_irg_frame_type(irg);
335 do_type_walk(cont, pre, post, env);
337 current_ir_graph = rem;
340 static void type_walk_s2s_2(type_or_ent tore,
342 type_walk_func *post,
349 switch (get_kind(tore.ent)) {
351 if (entity_visited(tore.ent)) return;
354 if (type_id == get_type_tpop(tore.typ)) {
355 cont.typ = skip_tid(tore.typ);
356 type_walk_s2s_2(cont, pre, post, env);
359 if (type_visited(tore.typ)) return;
366 switch (get_kind(tore.typ)) {
369 ir_type *tp = tore.typ;
370 mark_type_visited(tp);
371 switch (get_type_tpop_code(tp)) {
374 n = get_class_n_supertypes(tp);
375 for (i = 0; i < n; ++i) {
376 cont.typ = get_class_supertype(tp, i);
377 type_walk_s2s_2(cont, pre, post, env);
379 /* execute pre method */
384 n = get_class_n_subtypes(tp);
385 for (i = 0; i < n; ++i) {
386 cont.typ = get_class_subtype(tp, i);
387 type_walk_s2s_2(cont, pre, post, env);
390 /* execute post method */
399 case tpo_enumeration:
406 printf(" *** Faulty type! \n");
409 } break; /* end case k_type */
414 printf(" *** Faulty type or entity! \n");
419 void type_walk_super2sub(type_walk_func *pre,
420 type_walk_func *post,
424 int i, n_types = get_irp_n_types();
426 inc_master_type_visited();
427 cont.typ = get_glob_type();
428 type_walk_s2s_2(cont, pre, post, env);
429 for (i = 0; i < n_types; ++i) {
430 cont.typ = get_irp_type(i);
431 type_walk_s2s_2(cont, pre, post, env);
435 /*****************************************************************************/
438 type_walk_super_2(type_or_ent tore,
440 type_walk_func *post,
446 switch (get_kind(tore.ent)) {
448 if (entity_visited(tore.ent))
452 if (type_id == get_type_tpop(tore.typ)) {
453 cont.typ = skip_tid(tore.typ);
454 type_walk_super_2(cont, pre, post, env);
457 if (type_visited(tore.typ))
465 switch (get_kind(tore.typ)) {
468 ir_type *tp = tore.typ;
469 mark_type_visited(tp);
470 switch (get_type_tpop_code(tp)) {
473 /* execute pre method */
478 n = get_class_n_supertypes(tp);
479 for (i = 0; i < n; ++i) {
480 cont.typ = get_class_supertype(tp, i);
481 type_walk_super_2(cont, pre, post, env);
484 /* execute post method */
493 case tpo_enumeration:
500 printf(" *** Faulty type! \n");
503 } break; /* end case k_type */
508 printf(" *** Faulty type or entity! \n");
513 void type_walk_super(type_walk_func *pre,
514 type_walk_func *post,
516 int i, n_types = get_irp_n_types();
519 inc_master_type_visited();
520 cont.typ = get_glob_type();
521 type_walk_super_2(cont, pre, post, env);
522 for (i = 0; i < n_types; ++i) {
523 cont.typ = get_irp_type(i);
524 type_walk_super_2(cont, pre, post, env);
528 /*****************************************************************************/
532 class_walk_s2s_2(ir_type *tp,
533 class_walk_func *pre,
534 class_walk_func *post,
540 if (type_visited(tp)) return;
542 assert(is_Class_type(tp));
543 /* Assure all supertypes are visited before */
544 n = get_class_n_supertypes(tp);
545 for (i = 0; i < n; ++i) {
546 if (type_not_visited(get_class_supertype(tp, i)))
550 mark_type_visited(tp);
552 /* execute pre method */
557 n = get_class_n_subtypes(tp);
558 for (i = 0; i < n; ++i) {
559 class_walk_s2s_2(get_class_subtype(tp, i), pre, post, env);
561 /* execute post method */
566 void class_walk_super2sub(class_walk_func *pre,
567 class_walk_func *post,
570 int i, n_types = get_irp_n_types();
573 inc_master_type_visited();
574 for (i = 0; i < n_types; i++) {
575 tp = get_irp_type(i);
576 if (is_Class_type(tp) &&
577 (get_class_n_supertypes(tp) == 0) &&
578 type_not_visited(tp)) {
579 assert(! is_frame_type(tp));
580 assert(tp != get_glob_type());
581 class_walk_s2s_2(tp, pre, post, env);
587 /* Walks over all entities in the type */
588 void walk_types_entities(ir_type *tp,
589 entity_walk_func *doit,
594 switch (get_type_tpop_code(tp)) {
596 n = get_class_n_members(tp);
597 for (i = 0; i < n; ++i)
598 doit(get_class_member(tp, i), env);
601 n = get_struct_n_members(tp);
602 for (i = 0; i < n; ++i)
603 doit(get_struct_member(tp, i), env);
606 n = get_union_n_members(tp);
607 for (i = 0; i < n; ++i)
608 doit(get_union_member(tp, i), env);
611 doit(get_array_element_entity(tp), env);
614 case tpo_enumeration: