comments added
[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;
46     break;
47   case k_type:
48     if(type_id == get_type_tpop((type*)tore)) {
49       type_walk_2((type_or_ent *)skip_tid((type *)tore), pre, post, env);
50       return;
51     }
52     if (((type *)tore)->visit >= type_visited) return;
53     break;
54   default:
55     break;
56   }
57
58   /* execute pre method */
59   if(pre)
60     pre(tore, env);
61
62   /* iterate */
63   switch (get_kind(tore)) {
64   case k_entity:
65     {
66
67       entity *ent = (entity *)tore;
68       ent->visit = type_visited;
69       type_walk_2((type_or_ent *)get_entity_owner(ent), pre, post, env);
70       type_walk_2((type_or_ent *)get_entity_type(ent), pre, post, env);
71     }
72     break;
73   case k_type:
74     {
75       type *tp = (type *)tore;
76       mark_type_visited(tp);
77       switch (get_type_tpop_code(tp)) {
78       case tpo_class:
79         {
80           for (i=0; i<get_class_n_supertype(tp); i++)
81             type_walk_2((type_or_ent *)get_class_supertype(tp, i), pre, post, env);
82           for (i=0; i<get_class_n_member(tp); i++)
83             type_walk_2((type_or_ent *)get_class_member(tp, i), pre, post, env);
84           for (i=0; i<get_class_n_subtype(tp); i++)
85             type_walk_2((type_or_ent *)get_class_subtype(tp, i), pre, post, env);
86         }
87         break;
88       case tpo_struct:
89         {
90           for (i=0; i<get_struct_n_member(tp); i++)
91             type_walk_2((type_or_ent *)get_struct_member(tp, i), pre, post, env);
92         }
93         break;
94       case tpo_method:
95         {
96           for (i = 0; i < get_method_n_params(tp); i++)
97             type_walk_2((type_or_ent *)get_method_param_type(tp, i), pre, post, env);
98           for (i = 0; i < get_method_n_res(tp); i++)
99             type_walk_2((type_or_ent *)get_method_res_type(tp, i), pre, post, env);
100         }
101         break;
102       case tpo_union:
103         {
104           for (i = 0; i < get_union_n_members(tp); i++)
105             type_walk_2((type_or_ent *)get_union_member(tp, i), pre, post, env);
106         }
107         break;
108       case tpo_array:
109         type_walk_2((type_or_ent *)get_array_element_type(tp),
110                     pre, post, env);
111         break;
112       case tpo_enumeration:
113         /* a leave */
114         break;
115       case tpo_pointer:
116         type_walk_2((type_or_ent *)get_pointer_points_to_type(tp),
117                     pre, post, env);
118         break;
119       case tpo_primitive:
120       case tpo_id:
121         /* a leave. */
122         break;
123       default:
124         printf(" *** Faulty type! \n");
125         break;
126       }
127     } break; /* end case k_type */
128   default:
129     printf(" *** Faulty type or entity! \n");
130     break;
131   }
132
133   /* execute post method */
134   if(post)
135     post(tore, env);
136
137   return;
138 }
139
140 void start_type_walk(ir_node *node, void *env) {
141   void *pre  = ((type_walk_env *)env)->pre;
142   void *post = ((type_walk_env *)env)->post;
143   void *envi = ((type_walk_env *)env)->env;
144
145   assert(node);
146
147   switch (get_irn_opcode(node)) {  /* node label */
148   case iro_SymConst:
149     if (   (get_SymConst_kind(node) == type_tag)
150            || (get_SymConst_kind(node) == size))
151       type_walk_2((type_or_ent *)get_SymConst_type(node), pre, post, envi);
152     break;
153   case iro_Sel:
154     type_walk_2((type_or_ent *)get_Sel_entity(node), pre, post, envi);
155     break;
156   case iro_Call:
157     type_walk_2((type_or_ent *)get_Call_type(node), pre, post, envi);
158     break;
159   case iro_Alloc:
160     type_walk_2((type_or_ent *)get_Alloc_type(node), pre, post, envi);
161     break;
162   case iro_Free:
163     printf("here in typewalk\n");
164     type_walk_2((type_or_ent *)get_Free_type(node), pre, post, envi);
165     break;
166   default:
167     break;
168   }
169 }
170
171 void type_walk(void (pre)(type_or_ent*, void*),
172                void (post)(type_or_ent*, void*),
173                void *env) {
174   int i;
175   ++type_visited;
176   type_walk_2((type_or_ent *)get_glob_type(), pre, post, env);
177   for (i = 0; i < get_irp_n_types(); i++) {
178     type_walk_2((type_or_ent *)get_irp_type(i), pre, post, env);
179   }
180 }
181
182 void type_walk_irg (ir_graph *irg,
183                     void (pre)(type_or_ent*, void*),
184                     void (post)(type_or_ent*, void*),
185                     void *env)
186 {
187   /* this is needed to pass the parameters to the walker that actually
188      walks the type information */
189   type_walk_env* type_env;
190   type_env = (type_walk_env *) malloc (sizeof(type_walk_env));
191   type_env->pre = pre;
192   type_env->post = post;
193   type_env->env = env;
194
195   ++type_visited;
196   irg_walk(get_irg_end(irg), start_type_walk, NULL, type_env);
197
198   type_walk_2((type_or_ent *)get_irg_ent(irg), pre, post, env);
199
200   free(type_env);
201   return;
202 }
203
204 void type_walk_s2s_2(type_or_ent *tore,
205                      void (pre)(type_or_ent*, void*),
206                      void (post)(type_or_ent*, void*),
207                      void *env)
208 {
209   int i;
210
211   /* marked? */
212   switch (get_kind(tore)) {
213   case k_entity:
214     if (((entity *)tore)->visit >= type_visited) return;
215     break;
216   case k_type:
217     if(type_id == get_type_tpop((type*)tore)) {
218       type_walk_s2s_2((type_or_ent *)skip_tid((type *)tore), pre, post, env);
219       return;
220     }
221     if (((type *)tore)->visit >= type_visited) return;
222     break;
223   default:
224     break;
225   }
226
227   /* iterate */
228   switch (get_kind(tore)) {
229   case k_type:
230     {
231       type *tp = (type *)tore;
232       mark_type_visited(tp);
233       switch (get_type_tpop_code(tp)) {
234       case tpo_class:
235         {
236           for (i=0; i<get_class_n_supertype(tp); i++)
237             type_walk_s2s_2((type_or_ent *)get_class_supertype(tp, i), pre, post, env);
238
239           /* execute pre method */
240           if(pre)
241             pre(tore, env);
242           tp = skip_tid((type*)tore);
243
244           for (i=0; i<get_class_n_subtype(tp); i++)
245             type_walk_s2s_2((type_or_ent *)get_class_subtype(tp, i), pre, post, env);
246
247           /* execute post method */
248           if(post)
249             post(tore, env);
250         }
251         break;
252       case tpo_struct:
253       case tpo_method:
254       case tpo_union:
255       case tpo_array:
256       case tpo_enumeration:
257       case tpo_pointer:
258       case tpo_primitive:
259       case tpo_id:
260         /* dont care */
261         break;
262       default:
263         printf(" *** Faulty type! \n");
264         break;
265       }
266     } break; /* end case k_type */
267   case k_entity:
268     /* dont care */
269     break;
270   default:
271     printf(" *** Faulty type or entity! \n");
272     break;
273   }
274   return;
275 }
276
277 void type_walk_super2sub(void (pre)(type_or_ent*, void*),
278                          void (post)(type_or_ent*, void*),
279                          void *env) {
280   int i;
281   ++type_visited;
282   type_walk_s2s_2((type_or_ent *)get_glob_type(), pre, post, env);
283   for (i = 0; i < get_irp_n_types(); i++) {
284     type_walk_s2s_2((type_or_ent *)get_irp_type(i), pre, post, env);
285   }
286 }