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.
40 #include "dbginfo_t.h"
41 #include "iropt_dbg.h"
51 /* Eindeutige Adresse zur Markierung von besuchten Knoten und zur
52 * Darstellung der unbekannten Methode. */
53 static void * MARK = &MARK;
57 /* --- sel methods ---------------------------------------------------------- */
60 static eset * entities = NULL;
63 /** Bestimmt die eindeutige Methode, die die Methode für den
64 * übergebenen (dynamischen) Typ überschreibt. */
65 static entity * get_implementation(type * class, entity * method) {
67 if (get_entity_peculiarity(method) != peculiarity_description &&
68 get_entity_owner(method) == class) {
71 for (i = get_entity_n_overwrittenby(method) - 1; i >= 0; --i) {
72 entity * e = get_entity_overwrittenby(method, i);
73 if (get_entity_peculiarity(e) != peculiarity_description && get_entity_owner(e) == class) {
77 for (i = get_class_n_supertypes(class) - 1; i >= 0; --i) {
78 entity * e = get_implementation(get_class_supertype(class, i), method);
83 assert(0 && "implementation not found");
87 /** Returns the entity that contains the implementation of the inherited
88 entity if available, else returns the entity passed. */
89 static entity *get_inherited_methods_implementation(entity *inh_meth) {
90 assert(get_atomic_ent_value(inh_meth) && "constant entity without value");
91 assert((get_irn_op(get_atomic_ent_value(inh_meth)) == op_SymConst) &&
92 (get_SymConst_kind(get_atomic_ent_value(inh_meth)) == symconst_addr_ent) &&
93 "Complex constant values not supported -- address of method should be straight constant!");
95 return get_SymConst_entity(get_atomic_ent_value(inh_meth));
97 #if 0 // this stuff is outdated, I think. GL 10.11.04
98 entity *impl_meth = NULL;
99 ir_node *addr = get_atomic_ent_value(inh_meth);
101 assert(get_atomic_ent_value(inh_meth) && "constant entity without value");
103 if ((get_irn_op(addr) == op_SymConst) &&
104 (get_SymConst_kind(addr) == symconst_addr_ent)) {
105 impl_meth = get_SymConst_entity(addr);
107 assert(0 && "Complex constant values not supported -- address of method should be straight constant!");
110 if (impl_meth && (get_entity_peculiarity(impl_meth) != peculiarity_existent)) {
112 printf("this_meth: "); DDMEO(inh_meth);
113 printf("impl meth: "); DDMEO(impl_meth);
114 assert(!impl_meth || get_entity_peculiarity(impl_meth) == peculiarity_existent);
119 assert((impl_meth || inh_meth) && "no implementation for inherited entity");
120 return impl_meth? impl_meth : inh_meth;
125 /** Collect the entity representing the implementation of this
126 * entity (not the same if inherited) and all entities for overwriting
127 * implementations in "set".
128 * If the implementation of the method is not included in the
129 * compilation unit "open" is set to true.
130 * A recursive descend in the overwritten relation.
131 * Cycle-free, therefore must terminate.
134 * @param set A set of entities.
135 * @param size Number of entities in set.
138 static void collect_impls(entity *method, eset *set, int *size, bool *open) {
141 if (get_entity_peculiarity(method) == peculiarity_existent) {
142 if ((get_entity_visibility(method) == visibility_external_allocated)
143 && (NULL == get_entity_irg(method))) {
144 /* We could also add these entities to the callees, but right now we
145 subsume them by unknown_entity. */
148 assert(get_entity_irg(method) != NULL);
149 if (!eset_contains(set, method)) {
150 eset_insert(set, method);
156 if (get_entity_peculiarity(method) == peculiarity_inherited) {
157 entity *impl_ent = get_inherited_methods_implementation(method);
158 if (get_entity_visibility(impl_ent) == visibility_external_allocated) {
159 assert(get_entity_irg(impl_ent) == NULL);
162 assert(get_entity_irg(impl_ent) != NULL);
163 if (!eset_contains(set, impl_ent)) {
164 eset_insert(set, impl_ent);
170 /* Only the assertions: */
171 if (get_entity_peculiarity(method) == peculiarity_existent) {
172 if ((get_entity_visibility(method) == visibility_external_allocated)
173 && (NULL == get_entity_irg(method))) {
175 assert(get_entity_irg(method) != NULL);
178 if (get_entity_peculiarity(method) == peculiarity_inherited) {
179 entity *impl_ent = get_inherited_methods_implementation(method);
180 if (get_entity_visibility(impl_ent) == visibility_external_allocated) {
181 assert(get_entity_irg(impl_ent) == NULL);
183 assert(get_entity_irg(impl_ent) != NULL);
187 /* Add the implementation to the set if it contains an irg, else
188 remember that there are more methods called. */
189 /* @@@ We could also add unknown_entity, or the entities with the
190 unknown irgs. The first case would result in the exact same
191 behaviour: all unknown irgs are represented by the one and only
192 unknown entity. If we add all entities, we known the number of
193 entities possibly called, and whether there are real unknown
194 entities, i.e, such not represented in the type description.
195 This would be better for an analyses: it could rule out more
197 entity *impl = method;
198 if (get_entity_peculiarity(method) == peculiarity_inherited)
199 impl = get_inherited_methods_implementation(method);
201 if (get_entity_peculiarity(method) != peculiarity_description) {
202 //if (get_entity_irg(impl)) {
203 eset_insert(set, impl);
206 /* GL: better: eset_insert(set, unknown_entity); */
211 /*- recursive descent -*/
212 for (i = get_entity_n_overwrittenby(method) - 1; i >= 0; --i)
213 collect_impls(get_entity_overwrittenby(method, i), set, size, open);
217 /** Alle Methoden bestimmen, die die übergebene Methode überschreiben
218 * (und implementieren). In der zurückgegebenen Reihung kommt jede
219 * Methode nur einmal vor. Der Wert 'NULL' steht für unbekannte
220 * (externe) Methoden. Die zurückgegebene Reihung muß vom Aufrufer
221 * wieder freigegeben werden (siehe "DEL_ARR_F"). Gibt es überhaupt
222 * keine Methoden, die "method" überschreiben, so gibt die Methode
227 static entity ** get_impl_methods(entity * method) {
228 eset * set = eset_create();
233 /* Collect all method entities that can be called here */
234 collect_impls(method, set, &size, &open);
236 /* Vorgaenger einfuegen. */
237 if (size == 0 && !open) {
238 /* keine implementierte überschriebene Methode */
242 arr = NEW_ARR_F(entity *, size + 1);
243 arr[0] = NULL; /* Represents open method */
244 for (ent = eset_first(set); size > 0; ent = eset_next(set), --size)
248 arr = NEW_ARR_F(entity *, size);
249 for (size -= 1, ent = eset_first(set); size >= 0; ent = eset_next(set), --size)
256 /** Analyse address computations.
258 * - If the node is a SymConst(name) replace it by SymConst(ent) if possible.
259 * - If the node is a Sel:
260 * * If the pointer to the Sel comes directly from an Alloc node
261 * replace the Sel by a SymConst(ent).
264 * @param node The node to analyze
265 * @param env A map that maps names of entities to the entities.
267 static void sel_methods_walker(ir_node * node, void *env) {
268 pmap *ldname_map = env;
270 /* replace SymConst(name)-operations by SymConst(ent) */
271 if (get_irn_op(node) == op_SymConst) {
272 if (get_SymConst_kind(node) == symconst_addr_name) {
273 pmap_entry * entry = pmap_find(ldname_map, (void *) get_SymConst_name(node));
274 if (entry != NULL) { /* Method is declared in the compiled code */
275 entity * ent = entry->value;
276 if (get_opt_normalize() && (get_entity_visibility(ent) != visibility_external_allocated)) { /* Meth. is defined */
277 set_irg_current_block(current_ir_graph, get_nodes_block(node));
278 ir_node *new_node = copy_const_value(get_atomic_ent_value(ent));
280 DBG_OPT_CSTEVAL(node, new_node);
282 assert(get_entity_irg(ent));
284 exchange(node, new_node);
289 else if (get_irn_op(node) == op_Sel &&
290 is_method_type(get_entity_type(get_Sel_entity(node)))) {
291 entity * ent = get_Sel_entity(node);
293 /* Sel from Alloc: replace by constant */
294 if (get_opt_optimize() && get_opt_dyn_meth_dispatch() &&
295 (get_irn_op(skip_Proj(get_Sel_ptr(node))) == op_Alloc)) {
299 /* We know which method will be called, no dispatch necessary. */
300 called_ent = resolve_ent_polymorphy(get_Alloc_type(skip_Proj(get_Sel_ptr(node))), ent);
301 set_irg_current_block(current_ir_graph, get_nodes_block(node));
303 /* called_ent may not be description: has no Address/Const to Call! */
304 assert(get_entity_peculiarity(called_ent) != peculiarity_description);
305 new_node = copy_const_value(get_atomic_ent_value(called_ent));
307 DBG_OPT_POLY_ALLOC(node, new_node);
308 exchange(node, new_node);
311 assert(get_entity_peculiarity(ent) != peculiarity_inherited);
312 if (!eset_contains(entities, ent)) {
313 /* Entity noch nicht behandelt. Alle (intern oder extern)
314 * implementierten Methoden suchen, die diese Entity
315 * überschreiben. Die Menge an entity.link speichern. */
316 set_entity_link(ent, get_impl_methods(ent));
317 eset_insert(entities, ent);
319 if (get_entity_link(ent) == NULL) {
320 /* Die Sel-Operation kann nie einen Zeiger auf eine aufrufbare
321 * Methode zurückgeben. Damit ist sie insbesondere nicht
322 * ausführbar und nicht erreichbar. */
323 /* Gib eine Warnung aus wenn die Entitaet eine Beschreibung ist
324 fuer die es keine Implementierung gibt. */
325 if (get_entity_peculiarity(ent) == peculiarity_description) {
326 /* This is possible: We call a method in a dead part of the program. */
329 assert(0); /* Why should this happen ??? */
330 //exchange(node, new_Bad());
333 entity ** arr = get_entity_link(ent);
337 printf("\nCall site "); DDMN(node);
338 printf(" in "); DDME(get_irg_entity(current_ir_graph));
339 printf(" can call:\n");
340 for (i = 0; i < ARR_LEN(arr); i++) {
341 printf(" - "); DDME(arr[i]);
342 printf(" with owner "); DDMT(get_entity_owner(arr[i]));
347 if (get_opt_optimize() && get_opt_dyn_meth_dispatch() &&
348 (ARR_LEN(arr) == 1 && arr[0] != NULL)) {
350 /* Die Sel-Operation kann immer nur _einen_ Wert auf eine
351 * interne Methode zurückgeben. Wir können daher die
352 * Sel-Operation durch eine Const- bzw. SymConst-Operation
354 set_irg_current_block(current_ir_graph, get_nodes_block(node));
355 assert(get_entity_peculiarity(get_SymConst_entity(get_atomic_ent_value(arr[0]))) ==
356 peculiarity_existent);
357 new_node = copy_const_value(get_atomic_ent_value(arr[0]));
358 DBG_OPT_POLY(node, new_node);
359 exchange (node, new_node);
367 /** Datenstruktur initialisieren. Zusätzlich werden alle
368 * SymConst(name)-Operationen, die auf interne Methoden verweisen, durch
369 * SymConst(entity)-Operationen ersetzt. */
370 static void sel_methods_init(void) {
372 pmap * ldname_map = pmap_create(); /* Map entity names to entities: to replace SymConst(name) by SymConst(ent). */
374 assert(entities == NULL);
375 entities = eset_create();
376 for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
377 ir_graph *irg = get_irp_irg(i);
378 entity * ent = get_irg_entity(irg);
379 /* Nur extern sichtbare Methoden können überhaupt mit SymConst
380 * aufgerufen werden. */
381 if (get_entity_visibility(ent) != visibility_local) {
382 pmap_insert(ldname_map, (void *) get_entity_ld_ident(ent), ent);
385 all_irg_walk(sel_methods_walker, NULL, ldname_map);
386 pmap_destroy(ldname_map);
389 /*****************************************************************************/
391 /** Frees the allocated entity map */
392 static void sel_methods_dispose(void) {
395 for (ent = eset_first(entities); ent; ent = eset_next(entities)) {
396 entity ** arr = get_entity_link(ent);
400 set_entity_link(ent, NULL);
402 eset_destroy(entities);
408 * Returns an array of all methods that could be called at a Sel node.
409 * This array contains every entry only once.
411 static entity ** get_Sel_arr(ir_node * sel) {
412 static entity ** NULL_ARRAY = NULL;
416 assert(sel && get_irn_op(sel) == op_Sel);
417 ent = get_Sel_entity(sel);
418 assert(is_method_type(get_entity_type(ent))); /* what else? */
419 arr = get_entity_link(ent);
423 /* "NULL" zeigt an, dass keine Implementierung existiert. Dies
424 * kann für polymorphe (abstrakte) Methoden passieren. */
426 NULL_ARRAY = NEW_ARR_F(entity *, 0);
433 * Returns the number of possible called methods at a Sel node.
435 static int get_Sel_n_methods(ir_node * sel) {
436 return ARR_LEN(get_Sel_arr(sel));
440 * Returns the ith possible called method entity at a Sel node.
442 static entity * get_Sel_method(ir_node * sel, int pos) {
443 entity ** arr = get_Sel_arr(sel);
444 assert(pos >= 0 && pos < ARR_LEN(arr));
450 /* --- callee analysis ------------------------------------------------------ */
453 static void callee_ana_node(ir_node * node, eset * methods);
456 static void callee_ana_proj(ir_node * node, long n, eset * methods) {
457 assert(get_irn_mode(node) == mode_T);
458 if (get_irn_link(node) == MARK) {
459 /* already visited */
462 set_irn_link(node, MARK);
464 switch (get_irn_opcode(node)) {
466 /* proj_proj: in einem "sinnvollen" Graphen kommt jetzt ein
467 * op_Tuple oder ein Knoten, der eine "freie Methode"
469 ir_node * pred = get_Proj_pred(node);
470 if (get_irn_link(pred) != MARK) {
471 if (get_irn_op(pred) == op_Tuple) {
472 callee_ana_proj(get_Tuple_pred(pred, get_Proj_proj(node)), n, methods);
474 eset_insert(methods, MARK); /* free method -> unknown */
481 callee_ana_node(get_Tuple_pred(node, n), methods);
485 callee_ana_proj(get_Id_pred(node), n, methods);
489 eset_insert(methods, MARK); /* free method -> unknown */
493 set_irn_link(node, NULL);
497 static void callee_ana_node(ir_node * node, eset * methods) {
500 assert(mode_is_reference(get_irn_mode(node)) || is_Bad(node));
501 /* rekursion verhindern */
502 if (get_irn_link(node) == MARK) {
503 /* already visited */
506 set_irn_link(node, MARK);
508 switch (get_irn_opcode(node)) {
510 if (get_SymConst_kind(node) == symconst_addr_ent) {
511 entity * ent = get_SymConst_entity(node);
512 assert(ent && is_method_type(get_entity_type(ent)));
513 eset_insert(methods, ent);
515 assert(get_SymConst_kind(node) == symconst_addr_name);
516 /* externe Methode (wegen fix_symconst!) */
517 eset_insert(methods, MARK); /* free method -> unknown */
521 /* polymorphe Methode */
522 for (i = get_Sel_n_methods(node) - 1; i >= 0; --i) {
523 entity * ent = get_Sel_method(node, i);
525 eset_insert(methods, ent);
527 eset_insert(methods, MARK);
536 case iro_Phi: /* Vereinigung */
537 for (i = get_Phi_n_preds(node) - 1; i >= 0; --i) {
538 callee_ana_node(get_Phi_pred(node, i), methods);
543 callee_ana_node(get_Id_pred(node), methods);
547 callee_ana_proj(get_Proj_pred(node), get_Proj_proj(node), methods);
554 eset_insert(methods, MARK); /* free method -> unknown */
558 assert(0 && "invalid opcode or opcode not implemented");
562 set_irn_link(node, NULL);
566 static void callee_walker(ir_node * call, void * env) {
567 if (get_irn_op(call) == op_Call) {
568 eset * methods = eset_create();
570 entity ** arr = NEW_ARR_F(entity *, 0);
571 assert(get_irn_op(get_Call_ptr(call)) != op_Id);
572 callee_ana_node(get_Call_ptr(call), methods);
573 if (eset_contains(methods, MARK)) { /* unknown method */
574 ARR_APP1(entity *, arr, unknown_entity);
576 for (ent = eset_first(methods); ent; ent = eset_next(methods)) {
578 ARR_APP1(entity *, arr, ent);
581 #if 0 /* This generates Bad nodes when we don't want it.
582 Call it with a check for valid cgana information in local_optimize. */
583 if (ARR_LEN(arr) == 0 && get_opt_optimize() && get_opt_dyn_meth_dispatch()) {
584 /* Kann vorkommen, wenn der Vorgänger beispielsweise eine
585 * Sel-Operation war, die keine Methoden zurückgeben
586 * konnte. Wir ersetzen die Call-Operation ebenfalls durch
587 * eine Bad-Operation. Die Verlinkung muss wiederhergestellt
589 ir_node *mem = get_Call_mem(call);
590 turn_into_tuple (call, 5 /* pn_Call_max */);
591 set_Tuple_pred(call, pn_Call_M_regular , mem);
592 set_Tuple_pred(call, pn_Call_T_result , new_Bad());
593 set_Tuple_pred(call, pn_Call_P_value_res_base, new_Bad());
594 set_Tuple_pred(call, pn_Call_X_except , new_Bad()); /* new_Jmp() ?? new_Raise() ?? */
595 set_Tuple_pred(call, pn_Call_M_except , new_Bad());
600 /* remove, what we repaired. */
602 for (i = 0; i < ARR_LEN(arr); ++i) {
604 //if (arr[i] == unknown_entity) arr[i] = NULL;
607 set_Call_callee_arr(call, ARR_LEN(arr), arr);
610 eset_destroy(methods);
615 static void remove_Tuples(ir_node * proj, void * env) {
617 if (get_irn_opcode(proj) != iro_Proj) return;
619 new = skip_Tuple(proj);
620 if (new != proj) exchange(proj, new);
624 /* Bestimmt für jede Call-Operation die Menge der aufrufbaren Methode
625 * und speichert das Ergebnis in der Call-Operation. (siehe
626 * "set_Call_callee"). "sel_methods" wird für den Aufbau benötigt und
627 * muss bereits aufgebaut sein. */
628 static void callee_ana(void) {
630 /* Alle Graphen analysieren. */
631 for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
632 irg_walk_graph(get_irp_irg(i), callee_walker, remove_Tuples, NULL);
633 set_irg_callee_info_state(get_irp_irg(i), irg_callee_info_consistent);
635 set_irp_callee_info_state(irg_callee_info_consistent);
640 /* --- free method analysis ------------------------------------------------- */
643 static void free_mark(ir_node * node, eset * set);
645 static void free_mark_proj(ir_node * node, long n, eset * set) {
646 assert(get_irn_mode(node) == mode_T);
647 if (get_irn_link(node) == MARK) {
648 /* already visited */
651 set_irn_link(node, MARK);
652 switch (get_irn_opcode(node)) {
654 /* proj_proj: in einem "sinnvollen" Graphen kommt jetzt ein
655 * op_Tuple oder ein Knoten, der in "free_ana_walker" behandelt
657 ir_node * pred = get_Proj_pred(node);
658 if (get_irn_link(pred) != MARK && get_irn_op(pred) == op_Tuple) {
659 free_mark_proj(get_Tuple_pred(pred, get_Proj_proj(node)), n, set);
661 /* nothing: da in "free_ana_walker" behandelt. */
667 free_mark(get_Tuple_pred(node, n), set);
671 free_mark_proj(get_Id_pred(node), n, set);
677 /* nothing: Die Operationen werden in "free_ana_walker" selbst
682 assert(0 && "unexpected opcode or opcode not implemented");
685 set_irn_link(node, NULL);
689 static void free_mark(ir_node * node, eset * set) {
692 if (get_irn_link(node) == MARK) {
693 return; /* already visited */
695 set_irn_link(node, MARK);
696 switch (get_irn_opcode(node)) {
698 entity * ent = get_Sel_entity(node);
699 if (is_method_type(get_entity_type(ent))) {
700 for (i = get_Sel_n_methods(node) - 1; i >= 0; --i) {
701 eset_insert(set, get_Sel_method(node, i));
707 if (get_SymConst_kind(node) == symconst_addr_ent) {
708 entity * ent = get_SymConst_entity(node);
709 if (is_method_type(get_entity_type(ent))) {
710 eset_insert(set, ent);
713 assert(get_SymConst_kind(node) == symconst_addr_name);
714 /* nothing: SymConst points to extern method */
719 for (i = get_Phi_n_preds(node) - 1; i >= 0; --i) {
720 free_mark(get_Phi_pred(node, i), set);
724 free_mark(get_Id_pred(node), set);
727 free_mark_proj(get_Proj_pred(node), get_Proj_proj(node), set);
730 /* nothing: Wird unten behandelt! */
733 set_irn_link(node, NULL);
737 static void free_ana_walker(ir_node * node, eset * set) {
739 if (get_irn_link(node) == MARK) {
740 /* bereits in einem Zyklus besucht. */
743 switch (get_irn_opcode(node)) {
754 /* Sonderbehandlung, da der Funktionszeigereingang natürlich kein
757 set_irn_link(node, MARK);
758 for (i = get_Call_arity(node) - 1; i >= 0; --i) {
759 ir_node * pred = get_Call_param(node, i);
760 if (mode_is_reference(get_irn_mode(pred))) {
761 free_mark(pred, set);
765 /* other nodes: Alle anderen Knoten nehmen wir als Verräter an, bis
766 * jemand das Gegenteil implementiert. */
768 set_irn_link(node, MARK);
769 for (i = get_irn_arity(node) - 1; i >= 0; --i) {
770 ir_node * pred = get_irn_n(node, i);
771 if (mode_is_reference(get_irn_mode(pred))) {
772 free_mark(pred, set);
777 set_irn_link(node, NULL);
781 /* Die Datenstrukturen für sel-Methoden (sel_methods) muß vor dem
782 * Aufruf von "get_free_methods" aufgebaut sein. Die (internen)
783 * SymConst-Operationen müssen in passende Const-Operationen
784 * umgewandelt worden sein, d.h. SymConst-Operationen verweisen immer
785 * auf eine echt externe Methode. */
786 static entity ** get_free_methods(void)
788 eset * set = eset_create();
790 entity ** arr = NEW_ARR_F(entity *, 0);
793 for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
794 ir_graph * irg = get_irp_irg(i);
795 entity * ent = get_irg_entity(irg);
796 /* insert "external visible" methods. */
797 if (get_entity_visibility(ent) != visibility_local) {
798 eset_insert(set, ent);
800 /* Finde alle Methoden die in dieser Methode extern sichtbar werden,
801 z.B. da die Adresse einer Methode abgespeichert wird. */
802 irg_walk_graph(irg, NULL, (irg_walk_func *) free_ana_walker, set);
805 /* insert sticky methods, too */
806 for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
807 ir_graph * irg = get_irp_irg(i);
808 entity * ent = get_irg_entity(irg);
809 /* insert "external visible" methods. */
810 if (get_entity_stickyness (ent) == stickyness_sticky) {
811 eset_insert(set, ent);
815 /* Hauptprogramm ist auch dann frei, wenn es nicht "external
817 if (get_irp_main_irg()) {
818 eset_insert(set, get_irg_entity(get_irp_main_irg()));
820 /* Wandle Menge in Feld um. Effizienter. */
821 for (ent = eset_first(set); ent; ent = eset_next(set)) {
822 ARR_APP1(entity *, arr, ent);
829 void cgana(int *length, entity ***free_methods) {
830 entity ** free_meths, **p;
833 free_meths = get_free_methods();
835 sel_methods_dispose();
837 /* Convert the flexible array to an array that can be handled
839 p = (entity **)xmalloc(sizeof(*p) * ARR_LEN(free_meths));
840 memcpy(p, free_meths, ARR_LEN(free_meths) * sizeof(*p));
842 *length = ARR_LEN(free_meths);
845 DEL_ARR_F(free_meths);
850 static void destruct_walker(ir_node * node, void * env) {
851 if (get_irn_op(node) == op_Call) {
852 remove_Call_callee_arr(node);
856 void free_callee_info(ir_graph *irg) {
857 irg_walk_graph(irg, destruct_walker, NULL, NULL);
858 set_irg_callee_info_state(irg, irg_callee_info_none);
862 /* Optimize the address expressions passed to call nodes.
864 * This optimization performs the following transformations for
866 * - All SymConst operations that refer to intern methods are replaced
867 * by Const operations refering to the corresponding entity.
868 * - Sel nodes, that select entities that are not overwritten are
869 * replaced by Const nodes refering to the selected entity.
870 * - Sel nodes, for witch no method exists at all are replaced by Bad
872 * - Sel nodes with a pointer input that is an Alloc node are replaced
873 * by Const nodes refering to the entity that implements the method in
874 * the type given by the Alloc node.
876 void opt_call_addrs(void) {
878 sel_methods_dispose();