3 * File name: ir/ana/cgana.c
4 * Purpose: Intraprozedural analyses to estimate the call graph.
5 * Author: Hubert Schmid
9 * Copyright: (c) 1999-2003 Universität Karlsruhe
10 * Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE.
15 * Intraprozedurale Analyse zur Abschätzung der Aufrufrelation. Es
16 * wird eine Menge von freien Methoden und anschließend die an den
17 * Call-Operationen aufrufbaren Methoden bestimmt.
36 #include "dbginfo_t.h"
37 #include "iropt_dbg.h"
47 /* Eindeutige Adresse zur Markierung von besuchten Knoten und zur
48 * Darstellung der unbekannten Methode. */
49 static void * MARK = &MARK;
53 /* --- sel methods ---------------------------------------------------------- */
56 static eset * entities = NULL;
59 /** Bestimmt die eindeutige Methode, die die Methode für den
60 * übergebenen (dynamischen) Typ überschreibt. */
61 static entity * get_implementation(type * class, entity * method) {
63 if (get_entity_peculiarity(method) != peculiarity_description &&
64 get_entity_owner(method) == class) {
67 for (i = get_entity_n_overwrittenby(method) - 1; i >= 0; --i) {
68 entity * e = get_entity_overwrittenby(method, i);
69 if (get_entity_peculiarity(e) != peculiarity_description && get_entity_owner(e) == class) {
73 for (i = get_class_n_supertypes(class) - 1; i >= 0; --i) {
74 entity * e = get_implementation(get_class_supertype(class, i), method);
79 assert(0 && "implementation not found");
83 /** Returns the entity that contains the implementation of the inherited
84 entity if available, else returns the entity passed. */
85 static entity *get_inherited_methods_implementation(entity *inh_meth) {
86 assert(get_atomic_ent_value(inh_meth) && "constant entity without value");
87 assert((get_irn_op(get_atomic_ent_value(inh_meth)) == op_SymConst) &&
88 (get_SymConst_kind(get_atomic_ent_value(inh_meth)) == symconst_addr_ent) &&
89 "Complex constant values not supported -- address of method should be straight constant!");
91 return get_SymConst_entity(get_atomic_ent_value(inh_meth));
93 #if 0 // this stuff is outdated, I think. GL 10.11.04
94 entity *impl_meth = NULL;
95 ir_node *addr = get_atomic_ent_value(inh_meth);
97 assert(get_atomic_ent_value(inh_meth) && "constant entity without value");
99 if ((get_irn_op(addr) == op_SymConst) &&
100 (get_SymConst_kind(addr) == symconst_addr_ent)) {
101 impl_meth = get_SymConst_entity(addr);
103 assert(0 && "Complex constant values not supported -- address of method should be straight constant!");
106 if (impl_meth && (get_entity_peculiarity(impl_meth) != peculiarity_existent)) {
108 printf("this_meth: "); DDMEO(inh_meth);
109 printf("impl meth: "); DDMEO(impl_meth);
110 assert(!impl_meth || get_entity_peculiarity(impl_meth) == peculiarity_existent);
115 assert((impl_meth || inh_meth) && "no implementation for inherited entity");
116 return impl_meth? impl_meth : inh_meth;
121 /** Collect the entity representing the implementation of this
122 * entity (not the same if inherited) and all entities for overwriting
123 * implementations in "set".
124 * If the implementation of the method is not included in the
125 * compilation unit "open" is set to true.
126 * A recursive descend in the overwritten relation.
127 * Cycle-free, therefore must terminate.
130 * @param set A set of entities.
131 * @param size Number of entities in set.
134 static void collect_impls(entity *method, eset *set, int *size, bool *open) {
137 if (get_entity_peculiarity(method) == peculiarity_existent) {
138 if ((get_entity_visibility(method) == visibility_external_allocated)
139 && (NULL == get_entity_irg(method))) {
140 /* We could also add these entities to the callees, but right now we
141 subsume them by unknown_entity. */
144 assert(get_entity_irg(method) != NULL);
145 if (!eset_contains(set, method)) {
146 eset_insert(set, method);
152 if (get_entity_peculiarity(method) == peculiarity_inherited) {
153 entity *impl_ent = get_inherited_methods_implementation(method);
154 if (get_entity_visibility(impl_ent) == visibility_external_allocated) {
155 assert(get_entity_irg(impl_ent) == NULL);
158 assert(get_entity_irg(impl_ent) != NULL);
159 if (!eset_contains(set, impl_ent)) {
160 eset_insert(set, impl_ent);
166 /* Only the assertions: */
167 if (get_entity_peculiarity(method) == peculiarity_existent) {
168 if ((get_entity_visibility(method) == visibility_external_allocated)
169 && (NULL == get_entity_irg(method))) {
171 assert(get_entity_irg(method) != NULL);
174 if (get_entity_peculiarity(method) == peculiarity_inherited) {
175 entity *impl_ent = get_inherited_methods_implementation(method);
176 if (get_entity_visibility(impl_ent) == visibility_external_allocated) {
177 assert(get_entity_irg(impl_ent) == NULL);
179 assert(get_entity_irg(impl_ent) != NULL);
183 /* Add the implementation to the set if it contains an irg, else
184 remember that there are more methods called. */
185 /* @@@ We could also add unknown_entity, or the entities with the
186 unknown irgs. The first case would result in the exact same
187 behaviour: all unknown irgs are represented by the one and only
188 unknown entity. If we add all entities, we known the number of
189 entities possibly called, and whether there are real unknown
190 entities, i.e, such not represented in the type description.
191 This would be better for an analyses: it could rule out more
193 entity *impl = method;
194 if (get_entity_peculiarity(method) == peculiarity_inherited)
195 impl = get_inherited_methods_implementation(method);
197 if (get_entity_peculiarity(method) != peculiarity_description) {
198 //if (get_entity_irg(impl)) {
199 eset_insert(set, impl);
202 /* GL: better: eset_insert(set, unknown_entity); */
207 /*- recursive descent -*/
208 for (i = get_entity_n_overwrittenby(method) - 1; i >= 0; --i)
209 collect_impls(get_entity_overwrittenby(method, i), set, size, open);
213 /** Alle Methoden bestimmen, die die übergebene Methode überschreiben
214 * (und implementieren). In der zurückgegebenen Reihung kommt jede
215 * Methode nur einmal vor. Der Wert 'NULL' steht für unbekannte
216 * (externe) Methoden. Die zurückgegebene Reihung muß vom Aufrufer
217 * wieder freigegeben werden (siehe "DEL_ARR_F"). Gibt es überhaupt
218 * keine Methoden, die "method" überschreiben, so gibt die Methode
223 static entity ** get_impl_methods(entity * method) {
224 eset * set = eset_create();
229 /* Collect all method entities that can be called here */
230 collect_impls(method, set, &size, &open);
232 /* Vorgaenger einfuegen. */
233 if (size == 0 && !open) {
234 /* keine implementierte überschriebene Methode */
238 arr = NEW_ARR_F(entity *, size + 1);
239 arr[0] = NULL; /* Represents open method */
240 for (ent = eset_first(set); size > 0; ent = eset_next(set), --size)
244 arr = NEW_ARR_F(entity *, size);
245 for (size -= 1, ent = eset_first(set); size >= 0; ent = eset_next(set), --size)
252 /** Analyse address computations.
254 * - If the node is a SymConst(name) replace it by SymConst(ent) if possible.
255 * - If the node is a Sel:
256 * * If the pointer to the Sel comes directly from an Alloc node
257 * replace the Sel by a SymConst(ent).
260 * @param node The node to analyze
261 * @param env A map that maps names of entities to the entities.
263 static void sel_methods_walker(ir_node * node, void *env) {
264 pmap *ldname_map = env;
266 /* replace SymConst(name)-operations by SymConst(ent) */
267 if (get_irn_op(node) == op_SymConst) {
268 if (get_SymConst_kind(node) == symconst_addr_name) {
269 pmap_entry * entry = pmap_find(ldname_map, (void *) get_SymConst_name(node));
270 if (entry != NULL) { /* Method is declared in the compiled code */
271 entity * ent = entry->value;
272 if (get_opt_normalize() && (get_entity_visibility(ent) != visibility_external_allocated)) { /* Meth. is defined */
273 set_irg_current_block(current_ir_graph, get_nodes_block(node));
274 ir_node *new_node = copy_const_value(get_atomic_ent_value(ent));
276 DBG_OPT_CSTEVAL(node, new_node);
278 assert(get_entity_irg(ent));
280 exchange(node, new_node);
285 else if (get_irn_op(node) == op_Sel &&
286 is_method_type(get_entity_type(get_Sel_entity(node)))) {
287 entity * ent = get_Sel_entity(node);
289 /* Sel from Alloc: replace by constant */
290 if (get_opt_optimize() && get_opt_dyn_meth_dispatch() &&
291 (get_irn_op(skip_Proj(get_Sel_ptr(node))) == op_Alloc)) {
295 /* We know which method will be called, no dispatch necessary. */
296 called_ent = resolve_ent_polymorphy(get_Alloc_type(skip_Proj(get_Sel_ptr(node))), ent);
297 set_irg_current_block(current_ir_graph, get_nodes_block(node));
299 /* called_ent may not be description: has no Address/Const to Call! */
300 assert(get_entity_peculiarity(called_ent) != peculiarity_description);
301 new_node = copy_const_value(get_atomic_ent_value(called_ent));
303 DBG_OPT_POLY_ALLOC(node, new_node);
304 exchange(node, new_node);
307 assert(get_entity_peculiarity(ent) != peculiarity_inherited);
308 if (!eset_contains(entities, ent)) {
309 /* Entity noch nicht behandelt. Alle (intern oder extern)
310 * implementierten Methoden suchen, die diese Entity
311 * überschreiben. Die Menge an entity.link speichern. */
312 set_entity_link(ent, get_impl_methods(ent));
313 eset_insert(entities, ent);
315 if (get_entity_link(ent) == NULL) {
316 /* Die Sel-Operation kann nie einen Zeiger auf eine aufrufbare
317 * Methode zurückgeben. Damit ist sie insbesondere nicht
318 * ausführbar und nicht erreichbar. */
319 /* Gib eine Warnung aus wenn die Entitaet eine Beschreibung ist
320 fuer die es keine Implementierung gibt. */
321 if (get_entity_peculiarity(ent) == peculiarity_description) {
322 /* This is possible: We call a method in a dead part of the program. */
325 assert(0); /* Why should this happen ??? */
326 //exchange(node, new_Bad());
329 entity ** arr = get_entity_link(ent);
333 printf("\nCall site "); DDMN(node);
334 printf(" in "); DDME(get_irg_entity(current_ir_graph));
335 printf(" can call:\n");
336 for (i = 0; i < ARR_LEN(arr); i++) {
337 printf(" - "); DDME(arr[i]);
338 printf(" with owner "); DDMT(get_entity_owner(arr[i]));
343 if (get_opt_optimize() && get_opt_dyn_meth_dispatch() &&
344 (ARR_LEN(arr) == 1 && arr[0] != NULL)) {
346 /* Die Sel-Operation kann immer nur _einen_ Wert auf eine
347 * interne Methode zurückgeben. Wir können daher die
348 * Sel-Operation durch eine Const- bzw. SymConst-Operation
350 set_irg_current_block(current_ir_graph, get_nodes_block(node));
351 assert(get_entity_peculiarity(get_SymConst_entity(get_atomic_ent_value(arr[0]))) ==
352 peculiarity_existent);
353 new_node = copy_const_value(get_atomic_ent_value(arr[0]));
354 DBG_OPT_POLY(node, new_node);
355 exchange (node, new_node);
363 /** Datenstruktur initialisieren. Zusätzlich werden alle
364 * SymConst(name)-Operationen, die auf interne Methoden verweisen, durch
365 * SymConst(entity)-Operationen ersetzt. */
366 static void sel_methods_init(void) {
368 pmap * ldname_map = pmap_create(); /* Map entity names to entities: to replace SymConst(name) by SymConst(ent). */
370 assert(entities == NULL);
371 entities = eset_create();
372 for (i = get_irp_n_allirgs() - 1; i >= 0; --i) {
373 entity * ent = get_irg_entity(get_irp_allirg(i));
374 /* Nur extern sichtbare Methode können überhaupt mit SymConst
375 * aufgerufen werden. */
376 if (get_entity_visibility(ent) != visibility_local) {
377 pmap_insert(ldname_map, (void *) get_entity_ld_ident(ent), ent);
380 all_irg_walk(sel_methods_walker, NULL, ldname_map);
381 pmap_destroy(ldname_map);
384 /*****************************************************************************/
386 /** Frees the allocated entity map */
387 static void sel_methods_dispose(void) {
390 for (ent = eset_first(entities); ent; ent = eset_next(entities)) {
391 entity ** arr = get_entity_link(ent);
395 set_entity_link(ent, NULL);
397 eset_destroy(entities);
403 * Returns an array of all methods that could be called at a Sel node.
404 * This array contains every entry only once.
406 static entity ** get_Sel_arr(ir_node * sel) {
407 static entity ** NULL_ARRAY = NULL;
411 assert(sel && get_irn_op(sel) == op_Sel);
412 ent = get_Sel_entity(sel);
413 assert(is_method_type(get_entity_type(ent))); /* what else? */
414 arr = get_entity_link(ent);
418 /* "NULL" zeigt an, dass keine Implementierung existiert. Dies
419 * kann für polymorphe (abstrakte) Methoden passieren. */
421 NULL_ARRAY = NEW_ARR_F(entity *, 0);
428 * Returns the number of possible called methods at a Sel node.
430 static int get_Sel_n_methods(ir_node * sel) {
431 return ARR_LEN(get_Sel_arr(sel));
435 * Returns the ith possible called method entity at a Sel node.
437 static entity * get_Sel_method(ir_node * sel, int pos) {
438 entity ** arr = get_Sel_arr(sel);
439 assert(pos >= 0 && pos < ARR_LEN(arr));
445 /* --- callee analysis ------------------------------------------------------ */
448 static void callee_ana_node(ir_node * node, eset * methods);
451 static void callee_ana_proj(ir_node * node, long n, eset * methods) {
452 assert(get_irn_mode(node) == mode_T);
453 if (get_irn_link(node) == MARK) {
454 /* already visited */
457 set_irn_link(node, MARK);
459 switch (get_irn_opcode(node)) {
461 /* proj_proj: in einem "sinnvollen" Graphen kommt jetzt ein
462 * op_Tuple oder ein Knoten, der eine "freie Methode"
464 ir_node * pred = get_Proj_pred(node);
465 if (get_irn_link(pred) != MARK) {
466 if (get_irn_op(pred) == op_Tuple) {
467 callee_ana_proj(get_Tuple_pred(pred, get_Proj_proj(node)), n, methods);
469 eset_insert(methods, MARK); /* free method -> unknown */
476 callee_ana_node(get_Tuple_pred(node, n), methods);
480 callee_ana_proj(get_Id_pred(node), n, methods);
484 eset_insert(methods, MARK); /* free method -> unknown */
488 set_irn_link(node, NULL);
492 static void callee_ana_node(ir_node * node, eset * methods) {
495 assert(mode_is_reference(get_irn_mode(node)) || is_Bad(node));
496 /* rekursion verhindern */
497 if (get_irn_link(node) == MARK) {
498 /* already visited */
501 set_irn_link(node, MARK);
503 switch (get_irn_opcode(node)) {
505 if (get_SymConst_kind(node) == symconst_addr_ent) {
506 entity * ent = get_SymConst_entity(node);
507 assert(ent && is_method_type(get_entity_type(ent)));
508 eset_insert(methods, ent);
510 assert(get_SymConst_kind(node) == symconst_addr_name);
511 /* externe Methode (wegen fix_symconst!) */
512 eset_insert(methods, MARK); /* free method -> unknown */
516 /* polymorphe Methode */
517 for (i = get_Sel_n_methods(node) - 1; i >= 0; --i) {
518 entity * ent = get_Sel_method(node, i);
520 eset_insert(methods, ent);
522 eset_insert(methods, MARK);
531 case iro_Phi: /* Vereinigung */
532 for (i = get_Phi_n_preds(node) - 1; i >= 0; --i) {
533 callee_ana_node(get_Phi_pred(node, i), methods);
538 callee_ana_node(get_Id_pred(node), methods);
542 callee_ana_proj(get_Proj_pred(node), get_Proj_proj(node), methods);
549 eset_insert(methods, MARK); /* free method -> unknown */
553 assert(0 && "invalid opcode or opcode not implemented");
557 set_irn_link(node, NULL);
561 static void callee_walker(ir_node * call, void * env) {
562 if (get_irn_op(call) == op_Call) {
563 eset * methods = eset_create();
565 entity ** arr = NEW_ARR_F(entity *, 0);
566 assert(get_irn_op(get_Call_ptr(call)) != op_Id);
567 callee_ana_node(get_Call_ptr(call), methods);
568 if (eset_contains(methods, MARK)) { /* unknown method */
569 ARR_APP1(entity *, arr, unknown_entity);
571 for (ent = eset_first(methods); ent; ent = eset_next(methods)) {
573 ARR_APP1(entity *, arr, ent);
576 #if 0 /* This generates Bad nodes when we don't want it.
577 Call it with a check for valid cgana information in local_optimize. */
578 if (ARR_LEN(arr) == 0 && get_opt_optimize() && get_opt_dyn_meth_dispatch()) {
579 /* Kann vorkommen, wenn der Vorgänger beispielsweise eine
580 * Sel-Operation war, die keine Methoden zurückgeben
581 * konnte. Wir ersetzen die Call-Operation ebenfalls durch
582 * eine Bad-Operation. Die Verlinkung muss wiederhergestellt
584 ir_node *mem = get_Call_mem(call);
585 turn_into_tuple (call, 5 /* pn_Call_max */);
586 set_Tuple_pred(call, pn_Call_M_regular , mem);
587 set_Tuple_pred(call, pn_Call_T_result , new_Bad());
588 set_Tuple_pred(call, pn_Call_P_value_res_base, new_Bad());
589 set_Tuple_pred(call, pn_Call_X_except , new_Bad()); /* new_Jmp() ?? new_Raise() ?? */
590 set_Tuple_pred(call, pn_Call_M_except , new_Bad());
595 /* remove, what we repaired. */
597 for (i = 0; i < ARR_LEN(arr); ++i) {
599 //if (arr[i] == unknown_entity) arr[i] = NULL;
602 set_Call_callee_arr(call, ARR_LEN(arr), arr);
605 eset_destroy(methods);
610 static void remove_Tuples(ir_node * proj, void * env) {
612 if (get_irn_opcode(proj) != iro_Proj) return;
614 new = skip_Tuple(proj);
615 if (new != proj) exchange(proj, new);
619 /* Bestimmt für jede Call-Operation die Menge der aufrufbaren Methode
620 * und speichert das Ergebnis in der Call-Operation. (siehe
621 * "set_Call_callee"). "sel_methods" wird für den Aufbau benötigt und
622 * muss bereits aufgebaut sein. */
623 static void callee_ana(void) {
625 /* Alle Graphen analysieren. */
626 for (i = get_irp_n_allirgs() - 1; i >= 0; --i) {
627 irg_walk_graph(get_irp_allirg(i), callee_walker, remove_Tuples, NULL);
628 set_irg_callee_info_state(get_irp_allirg(i), irg_callee_info_consistent);
630 set_irp_callee_info_state(irg_callee_info_consistent);
635 /* --- free method analysis ------------------------------------------------- */
638 static void free_mark(ir_node * node, eset * set);
640 static void free_mark_proj(ir_node * node, long n, eset * set) {
641 assert(get_irn_mode(node) == mode_T);
642 if (get_irn_link(node) == MARK) {
643 /* already visited */
646 set_irn_link(node, MARK);
647 switch (get_irn_opcode(node)) {
649 /* proj_proj: in einem "sinnvollen" Graphen kommt jetzt ein
650 * op_Tuple oder ein Knoten, der in "free_ana_walker" behandelt
652 ir_node * pred = get_Proj_pred(node);
653 if (get_irn_link(pred) != MARK && get_irn_op(pred) == op_Tuple) {
654 free_mark_proj(get_Tuple_pred(pred, get_Proj_proj(node)), n, set);
656 /* nothing: da in "free_ana_walker" behandelt. */
662 free_mark(get_Tuple_pred(node, n), set);
666 free_mark_proj(get_Id_pred(node), n, set);
672 /* nothing: Die Operationen werden in "free_ana_walker" selbst
677 assert(0 && "unexpected opcode or opcode not implemented");
680 set_irn_link(node, NULL);
684 static void free_mark(ir_node * node, eset * set) {
687 if (get_irn_link(node) == MARK) {
688 return; /* already visited */
690 set_irn_link(node, MARK);
691 switch (get_irn_opcode(node)) {
693 entity * ent = get_Sel_entity(node);
694 if (is_method_type(get_entity_type(ent))) {
695 for (i = get_Sel_n_methods(node) - 1; i >= 0; --i) {
696 eset_insert(set, get_Sel_method(node, i));
702 if (get_SymConst_kind(node) == symconst_addr_ent) {
703 entity * ent = get_SymConst_entity(node);
704 if (is_method_type(get_entity_type(ent))) {
705 eset_insert(set, ent);
708 assert(get_SymConst_kind(node) == symconst_addr_name);
709 /* nothing: SymConst points to extern method */
714 for (i = get_Phi_n_preds(node) - 1; i >= 0; --i) {
715 free_mark(get_Phi_pred(node, i), set);
719 free_mark(get_Id_pred(node), set);
722 free_mark_proj(get_Proj_pred(node), get_Proj_proj(node), set);
725 /* nothing: Wird unten behandelt! */
728 set_irn_link(node, NULL);
732 static void free_ana_walker(ir_node * node, eset * set) {
734 if (get_irn_link(node) == MARK) {
735 /* bereits in einem Zyklus besucht. */
738 switch (get_irn_opcode(node)) {
749 /* Sonderbehandlung, da der Funktionszeigereingang natürlich kein
752 set_irn_link(node, MARK);
753 for (i = get_Call_arity(node) - 1; i >= 0; --i) {
754 ir_node * pred = get_Call_param(node, i);
755 if (mode_is_reference(get_irn_mode(pred))) {
756 free_mark(pred, set);
760 /* other nodes: Alle anderen Knoten nehmen wir als Verräter an, bis
761 * jemand das Gegenteil implementiert. */
763 set_irn_link(node, MARK);
764 for (i = get_irn_arity(node) - 1; i >= 0; --i) {
765 ir_node * pred = get_irn_n(node, i);
766 if (mode_is_reference(get_irn_mode(pred))) {
767 free_mark(pred, set);
772 set_irn_link(node, NULL);
776 /* Die Datenstrukturen für sel-Methoden (sel_methods) muß vor dem
777 * Aufruf von "get_free_methods" aufgebaut sein. Die (internen)
778 * SymConst-Operationen müssen in passende Const-Operationen
779 * umgewandelt worden sein, d.h. SymConst-Operationen verweisen immer
780 * auf eine echt externe Methode. */
781 static entity ** get_free_methods(void)
783 eset * set = eset_create();
785 entity ** arr = NEW_ARR_F(entity *, 0);
788 for (i = get_irp_n_allirgs() - 1; i >= 0; --i) {
789 ir_graph * irg = get_irp_allirg(i);
790 entity * ent = get_irg_entity(irg);
791 /* insert "external visible" methods. */
792 if (get_entity_visibility(ent) != visibility_local) {
793 eset_insert(set, ent);
795 /* Finde alle Methoden die in dieser Methode extern sichtbar werden,
796 z.B. da die Adresse einer Methode abgespeichert wird. */
797 irg_walk_graph(irg, NULL, (irg_walk_func *) free_ana_walker, set);
800 /* insert sticky methods, too */
801 for (i = get_irp_n_allirgs() - 1; i >= 0; --i) {
802 ir_graph * irg = get_irp_allirg(i);
803 entity * ent = get_irg_entity(irg);
804 /* insert "external visible" methods. */
805 if (get_entity_stickyness (ent) == stickyness_sticky) {
806 eset_insert(set, ent);
810 /* Hauptprogramm ist auch dann frei, wenn es nicht "external
812 if (get_irp_main_irg()) {
813 eset_insert(set, get_irg_entity(get_irp_main_irg()));
815 /* Wandle Menge in Feld um. Effizienter. */
816 for (ent = eset_first(set); ent; ent = eset_next(set)) {
817 ARR_APP1(entity *, arr, ent);
824 void cgana(int *length, entity ***free_methods) {
825 entity ** free_meths, **p;
828 free_meths = get_free_methods();
830 sel_methods_dispose();
832 /* Convert the flexible array to an array that can be handled
834 p = (entity **)malloc(sizeof(*p) * ARR_LEN(free_meths));
835 memcpy(p, free_meths, ARR_LEN(free_meths) * sizeof(*p));
837 *length = ARR_LEN(free_meths);
840 DEL_ARR_F(free_meths);
845 static void destruct_walker(ir_node * node, void * env) {
846 if (get_irn_op(node) == op_Call) {
847 remove_Call_callee_arr(node);
851 void free_callee_info(ir_graph *irg) {
852 irg_walk_graph(irg, destruct_walker, NULL, NULL);
853 set_irg_callee_info_state(irg, irg_callee_info_none);
857 /* Optimize the address expressions passed to call nodes.
859 * This optimization performs the following transformations for
861 * - All SymConst operations that refer to intern methods are replaced
862 * by Const operations refering to the corresponding entity.
863 * - Sel nodes, that select entities that are not overwritten are
864 * replaced by Const nodes refering to the selected entity.
865 * - Sel nodes, for witch no method exists at all are replaced by Bad
867 * - Sel nodes with a pointer input that is an Alloc node are replaced
868 * by Const nodes refering to the entity that implements the method in
869 * the type given by the Alloc node.
871 void opt_call_addrs(void) {
873 sel_methods_dispose();