Changed implementation of tr module.
[libfirm] / ir / tr / typewalk.c
1 /* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
2 ** All rights reserved.
3 **
4 ** Author: Goetz Lindenmaier
5 **
6 ** traverse the type information.  The walker walks the whole ir graph
7 ** to find the distinct type trees in the type graph forest.
8 ** - execute the pre function before recursion
9 ** - execute the post function after recursion
10 */
11
12 #ifdef HAVE_CONFIG_H
13 # include <config.h>
14 #endif
15
16 #include <stdlib.h>
17 #include <stdio.h>
18 #include "irgwalk.h"
19 #include "irgraph.h"
20 #include "irnode.h"
21 #include "irprog.h"
22 #include "type_or_entity.h"
23
24 /* Make types visible to allow most efficient access */
25 # include "entity_t.h"
26 #include "type_t.h"
27
28 typedef struct type_walk_env {
29   void *pre;
30   void *post;
31   void *env;
32 } type_walk_env;
33
34
35 void type_walk_2(type_or_ent *tore,
36                void (pre)(type_or_ent*, void*),
37                void (post)(type_or_ent*, void*),
38                void *env)
39 {
40   int i;
41
42   /* marked? */
43   switch (get_kind(tore)) {
44   case k_entity:
45     if (((entity *)tore)->visit >= type_visited) return; break;
46   case k_type:
47     if (((type *)tore)->visit >= type_visited) return; break;
48   default:
49     break;
50   }
51
52   /* execute pre method */
53   if(pre)
54     pre(tore, env);
55
56   /* iterate */
57   switch (get_kind(tore)) {
58   case k_entity:
59     {
60
61       entity *ent = (entity *)tore;
62       ent->visit = type_visited;
63       type_walk_2((type_or_ent *)get_entity_owner(ent), pre, post, env);
64       type_walk_2((type_or_ent *)get_entity_type(ent), pre, post, env);
65     }
66     break;
67   case k_type:
68     {
69       type *tp = (type *)tore;
70       mark_type_visited(tp);
71       switch (get_type_tpop_code(tp))
72         case tpo_class:
73           {
74             for (i=0; i<get_class_n_member(tp); i++)
75               type_walk_2((type_or_ent *)get_class_member(tp, i), pre, post, env);
76             for (i=0; i<get_class_n_subtype(tp); i++)
77               type_walk_2((type_or_ent *)get_class_subtype(tp, i), pre, post, env);
78             for (i=0; i<get_class_n_supertype(tp); i++)   {
79               type_walk_2((type_or_ent *)get_class_supertype(tp, i), pre, post, env);
80             }
81             break;
82           case tpo_struct:
83             {
84               for (i=0; i<get_struct_n_member(tp); i++)
85                 type_walk_2((type_or_ent *)get_struct_member(tp, i), pre, post, env);
86             }
87             break;
88           case tpo_method:
89             {
90               for (i = 0; i < get_method_n_params(tp); i++)
91                 type_walk_2((type_or_ent *)get_method_param_type(tp, i), pre, post, env);
92               for (i = 0; i < get_method_n_res(tp); i++)
93                 type_walk_2((type_or_ent *)get_method_res_type(tp, i), pre, post, env);
94             }
95             break;
96           case tpo_union:
97             {
98               for (i = 0; i < get_union_n_types(tp); i++)
99                 type_walk_2((type_or_ent *)get_union_unioned_type(tp, i), pre, post, env);
100             }
101             break;
102           case tpo_array:
103             type_walk_2((type_or_ent *)get_array_element_type(tp),
104                         pre, post, env);
105             break;
106           case tpo_enumeration:
107             /* a leave */
108             break;
109           case tpo_pointer:
110             type_walk_2((type_or_ent *)get_pointer_points_to_type(tp),
111                         pre, post, env);
112             break;
113           case tpo_primitive:
114             /* a leave. */
115             break;
116           default:
117             printf(" *** Faulty type! \n");
118             break;
119           }
120     } break; /* end case k_type */
121   default:
122     printf(" *** Faulty type or entity! \n");
123     break;
124   }
125
126   /* execute post method */
127   if(post)
128     post(tore, env);
129
130   return;
131 }
132
133 void start_type_walk(ir_node *node, void *env) {
134   void *pre  = ((type_walk_env *)env)->pre;
135   void *post = ((type_walk_env *)env)->post;
136   void *envi = ((type_walk_env *)env)->env;
137
138   assert(node);
139
140   switch (get_irn_opcode(node)) {  /* node label */
141   case iro_SymConst:
142     if (   (get_SymConst_kind(node) == type_tag)
143            || (get_SymConst_kind(node) == size))
144       type_walk_2((type_or_ent *)get_SymConst_type(node), pre, post, envi);
145     break;
146   case iro_Sel:
147     type_walk_2((type_or_ent *)get_Sel_entity(node), pre, post, envi);
148     break;
149   case iro_Call:
150     type_walk_2((type_or_ent *)get_Call_type(node), pre, post, envi);
151     break;
152   case iro_Alloc:
153     type_walk_2((type_or_ent *)get_Alloc_type(node), pre, post, envi);
154     break;
155   case iro_Free:
156     printf("here in typewalk\n");
157     type_walk_2((type_or_ent *)get_Free_type(node), pre, post, envi);
158     break;
159   default:
160     break;
161   }
162 }
163
164 void type_walk(void (pre)(type_or_ent*, void*),
165                void (post)(type_or_ent*, void*),
166                void *env) {
167   int i;
168   ++type_visited;
169   type_walk_2((type_or_ent *)get_glob_type(), pre, post, env);
170   for (i = 0; i < get_irp_n_types(); i++) {
171     type_walk_2((type_or_ent *)get_irp_type(i), pre, post, env);
172   }
173 }
174
175 void type_walk_irg (ir_graph *irg,
176                     void (pre)(type_or_ent*, void*),
177                     void (post)(type_or_ent*, void*),
178                     void *env)
179 {
180   /* this is needed to pass the parameters to the walker that actually
181      walks the type information */
182   type_walk_env* type_env;
183   type_env = (type_walk_env *) malloc (sizeof(type_walk_env));
184   type_env->pre = pre;
185   type_env->post = post;
186   type_env->env = env;
187
188   ++type_visited;
189   irg_walk(get_irg_end(irg), start_type_walk, NULL, type_env);
190
191   type_walk_2((type_or_ent *)get_irg_ent(irg), pre, post, env);
192
193   free(type_env);
194   return;
195 }