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;
104 switch (get_kind(tore)) {
106 ent = (ir_entity *)tore;
107 if (entity_visited(ent)) return;
110 tp = skip_tid((ir_type *)tore);
111 if (type_visited(tp)) return;
117 /* execute pre method */
122 switch (get_kind(tore)) {
124 mark_entity_visited(ent);
125 do_type_walk((type_or_ent *)get_entity_owner(ent), pre, post, env);
126 do_type_walk((type_or_ent *)get_entity_type(ent), 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 do_type_walk((type_or_ent *)get_class_supertype(tp, i), pre, post, env);
153 n_mem = get_class_n_members(tp);
154 for (i = 0; i < n_mem; ++i)
155 do_type_walk((type_or_ent *)get_class_member(tp, i), pre, post, env);
157 n_types = get_class_n_subtypes(tp);
158 for (i = 0; i < n_types; ++i)
159 do_type_walk((type_or_ent *)get_class_subtype(tp, i), pre, post, env);
163 n_mem = get_struct_n_members(tp);
164 for (i = 0; i < n_mem; ++i)
165 do_type_walk((type_or_ent *)get_struct_member(tp, i), pre, post, env);
169 n_mem = get_method_n_params(tp);
170 for (i = 0; i < n_mem; ++i)
171 do_type_walk((type_or_ent *)get_method_param_type(tp, i), pre, post, env);
173 n_mem = get_method_n_ress(tp);
174 for (i = 0; i < n_mem; ++i)
175 do_type_walk((type_or_ent *)get_method_res_type(tp, i), pre, post, env);
179 n_mem = get_union_n_members(tp);
180 for (i = 0; i < n_mem; ++i)
181 do_type_walk((type_or_ent *)get_union_member(tp, i), pre, post, env);
185 do_type_walk((type_or_ent *)get_array_element_type(tp),
187 do_type_walk((type_or_ent *)get_array_element_entity(tp),
191 case tpo_enumeration:
196 do_type_walk((type_or_ent *)get_pointer_points_to_type(tp),
207 assert(0 && "Faulty type");
210 break; /* end case k_type */
213 printf(" *** Faulty type or entity! \n");
217 /* execute post method */
224 /** Check whether node contains types or entities as an attribute.
225 If so start a walk over that information. */
226 static void irn_type_walker(
227 ir_node *node, type_walk_func *pre, type_walk_func *post, void *env)
234 ent = get_irn_entity_attr(node);
236 do_type_walk((type_or_ent *)ent, pre, post, env);
237 tp = get_irn_type_attr(node);
239 do_type_walk((type_or_ent *)tp, pre, post, env);
242 /** Check whether node contains types or entities as an attribute.
243 If so start a walk over that information. */
244 static void start_type_walk(ir_node *node, void *ctx) {
245 type_walk_env *env = ctx;
247 type_walk_func *post;
254 irn_type_walker(node, pre, post, envi);
257 /* walker: walks over all types */
258 void type_walk(type_walk_func *pre, type_walk_func *post, void *env) {
259 int i, n_types = get_irp_n_types();
261 inc_master_type_visited();
262 for (i = 0; i < n_types; ++i) {
263 do_type_walk((type_or_ent *)get_irp_type(i), pre, post, env);
265 do_type_walk((type_or_ent *)get_glob_type(), pre, post, env);
268 void type_walk_irg(ir_graph *irg,
270 type_walk_func *post,
273 ir_graph *rem = current_ir_graph;
274 /* this is needed to pass the parameters to the walker that actually
275 walks the type information */
276 type_walk_env type_env;
279 type_env.post = post;
282 current_ir_graph = irg;
284 /* We walk over the irg to find all irnodes that contain an attribute
285 with type information. If we find one we call a type walker to
286 touch the reachable type information.
287 The same type can be referenced by several irnodes. To avoid
288 repeated visits of the same type node we must decrease the
289 type visited flag for each walk. This is done in start_type_walk().
290 Here we initially increase the flag. We only call do_type_walk that does
291 not increase the flag.
293 inc_master_type_visited();
294 irg_walk(get_irg_end(irg), start_type_walk, NULL, &type_env);
296 do_type_walk((type_or_ent *)get_irg_entity(irg), pre, post, env);
298 do_type_walk((type_or_ent *)get_irg_frame_type(irg), pre, post, env);
300 current_ir_graph = rem;
304 static void type_walk_s2s_2(type_or_ent *tore,
306 type_walk_func *post,
312 switch (get_kind(tore)) {
314 if (entity_visited((ir_entity *)tore)) return;
317 if (type_id == get_type_tpop((ir_type*)tore)) {
318 type_walk_s2s_2((type_or_ent *)skip_tid((ir_type *)tore), pre, post, env);
321 if (type_visited((ir_type *)tore)) return;
328 switch (get_kind(tore)) {
331 ir_type *tp = (ir_type *)tore;
332 mark_type_visited(tp);
333 switch (get_type_tpop_code(tp)) {
336 n = get_class_n_supertypes(tp);
337 for (i = 0; i < n; ++i) {
338 type_walk_s2s_2((type_or_ent *)get_class_supertype(tp, i), pre, post, env);
340 /* execute pre method */
343 tp = skip_tid((ir_type*)tore);
345 n = get_class_n_subtypes(tp);
346 for (i = 0; i < n; ++i) {
347 type_walk_s2s_2((type_or_ent *)get_class_subtype(tp, i), pre, post, env);
350 /* execute post method */
359 case tpo_enumeration:
366 printf(" *** Faulty type! \n");
369 } break; /* end case k_type */
374 printf(" *** Faulty type or entity! \n");
380 void type_walk_super2sub(type_walk_func *pre,
381 type_walk_func *post,
384 int i, n_types = get_irp_n_types();
387 inc_master_type_visited();
388 type_walk_s2s_2((type_or_ent *)get_glob_type(), pre, post, env);
389 for (i = 0; i < n_types; ++i) {
390 tp = get_irp_type(i);
391 type_walk_s2s_2((type_or_ent *)tp, pre, post, env);
395 /*****************************************************************************/
398 type_walk_super_2(type_or_ent *tore,
400 type_walk_func *post,
405 switch (get_kind(tore)) {
407 if (entity_visited((ir_entity *)tore)) return;
410 if (type_id == get_type_tpop((ir_type*)tore)) {
411 type_walk_super_2((type_or_ent *)skip_tid((ir_type *)tore), pre, post, env);
414 if (type_visited((ir_type *)tore)) return;
421 switch (get_kind(tore)) {
424 ir_type *tp = (ir_type *)tore;
425 mark_type_visited(tp);
426 switch (get_type_tpop_code(tp)) {
429 /* execute pre method */
432 tp = skip_tid((ir_type*)tore);
434 n = get_class_n_supertypes(tp);
435 for (i = 0; i < n; ++i) {
436 type_walk_super_2((type_or_ent *)get_class_supertype(tp, i), pre,
440 /* execute post method */
449 case tpo_enumeration:
456 printf(" *** Faulty type! \n");
459 } break; /* end case k_type */
464 printf(" *** Faulty type or entity! \n");
470 void type_walk_super(type_walk_func *pre,
471 type_walk_func *post,
473 int i, n_types = get_irp_n_types();
476 inc_master_type_visited();
477 type_walk_super_2((type_or_ent *)get_glob_type(), pre, post, env);
478 for (i = 0; i < n_types; ++i) {
479 tp = get_irp_type(i);
480 type_walk_super_2((type_or_ent *)tp, pre, post, env);
484 /*****************************************************************************/
488 class_walk_s2s_2(ir_type *tp,
489 class_walk_func *pre,
490 class_walk_func *post,
496 if (type_visited(tp)) return;
498 assert(is_Class_type(tp));
499 /* Assure all supertypes are visited before */
500 n = get_class_n_supertypes(tp);
501 for (i = 0; i < n; ++i) {
502 if (type_not_visited(get_class_supertype(tp, i)))
506 mark_type_visited(tp);
508 /* execute pre method */
513 n = get_class_n_subtypes(tp);
514 for (i = 0; i < n; ++i) {
515 class_walk_s2s_2(get_class_subtype(tp, i), pre, post, env);
517 /* execute post method */
524 void class_walk_super2sub(class_walk_func *pre,
525 class_walk_func *post,
528 int i, n_types = get_irp_n_types();
531 inc_master_type_visited();
532 for (i = 0; i < n_types; i++) {
533 tp = get_irp_type(i);
534 if (is_Class_type(tp) &&
535 (get_class_n_supertypes(tp) == 0) &&
536 type_not_visited(tp)) {
537 assert(! is_frame_type(tp));
538 assert(tp != get_glob_type());
539 class_walk_s2s_2(tp, pre, post, env);
545 /* Walks over all entities in the type */
546 void walk_types_entities(ir_type *tp,
547 entity_walk_func *doit,
552 switch (get_type_tpop_code(tp)) {
554 n = get_class_n_members(tp);
555 for (i = 0; i < n; ++i)
556 doit(get_class_member(tp, i), env);
559 n = get_struct_n_members(tp);
560 for (i = 0; i < n; ++i)
561 doit(get_struct_member(tp, i), env);
564 n = get_union_n_members(tp);
565 for (i = 0; i < n; ++i)
566 doit(get_union_member(tp, i), env);
569 doit(get_array_element_entity(tp), env);
572 case tpo_enumeration: