3 * File name: ir/ana/trouts.c
4 * Purpose: Reverse edges that reference types/entities.
5 * Author: Goetz Lindenmaier
9 * Copyright: (c) 2004 Universität Karlsruhe
10 * Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE.
21 /**------------------------------------------------------------------*/
22 /* We represent the fields in entities/types by hashmaps. */
23 /**------------------------------------------------------------------*/
25 static pmap *entity_access_map = NULL;
26 static pmap *entity_reference_map = NULL;
27 static pmap *type_alloc_map = NULL;
29 static ir_node **get_entity_access_array(entity *ent) {
31 if (!entity_access_map) entity_access_map = pmap_create();
33 if (pmap_contains(entity_access_map, (void *)ent)) {
34 res = (ir_node **) pmap_get(entity_access_map, (void *)ent);
36 res = NEW_ARR_F(ir_node *, 0);
37 pmap_insert(entity_access_map, (void *)ent, (void *)res);
42 void set_entity_access_array(entity *ent, ir_node **accs) {
43 ir_node **old = pmap_get(entity_access_map, (void *)ent);
45 pmap_insert(entity_access_map, (void *)ent, (void *)accs);
48 static ir_node **get_entity_reference_array(entity *ent) {
50 if (!entity_reference_map) entity_reference_map = pmap_create();
52 if (pmap_contains(entity_reference_map, (void *)ent)) {
53 res = (ir_node **) pmap_get(entity_reference_map, (void *)ent);
55 res = NEW_ARR_F(ir_node *, 0);
56 pmap_insert(entity_reference_map, (void *)ent, (void *)res);
61 void set_entity_reference_array(entity *ent, ir_node **refs) {
62 ir_node **old = pmap_get(entity_reference_map, (void *)ent);
64 pmap_insert(entity_reference_map, (void *)ent, (void *)refs);
67 static ir_node **get_type_alloc_array(type *tp) {
69 if (!type_alloc_map) type_alloc_map = pmap_create();
71 if (pmap_contains(type_alloc_map, (void *)tp)) {
72 res = (ir_node **) pmap_get(type_alloc_map, (void *)tp);
74 res = NEW_ARR_F(ir_node *, 0);
75 pmap_insert(type_alloc_map, (void *)tp, (void *)res);
80 void set_type_alloc_array(type *tp, ir_node **alls) {
81 ir_node **old = pmap_get(type_alloc_map, (void *)tp);
83 pmap_insert(type_alloc_map, (void *)tp, (void *)alls);
87 /*------------------------------------------------------------------*/
88 /* Accessing the out datastructures. */
89 /* These routines only work properly if firm is in state */
90 /* trouts_consistent or trouts_inconsistent. */
91 /*------------------------------------------------------------------*/
93 /**------------------------------------------------------------------*/
94 /* Access routines for entities */
95 /**------------------------------------------------------------------*/
97 int get_entity_n_accesses(entity *ent) {
98 assert(ent && is_entity(ent));
100 ir_node ** accs = (ir_node **)get_entity_access_array(ent);
101 return ARR_LEN(accs);
104 ir_node *get_entity_access(entity *ent, int pos) {
105 assert(0 <= pos && pos < get_entity_n_accesses(ent));
107 ir_node ** accs = (ir_node **)get_entity_access_array(ent);
111 void add_entity_access(entity *ent, ir_node *n) {
112 assert(ent && is_entity(ent));
113 assert(n && is_ir_node(n));
115 ir_node ** accs = (ir_node **)get_entity_access_array(ent);
116 ARR_APP1(ir_node *, accs, n);
117 set_entity_access_array(ent, accs);
120 void set_entity_access(entity *ent, int pos, ir_node *n) {
121 assert(0 <= pos && pos < get_entity_n_accesses(ent));
122 assert(n && is_ir_node(n));
124 ir_node ** accs = (ir_node **)get_entity_access_array(ent);
128 /**------------------------------------------------------------------*/
130 int get_entity_n_references(entity *ent) {
131 assert(ent && is_entity(ent));
133 ir_node ** refs = (ir_node **)get_entity_reference_array(ent);
134 return ARR_LEN(refs);
137 ir_node *get_entity_reference(entity *ent, int pos) {
138 assert(0 <= pos && pos < get_entity_n_references(ent));
140 ir_node ** refs = (ir_node **)get_entity_reference_array(ent);
144 void add_entity_reference(entity *ent, ir_node *n) {
145 assert(ent && is_entity(ent));
146 assert(n && is_ir_node(n));
148 ir_node ** refs = (ir_node **)get_entity_reference_array(ent);
149 ARR_APP1(ir_node *, refs, n);
150 set_entity_reference_array(ent, refs);
153 void set_entity_reference(entity *ent, int pos, ir_node *n) {
154 assert(0 <= pos && pos < get_entity_n_references(ent));
155 assert(n && is_ir_node(n));
157 ir_node ** refs = (ir_node **)get_entity_reference_array(ent);
162 /**------------------------------------------------------------------*/
163 /* Access routines for types */
164 /**------------------------------------------------------------------*/
166 /* Number of Alloc nodes that create an instance of this type */
167 int get_type_n_allocations(type *tp) {
168 assert(tp && is_type(tp));
170 ir_node **allocs = get_type_alloc_array(tp);
171 return ARR_LEN(allocs);
174 /* Alloc node that creates an instance of this type */
175 ir_node *get_type_allocation(type *tp, int pos) {
176 assert(0 <= pos && pos < get_type_n_allocations(tp));
178 ir_node **allocs = get_type_alloc_array(tp);
182 void add_type_allocation(type *tp, ir_node *n) {
183 assert(tp && is_type(tp));
184 assert(n && is_ir_node(n));
186 ir_node **allocs = get_type_alloc_array(tp);
187 ARR_APP1(ir_node *, allocs, n);
188 set_type_alloc_array(tp, allocs);
191 void set_type_allocation(type *tp, int pos, ir_node *n) {
192 assert(0 <= pos && pos < get_type_n_allocations(tp));
193 assert(n && is_ir_node(n));
195 ir_node **allocs = get_type_alloc_array(tp);
199 /*------------------------------------------------------------------*/
200 /* Building and Removing the out datastructure */
201 /*------------------------------------------------------------------*/
203 static void init_trouts(void) {
206 /* The entities that can be accessed by this Sel node. */
207 static int get_Sel_n_accessed_entities(ir_node *sel) {
211 static entity *get_Sel_accessed_entity(ir_node *sel, int pos) {
212 return get_Sel_entity(sel);
215 /* An addr node is a SymConst or a Sel. */
216 static int get_addr_n_entities(ir_node *addr) {
219 switch (get_irn_opcode(addr)) {
221 /* Treat jack array sels? */
222 n_ents = get_Sel_n_accessed_entities(addr);
225 if (get_SymConst_kind(addr) == symconst_addr_ent) {
230 //assert(0 && "unexpected address expression");
237 /* An addr node is a SymConst or a Sel. */
238 static entity *get_addr_entity(ir_node *addr, int pos) {
241 switch (get_irn_opcode(addr)) {
243 /* Treat jack array sels? */
244 assert (0 <= pos && pos < get_Sel_n_accessed_entities(addr));
245 ent = get_Sel_accessed_entity(addr, pos);
248 if (get_SymConst_kind(addr) == symconst_addr_ent) {
250 ent = get_SymConst_entity(addr);
260 static void chain_accesses(ir_node *n, void *env) {
264 if (get_irn_op(n) == op_Alloc) {
265 add_type_allocation(get_Alloc_type(n), n);
269 if (get_irn_op(n) == op_Sel) {
270 add_entity_reference(get_Sel_entity(n), n);
272 } else if (get_irn_op(n) == op_SymConst && (get_SymConst_kind(n) == symconst_addr_ent)) {
273 add_entity_reference(get_SymConst_entity(n), n);
278 addr = get_memop_ptr(n);
279 } else if (get_irn_op(n) == op_Call) {
280 addr = get_Call_ptr(n);
281 if (get_irn_op(addr) != op_Sel) return; /* Sels before Calls mean a Load / polymorphic Call. */
286 n_ents = get_addr_n_entities(addr);
287 for (i = 0; i < n_ents; ++i) {
288 entity *ent = get_addr_entity(addr, i);
290 add_entity_access(ent, n);
292 //add_unrecognized_access(n);
296 /* compute the field temperature. */
297 void compute_trouts(void) {
298 int i, n_irgs = get_irp_n_irgs();
302 for (i=0; i < n_irgs; i++) {
303 current_ir_graph = get_irp_irg(i);
304 irg_walk_graph(current_ir_graph, NULL, chain_accesses, NULL);
306 walk_const_code(NULL, chain_accesses, NULL);
310 void free_trouts(void) {
311 if (entity_access_map) {
313 for (accs = (ir_node **)pmap_first(entity_access_map);
315 accs = (ir_node **)pmap_next(entity_access_map))
317 pmap_destroy(entity_access_map);
318 entity_access_map = NULL;
320 if (entity_reference_map) {
322 for (refs = (ir_node **)pmap_first(entity_reference_map);
324 refs = (ir_node **)pmap_next(entity_reference_map))
326 pmap_destroy(entity_reference_map);
327 entity_reference_map = NULL;
329 if (type_alloc_map) {
331 for (alls = (ir_node **)pmap_first(type_alloc_map);
333 alls = (ir_node **)pmap_next(type_alloc_map))
335 pmap_destroy(type_alloc_map);
336 type_alloc_map = NULL;