for i in *.[ch]; do sed -e 's/Copyrigth/Copyright/g' -i modeconv.h; done
[libfirm] / ir / ana / trouts.c
1 /*
2  * Copyright (C) 1995-2007 University of Karlsruhe.  All right reserved.
3  *
4  * This file is part of libFirm.
5  *
6  * This file may be distributed and/or modified under the terms of the
7  * GNU General Public License version 2 as published by the Free Software
8  * Foundation and appearing in the file LICENSE.GPL included in the
9  * packaging of this file.
10  *
11  * Licensees holding valid libFirm Professional Edition licenses may use
12  * this file in accordance with the libFirm Commercial License.
13  * Agreement provided with the Software.
14  *
15  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE.
18  */
19
20 /**
21  * @file
22  * @brief    Reverse edges that reference types/entities.
23  * @author   Goetz Lindenmaier
24  * @date     29.10.2004
25  * @version  $Id$
26  */
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30
31 #include "irnode.h"
32 #include "trouts.h"
33
34 #include "array.h"
35 #include "pmap.h"
36
37 #include "irprog_t.h"
38 #include "irgwalk.h"
39 #include "irnode.h"
40
41
42 /*------------------------------------------------------------------*/
43 /* We represent the fields in entities/types by hashmaps.           */
44 /*------------------------------------------------------------------*/
45
46 static pmap *entity_access_map = NULL;
47 static pmap *entity_reference_map = NULL;
48 static pmap *type_alloc_map = NULL;
49 static pmap *type_cast_map = NULL;
50 static pmap *type_pointertype_map = NULL;
51 static pmap *type_arraytype_map = NULL;
52
53 /**
54  * Return a flexible array containing all IR-nodes
55  * that access a given entity.
56  */
57 static ir_node **get_entity_access_array(ir_entity *ent) {
58   ir_node **res;
59   if (!entity_access_map) entity_access_map = pmap_create();
60
61   if (pmap_contains(entity_access_map, (void *)ent)) {
62     res = (ir_node **) pmap_get(entity_access_map, (void *)ent);
63   } else {
64     res = NEW_ARR_F(ir_node *, 0);
65     pmap_insert(entity_access_map, (void *)ent, (void *)res);
66   }
67
68   return res;
69 }
70 void set_entity_access_array(ir_entity *ent, ir_node **accs) {
71   ir_node **old = pmap_get(entity_access_map, (void *)ent);
72   if (old != accs)
73     pmap_insert(entity_access_map, (void *)ent, (void *)accs);
74 }
75
76 /**
77  * Return a flexible array containing all IR-nodes
78  * that reference a given entity.
79  */
80 static ir_node **get_entity_reference_array(ir_entity *ent) {
81   ir_node **res;
82   if (!entity_reference_map) entity_reference_map = pmap_create();
83
84   if (pmap_contains(entity_reference_map, (void *)ent)) {
85     res = (ir_node **) pmap_get(entity_reference_map, (void *)ent);
86   } else {
87     res = NEW_ARR_F(ir_node *, 0);
88     pmap_insert(entity_reference_map, (void *)ent, (void *)res);
89   }
90
91   return res;
92 }
93 void set_entity_reference_array(ir_entity *ent, ir_node **refs) {
94   ir_node **old = pmap_get(entity_reference_map, (void *)ent);
95   if (old != refs)
96     pmap_insert(entity_reference_map, (void *)ent, (void *)refs);
97 }
98
99 /**
100  * Return a flexible array containing all IR-nodes
101  * that allocate a given type.
102  */
103 static ir_node **get_type_alloc_array(ir_type *tp) {
104   ir_node **res;
105   if (!type_alloc_map) type_alloc_map = pmap_create();
106
107   if (pmap_contains(type_alloc_map, (void *)tp)) {
108     res = (ir_node **) pmap_get(type_alloc_map, (void *)tp);
109   } else {
110     res = NEW_ARR_F(ir_node *, 0);
111     pmap_insert(type_alloc_map, (void *)tp, (void *)res);
112   }
113
114   return res;
115 }
116 void set_type_alloc_array(ir_type *tp, ir_node **alls) {
117   ir_node **old = pmap_get(type_alloc_map, (void *)tp);
118   if (old != alls)
119     pmap_insert(type_alloc_map, (void *)tp, (void *)alls);
120 }
121
122 /**
123  * Return a flexible array containing all Cast-nodes
124  * that "create" a given type.
125  */
126 static ir_node **get_type_cast_array(ir_type *tp) {
127   ir_node **res;
128   if (!type_cast_map) type_cast_map = pmap_create();
129
130   if (pmap_contains(type_cast_map, (void *)tp)) {
131     res = (ir_node **) pmap_get(type_cast_map, (void *)tp);
132   } else {
133     res = NEW_ARR_F(ir_node *, 0);
134     pmap_insert(type_cast_map, (void *)tp, (void *)res);
135   }
136   return res;
137 }
138
139 void set_type_cast_array(ir_type *tp, ir_node **alls) {
140   ir_node **old = pmap_get(type_cast_map, (void *)tp);
141   if (old != alls)
142     pmap_insert(type_cast_map, (void *)tp, (void *)alls);
143 }
144
145 /**
146  * Return a flexible array containing all pointer
147  * types that points-to a given type.
148  */
149 static ir_type **get_type_pointertype_array(ir_type *tp) {
150   ir_type **res;
151   if (!type_pointertype_map) type_pointertype_map = pmap_create();
152
153   if (pmap_contains(type_pointertype_map, (void *)tp)) {
154     res = (ir_type **) pmap_get(type_pointertype_map, (void *)tp);
155   } else {
156     res = NEW_ARR_F(ir_type *, 0);
157     pmap_insert(type_pointertype_map, (void *)tp, (void *)res);
158   }
159
160   return res;
161 }
162 void set_type_pointertype_array(ir_type *tp, ir_type **pts) {
163   ir_type **old = pmap_get(type_pointertype_map, (void *)tp);
164   if (old != pts)
165     pmap_insert(type_pointertype_map, (void *)tp, (void *)pts);
166 }
167
168 /**
169  * Return a flexible array containing all array
170  * types that have a given type as element type.
171  */
172 static ir_type **get_type_arraytype_array(ir_type *tp) {
173   ir_type **res;
174   if (!type_arraytype_map) type_arraytype_map = pmap_create();
175
176   if (pmap_contains(type_arraytype_map, (void *)tp)) {
177     res = (ir_type **) pmap_get(type_arraytype_map, (void *)tp);
178   } else {
179     res = NEW_ARR_F(ir_type *, 0);
180     pmap_insert(type_arraytype_map, (void *)tp, (void *)res);
181   }
182
183   return res;
184 }
185
186 void set_type_arraytype_array(ir_type *tp, ir_type **pts) {
187   ir_type **old = pmap_get(type_arraytype_map, (void *)tp);
188   if (old != pts)
189     pmap_insert(type_arraytype_map, (void *)tp, (void *)pts);
190 }
191
192 /*------------------------------------------------------------------*/
193 /* Accessing the out data structures.                               */
194 /* These routines only work properly if firm is in state            */
195 /* trouts_consistent or trouts_inconsistent.                        */
196 /*------------------------------------------------------------------*/
197
198 /**------------------------------------------------------------------*/
199 /*   Access routines for entities                                    */
200 /**------------------------------------------------------------------*/
201
202 int get_entity_n_accesses(ir_entity *ent) {
203   ir_node ** accs;
204
205   assert(ent && is_entity(ent));
206
207   accs = get_entity_access_array(ent);
208   return ARR_LEN(accs);
209 }
210
211 ir_node *get_entity_access(ir_entity *ent, int pos) {
212   ir_node ** accs;
213
214   assert(0 <= pos && pos < get_entity_n_accesses(ent));
215
216   accs = get_entity_access_array(ent);
217   return accs[pos];
218 }
219
220 void add_entity_access(ir_entity *ent, ir_node *n) {
221   ir_node ** accs;
222
223   assert(ent && is_entity(ent));
224   assert(n && is_ir_node(n));
225
226   accs = get_entity_access_array(ent);
227   ARR_APP1(ir_node *, accs, n);
228   set_entity_access_array(ent, accs);
229 }
230
231 void set_entity_access(ir_entity *ent, int pos, ir_node *n) {
232   ir_node ** accs;
233
234   assert(0 <= pos && pos < get_entity_n_accesses(ent));
235   assert(n && is_ir_node(n));
236
237   accs = get_entity_access_array(ent);
238   accs[pos] = n;
239 }
240
241 /**------------------------------------------------------------------*/
242
243 int get_entity_n_references(ir_entity *ent) {
244   ir_node ** refs;
245
246   assert(ent && is_entity(ent));
247
248   refs = get_entity_reference_array(ent);
249   return ARR_LEN(refs);
250 }
251
252 ir_node *get_entity_reference(ir_entity *ent, int pos) {
253   ir_node ** refs;
254
255   assert(0 <= pos && pos < get_entity_n_references(ent));
256
257   refs = get_entity_reference_array(ent);
258   return refs[pos];
259 }
260
261 void add_entity_reference(ir_entity *ent, ir_node *n) {
262   ir_node ** refs;
263
264   assert(ent && is_entity(ent));
265   assert(n && is_ir_node(n));
266
267   refs = get_entity_reference_array(ent);
268   ARR_APP1(ir_node *, refs, n);
269   set_entity_reference_array(ent, refs);
270 }
271
272 void set_entity_reference(ir_entity *ent, int pos, ir_node *n) {
273   ir_node ** refs;
274
275   assert(0 <= pos && pos < get_entity_n_references(ent));
276   assert(n && is_ir_node(n));
277
278   refs = get_entity_reference_array(ent);
279   refs[pos] = n;
280 }
281
282
283 /**------------------------------------------------------------------*/
284 /*   Access routines for types                                       */
285 /**------------------------------------------------------------------*/
286
287 /* Number of Alloc nodes that create an instance of this type */
288 int get_type_n_allocs(ir_type *tp) {
289   ir_node **allocs;
290
291   assert(tp && is_type(tp));
292
293   allocs = get_type_alloc_array(tp);
294   return ARR_LEN(allocs);
295 }
296
297 /* Alloc node that creates an instance of this type */
298 ir_node *get_type_alloc(ir_type *tp, int pos) {
299   ir_node **allocs;
300   assert(0 <= pos && pos < get_type_n_allocs(tp));
301
302   allocs = get_type_alloc_array(tp);
303   return allocs[pos];
304 }
305
306 void add_type_alloc(ir_type *tp, ir_node *n) {
307   ir_node **allocs;
308
309   assert(tp && is_type(tp));
310   assert(n && is_ir_node(n));
311
312   allocs = get_type_alloc_array(tp);
313   ARR_APP1(ir_node *, allocs, n);
314   set_type_alloc_array(tp, allocs);
315 }
316
317 void set_type_alloc(ir_type *tp, int pos, ir_node *n) {
318   ir_node **allocs;
319
320   assert(0 <= pos && pos < get_type_n_allocs(tp));
321   assert(n && is_ir_node(n));
322
323   allocs = get_type_alloc_array(tp);
324   allocs[pos] = n;
325 }
326
327 /* Number of Cast nodes that create an instance of this type */
328 int get_type_n_casts(ir_type *tp) {
329   ir_node **casts;
330
331   assert(tp && is_type(tp));
332
333   casts = get_type_cast_array(tp);
334   return ARR_LEN(casts);
335 }
336
337
338 int get_class_n_upcasts(ir_type *clss) {
339   int i, n_casts = get_type_n_casts(clss);
340   int n_instances = 0;
341   for (i = 0; i < n_casts; ++i) {
342     ir_node *cast = get_type_cast(clss, i);
343     if (is_Cast_upcast(cast)) n_instances ++;
344   }
345   return n_instances;
346 }
347
348 int get_class_n_downcasts(ir_type *clss) {
349   int i, n_casts = get_type_n_casts(clss);
350   int n_instances = 0;
351   for (i = 0; i < n_casts; ++i) {
352     ir_node *cast = get_type_cast(clss, i);
353     if (is_Cast_downcast(cast)) n_instances ++;
354   }
355   return n_instances;
356 }
357
358
359 /* Cast node that creates an instance of this type */
360 ir_node *get_type_cast(ir_type *tp, int pos) {
361   ir_node **casts;
362   assert(0 <= pos && pos < get_type_n_casts(tp));
363
364   casts = get_type_cast_array(tp);
365   return casts[pos];
366 }
367
368 void add_type_cast(ir_type *tp, ir_node *n) {
369   ir_node **casts;
370
371   assert(tp && is_type(tp));
372   assert(n && is_ir_node(n));
373
374   casts = get_type_cast_array(tp);
375   ARR_APP1(ir_node *, casts, n);
376   set_type_cast_array(tp, casts);
377 }
378
379 void set_type_cast(ir_type *tp, int pos, ir_node *n) {
380   ir_node **casts;
381
382   assert(0 <= pos && pos < get_type_n_casts(tp));
383   assert(n && is_ir_node(n));
384
385   casts = get_type_cast_array(tp);
386   casts[pos] = n;
387 }
388
389 /**------------------------------------------------------------------*/
390
391 int get_type_n_pointertypes_to(ir_type *tp) {
392   ir_type ** pts;
393
394   assert(tp && is_type(tp));
395
396   pts = get_type_pointertype_array(tp);
397   return ARR_LEN(pts);
398 }
399
400 ir_type *get_type_pointertype_to(ir_type *tp, int pos) {
401   ir_type ** pts;
402
403   assert(0 <= pos && pos < get_type_n_pointertypes_to(tp));
404
405   pts = get_type_pointertype_array(tp);
406   return pts[pos];
407 }
408
409 void add_type_pointertype_to(ir_type *tp, ir_type *ptp) {
410   ir_type ** pts;
411
412   assert(tp && is_type(tp));
413   assert(ptp && is_Pointer_type(ptp));
414
415   pts = get_type_pointertype_array(tp);
416   ARR_APP1(ir_node *, pts, ptp);
417   set_type_pointertype_array(tp, pts);
418 }
419
420 void set_type_pointertype_to(ir_type *tp, int pos, ir_type *ptp) {
421   ir_type ** pts;
422
423   assert(0 <= pos && pos < get_type_n_pointertypes_to(tp));
424   assert(ptp && is_Pointer_type(ptp));
425
426   pts = get_type_pointertype_array(tp);
427   pts[pos] = ptp;
428 }
429
430
431 /**------------------------------------------------------------------*/
432
433 int   get_type_n_arraytypes_of(ir_type *tp) {
434   ir_type ** pts;
435
436   assert(tp && is_type(tp));
437
438   pts = get_type_arraytype_array(tp);
439   return ARR_LEN(pts);
440 }
441
442 ir_type *get_type_arraytype_of(ir_type *tp, int pos) {
443   ir_type ** pts;
444
445   assert(0 <= pos && pos < get_type_n_arraytypes_of(tp));
446
447   pts = get_type_arraytype_array(tp);
448   return pts[pos];
449 }
450
451 void  add_type_arraytype_of(ir_type *tp, ir_type *atp) {
452   ir_type ** pts;
453
454   assert(tp && is_type(tp));
455   assert(atp && is_Array_type(atp));
456
457   pts = get_type_arraytype_array(tp);
458   ARR_APP1(ir_node *, pts, atp);
459   set_type_arraytype_array(tp, pts);
460 }
461
462 void  set_type_arraytype_of(ir_type *tp, int pos, ir_type *atp) {
463   ir_type ** pts;
464
465   assert(0 <= pos && pos < get_type_n_arraytypes_of(tp));
466   assert(atp && is_Array_type(atp));
467
468   pts = get_type_arraytype_array(tp);
469   pts[pos] = atp;
470 }
471
472 /*------------------------------------------------------------------*/
473 /* Building and Removing the out datastructure                      */
474 /*------------------------------------------------------------------*/
475
476 static void init_trouts(void) {
477
478 }
479
480 /** The number of entities that can be accessed by this Sel node. */
481 static int get_Sel_n_accessed_entities(ir_node *sel) {
482   return 1;
483 }
484
485 /** The entity that cat be accessed by this Sel node. */
486 static ir_entity *get_Sel_accessed_entity(ir_node *sel) {
487   return get_Sel_entity(sel);
488 }
489
490 /** An addr node is a SymConst or a Sel. */
491 static int get_addr_n_entities(ir_node *addr) {
492   int n_ents;
493
494   switch (get_irn_opcode(addr)) {
495   case iro_Sel:
496     /* Treat jack array sels? */
497     n_ents = get_Sel_n_accessed_entities(addr);
498     break;
499   case iro_SymConst:
500     if (get_SymConst_kind(addr) == symconst_addr_ent) {
501       n_ents = 1;
502       break;
503     }
504   default:
505     //assert(0 && "unexpected address expression");
506     n_ents = 0;
507   }
508
509   return n_ents;
510 }
511
512 /** An addr node is a SymConst or a Sel.
513     If Sel follow to outermost of compound. */
514 static ir_entity *get_addr_entity(ir_node *addr, int pos) {
515   ir_entity *ent;
516
517   switch (get_irn_opcode(addr)) {
518   case iro_Sel:
519     /* Treat jack array sels? They are compounds!  Follow to outermost entity.  */
520     while (is_Sel(get_Sel_ptr(addr))) {
521       addr = get_Sel_ptr(addr);
522     }
523     assert (0 <= pos && pos < get_Sel_n_accessed_entities(addr));
524     ent = get_Sel_accessed_entity(addr);
525     break;
526   case iro_SymConst:
527     if (get_SymConst_kind(addr) == symconst_addr_ent) {
528       assert(pos == 0);
529       ent = get_SymConst_entity(addr);
530       break;
531     }
532   default:
533     ent = NULL;
534   }
535
536   return ent;
537 }
538
539 static void chain_accesses(ir_node *n, void *env) {
540   int i, n_ents;
541   ir_node *addr;
542
543   if (get_irn_op(n) == op_Alloc) {
544     add_type_alloc(get_Alloc_type(n), n);
545     return;
546   } else
547
548   if (get_irn_op(n) == op_Cast) {
549     add_type_cast(get_Cast_type(n), n);
550     return;
551   } else
552
553   if (get_irn_op(n) == op_Sel) {
554     add_entity_reference(get_Sel_entity(n), n);
555     return;
556   } else if (get_irn_op(n) == op_SymConst && (get_SymConst_kind(n) == symconst_addr_ent)) {
557     add_entity_reference(get_SymConst_entity(n), n);
558     return;
559   } else
560
561   if (is_memop(n)) {
562     addr = get_memop_ptr(n);
563   } else if (get_irn_op(n) == op_Call) {
564     addr = get_Call_ptr(n);
565     if (! is_Sel(addr)) return;  /* Sels before Calls mean a Load / polymorphic Call. */
566   } else {
567     return;
568   }
569
570   n_ents = get_addr_n_entities(addr);  /* == 1 */
571   for (i = 0; i < n_ents; ++i) {
572     ir_entity *ent = get_addr_entity(addr, i);
573     if (ent)
574       add_entity_access(ent, n);
575     //else
576       //add_unrecognized_access(n);
577   }
578 }
579
580 static void chain_types(ir_type *tp) {
581   if (is_Pointer_type(tp)) {
582     add_type_pointertype_to(get_pointer_points_to_type(tp), tp);
583   } else if (is_Array_type(tp)) {
584     add_type_arraytype_of(get_array_element_type(tp), tp);
585   }
586 }
587
588 irg_outs_state get_trouts_state(void) {
589   return irp->trouts_state;
590 }
591 void           set_trouts_inconsistent(void) {
592   if (irp->trouts_state == outs_consistent)
593     irp->trouts_state = outs_inconsistent;
594 }
595
596
597 /* compute the field temperature. */
598 void compute_trouts(void) {
599   int i,
600       n_irgs = get_irp_n_irgs(),
601       n_types = get_irp_n_types();
602
603   free_trouts();
604   init_trouts();
605
606   /* Compute outs for irnodes. */
607   for (i = 0; i < n_irgs; i++) {
608     irg_walk_graph(get_irp_irg(i), NULL, chain_accesses, NULL);
609   }
610   walk_const_code(NULL, chain_accesses, NULL);
611
612   /* Compute outs for types */
613   for (i = 0; i < n_types; ++i) {
614     chain_types(get_irp_type(i));
615   }
616
617   irp->trouts_state = outs_consistent;
618 }
619
620
621 void free_trouts(void) {
622
623   if (entity_access_map) {
624     ir_node **accs;
625     for (accs = (ir_node **)pmap_first(entity_access_map);
626          accs;
627          accs = (ir_node **)pmap_next(entity_access_map))
628       ; //DEL_ARR_F(accs);
629     pmap_destroy(entity_access_map);
630     entity_access_map = NULL;
631   }
632
633   if (entity_reference_map) {
634     ir_node **refs;
635     for (refs = (ir_node **)pmap_first(entity_reference_map);
636          refs;
637          refs = (ir_node **)pmap_next(entity_reference_map))
638       ; //DEL_ARR_F(refs);
639     pmap_destroy(entity_reference_map);
640     entity_reference_map = NULL;
641   }
642
643   if (type_alloc_map) {
644     ir_node **alls;
645     for (alls = (ir_node **)pmap_first(type_alloc_map);
646          alls;
647          alls = (ir_node **)pmap_next(type_alloc_map))
648       ; //DEL_ARR_F(alls);
649     pmap_destroy(type_alloc_map);
650     type_alloc_map = NULL;
651   }
652
653   if (type_cast_map) {
654     ir_node **casts;
655     for (casts = (ir_node **)pmap_first(type_cast_map);
656          casts;
657          casts = (ir_node **)pmap_next(type_cast_map))
658       ; //DEL_ARR_F(alls);
659     pmap_destroy(type_cast_map);
660     type_cast_map = NULL;
661   }
662
663   if (type_pointertype_map) {
664     ir_node **pts;
665     for (pts = (ir_node **)pmap_first(type_pointertype_map);
666          pts;
667          pts = (ir_node **)pmap_next(type_pointertype_map))
668       ; //DEL_ARR_F(pts);
669     pmap_destroy(type_pointertype_map);
670     type_pointertype_map = NULL;
671   }
672
673   if (type_arraytype_map) {
674     ir_node **pts;
675     for (pts = (ir_node **)pmap_first(type_arraytype_map);
676          pts;
677          pts = (ir_node **)pmap_next(type_arraytype_map))
678       ; //DEL_ARR_F(pts);
679     pmap_destroy(type_arraytype_map);
680     type_arraytype_map = NULL;
681   }
682
683   irp->trouts_state = outs_none;
684 }