53bd324ceda5f84f06899739e04167b29f824439
[libfirm] / ir / ana / trouts.c
1 /*
2  * Project:     libFIRM
3  * File name:   ir/ana/trouts.c
4  * Purpose:     Reverse edges that reference types/entities.
5  * Author:      Goetz Lindenmaier
6  * Modified by:
7  * Created:     29.10.2004
8  * CVS-ID:      $Id$
9  * Copyright:   (c) 2004 Universität Karlsruhe
10  * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
11  */
12
13 #include "trouts.h"
14
15 #include "array.h"
16 #include "pmap.h"
17
18 #include "irprog.h"
19 #include "irgwalk.h"
20
21 /**------------------------------------------------------------------*/
22 /* We represent the fields in entities/types by hashmaps.            */
23 /**------------------------------------------------------------------*/
24
25 static pmap *entity_access_map = NULL;
26 static pmap *entity_reference_map = NULL;
27 static pmap *type_alloc_map = NULL;
28
29 static ir_node **get_entity_access_array(entity *ent) {
30   ir_node **res;
31   if (!entity_access_map) entity_access_map = pmap_create();
32
33   if (pmap_contains(entity_access_map, (void *)ent)) {
34     res = (ir_node **) pmap_get(entity_access_map, (void *)ent);
35   } else {
36     res = NEW_ARR_F(ir_node *, 0);
37     pmap_insert(entity_access_map, (void *)ent, (void *)res);
38   }
39
40   return res;
41 }
42 void set_entity_access_array(entity *ent, ir_node **accs) {
43   ir_node **old = pmap_get(entity_access_map, (void *)ent);
44   if (old != accs)
45     pmap_insert(entity_access_map, (void *)ent, (void *)accs);
46 }
47
48 static ir_node **get_entity_reference_array(entity *ent) {
49   ir_node **res;
50   if (!entity_reference_map) entity_reference_map = pmap_create();
51
52   if (pmap_contains(entity_reference_map, (void *)ent)) {
53     res = (ir_node **) pmap_get(entity_reference_map, (void *)ent);
54   } else {
55     res = NEW_ARR_F(ir_node *, 0);
56     pmap_insert(entity_reference_map, (void *)ent, (void *)res);
57   }
58
59   return res;
60 }
61 void set_entity_reference_array(entity *ent, ir_node **refs) {
62   ir_node **old = pmap_get(entity_reference_map, (void *)ent);
63   if (old != refs)
64     pmap_insert(entity_reference_map, (void *)ent, (void *)refs);
65 }
66
67 static ir_node **get_type_alloc_array(type *tp) {
68   ir_node **res;
69   if (!type_alloc_map) type_alloc_map = pmap_create();
70
71   if (pmap_contains(type_alloc_map, (void *)tp)) {
72     res = (ir_node **) pmap_get(type_alloc_map, (void *)tp);
73   } else {
74     res = NEW_ARR_F(ir_node *, 0);
75     pmap_insert(type_alloc_map, (void *)tp, (void *)res);
76   }
77
78   return res;
79 }
80 void set_type_alloc_array(type *tp, ir_node **alls) {
81   ir_node **old = pmap_get(type_alloc_map, (void *)tp);
82   if (old != alls)
83     pmap_insert(type_alloc_map, (void *)tp, (void *)alls);
84 }
85
86
87 /*------------------------------------------------------------------*/
88 /* Accessing the out data structures.                               */
89 /* These routines only work properly if firm is in state            */
90 /* trouts_consistent or trouts_inconsistent.                        */
91 /*------------------------------------------------------------------*/
92
93 /**------------------------------------------------------------------*/
94 /*   Access routines for entities                                    */
95 /**------------------------------------------------------------------*/
96
97 int get_entity_n_accesses(entity *ent) {
98   ir_node ** accs;
99
100   assert(ent && is_entity(ent));
101
102   accs = get_entity_access_array(ent);
103   return ARR_LEN(accs);
104 }
105
106 ir_node *get_entity_access(entity *ent, int pos) {
107   ir_node ** accs;
108
109   assert(0 <= pos && pos < get_entity_n_accesses(ent));
110
111   accs = get_entity_access_array(ent);
112   return accs[pos];
113 }
114
115 void add_entity_access(entity *ent, ir_node *n) {
116   ir_node ** accs;
117
118   assert(ent && is_entity(ent));
119   assert(n && is_ir_node(n));
120
121   accs = get_entity_access_array(ent);
122   ARR_APP1(ir_node *, accs, n);
123   set_entity_access_array(ent, accs);
124 }
125
126 void set_entity_access(entity *ent, int pos, ir_node *n) {
127   ir_node ** accs;
128
129   assert(0 <= pos && pos < get_entity_n_accesses(ent));
130   assert(n && is_ir_node(n));
131
132   accs = get_entity_access_array(ent);
133   accs[pos] = n;
134 }
135
136 /**------------------------------------------------------------------*/
137
138 int get_entity_n_references(entity *ent) {
139   ir_node ** refs;
140
141   assert(ent && is_entity(ent));
142
143   refs = get_entity_reference_array(ent);
144   return ARR_LEN(refs);
145 }
146
147 ir_node *get_entity_reference(entity *ent, int pos) {
148   ir_node ** refs;
149
150   assert(0 <= pos && pos < get_entity_n_references(ent));
151
152   refs = get_entity_reference_array(ent);
153   return refs[pos];
154 }
155
156 void add_entity_reference(entity *ent, ir_node *n) {
157   ir_node ** refs;
158
159   assert(ent && is_entity(ent));
160   assert(n && is_ir_node(n));
161
162   refs = get_entity_reference_array(ent);
163   ARR_APP1(ir_node *, refs, n);
164   set_entity_reference_array(ent, refs);
165 }
166
167 void set_entity_reference(entity *ent, int pos, ir_node *n) {
168   ir_node ** refs;
169
170   assert(0 <= pos && pos < get_entity_n_references(ent));
171   assert(n && is_ir_node(n));
172
173   refs = get_entity_reference_array(ent);
174   refs[pos] = n;
175 }
176
177
178 /**------------------------------------------------------------------*/
179 /*   Access routines for types                                       */
180 /**------------------------------------------------------------------*/
181
182 /* Number of Alloc nodes that create an instance of this type */
183 int get_type_n_allocations(type *tp) {
184   ir_node **allocs;
185
186   assert(tp && is_type(tp));
187
188   allocs = get_type_alloc_array(tp);
189   return ARR_LEN(allocs);
190 }
191
192 /* Alloc node that creates an instance of this type */
193 ir_node *get_type_allocation(type *tp, int pos) {
194   ir_node **allocs;
195   assert(0 <= pos && pos < get_type_n_allocations(tp));
196
197   allocs = get_type_alloc_array(tp);
198   return allocs[pos];
199 }
200
201 void add_type_allocation(type *tp, ir_node *n) {
202   ir_node **allocs;
203
204   assert(tp && is_type(tp));
205   assert(n && is_ir_node(n));
206
207   allocs = get_type_alloc_array(tp);
208   ARR_APP1(ir_node *, allocs, n);
209   set_type_alloc_array(tp, allocs);
210 }
211
212 void set_type_allocation(type *tp, int pos, ir_node *n) {
213   ir_node **allocs;
214
215   assert(0 <= pos && pos < get_type_n_allocations(tp));
216   assert(n && is_ir_node(n));
217
218   allocs = get_type_alloc_array(tp);
219   allocs[pos] = n;
220 }
221
222 /*------------------------------------------------------------------*/
223 /* Building and Removing the out datastructure                      */
224 /*------------------------------------------------------------------*/
225
226 static void init_trouts(void) {
227 }
228
229 /* The entities that can be accessed by this Sel node. */
230 static int get_Sel_n_accessed_entities(ir_node *sel) {
231   return 1;
232 }
233
234 static entity *get_Sel_accessed_entity(ir_node *sel, int pos) {
235   return get_Sel_entity(sel);
236 }
237
238 /* An addr node is a SymConst or a Sel. */
239 static int get_addr_n_entities(ir_node *addr) {
240   int n_ents;
241
242   switch (get_irn_opcode(addr)) {
243   case iro_Sel:
244     /* Treat jack array sels? */
245     n_ents = get_Sel_n_accessed_entities(addr);
246     break;
247   case iro_SymConst:
248     if (get_SymConst_kind(addr) == symconst_addr_ent) {
249       n_ents = 1;
250       break;
251     }
252   default:
253     //assert(0 && "unexpected address expression");
254     n_ents = 0;
255   }
256
257   return n_ents;
258 }
259
260 /* An addr node is a SymConst or a Sel. */
261 static entity *get_addr_entity(ir_node *addr, int pos) {
262   entity *ent;
263
264   switch (get_irn_opcode(addr)) {
265   case iro_Sel:
266     /* Treat jack array sels? */
267     assert (0 <= pos && pos < get_Sel_n_accessed_entities(addr));
268     ent = get_Sel_accessed_entity(addr, pos);
269     break;
270   case iro_SymConst:
271     if (get_SymConst_kind(addr) == symconst_addr_ent) {
272       assert(pos == 0);
273       ent = get_SymConst_entity(addr);
274       break;
275     }
276   default:
277     ent = NULL;
278   }
279
280   return ent;
281 }
282
283 static void chain_accesses(ir_node *n, void *env) {
284   int i, n_ents;
285   ir_node *addr;
286
287   if (get_irn_op(n) == op_Alloc) {
288     add_type_allocation(get_Alloc_type(n), n);
289     return;
290   } else
291
292   if (get_irn_op(n) == op_Sel) {
293     add_entity_reference(get_Sel_entity(n), n);
294     return;
295   } else if (get_irn_op(n) == op_SymConst && (get_SymConst_kind(n) == symconst_addr_ent)) {
296     add_entity_reference(get_SymConst_entity(n), n);
297     return;
298   } else
299
300   if (is_memop(n)) {
301     addr = get_memop_ptr(n);
302   } else if (get_irn_op(n) == op_Call) {
303     addr = get_Call_ptr(n);
304     if (get_irn_op(addr) != op_Sel) return;  /* Sels before Calls mean a Load / polymorphic Call. */
305   } else {
306     return;
307   }
308
309   n_ents = get_addr_n_entities(addr);
310   for (i = 0; i < n_ents; ++i) {
311     entity *ent = get_addr_entity(addr, i);
312     if (ent)
313       add_entity_access(ent, n);
314     //else
315       //add_unrecognized_access(n);
316   }
317 }
318
319 /* compute the field temperature. */
320 void compute_trouts(void) {
321   int i, n_irgs = get_irp_n_irgs();
322
323   init_trouts();
324
325   for (i=0; i < n_irgs; i++) {
326     current_ir_graph = get_irp_irg(i);
327     irg_walk_graph(current_ir_graph, NULL, chain_accesses, NULL);
328   }
329   walk_const_code(NULL, chain_accesses, NULL);
330 }
331
332
333 void free_trouts(void) {
334   if (entity_access_map) {
335     ir_node **accs;
336     for (accs = (ir_node **)pmap_first(entity_access_map);
337          accs;
338          accs = (ir_node **)pmap_next(entity_access_map))
339       ; //DEL_ARR_F(accs);
340     pmap_destroy(entity_access_map);
341     entity_access_map = NULL;
342   }
343   if (entity_reference_map) {
344     ir_node **refs;
345     for (refs = (ir_node **)pmap_first(entity_reference_map);
346          refs;
347          refs = (ir_node **)pmap_next(entity_reference_map))
348       ; //DEL_ARR_F(refs);
349     pmap_destroy(entity_reference_map);
350     entity_reference_map = NULL;
351   }
352   if (type_alloc_map) {
353     ir_node **alls;
354     for (alls = (ir_node **)pmap_first(type_alloc_map);
355          alls;
356          alls = (ir_node **)pmap_next(type_alloc_map))
357       ; //DEL_ARR_F(alls);
358     pmap_destroy(type_alloc_map);
359     type_alloc_map = NULL;
360   }
361 }