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