Initial revision
[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 "irgwalk.h"
13 #include "irgraph.h"
14 #include "irnode.h"
15 #include "type_or_entity.h"
16
17 typedef struct type_walk_env {
18   void *pre;
19   void *post;
20   void *env;
21 } type_walk_env;
22
23
24 void type_walk_2(type_or_ent *tore,
25               void (pre)(type_or_ent*, void*), void (post)(type_or_ent*, void*),
26             void *env)
27 {
28   int i, visited = 0;
29
30   /* marked? */
31   switch (get_kind(tore)) {
32   case k_entity:
33     if (((entity *)tore)->visit >= type_visited) visited = 1; break;
34   case k_type_class:
35     if (((type_class *)tore)->visit >= type_visited) visited = 1; break;
36   case k_type_strct:
37     if (((type_strct *)tore)->visit >= type_visited) visited = 1; break;
38   case k_type_method:
39     if (((type_method *)tore)->visit >= type_visited) visited = 1; break;
40   case k_type_union:
41     if (((type_union *)tore)->visit >= type_visited) visited = 1; break;
42   case k_type_array:
43     if (((type_array *)tore)->visit >= type_visited) visited = 1; break;
44   case k_type_enumeration:
45     if (((type_enumeration *)tore)->visit >= type_visited) visited = 1; break;
46   case k_type_pointer:
47     if (((type_pointer *)tore)->visit >= type_visited) visited = 1;  break;
48   case k_type_primitive:
49     if (((type_primitive *)tore)->visit >= type_visited) visited = 1;  break;
50   default:
51     break;
52   }
53
54   if (!visited) { /* not marked. */
55
56     /* execute pre method */
57     if(pre)
58       pre(tore, env);
59
60     /* iterate */
61     switch (get_kind(tore)) {
62     case k_entity:
63       {
64         entity *ent = (entity *)tore;
65         ent->visit = type_visited;
66         type_walk_2((type_or_ent *)get_entity_owner(ent), pre, post, env);
67         type_walk_2((type_or_ent *)get_entity_type(ent), pre, post, env);
68       }
69       break;
70     case k_type_class:
71       ((type_class *)tore)->visit = type_visited;
72       /* !!!!! */
73       break;
74     case k_type_strct:
75       ((type_strct *)tore)->visit = type_visited;
76       /* !!!!! */
77       break;
78     case k_type_method:
79       {
80         type_method *meth  = (type_method *)tore;
81         meth->visit = type_visited;
82         for (i = 0; i < get_method_arity(meth); i++)
83           type_walk_2((type_or_ent *)get_method_param_type(meth, i), pre, post, env);
84         for (i = 0; i < get_method_n_res(meth); i++)
85           type_walk_2((type_or_ent *)get_method_res_type(meth, i), pre, post, env);
86       }
87       break;
88     case k_type_union:
89       ((type_union *)tore)->visit = type_visited;
90       break;
91     case k_type_array:
92       ((type_array *)tore)->visit = type_visited;
93       type_walk_2((type_or_ent *)get_array_element_type((type_array *)tore),
94                   pre, post, env);
95       break;
96     case k_type_enumeration:
97       ((type_enumeration *)tore)->visit = type_visited;
98       /* a leave */
99       break;
100     case k_type_pointer:
101       ((type_pointer *)tore)->visit = type_visited;
102       type_walk_2((type_or_ent *)get_pointer_points_to_type((type_pointer *)tore),
103                   pre, post, env);
104       break;
105     case k_type_primitive:
106       ((type_primitive *)tore)->visit = type_visited;
107       /* a leave. */
108       break;
109     default:
110       break;
111     }
112
113     /* execute post method */
114     if(post)
115       post(tore, env);
116   }
117
118   return;
119 }
120
121 void start_type_walk(ir_node *node, void *env) {
122   void *pre  = ((type_walk_env *)env)->pre;
123   void *post = ((type_walk_env *)env)->post;
124   void *envi  = ((type_walk_env *)env)->env;
125
126   assert(node);
127
128     switch (get_irn_opcode(node)) {  /* node label */
129     case iro_SymConst:
130       if (   (get_SymConst_kind(node) == type_tag)
131           || (get_SymConst_kind(node) == size))
132         type_walk_2((type_or_ent *)get_SymConst_type(node), pre, post, envi);
133       break;
134     case iro_Sel:
135       type_walk_2((type_or_ent *)get_Sel_entity(node), pre, post, envi);
136       break;
137     case iro_Call:
138       type_walk_2((type_or_ent *)get_Call_type(node), pre, post, envi);
139       break;
140     case iro_Alloc:
141       type_walk_2((type_or_ent *)get_Alloc_type(node), pre, post, envi);
142     case iro_Free:
143       type_walk_2((type_or_ent *)get_Free_type(node), pre, post, envi);
144       break;
145   assert(node);
146     default:
147       break;
148     }
149 }
150
151 void type_walk(ir_graph *irg,
152               void (pre)(type_or_ent*, void*), void (post)(type_or_ent*, void*),
153               void *env)
154 {
155   /* this is needed to pass the parameters to the walker that actually
156      walks the type information */
157   type_walk_env* type_env;
158   type_env = (type_walk_env *) malloc (sizeof(type_walk_env));
159   type_env->pre = pre;
160   type_env->post = post;
161   type_env->env = env;
162
163   ++type_visited;
164   irg_walk(irg->end, start_type_walk, NULL, type_env);
165
166   return;
167 }