*** empty log message ***
[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 #include <stdlib.h>
13 #include <stdio.h>
14 #include "irgwalk.h"
15 #include "irgraph.h"
16 #include "irnode.h"
17 #include "irprog.h"
18 #include "type_or_entity.h"
19
20 /* Make types visible to allow most efficient access */
21 # include "entity_t.h"
22
23 typedef struct type_walk_env {
24   void *pre;
25   void *post;
26   void *env;
27 } type_walk_env;
28
29
30 void type_walk_2(type_or_ent *tore,
31                void (pre)(type_or_ent*, void*),
32                void (post)(type_or_ent*, void*),
33                void *env)
34 {
35   int i, visited = 0;
36
37   /* marked? */
38   switch (get_kind(tore)) {
39   case k_entity:
40     if (((entity *)tore)->visit >= type_visited) visited = 1; break;
41   case k_type_class:
42     if (((type_class *)tore)->visit >= type_visited) visited = 1; break;
43   case k_type_strct:
44     if (((type_strct *)tore)->visit >= type_visited) visited = 1; break;
45   case k_type_method:
46     if (((type_method *)tore)->visit >= type_visited) visited = 1; break;
47   case k_type_union:
48     if (((type_union *)tore)->visit >= type_visited) visited = 1; break;
49   case k_type_array:
50     if (((type_array *)tore)->visit >= type_visited) visited = 1; break;
51   case k_type_enumeration:
52     if (((type_enumeration *)tore)->visit >= type_visited) visited = 1; break;
53   case k_type_pointer:
54     if (((type_pointer *)tore)->visit >= type_visited) visited = 1;  break;
55   case k_type_primitive:
56     if (((type_primitive *)tore)->visit >= type_visited) visited = 1;  break;
57   default:
58     break;
59   }
60
61   if (!visited) { /* not marked. */
62
63     /* execute pre method */
64     if(pre)
65       pre(tore, env);
66
67     /* iterate */
68     switch (get_kind(tore)) {
69     case k_entity:
70       {
71         entity *ent = (entity *)tore;
72         ent->visit = type_visited;
73         type_walk_2((type_or_ent *)get_entity_owner(ent), pre, post, env);
74         type_walk_2((type_or_ent *)get_entity_type(ent), pre, post, env);
75       }
76       break;
77     case k_type_class:
78       {
79         int i;
80         ((type_class *)tore)->visit = type_visited;
81         //CS
82         for (i=0; i<get_class_n_member((type_class *)tore); i++)
83           {
84             type_walk_2((type_or_ent *)get_class_member((type_class *)tore, i),
85                         pre, post, env);
86           }
87         for (i=0; i<get_class_n_subtype((type_class *)tore); i++)
88           {
89             type_walk_2((type_or_ent *)get_class_subtype((type_class *)tore, i),
90                         pre, post, env);
91           }
92         for (i=0; i<get_class_n_supertype((type_class *)tore); i++)
93           {
94             type_walk_2((type_or_ent *)get_class_supertype((type_class *)tore, i),
95                         pre, post, env);
96           }
97       }
98       break;
99     case k_type_strct:
100       {
101         int i;
102
103         ((type_strct *)tore)->visit = type_visited;
104         //CS
105         for (i=0; i<get_strct_n_member((type_strct *)tore); i++)
106           {
107             type_walk_2((type_or_ent *)get_strct_member((type_strct *)tore, i),
108                         pre, post, env);
109           }
110       }
111       break;
112     case k_type_method:
113       {
114         type_method *meth  = (type_method *)tore;
115         meth->visit = type_visited;
116         for (i = 0; i < get_method_arity(meth); i++)
117           type_walk_2((type_or_ent *)get_method_param_type(meth, i), pre, post, env);
118         for (i = 0; i < get_method_n_res(meth); i++)
119           type_walk_2((type_or_ent *)get_method_res_type(meth, i), pre, post, env);
120       }
121       break;
122     case k_type_union:
123       ((type_union *)tore)->visit = type_visited;
124       /* !!!!! */
125       break;
126     case k_type_array:
127       ((type_array *)tore)->visit = type_visited;
128       type_walk_2((type_or_ent *)get_array_element_type((type_array *)tore),
129                   pre, post, env);
130       break;
131     case k_type_enumeration:
132       ((type_enumeration *)tore)->visit = type_visited;
133       /* a leave */
134       break;
135     case k_type_pointer:
136       ((type_pointer *)tore)->visit = type_visited;
137       type_walk_2((type_or_ent *)get_pointer_points_to_type((type_pointer *)tore),
138                   pre, post, env);
139       break;
140     case k_type_primitive:
141       ((type_primitive *)tore)->visit = type_visited;
142       /* a leave. */
143       break;
144     default:
145       break;
146     }
147
148     /* execute post method */
149     if(post)
150       post(tore, env);
151   }
152
153   return;
154 }
155
156 void start_type_walk(ir_node *node, void *env) {
157   void *pre  = ((type_walk_env *)env)->pre;
158   void *post = ((type_walk_env *)env)->post;
159   void *envi  = ((type_walk_env *)env)->env;
160
161   assert(node);
162
163     switch (get_irn_opcode(node)) {  /* node label */
164     case iro_SymConst:
165       if (   (get_SymConst_kind(node) == type_tag)
166           || (get_SymConst_kind(node) == size))
167         type_walk_2((type_or_ent *)get_SymConst_type(node), pre, post, envi);
168       break;
169     case iro_Sel:
170       type_walk_2((type_or_ent *)get_Sel_entity(node), pre, post, envi);
171       break;
172     case iro_Call:
173       type_walk_2((type_or_ent *)get_Call_type(node), pre, post, envi);
174       break;
175     case iro_Alloc:
176       type_walk_2((type_or_ent *)get_Alloc_type(node), pre, post, envi);
177       break;
178     case iro_Free:
179       printf("here in typewalk\n");
180       type_walk_2((type_or_ent *)get_Free_type(node), pre, post, envi);
181       break;
182   assert(node);
183     default:
184       break;
185     }
186 }
187
188 void type_walk(void (pre)(type_or_ent*, void*),
189                void (post)(type_or_ent*, void*),
190                void *env) {
191   int i;
192   ++type_visited;
193   type_walk_2((type_or_ent *)get_glob_type(), pre, post, env);
194   for (i = 0; i < get_irp_n_types(); i++) {
195     type_walk_2((type_or_ent *)get_irp_type(i), pre, post, env);
196   }
197 }
198
199 void type_walk_irg (ir_graph *irg,
200                     void (pre)(type_or_ent*, void*),
201                     void (post)(type_or_ent*, void*),
202                     void *env)
203 {
204   /* this is needed to pass the parameters to the walker that actually
205      walks the type information */
206   type_walk_env* type_env;
207   type_env = (type_walk_env *) malloc (sizeof(type_walk_env));
208   type_env->pre = pre;
209   type_env->post = post;
210   type_env->env = env;
211
212   ++type_visited;
213   irg_walk(get_irg_end(irg), start_type_walk, NULL, type_env);
214
215   type_walk_2((type_or_ent *)get_irg_ent(irg), pre, post, env);
216
217   /* @@@ free type_walk_env!! */
218   return;
219 }