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) {
143 if (get_entity_peculiarity(method) == peculiarity_existent) {
144 if ((get_entity_visibility(method) == visibility_external_allocated)
145 && (NULL == get_entity_irg(method))) {
146 /* We could also add these entities to the callees, but right now we
147 subsume them by unknown_entity. */
150 assert(get_entity_irg(method) != NULL);
151 if (!eset_contains(set, method)) {
152 eset_insert(set, method);
158 if (get_entity_peculiarity(method) == peculiarity_inherited) {
159 entity *impl_ent = get_inherited_methods_implementation(method);
160 if (get_entity_visibility(impl_ent) == visibility_external_allocated) {
161 assert(get_entity_irg(impl_ent) == NULL);
164 assert(get_entity_irg(impl_ent) != NULL);
165 if (!eset_contains(set, impl_ent)) {
166 eset_insert(set, impl_ent);
172 /* Only the assertions: */
173 if (get_entity_peculiarity(method) == peculiarity_existent) {
174 if ((get_entity_visibility(method) == visibility_external_allocated)
175 && (NULL == get_entity_irg(method))) {
177 assert(get_entity_irg(method) != NULL);
180 if (get_entity_peculiarity(method) == peculiarity_inherited) {
181 entity *impl_ent = get_inherited_methods_implementation(method);
182 if (get_entity_visibility(impl_ent) == visibility_external_allocated) {
183 assert(get_entity_irg(impl_ent) == NULL);
185 assert(get_entity_irg(impl_ent) != NULL);
189 /* Add the implementation to the set if it contains an irg, else
190 remember that there are more methods called. */
191 /* @@@ We could also add unknown_entity, or the entities with the
192 unknown irgs. The first case would result in the exact same
193 behavior: all unknown irgs are represented by the one and only
194 unknown entity. If we add all entities, we known the number of
195 entities possibly called, and whether there are real unknown
196 entities, i.e, such not represented in the type description.
197 This would be better for an analysis: it could rule out more
200 if (get_entity_peculiarity(method) == peculiarity_inherited)
201 impl = get_inherited_methods_implementation(method);
203 if (get_entity_peculiarity(method) != peculiarity_description) {
204 //if (get_entity_irg(impl)) {
205 eset_insert(set, impl);
208 /* GL: better: eset_insert(set, unknown_entity); */
213 /*- recursive descent -*/
214 for (i = get_entity_n_overwrittenby(method) - 1; i >= 0; --i)
215 collect_impls(get_entity_overwrittenby(method, i), set, size, open);
219 /** Alle Methoden bestimmen, die die übergebene Methode überschreiben
220 * (und implementieren). In der zurückgegebenen Reihung kommt jede
221 * Methode nur einmal vor. Der Wert 'NULL' steht für unbekannte
222 * (externe) Methoden. Die zurückgegebene Reihung muß vom Aufrufer
223 * wieder freigegeben werden (siehe "DEL_ARR_F"). Gibt es überhaupt
224 * keine Methoden, die "method" überschreiben, so gibt die Methode
229 static entity ** get_impl_methods(entity * method) {
230 eset * set = eset_create();
235 /* Collect all method entities that can be called here */
236 collect_impls(method, set, &size, &open);
238 /* Vorgaenger einfuegen. */
239 if (size == 0 && !open) {
240 /* keine implementierte überschriebene Methode */
244 arr = NEW_ARR_F(entity *, size + 1);
245 arr[0] = NULL; /* Represents open method */
246 for (ent = eset_first(set); size > 0; ent = eset_next(set), --size)
250 arr = NEW_ARR_F(entity *, size);
251 for (size -= 1, ent = eset_first(set); size >= 0; ent = eset_next(set), --size)
258 /** Analyze address computations.
260 * - If the node is a SymConst(name) replace it by SymConst(ent) if possible.
261 * - If the node is a Sel:
262 * * If the pointer to the Sel comes directly from an Alloc node
263 * replace the Sel by a SymConst(ent).
266 * @param node The node to analyze
267 * @param env A map that maps names of entities to the entities.
269 static void sel_methods_walker(ir_node * node, void *env) {
270 pmap *ldname_map = env;
272 /* replace SymConst(name)-operations by SymConst(ent) */
273 if (get_irn_op(node) == op_SymConst) {
274 if (get_SymConst_kind(node) == symconst_addr_name) {
275 pmap_entry * entry = pmap_find(ldname_map, (void *) get_SymConst_name(node));
276 if (entry != NULL) { /* Method is declared in the compiled code */
277 entity * ent = entry->value;
278 if (get_opt_normalize() && (get_entity_visibility(ent) != visibility_external_allocated)) { /* Meth. is defined */
281 set_irg_current_block(current_ir_graph, get_nodes_block(node));
282 new_node = copy_const_value(get_atomic_ent_value(ent));
284 DBG_OPT_CSTEVAL(node, new_node);
286 assert(get_entity_irg(ent));
288 exchange(node, new_node);
293 else if (get_irn_op(node) == op_Sel &&
294 is_Method_type(get_entity_type(get_Sel_entity(node)))) {
295 entity * ent = get_Sel_entity(node);
297 /* Sel from Alloc: replace by constant */
298 if (get_opt_optimize() && get_opt_dyn_meth_dispatch() &&
299 (get_irn_op(skip_Proj(get_Sel_ptr(node))) == op_Alloc)) {
303 /* We know which method will be called, no dispatch necessary. */
304 called_ent = resolve_ent_polymorphy(get_Alloc_type(skip_Proj(get_Sel_ptr(node))), ent);
305 set_irg_current_block(current_ir_graph, get_nodes_block(node));
307 /* called_ent may not be description: has no Address/Const to Call! */
308 assert(get_entity_peculiarity(called_ent) != peculiarity_description);
309 new_node = copy_const_value(get_atomic_ent_value(called_ent));
311 DBG_OPT_POLY_ALLOC(node, new_node);
312 exchange(node, new_node);
315 assert(get_entity_peculiarity(ent) != peculiarity_inherited);
316 if (!eset_contains(entities, ent)) {
317 /* Entity noch nicht behandelt. Alle (intern oder extern)
318 * implementierten Methoden suchen, die diese Entity
319 * überschreiben. Die Menge an entity.link speichern. */
320 set_entity_link(ent, get_impl_methods(ent));
321 eset_insert(entities, ent);
323 if (get_entity_link(ent) == NULL) {
324 /* Die Sel-Operation kann nie einen Zeiger auf eine aufrufbare
325 * Methode zurückgeben. Damit ist sie insbesondere nicht
326 * ausführbar und nicht erreichbar. */
327 /* Gib eine Warnung aus wenn die Entitaet eine Beschreibung ist
328 fuer die es keine Implementierung gibt. */
329 if (get_entity_peculiarity(ent) == peculiarity_description) {
330 /* This is possible: We call a method in a dead part of the program. */
333 assert(0); /* Why should this happen ??? */
334 //exchange(node, new_Bad());
337 entity ** arr = get_entity_link(ent);
341 printf("\nCall site "); DDMN(node);
342 printf(" in "); DDME(get_irg_entity(current_ir_graph));
343 printf(" can call:\n");
344 for (i = 0; i < ARR_LEN(arr); i++) {
345 printf(" - "); DDME(arr[i]);
346 printf(" with owner "); DDMT(get_entity_owner(arr[i]));
351 if (get_opt_optimize() && get_opt_dyn_meth_dispatch() &&
352 (ARR_LEN(arr) == 1 && arr[0] != NULL)) {
354 /* Die Sel-Operation kann immer nur _einen_ Wert auf eine
355 * interne Methode zurückgeben. Wir können daher die
356 * Sel-Operation durch eine Const- bzw. SymConst-Operation
358 set_irg_current_block(current_ir_graph, get_nodes_block(node));
359 assert(get_entity_peculiarity(get_SymConst_entity(get_atomic_ent_value(arr[0]))) ==
360 peculiarity_existent);
361 new_node = copy_const_value(get_atomic_ent_value(arr[0]));
362 DBG_OPT_POLY(node, new_node);
363 exchange (node, new_node);
371 /** Datenstruktur initialisieren. Zusätzlich werden alle
372 * SymConst(name)-Operationen, die auf interne Methoden verweisen, durch
373 * SymConst(entity)-Operationen ersetzt. */
374 static void sel_methods_init(void) {
376 pmap * ldname_map = pmap_create(); /* Map entity names to entities: to replace SymConst(name) by SymConst(ent). */
378 assert(entities == NULL);
379 entities = eset_create();
380 for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
381 ir_graph *irg = get_irp_irg(i);
382 entity * ent = get_irg_entity(irg);
383 /* Nur extern sichtbare Methoden können überhaupt mit SymConst
384 * aufgerufen werden. */
385 if (get_entity_visibility(ent) != visibility_local) {
386 pmap_insert(ldname_map, (void *) get_entity_ld_ident(ent), ent);
389 all_irg_walk(sel_methods_walker, NULL, ldname_map);
390 pmap_destroy(ldname_map);
393 /*****************************************************************************/
395 /** Frees the allocated entity map */
396 static void sel_methods_dispose(void) {
399 for (ent = eset_first(entities); ent; ent = eset_next(entities)) {
400 entity ** arr = get_entity_link(ent);
404 set_entity_link(ent, NULL);
406 eset_destroy(entities);
412 * Returns an array of all methods that could be called at a Sel node.
413 * This array contains every entry only once.
415 static entity ** get_Sel_arr(ir_node * sel) {
416 static entity ** NULL_ARRAY = NULL;
420 assert(sel && get_irn_op(sel) == op_Sel);
421 ent = get_Sel_entity(sel);
422 assert(is_Method_type(get_entity_type(ent))); /* what else? */
423 arr = get_entity_link(ent);
427 /* "NULL" zeigt an, dass keine Implementierung existiert. Dies
428 * kann für polymorphe (abstrakte) Methoden passieren. */
430 NULL_ARRAY = NEW_ARR_F(entity *, 0);
437 * Returns the number of possible called methods at a Sel node.
439 static int get_Sel_n_methods(ir_node * sel) {
440 return ARR_LEN(get_Sel_arr(sel));
444 * Returns the ith possible called method entity at a Sel node.
446 static entity * get_Sel_method(ir_node * sel, int pos) {
447 entity ** arr = get_Sel_arr(sel);
448 assert(pos >= 0 && pos < ARR_LEN(arr));
454 /* --- callee analysis ------------------------------------------------------ */
457 static void callee_ana_node(ir_node * node, eset * methods);
460 static void callee_ana_proj(ir_node * node, long n, eset * methods) {
461 assert(get_irn_mode(node) == mode_T);
462 if (get_irn_link(node) == MARK) {
463 /* already visited */
466 set_irn_link(node, MARK);
468 switch (get_irn_opcode(node)) {
470 /* proj_proj: in einem "sinnvollen" Graphen kommt jetzt ein
471 * op_Tuple oder ein Knoten, der eine "freie Methode"
473 ir_node * pred = get_Proj_pred(node);
474 if (get_irn_link(pred) != MARK) {
475 if (get_irn_op(pred) == op_Tuple) {
476 callee_ana_proj(get_Tuple_pred(pred, get_Proj_proj(node)), n, methods);
478 eset_insert(methods, MARK); /* free method -> unknown */
485 callee_ana_node(get_Tuple_pred(node, n), methods);
489 callee_ana_proj(get_Id_pred(node), n, methods);
493 eset_insert(methods, MARK); /* free method -> unknown */
497 set_irn_link(node, NULL);
501 static void callee_ana_node(ir_node * node, eset * methods) {
504 assert(mode_is_reference(get_irn_mode(node)) || is_Bad(node));
505 /* rekursion verhindern */
506 if (get_irn_link(node) == MARK) {
507 /* already visited */
510 set_irn_link(node, MARK);
512 switch (get_irn_opcode(node)) {
514 if (get_SymConst_kind(node) == symconst_addr_ent) {
515 entity * ent = get_SymConst_entity(node);
516 assert(ent && is_Method_type(get_entity_type(ent)));
517 eset_insert(methods, ent);
519 assert(get_SymConst_kind(node) == symconst_addr_name);
520 /* externe Methode (wegen fix_symconst!) */
521 eset_insert(methods, MARK); /* free method -> unknown */
525 /* polymorphe Methode */
526 for (i = get_Sel_n_methods(node) - 1; i >= 0; --i) {
527 entity * ent = get_Sel_method(node, i);
529 eset_insert(methods, ent);
531 eset_insert(methods, MARK);
540 case iro_Phi: /* Vereinigung */
541 for (i = get_Phi_n_preds(node) - 1; i >= 0; --i) {
542 callee_ana_node(get_Phi_pred(node, i), methods);
547 callee_ana_node(get_Mux_false(node), methods);
548 callee_ana_node(get_Mux_true(node), methods);
552 callee_ana_node(get_Id_pred(node), methods);
556 callee_ana_proj(get_Proj_pred(node), get_Proj_proj(node), methods);
563 eset_insert(methods, MARK); /* free method -> unknown */
567 assert(0 && "invalid opcode or opcode not implemented");
571 set_irn_link(node, NULL);
575 static void callee_walker(ir_node * call, void * env) {
576 if (get_irn_op(call) == op_Call) {
577 eset * methods = eset_create();
579 entity ** arr = NEW_ARR_F(entity *, 0);
580 assert(get_irn_op(get_Call_ptr(call)) != op_Id);
581 callee_ana_node(get_Call_ptr(call), methods);
582 if (eset_contains(methods, MARK)) { /* unknown method */
583 ARR_APP1(entity *, arr, unknown_entity);
585 for (ent = eset_first(methods); ent; ent = eset_next(methods)) {
587 ARR_APP1(entity *, arr, ent);
590 #if 0 /* This generates Bad nodes when we don't want it.
591 Call it with a check for valid cgana information in local_optimize. */
592 if (ARR_LEN(arr) == 0 && get_opt_optimize() && get_opt_dyn_meth_dispatch()) {
593 /* Kann vorkommen, wenn der Vorgänger beispielsweise eine
594 * Sel-Operation war, die keine Methoden zurückgeben
595 * konnte. Wir ersetzen die Call-Operation ebenfalls durch
596 * eine Bad-Operation. Die Verlinkung muss wiederhergestellt
598 ir_node *mem = get_Call_mem(call);
599 turn_into_tuple (call, 5 /* pn_Call_max */);
600 set_Tuple_pred(call, pn_Call_M_regular , mem);
601 set_Tuple_pred(call, pn_Call_T_result , new_Bad());
602 set_Tuple_pred(call, pn_Call_P_value_res_base, new_Bad());
603 set_Tuple_pred(call, pn_Call_X_except , new_Bad()); /* new_Jmp() ?? new_Raise() ?? */
604 set_Tuple_pred(call, pn_Call_M_except , new_Bad());
609 /* remove, what we repaired. */
611 for (i = 0; i < ARR_LEN(arr); ++i) {
613 //if (arr[i] == unknown_entity) arr[i] = NULL;
616 set_Call_callee_arr(call, ARR_LEN(arr), arr);
619 eset_destroy(methods);
624 static void remove_Tuples(ir_node * proj, void * env) {
626 if (get_irn_opcode(proj) != iro_Proj) return;
628 new = skip_Tuple(proj);
629 if (new != proj) exchange(proj, new);
633 /* Bestimmt für jede Call-Operation die Menge der aufrufbaren Methode
634 * und speichert das Ergebnis in der Call-Operation. (siehe
635 * "set_Call_callee"). "sel_methods" wird für den Aufbau benötigt und
636 * muss bereits aufgebaut sein. */
637 static void callee_ana(void) {
639 /* Alle Graphen analysieren. */
640 for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
641 irg_walk_graph(get_irp_irg(i), callee_walker, remove_Tuples, NULL);
642 set_irg_callee_info_state(get_irp_irg(i), irg_callee_info_consistent);
644 set_irp_callee_info_state(irg_callee_info_consistent);
649 /* --- free method analysis ------------------------------------------------- */
652 static void free_mark(ir_node * node, eset * set);
654 static void free_mark_proj(ir_node * node, long n, eset * set) {
655 assert(get_irn_mode(node) == mode_T);
656 if (get_irn_link(node) == MARK) {
657 /* already visited */
660 set_irn_link(node, MARK);
661 switch (get_irn_opcode(node)) {
663 /* proj_proj: in einem "sinnvollen" Graphen kommt jetzt ein
664 * op_Tuple oder ein Knoten, der in "free_ana_walker" behandelt
666 ir_node * pred = get_Proj_pred(node);
667 if (get_irn_link(pred) != MARK && get_irn_op(pred) == op_Tuple) {
668 free_mark_proj(get_Tuple_pred(pred, get_Proj_proj(node)), n, set);
670 /* nothing: da in "free_ana_walker" behandelt. */
676 free_mark(get_Tuple_pred(node, n), set);
680 free_mark_proj(get_Id_pred(node), n, set);
686 /* nothing: Die Operationen werden in "free_ana_walker" selbst
691 assert(0 && "unexpected opcode or opcode not implemented");
694 set_irn_link(node, NULL);
698 static void free_mark(ir_node * node, eset * set) {
701 if (get_irn_link(node) == MARK) {
702 return; /* already visited */
704 set_irn_link(node, MARK);
705 switch (get_irn_opcode(node)) {
707 entity * ent = get_Sel_entity(node);
708 if (is_Method_type(get_entity_type(ent))) {
709 for (i = get_Sel_n_methods(node) - 1; i >= 0; --i) {
710 eset_insert(set, get_Sel_method(node, i));
716 if (get_SymConst_kind(node) == symconst_addr_ent) {
717 entity * ent = get_SymConst_entity(node);
718 if (is_Method_type(get_entity_type(ent))) {
719 eset_insert(set, ent);
722 assert(get_SymConst_kind(node) == symconst_addr_name);
723 /* nothing: SymConst points to extern method */
728 for (i = get_Phi_n_preds(node) - 1; i >= 0; --i) {
729 free_mark(get_Phi_pred(node, i), set);
733 free_mark(get_Id_pred(node), set);
736 free_mark_proj(get_Proj_pred(node), get_Proj_proj(node), set);
739 /* nothing: Wird unten behandelt! */
742 set_irn_link(node, NULL);
746 static void free_ana_walker(ir_node * node, eset * set) {
748 if (get_irn_link(node) == MARK) {
749 /* bereits in einem Zyklus besucht. */
752 switch (get_irn_opcode(node)) {
763 /* Sonderbehandlung, da der Funktionszeigereingang natürlich kein
766 set_irn_link(node, MARK);
767 for (i = get_Call_arity(node) - 1; i >= 0; --i) {
768 ir_node * pred = get_Call_param(node, i);
769 if (mode_is_reference(get_irn_mode(pred))) {
770 free_mark(pred, set);
774 /* other nodes: Alle anderen Knoten nehmen wir als Verräter an, bis
775 * jemand das Gegenteil implementiert. */
777 set_irn_link(node, MARK);
778 for (i = get_irn_arity(node) - 1; i >= 0; --i) {
779 ir_node * pred = get_irn_n(node, i);
780 if (mode_is_reference(get_irn_mode(pred))) {
781 free_mark(pred, set);
786 set_irn_link(node, NULL);
790 /* Die Datenstrukturen für sel-Methoden (sel_methods) muß vor dem
791 * Aufruf von "get_free_methods" aufgebaut sein. Die (internen)
792 * SymConst-Operationen müssen in passende Const-Operationen
793 * umgewandelt worden sein, d.h. SymConst-Operationen verweisen immer
794 * auf eine echt externe Methode. */
795 static entity ** get_free_methods(void)
797 eset * set = eset_create();
799 entity ** arr = NEW_ARR_F(entity *, 0);
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_visibility(ent) != visibility_local) {
807 eset_insert(set, ent);
809 /* Finde alle Methoden die in dieser Methode extern sichtbar werden,
810 z.B. da die Adresse einer Methode abgespeichert wird. */
811 irg_walk_graph(irg, NULL, (irg_walk_func *) free_ana_walker, set);
814 /* insert sticky methods, too */
815 for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
816 ir_graph * irg = get_irp_irg(i);
817 entity * ent = get_irg_entity(irg);
818 /* insert "external visible" methods. */
819 if (get_entity_stickyness (ent) == stickyness_sticky) {
820 eset_insert(set, ent);
824 /* Hauptprogramm ist auch dann frei, wenn es nicht "external
826 if (get_irp_main_irg()) {
827 eset_insert(set, get_irg_entity(get_irp_main_irg()));
829 /* Wandle Menge in Feld um. Effizienter. */
830 for (ent = eset_first(set); ent; ent = eset_next(set)) {
831 ARR_APP1(entity *, arr, ent);
838 void cgana(int *length, entity ***free_methods) {
839 entity ** free_meths, **p;
842 free_meths = get_free_methods();
844 sel_methods_dispose();
846 /* Convert the flexible array to an array that can be handled
848 p = xmalloc(sizeof(*p) * ARR_LEN(free_meths));
849 memcpy(p, free_meths, ARR_LEN(free_meths) * sizeof(*p));
851 *length = ARR_LEN(free_meths);
854 DEL_ARR_F(free_meths);
859 static void destruct_walker(ir_node * node, void * env) {
860 if (get_irn_op(node) == op_Call) {
861 remove_Call_callee_arr(node);
865 void free_callee_info(ir_graph *irg) {
866 irg_walk_graph(irg, destruct_walker, NULL, NULL);
867 set_irg_callee_info_state(irg, irg_callee_info_none);
871 /* Optimize the address expressions passed to call nodes.
873 * This optimization performs the following transformations for
875 * - All SymConst operations that refer to intern methods are replaced
876 * by Const operations refering to the corresponding entity.
877 * - Sel nodes, that select entities that are not overwritten are
878 * replaced by Const nodes refering to the selected entity.
879 * - Sel nodes, for witch no method exists at all are replaced by Bad
881 * - Sel nodes with a pointer input that is an Alloc node are replaced
882 * by Const nodes refering to the entity that implements the method in
883 * the type given by the Alloc node.
885 void opt_call_addrs(void) {
887 sel_methods_dispose();