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 data structures. */
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) {
100 assert(ent && is_entity(ent));
102 accs = get_entity_access_array(ent);
103 return ARR_LEN(accs);
106 ir_node *get_entity_access(entity *ent, int pos) {
109 assert(0 <= pos && pos < get_entity_n_accesses(ent));
111 accs = get_entity_access_array(ent);
115 void add_entity_access(entity *ent, ir_node *n) {
118 assert(ent && is_entity(ent));
119 assert(n && is_ir_node(n));
121 accs = get_entity_access_array(ent);
122 ARR_APP1(ir_node *, accs, n);
123 set_entity_access_array(ent, accs);
126 void set_entity_access(entity *ent, int pos, ir_node *n) {
129 assert(0 <= pos && pos < get_entity_n_accesses(ent));
130 assert(n && is_ir_node(n));
132 accs = get_entity_access_array(ent);
136 /**------------------------------------------------------------------*/
138 int get_entity_n_references(entity *ent) {
141 assert(ent && is_entity(ent));
143 refs = get_entity_reference_array(ent);
144 return ARR_LEN(refs);
147 ir_node *get_entity_reference(entity *ent, int pos) {
150 assert(0 <= pos && pos < get_entity_n_references(ent));
152 refs = get_entity_reference_array(ent);
156 void add_entity_reference(entity *ent, ir_node *n) {
159 assert(ent && is_entity(ent));
160 assert(n && is_ir_node(n));
162 refs = get_entity_reference_array(ent);
163 ARR_APP1(ir_node *, refs, n);
164 set_entity_reference_array(ent, refs);
167 void set_entity_reference(entity *ent, int pos, ir_node *n) {
170 assert(0 <= pos && pos < get_entity_n_references(ent));
171 assert(n && is_ir_node(n));
173 refs = get_entity_reference_array(ent);
178 /**------------------------------------------------------------------*/
179 /* Access routines for types */
180 /**------------------------------------------------------------------*/
182 /* Number of Alloc nodes that create an instance of this type */
183 int get_type_n_allocations(type *tp) {
186 assert(tp && is_type(tp));
188 allocs = get_type_alloc_array(tp);
189 return ARR_LEN(allocs);
192 /* Alloc node that creates an instance of this type */
193 ir_node *get_type_allocation(type *tp, int pos) {
195 assert(0 <= pos && pos < get_type_n_allocations(tp));
197 allocs = get_type_alloc_array(tp);
201 void add_type_allocation(type *tp, ir_node *n) {
204 assert(tp && is_type(tp));
205 assert(n && is_ir_node(n));
207 allocs = get_type_alloc_array(tp);
208 ARR_APP1(ir_node *, allocs, n);
209 set_type_alloc_array(tp, allocs);
212 void set_type_allocation(type *tp, int pos, ir_node *n) {
215 assert(0 <= pos && pos < get_type_n_allocations(tp));
216 assert(n && is_ir_node(n));
218 allocs = get_type_alloc_array(tp);
222 /*------------------------------------------------------------------*/
223 /* Building and Removing the out datastructure */
224 /*------------------------------------------------------------------*/
226 static void init_trouts(void) {
229 /* The entities that can be accessed by this Sel node. */
230 static int get_Sel_n_accessed_entities(ir_node *sel) {
234 static entity *get_Sel_accessed_entity(ir_node *sel, int pos) {
235 return get_Sel_entity(sel);
238 /* An addr node is a SymConst or a Sel. */
239 static int get_addr_n_entities(ir_node *addr) {
242 switch (get_irn_opcode(addr)) {
244 /* Treat jack array sels? */
245 n_ents = get_Sel_n_accessed_entities(addr);
248 if (get_SymConst_kind(addr) == symconst_addr_ent) {
253 //assert(0 && "unexpected address expression");
260 /* An addr node is a SymConst or a Sel. */
261 static entity *get_addr_entity(ir_node *addr, int pos) {
264 switch (get_irn_opcode(addr)) {
266 /* Treat jack array sels? */
267 assert (0 <= pos && pos < get_Sel_n_accessed_entities(addr));
268 ent = get_Sel_accessed_entity(addr, pos);
271 if (get_SymConst_kind(addr) == symconst_addr_ent) {
273 ent = get_SymConst_entity(addr);
283 static void chain_accesses(ir_node *n, void *env) {
287 if (get_irn_op(n) == op_Alloc) {
288 add_type_allocation(get_Alloc_type(n), n);
292 if (get_irn_op(n) == op_Sel) {
293 add_entity_reference(get_Sel_entity(n), n);
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);
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. */
309 n_ents = get_addr_n_entities(addr);
310 for (i = 0; i < n_ents; ++i) {
311 entity *ent = get_addr_entity(addr, i);
313 add_entity_access(ent, n);
315 //add_unrecognized_access(n);
319 /* compute the field temperature. */
320 void compute_trouts(void) {
321 int i, n_irgs = get_irp_n_irgs();
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);
329 walk_const_code(NULL, chain_accesses, NULL);
333 void free_trouts(void) {
334 if (entity_access_map) {
336 for (accs = (ir_node **)pmap_first(entity_access_map);
338 accs = (ir_node **)pmap_next(entity_access_map))
340 pmap_destroy(entity_access_map);
341 entity_access_map = NULL;
343 if (entity_reference_map) {
345 for (refs = (ir_node **)pmap_first(entity_reference_map);
347 refs = (ir_node **)pmap_next(entity_reference_map))
349 pmap_destroy(entity_reference_map);
350 entity_reference_map = NULL;
352 if (type_alloc_map) {
354 for (alls = (ir_node **)pmap_first(type_alloc_map);
356 alls = (ir_node **)pmap_next(type_alloc_map))
358 pmap_destroy(type_alloc_map);
359 type_alloc_map = NULL;