9f1f3131e1518c5bf6e4631a366e8334c8f2a638
[libfirm] / ir / ana / cgana.c
1 /* -------------------------------------------------------------------
2  * $Id$
3  * -------------------------------------------------------------------
4  * Intraprozedurale Analyse zur Abschätzung der Aufrulrelation. Es
5  * wird eine Menge von freien Methoden und anschließend die an den
6  * Call-Operationen aufrufbaren Methoden bestimmt.
7  *
8  * Erstellt: Hubert Schmid, 09.06.2002
9  * ---------------------------------------------------------------- */
10
11 #include "stdlib.h"
12 #include "cgana.h"
13
14
15 #include "eset.h"
16 #include "pmap.h"
17 #include "array.h"
18 #include "irprog.h"
19 #include "irgwalk.h"
20 #include "ircons.h"
21 #include "irgmod.h"
22 #include "xprintf.h"
23 #include "irnode.h"
24
25 #include "dbginfo_t.h"
26
27 /* Eindeutige Adresse zur Markierung von besuchten Knoten und zur
28  * Darstellung der unbekannten Methode. */
29 static void * MARK = &MARK;
30
31
32
33 /* --- sel methods ---------------------------------------------------------- */
34
35
36 static eset * entities = NULL;
37
38
39 /* Bestimmt die eindeutige Methode, die die Methode für den
40  * übergebenene (dynamischen) Typ überschreibt. */
41 static entity * get_implementation(type * class, entity * method) {
42   int i;
43   if (get_entity_peculiarity(method) != description &&
44       get_entity_owner(method) == class) {
45     return method;
46   }
47   for (i = get_entity_n_overwrittenby(method) - 1; i >= 0; --i) {
48     entity * e = get_entity_overwrittenby(method, i);
49     if (get_entity_peculiarity(e) != description && get_entity_owner(e) == class) {
50       return e;
51     }
52   }
53   for (i = get_class_n_supertypes(class) - 1; i >= 0; --i) {
54     entity * e = get_implementation(get_class_supertype(class, i), method);
55     if (e) {
56       return e;
57     }
58   }
59   assert(0 && "implemenation not found");
60 }
61
62 /* Returns the entity that contains the implementation of the inherited
63    entity if available, else returns the entity passed. */
64 entity *get_inherited_methods_implementation(entity *inh_meth) {
65   entity *impl_meth = NULL;
66   ir_node *addr = get_atomic_ent_value(inh_meth);
67   assert(addr && "constant entity without value");
68
69   if (get_irn_op(addr) == op_Const) {
70     impl_meth = get_tv_entity(get_Const_tarval(addr));
71   }
72
73   assert(!impl_meth || get_entity_peculiarity(impl_meth) == existent);
74   return impl_meth? impl_meth : inh_meth;
75 }
76
77
78 /* Collect the entity representing the implementation of this
79    entity (not the same if inherited) and all entities for overwriting
80    implementations in "set".
81    If the implementation of the method is not included in the
82    compilation unit "open" is set to true.
83    A recursive descend in the overwritten relation.
84    Cycle-free, therefore must terminate. */
85 void collect_impls(entity *method, eset *set, int *size, bool *open) {
86   int i;
87   if (get_entity_peculiarity(method) == existent) {
88     if (get_entity_visibility(method) == external_allocated) {
89       assert(get_entity_irg(method) == NULL);
90       *open = true;
91     } else {
92       assert(get_entity_irg(method) != NULL);
93       if (!eset_contains(set, method)) {
94         eset_insert(set, method);
95         ++(*size);
96       }
97     }
98   }
99   if (get_entity_peculiarity(method) == inherited) {
100     entity *impl_ent = get_inherited_methods_implementation(method);
101     assert(impl_ent && "no implementation for inherited entity");
102     if (get_entity_visibility(impl_ent) == external_allocated) {
103       assert(get_entity_irg(impl_ent) == NULL);
104       *open = true;
105     } else {
106       assert(get_entity_irg(impl_ent) != NULL);
107       if (!eset_contains(set, impl_ent)) {
108         eset_insert(set, impl_ent);
109         ++(*size);
110       }
111     }
112   }
113   /** recursive descend **/
114   for (i = get_entity_n_overwrittenby(method) - 1; i >= 0; --i)
115     collect_impls(get_entity_overwrittenby(method, i), set, size, open);
116 }
117
118
119 /* Alle Methoden bestimmen, die die übergebene Methode überschreiben
120  * (und implementieren). In der zurückgegebenen Reihung kommt jede
121  * Methode nur einmal vor. Der Wert 'NULL' steht für unbekannte
122  * (externe) Methoden. Die zurückgegebene Reihung muß vom Aufrufer
123  * wieder freigegeben werden (siehe "DEL_ARR_F"). Gibt es überhaupt
124  * keine Methoden, die die "method" überschreiben, so gibt die Methode
125  * "NULL" zurück. */
126 static entity ** get_impl_methods(entity * method) {
127   eset * set = eset_create();
128   int size = 0;
129   entity ** arr;
130   bool open = false;
131
132   /** Collect all method entities that can be called here **/
133   collect_impls(method, set, &size, &open);
134
135 /**
136      Vorgaenger einfuegen. **/
137   if (size == 0 && !open) {
138     /* keine implementierte überschriebene Methode */
139     arr = NULL;
140   } else if (open) {
141     entity * ent;
142     arr = NEW_ARR_F(entity *, size + 1);
143     arr[0] = NULL;  /* Represents open method */
144     for (ent = eset_first(set); size > 0; ent = eset_next(set), --size)
145       arr[size] = ent;
146   } else {
147     entity * ent;
148     arr = NEW_ARR_F(entity *, size);
149     for (size -= 1, ent = eset_first(set); size >= 0; ent = eset_next(set), --size)
150       arr[size] = ent;
151   }
152   eset_destroy(set);
153   return arr;
154 }
155
156
157 /* debug makros used in sel_methods_walker */
158 #define SIZ(x)    sizeof(x)/sizeof((x)[0])
159
160 #define DBG_OPT_NORMALIZE                                                      \
161           __dbg_info_merge_pair(new_node, node, dbg_const_eval)
162 #define DBG_OPT_POLY_ALLOC                                                     \
163   do {                                                                         \
164         ir_node *ons[2];                                                       \
165         ons[0] = node;                                                         \
166         ons[1] = skip_Proj(get_Sel_ptr(node));                                 \
167         __dbg_info_merge_sets(&new_node, 1, ons, SIZ(ons), dbg_rem_poly_call); \
168      } while(0)
169 #define DBG_OPT_POLY                                                           \
170           __dbg_info_merge_pair(new_node, node, dbg_rem_poly_call)
171
172
173 static void sel_methods_walker(ir_node * node, pmap * ldname_map) {
174   if (get_irn_op(node) == op_SymConst) {
175     /* Wenn möglich SymConst-Operation durch Const-Operation
176      * ersetzen. */
177     if (get_SymConst_kind(node) == linkage_ptr_info) {
178       pmap_entry * entry = pmap_find(ldname_map, (void *) get_SymConst_ptrinfo(node));
179       if (entry != NULL) { /* Method is declared in the compiled code */
180         entity * ent = entry->value;
181         if (get_opt_normalize() && (get_entity_visibility(ent) != external_allocated)) { /* Meth. is defined */
182           ir_node *new_node;
183           assert(get_entity_irg(ent));
184           set_irg_current_block(current_ir_graph, get_nodes_Block(node));
185           new_node = new_d_Const(get_irn_dbg_info(node),
186                                  mode_P, tarval_P_from_entity(ent));       DBG_OPT_NORMALIZE;
187           exchange(node, new_node);
188         }
189       }
190     }
191   } else if (get_irn_op(node) == op_Sel &&
192              is_method_type(get_entity_type(get_Sel_entity(node)))) {
193     entity * ent = get_Sel_entity(node);
194     if (get_optimize() && get_opt_dyn_meth_dispatch() &&
195         (get_irn_op(skip_Proj(get_Sel_ptr(node))) == op_Alloc)) {
196       ir_node *new_node;
197       /* We know which method will be called, no dispatch necessary. */
198       assert(get_entity_peculiarity(ent) != description);
199       set_irg_current_block(current_ir_graph, get_nodes_Block(node));
200       /* @@@ Is this correct?? Alloc could reference a subtype of the owner
201          of Sel that overwrites the method referenced in Sel. */
202       new_node = copy_const_value(get_atomic_ent_value(ent));              DBG_OPT_POLY_ALLOC;
203       exchange (node, new_node);
204     } else {
205       assert(get_entity_peculiarity(ent) != inherited);
206       if (!eset_contains(entities, ent)) {
207         /* Entity noch nicht behandelt. Alle (intern oder extern)
208          * implementierten Methoden suchen, die diese Entity
209          * überschreiben. Die Menge an entity.link speichern. */
210         set_entity_link(ent, get_impl_methods(ent));
211         eset_insert(entities, ent);
212       }
213       if (get_entity_link(ent) == NULL) {
214         /* Die Sel-Operation kann nie einen Zeiger auf eine aufrufbare
215          * Methode zurückgeben. Damit ist sie insbesondere nicht
216          * ausführbar und nicht erreichbar. */
217         /* Gib eine Warnung aus wenn die Entitaet eine Beschreibung ist
218            fuer die es keine Implementierung gibt. */
219         if (get_entity_peculiarity(ent) == description) {
220           /* @@@ GL Methode um Fehler anzuzeigen aufrufen! */
221           xprintf("WARNING: Calling method description %I in method %I which has "
222                   "no implementation!\n", get_entity_ident(ent),
223                   get_entity_ident(get_irg_ent(current_ir_graph)));
224         } else {
225           exchange(node, new_Bad());
226         }
227       } else {
228         entity ** arr = get_entity_link(ent);
229
230 #if 0
231         int i;
232         printf("\nCall site "); DDMN(node);
233         printf("  in "); DDME(get_irg_ent(current_ir_graph));
234         printf("  can call:\n");
235         for (i = 0; i < ARR_LEN(arr); i++) {
236           printf("   - "); DDME(arr[i]);
237           printf("     with owner "); DDMT(get_entity_owner(arr[i]));
238         }
239         printf("\n");
240 #endif
241
242         if (get_optimize() && get_opt_dyn_meth_dispatch() &&
243             (ARR_LEN(arr) == 1 && arr[0] != NULL)) {
244           ir_node *new_node;
245           /* Die Sel-Operation kann immer nur einen Wert auf eine
246            * interne Methode zurückgeben. Wir können daher die
247            * Sel-Operation durch eine Const- bzw. SymConst-Operation
248            * ersetzen. */
249           set_irg_current_block(current_ir_graph, get_nodes_Block(node));
250           new_node = copy_const_value(get_atomic_ent_value(arr[0]));         DBG_OPT_POLY;
251           exchange (node, new_node);
252         }
253       }
254     }
255   }
256 }
257
258
259 /* Datenstruktur initialisieren. Zusätzlich werden alle
260  * SymConst-Operationen, die auf interne Methoden verweisen, durch
261  * Const-Operationen ersetzt. */
262 static void sel_methods_init(void) {
263   int i;
264   pmap * ldname_map = pmap_create();
265   assert(entities == NULL);
266   entities = eset_create();
267   for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
268     entity * ent = get_irg_ent(get_irp_irg(i));
269     /* Nur extern sichtbare Methode können überhaupt mit SymConst
270      * aufgerufen werden. */
271     if (get_entity_visibility(ent) != local) {
272       pmap_insert(ldname_map, (void *) get_entity_ld_ident(ent), ent);
273     }
274   }
275   all_irg_walk((irg_walk_func *) sel_methods_walker, NULL, ldname_map);
276   pmap_destroy(ldname_map);
277 }
278
279 /*****************************************************************************/
280
281 /* Datenstruktur freigeben. */
282 static void sel_methods_dispose(void) {
283   entity * ent;
284   assert(entities);
285   for (ent = eset_first(entities); ent; ent = eset_next(entities)) {
286     entity ** arr = get_entity_link(ent);
287     if (arr) {
288       DEL_ARR_F(arr);
289     }
290     set_entity_link(ent, NULL);
291   }
292   eset_destroy(entities);
293   entities = NULL;
294 }
295
296
297 /* Gibt die Menge aller Methoden zurück, die an diesem Sel-Knoten
298  * zurückgegeben werden können. Die Liste enthält keine doppelten
299  * Einträge. */
300 static entity ** get_Sel_arr(ir_node * sel) {
301   static entity ** NULL_ARRAY = NULL;
302   entity * ent;
303   entity ** arr;
304   assert(sel && get_irn_op(sel) == op_Sel);
305   ent = get_Sel_entity(sel);
306   assert(is_method_type(get_entity_type(ent))); /* what else? */
307   arr = get_entity_link(ent);
308   if (arr) {
309     return arr;
310   } else {
311     /* "NULL" zeigt an, dass keine Implementierung existiert. Dies
312      * kann für polymorphe (abstrakte) Methoden passieren. */
313     if (!NULL_ARRAY) {
314       NULL_ARRAY = NEW_ARR_F(entity *, 0);
315     }
316     return NULL_ARRAY;
317   }
318 }
319
320
321 static int get_Sel_n_methods(ir_node * sel) {
322   return ARR_LEN(get_Sel_arr(sel));
323 }
324
325
326 static entity * get_Sel_method(ir_node * sel, int pos) {
327   entity ** arr = get_Sel_arr(sel);
328   assert(pos >= 0 && pos < ARR_LEN(arr));
329   return arr[pos];
330 }
331
332
333
334 /* --- callee analysis ------------------------------------------------------ */
335
336
337 static void callee_ana_node(ir_node * node, eset * methods);
338
339
340 static void callee_ana_proj(ir_node * node, long n, eset * methods) {
341   assert(get_irn_mode(node) == mode_T);
342   if (get_irn_link(node) == MARK) {
343     /* already visited */
344     return;
345   }
346   set_irn_link(node, MARK);
347
348   switch (get_irn_opcode(node)) {
349   case iro_Proj: {
350     /* proj_proj: in einem "sinnvollen" Graphen kommt jetzt ein
351      * op_Tuple oder ein Knoten, der eine "freie Methode"
352      * zurückgibt. */
353     ir_node * pred = get_Proj_pred(node);
354     if (get_irn_link(pred) != MARK) {
355       if (get_irn_op(pred) == op_Tuple) {
356         callee_ana_proj(get_Tuple_pred(pred, get_Proj_proj(node)), n, methods);
357       } else {
358         eset_insert(methods, MARK); /* free method -> unknown */
359       }
360     }
361     break;
362   }
363
364   case iro_Tuple:
365     callee_ana_node(get_Tuple_pred(node, n), methods);
366     break;
367
368   case iro_Id:
369     callee_ana_proj(get_Id_pred(node), n, methods);
370     break;
371
372   default:
373     eset_insert(methods, MARK); /* free method -> unknown */
374     break;
375   }
376
377   set_irn_link(node, NULL);
378 }
379
380
381 static void callee_ana_node(ir_node * node, eset * methods) {
382   int i;
383
384   assert((get_irn_mode(node) == mode_P) || is_Bad(node));
385   /* rekursion verhindern */
386   if (get_irn_link(node) == MARK) {
387     /* already visited */
388     return;
389   }
390   set_irn_link(node, MARK);
391
392   switch (get_irn_opcode(node)) {
393   case iro_SymConst:
394     /* externe Methode (wegen fix_symconst!) */
395     eset_insert(methods, MARK); /* free method -> unknown */
396     break;
397
398   case iro_Const: {
399     /* interne Methode */
400     entity * ent = get_Const_tarval(node)->u.P.ent;
401     assert(ent && is_method_type(get_entity_type(ent)));
402     if (get_entity_visibility(ent) != external_allocated) {
403       assert(get_entity_irg(ent));
404       eset_insert(methods, ent);
405     } else {
406       eset_insert(methods, MARK); /* free method -> unknown */
407     }
408     break;
409   }
410
411   case iro_Sel:
412     /* polymorphe Methode */
413     for (i = get_Sel_n_methods(node) - 1; i >= 0; --i) {
414       entity * ent = get_Sel_method(node, i);
415       if (ent) {
416         eset_insert(methods, ent);
417       } else {
418         eset_insert(methods, MARK);
419       }
420     }
421     break;
422
423   case iro_Bad:
424     /* nothing */
425     break;
426
427   case iro_Phi: /* Vereinigung */
428     for (i = get_Phi_n_preds(node) - 1; i >= 0; --i) {
429       callee_ana_node(get_Phi_pred(node, i), methods);
430     }
431     break;
432
433   case iro_Id:
434     callee_ana_node(get_Id_pred(node), methods);
435     break;
436
437   case iro_Proj:
438     callee_ana_proj(get_Proj_pred(node), get_Proj_proj(node), methods);
439     break;
440
441   case iro_Add:
442   case iro_Sub:
443   case iro_Conv:
444     /* extern */
445     eset_insert(methods, MARK); /* free method -> unknown */
446     break;
447
448   default:
449     assert(0 && "invalid opcode or opcode not implemented");
450     break;
451   }
452
453   set_irn_link(node, NULL);
454 }
455
456
457 static void callee_walker(ir_node * call, void * env) {
458   if (get_irn_op(call) == op_Call) {
459     eset * methods = eset_create();
460     entity * ent;
461     entity ** arr = NEW_ARR_F(entity *, 0);
462     callee_ana_node(skip_nop(get_Call_ptr(call)), methods);
463     if (eset_contains(methods, MARK)) { /* unknown method */
464       ARR_APP1(entity *, arr, NULL);
465     }
466     for (ent = eset_first(methods); ent; ent = eset_next(methods)) {
467       if (ent != MARK) {
468         ARR_APP1(entity *, arr, ent);
469       }
470     }
471     if (ARR_LEN(arr) == 0) {
472       /* Kann vorkommen, wenn der Vorgänger beispielsweise eine
473        * Sel-Operation war, die keine Methoden zurückgeben
474        * konnte. Wir ersetzen die Call-Operation ebenfalls durch
475        * eine Bad-Operation. Die Verlinkung muss wiederhergestellt
476        * werden! */
477       exchange(call, new_Bad());
478     } else {
479       set_Call_callee_arr(call, ARR_LEN(arr), arr);
480     }
481     DEL_ARR_F(arr);
482     eset_destroy(methods);
483   }
484 }
485
486
487 /* Bestimmt für jede Call-Operation die Menge der aufrufbaren Methode
488  * und speichert das Ergebnis in der Call-Operation. (siehe
489  * "set_Call_callee"). "sel_methods" wird für den Aufbau benötigt und
490  * muss bereits aufgebaut sein. */
491 static void callee_ana(void) {
492   int i;
493   /* Alle Graphen analysieren. */
494   for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
495     irg_walk_graph(get_irp_irg(i), callee_walker, NULL, NULL);
496   }
497 }
498
499
500
501 /* --- free method analysis ------------------------------------------------- */
502
503
504 static void free_mark(ir_node * node, eset * set);
505
506 static void free_mark_proj(ir_node * node, long n, eset * set) {
507   assert(get_irn_mode(node) == mode_T);
508   if (get_irn_link(node) == MARK) {
509     /* already visited */
510     return;
511   }
512   set_irn_link(node, MARK);
513   switch (get_irn_opcode(node)) {
514   case iro_Proj: {
515     /* proj_proj: in einem "sinnvollen" Graphen kommt jetzt ein
516      * op_Tuple oder ein Knoten, der in "free_ana_walker" behandelt
517      * wird. */
518     ir_node * pred = get_Proj_pred(node);
519     if (get_irn_link(pred) != MARK && get_irn_op(pred) == op_Tuple) {
520       free_mark_proj(get_Tuple_pred(pred, get_Proj_proj(node)), n, set);
521     } else {
522       /* nothing: da in "free_ana_walker" behandelt. */
523     }
524     break;
525   }
526
527   case iro_Tuple:
528     free_mark(get_Tuple_pred(node, n), set);
529     break;
530
531   case iro_Id:
532     free_mark_proj(get_Id_pred(node), n, set);
533     break;
534
535   case iro_Start:
536   case iro_Alloc:
537   case iro_Load:
538     /* nothing: Die Operationen werden in "free_ana_walker" selbst
539      * behandelt. */
540     break;
541
542   default:
543     assert(0 && "unexpected opcode or opcode not implemented");
544     break;
545   }
546   set_irn_link(node, NULL);
547 }
548
549
550 static void free_mark(ir_node * node, eset * set) {
551   int i;
552   assert(get_irn_mode(node) == mode_P);
553   if (get_irn_link(node) == MARK) {
554     return; /* already visited */
555   }
556   set_irn_link(node, MARK);
557   switch (get_irn_opcode(node)) {
558   case iro_Sel: {
559     entity * ent = get_Sel_entity(node);
560     if (is_method_type(get_entity_type(ent))) {
561       for (i = get_Sel_n_methods(node) - 1; i >= 0; --i) {
562         eset_insert(set, get_Sel_method(node, i));
563       }
564     }
565     break;
566   }
567   case iro_SymConst:
568     /* nothing: SymConst points to extern method */
569     break;
570   case iro_Const: {
571     tarval * val = get_Const_tarval(node);
572     entity * ent = val->u.P.ent;
573     if (ent != NULL && is_method_type(get_entity_type(ent))) {
574       eset_insert(set, ent);
575     }
576     break;
577   }
578   case iro_Phi:
579     for (i = get_Phi_n_preds(node) - 1; i >= 0; --i) {
580       free_mark(get_Phi_pred(node, i), set);
581     }
582     break;
583   case iro_Id:
584     free_mark(get_Id_pred(node), set);
585     break;
586   case iro_Proj:
587     free_mark_proj(get_Proj_pred(node), get_Proj_proj(node), set);
588     break;
589   default:
590     /* nothing: Wird unten behandelt! */
591     break;
592   }
593   set_irn_link(node, NULL);
594 }
595
596
597 static void free_ana_walker(ir_node * node, eset * set) {
598   int i;
599   if (get_irn_link(node) == MARK) {
600     /* bereits in einem Zyklus besucht. */
601     return;
602   }
603   switch (get_irn_opcode(node)) {
604   /* special nodes */
605   case iro_Sel:
606   case iro_SymConst:
607   case iro_Const:
608   case iro_Phi:
609   case iro_Id:
610   case iro_Proj:
611   case iro_Tuple:
612     /* nothing */
613     break;
614   /* Sonderbehandlung, da der Funktionszeigereingang natürlich kein
615    * Verräter ist. */
616   case iro_Call:
617     set_irn_link(node, MARK);
618     for (i = get_Call_arity(node) - 1; i >= 0; --i) {
619       ir_node * pred = get_Call_param(node, i);
620       if (get_irn_mode(pred) == mode_P) {
621         free_mark(pred, set);
622       }
623     }
624     break;
625   /* other nodes: Alle anderen Knoten nehmen wir als Verräter an, bis
626    * jemand das Gegenteil implementiert. */
627   default:
628     set_irn_link(node, MARK);
629     for (i = get_irn_arity(node) - 1; i >= 0; --i) {
630       ir_node * pred = get_irn_n(node, i);
631       if (get_irn_mode(pred) == mode_P) {
632         free_mark(pred, set);
633       }
634     }
635     break;
636   }
637   set_irn_link(node, NULL);
638 }
639
640
641 /* Die Datenstrukturen für sel-Methoden (sel_methods) muß vor dem
642  * Aufruf von "get_free_methods" aufgebaut sein. Die (internen)
643  * SymConst-Operationen müssen in passende Const-Operationen
644  * umgewandelt worden sein, d.h. SymConst-Operationen verweisen immer
645  * auf eine echt externe Methode.  */
646 static entity ** get_free_methods(void) {
647   eset * set = eset_create();
648   int i;
649   entity ** arr = NEW_ARR_F(entity *, 0);
650   entity * ent;
651   for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
652     ir_graph * irg = get_irp_irg(i);
653     entity * ent = get_irg_ent(irg);
654     /* insert "external visible" methods. */
655     if (get_entity_visibility(ent) != local) {
656       eset_insert(set, ent);
657     }
658     irg_walk_graph(irg, NULL, (irg_walk_func *) free_ana_walker, set);
659   }
660   /* Hauptprogramm ist auch frei, auch wenn es nicht "external
661    * visible" ist. */
662   if(get_irp_main_irg()) {
663     eset_insert(set, get_irg_ent(get_irp_main_irg()));
664   }
665   for (ent = eset_first(set); ent; ent = eset_next(set)) {
666     ARR_APP1(entity *, arr, ent);
667   }
668   eset_destroy(set);
669
670   return arr;
671 }
672
673 void cgana(int *length, entity ***free_methods) {
674   entity ** free_meths;
675   int i;
676
677   sel_methods_init();
678   free_meths = get_free_methods();
679   callee_ana();
680   sel_methods_dispose();
681
682   /* Convert the flexible array to an array that can be handled
683      by standard C. */
684   *length = ARR_LEN(free_meths);
685   *free_methods = (entity **)malloc(sizeof(entity *) * (*length));
686   for (i = 0; i < (*length); i++) (*free_methods)[i] = free_meths[i];
687   DEL_ARR_F(free_meths);
688 }
689
690 /* Optimize the address expressions passed to call nodes.
691  * Alle SymConst-Operationen, die auf interne Methoden verweisen,
692  * werden durch Const-Operationen ersetzt.
693  * Sel Knoten deren entitaeten nicht ueberschrieben werden, werden
694  * durch Const ersetzt.
695  * Sel Knoten, fuer die keine Implementierung existiert, werden
696  * durch Bad ersetzt. */
697 void opt_call_addrs(void) {
698   sel_methods_init();
699   sel_methods_dispose();
700 #if 0
701   int i;
702   pmap * ldname_map = pmap_create();
703   assert(entities == NULL);
704   entities = eset_create();
705   for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
706     entity * ent = get_irg_ent(get_irp_irg(i));
707     /* Nur extern sichtbare Methoden können überhaupt mit SymConst
708      * aufgerufen werden. */
709     if (get_entity_visibility(ent) != local) {
710       pmap_insert(ldname_map, (void *) get_entity_ld_ident(ent), ent);
711     }
712   }
713   all_irg_walk((irg_walk_func *) sel_methods_walker, NULL, ldname_map);
714   pmap_destroy(ldname_map);
715 #endif
716 }