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_irgs() - 1; i >= 0; --i) {
373 ir_graph *irg = get_irp_irg(i);
374 entity * ent = get_irg_entity(irg);
375 /* Nur extern sichtbare Methoden können überhaupt mit SymConst
376 * aufgerufen werden. */
377 if (get_entity_visibility(ent) != visibility_local) {
378 pmap_insert(ldname_map, (void *) get_entity_ld_ident(ent), ent);
381 all_irg_walk(sel_methods_walker, NULL, ldname_map);
382 pmap_destroy(ldname_map);
385 /*****************************************************************************/
387 /** Frees the allocated entity map */
388 static void sel_methods_dispose(void) {
391 for (ent = eset_first(entities); ent; ent = eset_next(entities)) {
392 entity ** arr = get_entity_link(ent);
396 set_entity_link(ent, NULL);
398 eset_destroy(entities);
404 * Returns an array of all methods that could be called at a Sel node.
405 * This array contains every entry only once.
407 static entity ** get_Sel_arr(ir_node * sel) {
408 static entity ** NULL_ARRAY = NULL;
412 assert(sel && get_irn_op(sel) == op_Sel);
413 ent = get_Sel_entity(sel);
414 assert(is_method_type(get_entity_type(ent))); /* what else? */
415 arr = get_entity_link(ent);
419 /* "NULL" zeigt an, dass keine Implementierung existiert. Dies
420 * kann für polymorphe (abstrakte) Methoden passieren. */
422 NULL_ARRAY = NEW_ARR_F(entity *, 0);
429 * Returns the number of possible called methods at a Sel node.
431 static int get_Sel_n_methods(ir_node * sel) {
432 return ARR_LEN(get_Sel_arr(sel));
436 * Returns the ith possible called method entity at a Sel node.
438 static entity * get_Sel_method(ir_node * sel, int pos) {
439 entity ** arr = get_Sel_arr(sel);
440 assert(pos >= 0 && pos < ARR_LEN(arr));
446 /* --- callee analysis ------------------------------------------------------ */
449 static void callee_ana_node(ir_node * node, eset * methods);
452 static void callee_ana_proj(ir_node * node, long n, eset * methods) {
453 assert(get_irn_mode(node) == mode_T);
454 if (get_irn_link(node) == MARK) {
455 /* already visited */
458 set_irn_link(node, MARK);
460 switch (get_irn_opcode(node)) {
462 /* proj_proj: in einem "sinnvollen" Graphen kommt jetzt ein
463 * op_Tuple oder ein Knoten, der eine "freie Methode"
465 ir_node * pred = get_Proj_pred(node);
466 if (get_irn_link(pred) != MARK) {
467 if (get_irn_op(pred) == op_Tuple) {
468 callee_ana_proj(get_Tuple_pred(pred, get_Proj_proj(node)), n, methods);
470 eset_insert(methods, MARK); /* free method -> unknown */
477 callee_ana_node(get_Tuple_pred(node, n), methods);
481 callee_ana_proj(get_Id_pred(node), n, methods);
485 eset_insert(methods, MARK); /* free method -> unknown */
489 set_irn_link(node, NULL);
493 static void callee_ana_node(ir_node * node, eset * methods) {
496 assert(mode_is_reference(get_irn_mode(node)) || is_Bad(node));
497 /* rekursion verhindern */
498 if (get_irn_link(node) == MARK) {
499 /* already visited */
502 set_irn_link(node, MARK);
504 switch (get_irn_opcode(node)) {
506 if (get_SymConst_kind(node) == symconst_addr_ent) {
507 entity * ent = get_SymConst_entity(node);
508 assert(ent && is_method_type(get_entity_type(ent)));
509 eset_insert(methods, ent);
511 assert(get_SymConst_kind(node) == symconst_addr_name);
512 /* externe Methode (wegen fix_symconst!) */
513 eset_insert(methods, MARK); /* free method -> unknown */
517 /* polymorphe Methode */
518 for (i = get_Sel_n_methods(node) - 1; i >= 0; --i) {
519 entity * ent = get_Sel_method(node, i);
521 eset_insert(methods, ent);
523 eset_insert(methods, MARK);
532 case iro_Phi: /* Vereinigung */
533 for (i = get_Phi_n_preds(node) - 1; i >= 0; --i) {
534 callee_ana_node(get_Phi_pred(node, i), methods);
539 callee_ana_node(get_Id_pred(node), methods);
543 callee_ana_proj(get_Proj_pred(node), get_Proj_proj(node), methods);
550 eset_insert(methods, MARK); /* free method -> unknown */
554 assert(0 && "invalid opcode or opcode not implemented");
558 set_irn_link(node, NULL);
562 static void callee_walker(ir_node * call, void * env) {
563 if (get_irn_op(call) == op_Call) {
564 eset * methods = eset_create();
566 entity ** arr = NEW_ARR_F(entity *, 0);
567 assert(get_irn_op(get_Call_ptr(call)) != op_Id);
568 callee_ana_node(get_Call_ptr(call), methods);
569 if (eset_contains(methods, MARK)) { /* unknown method */
570 ARR_APP1(entity *, arr, unknown_entity);
572 for (ent = eset_first(methods); ent; ent = eset_next(methods)) {
574 ARR_APP1(entity *, arr, ent);
577 #if 0 /* This generates Bad nodes when we don't want it.
578 Call it with a check for valid cgana information in local_optimize. */
579 if (ARR_LEN(arr) == 0 && get_opt_optimize() && get_opt_dyn_meth_dispatch()) {
580 /* Kann vorkommen, wenn der Vorgänger beispielsweise eine
581 * Sel-Operation war, die keine Methoden zurückgeben
582 * konnte. Wir ersetzen die Call-Operation ebenfalls durch
583 * eine Bad-Operation. Die Verlinkung muss wiederhergestellt
585 ir_node *mem = get_Call_mem(call);
586 turn_into_tuple (call, 5 /* pn_Call_max */);
587 set_Tuple_pred(call, pn_Call_M_regular , mem);
588 set_Tuple_pred(call, pn_Call_T_result , new_Bad());
589 set_Tuple_pred(call, pn_Call_P_value_res_base, new_Bad());
590 set_Tuple_pred(call, pn_Call_X_except , new_Bad()); /* new_Jmp() ?? new_Raise() ?? */
591 set_Tuple_pred(call, pn_Call_M_except , new_Bad());
596 /* remove, what we repaired. */
598 for (i = 0; i < ARR_LEN(arr); ++i) {
600 //if (arr[i] == unknown_entity) arr[i] = NULL;
603 set_Call_callee_arr(call, ARR_LEN(arr), arr);
606 eset_destroy(methods);
611 static void remove_Tuples(ir_node * proj, void * env) {
613 if (get_irn_opcode(proj) != iro_Proj) return;
615 new = skip_Tuple(proj);
616 if (new != proj) exchange(proj, new);
620 /* Bestimmt für jede Call-Operation die Menge der aufrufbaren Methode
621 * und speichert das Ergebnis in der Call-Operation. (siehe
622 * "set_Call_callee"). "sel_methods" wird für den Aufbau benötigt und
623 * muss bereits aufgebaut sein. */
624 static void callee_ana(void) {
626 /* Alle Graphen analysieren. */
627 for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
628 irg_walk_graph(get_irp_irg(i), callee_walker, remove_Tuples, NULL);
629 set_irg_callee_info_state(get_irp_irg(i), irg_callee_info_consistent);
631 set_irp_callee_info_state(irg_callee_info_consistent);
636 /* --- free method analysis ------------------------------------------------- */
639 static void free_mark(ir_node * node, eset * set);
641 static void free_mark_proj(ir_node * node, long n, eset * set) {
642 assert(get_irn_mode(node) == mode_T);
643 if (get_irn_link(node) == MARK) {
644 /* already visited */
647 set_irn_link(node, MARK);
648 switch (get_irn_opcode(node)) {
650 /* proj_proj: in einem "sinnvollen" Graphen kommt jetzt ein
651 * op_Tuple oder ein Knoten, der in "free_ana_walker" behandelt
653 ir_node * pred = get_Proj_pred(node);
654 if (get_irn_link(pred) != MARK && get_irn_op(pred) == op_Tuple) {
655 free_mark_proj(get_Tuple_pred(pred, get_Proj_proj(node)), n, set);
657 /* nothing: da in "free_ana_walker" behandelt. */
663 free_mark(get_Tuple_pred(node, n), set);
667 free_mark_proj(get_Id_pred(node), n, set);
673 /* nothing: Die Operationen werden in "free_ana_walker" selbst
678 assert(0 && "unexpected opcode or opcode not implemented");
681 set_irn_link(node, NULL);
685 static void free_mark(ir_node * node, eset * set) {
688 if (get_irn_link(node) == MARK) {
689 return; /* already visited */
691 set_irn_link(node, MARK);
692 switch (get_irn_opcode(node)) {
694 entity * ent = get_Sel_entity(node);
695 if (is_method_type(get_entity_type(ent))) {
696 for (i = get_Sel_n_methods(node) - 1; i >= 0; --i) {
697 eset_insert(set, get_Sel_method(node, i));
703 if (get_SymConst_kind(node) == symconst_addr_ent) {
704 entity * ent = get_SymConst_entity(node);
705 if (is_method_type(get_entity_type(ent))) {
706 eset_insert(set, ent);
709 assert(get_SymConst_kind(node) == symconst_addr_name);
710 /* nothing: SymConst points to extern method */
715 for (i = get_Phi_n_preds(node) - 1; i >= 0; --i) {
716 free_mark(get_Phi_pred(node, i), set);
720 free_mark(get_Id_pred(node), set);
723 free_mark_proj(get_Proj_pred(node), get_Proj_proj(node), set);
726 /* nothing: Wird unten behandelt! */
729 set_irn_link(node, NULL);
733 static void free_ana_walker(ir_node * node, eset * set) {
735 if (get_irn_link(node) == MARK) {
736 /* bereits in einem Zyklus besucht. */
739 switch (get_irn_opcode(node)) {
750 /* Sonderbehandlung, da der Funktionszeigereingang natürlich kein
753 set_irn_link(node, MARK);
754 for (i = get_Call_arity(node) - 1; i >= 0; --i) {
755 ir_node * pred = get_Call_param(node, i);
756 if (mode_is_reference(get_irn_mode(pred))) {
757 free_mark(pred, set);
761 /* other nodes: Alle anderen Knoten nehmen wir als Verräter an, bis
762 * jemand das Gegenteil implementiert. */
764 set_irn_link(node, MARK);
765 for (i = get_irn_arity(node) - 1; i >= 0; --i) {
766 ir_node * pred = get_irn_n(node, i);
767 if (mode_is_reference(get_irn_mode(pred))) {
768 free_mark(pred, set);
773 set_irn_link(node, NULL);
777 /* Die Datenstrukturen für sel-Methoden (sel_methods) muß vor dem
778 * Aufruf von "get_free_methods" aufgebaut sein. Die (internen)
779 * SymConst-Operationen müssen in passende Const-Operationen
780 * umgewandelt worden sein, d.h. SymConst-Operationen verweisen immer
781 * auf eine echt externe Methode. */
782 static entity ** get_free_methods(void)
784 eset * set = eset_create();
786 entity ** arr = NEW_ARR_F(entity *, 0);
789 for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
790 ir_graph * irg = get_irp_irg(i);
791 entity * ent = get_irg_entity(irg);
792 /* insert "external visible" methods. */
793 if (get_entity_visibility(ent) != visibility_local) {
794 eset_insert(set, ent);
796 /* Finde alle Methoden die in dieser Methode extern sichtbar werden,
797 z.B. da die Adresse einer Methode abgespeichert wird. */
798 irg_walk_graph(irg, NULL, (irg_walk_func *) free_ana_walker, set);
801 /* insert sticky methods, too */
802 for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
803 ir_graph * irg = get_irp_irg(i);
804 entity * ent = get_irg_entity(irg);
805 /* insert "external visible" methods. */
806 if (get_entity_stickyness (ent) == stickyness_sticky) {
807 eset_insert(set, ent);
811 /* Hauptprogramm ist auch dann frei, wenn es nicht "external
813 if (get_irp_main_irg()) {
814 eset_insert(set, get_irg_entity(get_irp_main_irg()));
816 /* Wandle Menge in Feld um. Effizienter. */
817 for (ent = eset_first(set); ent; ent = eset_next(set)) {
818 ARR_APP1(entity *, arr, ent);
825 void cgana(int *length, entity ***free_methods) {
826 entity ** free_meths, **p;
829 free_meths = get_free_methods();
831 sel_methods_dispose();
833 /* Convert the flexible array to an array that can be handled
835 p = (entity **)malloc(sizeof(*p) * ARR_LEN(free_meths));
836 memcpy(p, free_meths, ARR_LEN(free_meths) * sizeof(*p));
838 *length = ARR_LEN(free_meths);
841 DEL_ARR_F(free_meths);
846 static void destruct_walker(ir_node * node, void * env) {
847 if (get_irn_op(node) == op_Call) {
848 remove_Call_callee_arr(node);
852 void free_callee_info(ir_graph *irg) {
853 irg_walk_graph(irg, destruct_walker, NULL, NULL);
854 set_irg_callee_info_state(irg, irg_callee_info_none);
858 /* Optimize the address expressions passed to call nodes.
860 * This optimization performs the following transformations for
862 * - All SymConst operations that refer to intern methods are replaced
863 * by Const operations refering to the corresponding entity.
864 * - Sel nodes, that select entities that are not overwritten are
865 * replaced by Const nodes refering to the selected entity.
866 * - Sel nodes, for witch no method exists at all are replaced by Bad
868 * - Sel nodes with a pointer input that is an Alloc node are replaced
869 * by Const nodes refering to the entity that implements the method in
870 * the type given by the Alloc node.
872 void opt_call_addrs(void) {
874 sel_methods_dispose();