include irmode_t.h to speed up mode access
[libfirm] / ir / ana / cgana.c
index 705f377..2df8c88 100644 (file)
 #include "irgmod.h"
 #include "irnode_t.h"
 #include "irflag_t.h"
+#include "irmode_t.h"
 
 #include "dbginfo_t.h"
 
+#include "irdump.h"
+
 /* Eindeutige Adresse zur Markierung von besuchten Knoten und zur
  * Darstellung der unbekannten Methode. */
 static void * MARK = &MARK;
@@ -49,9 +52,9 @@ static void * MARK = &MARK;
 static eset * entities = NULL;
 
 
-/* Bestimmt die eindeutige Methode, die die Methode für den
- * übergebenene (dynamischen) Typ überschreibt. */
-entity * get_implementation(type * class, entity * method) {
+/** Bestimmt die eindeutige Methode, die die Methode für den
+ * übergebenen (dynamischen) Typ überschreibt. */
+static entity * get_implementation(type * class, entity * method) {
   int i;
   if (get_entity_peculiarity(method) != peculiarity_description &&
       get_entity_owner(method) == class) {
@@ -73,9 +76,9 @@ entity * get_implementation(type * class, entity * method) {
   return NULL;
 }
 
-/* Returns the entity that contains the implementation of the inherited
-   entity if available, else returns the entity passed. */
-entity *get_inherited_methods_implementation(entity *inh_meth) {
+/** Returns the entity that contains the implementation of the inherited
+    entity if available, else returns the entity passed. */
+static entity *get_inherited_methods_implementation(entity *inh_meth) {
   entity *impl_meth = NULL;
   ir_node *addr = get_atomic_ent_value(inh_meth);
   assert(addr && "constant entity without value");
@@ -86,23 +89,33 @@ entity *get_inherited_methods_implementation(entity *inh_meth) {
     assert(0 && "Complex constant values not supported -- address of method should be straight constant!");
   }
   if (impl_meth && (get_entity_peculiarity(impl_meth) != peculiarity_existent)) {
-    printf("this_meth: "); DDMEO(inh_meth);
-    printf("impl meth: "); DDMEO(impl_meth);
-    assert(!impl_meth || get_entity_peculiarity(impl_meth) == peculiarity_existent);
+    /*
+      printf("this_meth: "); DDMEO(inh_meth);
+      printf("impl meth: "); DDMEO(impl_meth);
+      assert(!impl_meth || get_entity_peculiarity(impl_meth) == peculiarity_existent);
+    */
+    impl_meth = NULL;
   }
   return impl_meth? impl_meth : inh_meth;
 }
 
 
-/* Collect the entity representing the implementation of this
-   entity (not the same if inherited) and all entities for overwriting
-   implementations in "set".
-   If the implementation of the method is not included in the
-   compilation unit "open" is set to true.
-   A recursive descend in the overwritten relation.
-   Cycle-free, therefore must terminate. */
-void collect_impls(entity *method, eset *set, int *size, bool *open) {
+/** Collect the entity representing the implementation of this
+ *  entity (not the same if inherited) and all entities for overwriting
+ *  implementations in "set".
+ *  If the implementation of the method is not included in the
+ *  compilation unit "open" is set to true.
+ *  A recursive descend in the overwritten relation.
+ *  Cycle-free, therefore must terminate.
+ *
+ * @param method
+ * @param set      A set of entities.
+ * @param size     Number of entities in set.
+ * @param open
+ */
+static void collect_impls(entity *method, eset *set, int *size, bool *open) {
   int i;
+
   if (get_entity_peculiarity(method) == peculiarity_existent) {
     if (get_entity_visibility(method) == visibility_external_allocated) {
       assert(get_entity_irg(method) == NULL);
@@ -115,6 +128,7 @@ void collect_impls(entity *method, eset *set, int *size, bool *open) {
       }
     }
   }
+
   if (get_entity_peculiarity(method) == peculiarity_inherited) {
     entity *impl_ent = get_inherited_methods_implementation(method);
     assert(impl_ent && "no implementation for inherited entity");
@@ -135,24 +149,26 @@ void collect_impls(entity *method, eset *set, int *size, bool *open) {
 }
 
 
-/* Alle Methoden bestimmen, die die übergebene Methode überschreiben
- * (und implementieren). In der zurückgegebenen Reihung kommt jede
- * Methode nur einmal vor. Der Wert 'NULL' steht für unbekannte
- * (externe) Methoden. Die zurückgegebene Reihung muß vom Aufrufer
- * wieder freigegeben werden (siehe "DEL_ARR_F"). Gibt es überhaupt
- * keine Methoden, die die "method" überschreiben, so gibt die Methode
- * "NULL" zurück. */
+/** Alle Methoden bestimmen, die die übergebene Methode überschreiben
+ *  (und implementieren). In der zurückgegebenen Reihung kommt jede
+ *  Methode nur einmal vor. Der Wert 'NULL' steht für unbekannte
+ *  (externe) Methoden. Die zurückgegebene Reihung muß vom Aufrufer
+ *  wieder freigegeben werden (siehe "DEL_ARR_F"). Gibt es überhaupt
+ *  keine Methoden, die "method" überschreiben, so gibt die Methode
+ *  "NULL" zurück.
+ *
+ *  @param method
+ */
 static entity ** get_impl_methods(entity * method) {
   eset * set = eset_create();
   int size = 0;
   entity ** arr;
   bool open = false;
 
-  /** Collect all method entities that can be called here **/
+  /* Collect all method entities that can be called here */
   collect_impls(method, set, &size, &open);
 
-/**
-     Vorgaenger einfuegen. **/
+  /* Vorgaenger einfuegen. */
   if (size == 0 && !open) {
     /* keine implementierte überschriebene Methode */
     arr = NULL;
@@ -189,15 +205,29 @@ static entity ** get_impl_methods(entity * method) {
       __dbg_info_merge_pair(new_node, node, dbg_rem_poly_call)
 
 
+
+/** Analyse address computations.
+ *
+ *  - If the node is a SymConst replace it by Const(ent) if possible.
+ *  - If the node is a Sel:
+ *    * If the pointer to the Sel comes directly from an Alloc node
+ *      replace the Sel by a Const(ent).
+ *
+ *
+ *  @param node The node to analyze
+ *  @param ldname_map A map that mapps names of entities to the entities.
+ */
 static void sel_methods_walker(ir_node * node, pmap * ldname_map) {
+
   if (get_irn_op(node) == op_SymConst) {
     /* Wenn möglich SymConst-Operation durch Const-Operation
      * ersetzen. */
     if (get_SymConst_kind(node) == linkage_ptr_info) {
-      pmap_entry * entry = pmap_find(ldname_map, (void *) get_SymConst_ptrinfo(node));
+      pmap_entry *entry = pmap_find(ldname_map, (void *) get_SymConst_ptrinfo(node));
       if (entry != NULL) { /* Method is declared in the compiled code */
-        entity * ent = entry->value;
-        if (get_opt_normalize() && (get_entity_visibility(ent) != visibility_external_allocated)) { /* Meth. is defined */
+        entity *ent = entry->value;
+        if (get_opt_normalize() && (get_entity_visibility(ent) != visibility_external_allocated)) {
+         /* Meth. is defined */
           ir_node *new_node;
           assert(get_entity_irg(ent));
           set_irg_current_block(current_ir_graph, get_nodes_Block(node));
@@ -279,6 +309,7 @@ static void sel_methods_walker(ir_node * node, pmap * ldname_map) {
            * Sel-Operation durch eine Const- bzw. SymConst-Operation
            * ersetzen. */
           set_irg_current_block(current_ir_graph, get_nodes_Block(node));
+          /* assert(get_entity_peculiarity(tarval_to_entity(get_Const_tarval(get_atomic_ent_value(arr[0])))) == peculiarity_existent); */
           new_node = copy_const_value(get_atomic_ent_value(arr[0]));         DBG_OPT_POLY;
           exchange (node, new_node);
         }
@@ -288,12 +319,12 @@ static void sel_methods_walker(ir_node * node, pmap * ldname_map) {
 }
 
 
-/* Datenstruktur initialisieren. Zusätzlich werden alle
- * SymConst-Operationen, die auf interne Methoden verweisen, durch
- * Const-Operationen ersetzt. */
+/** Datenstruktur initialisieren. Zusätzlich werden alle
+ *  SymConst-Operationen, die auf interne Methoden verweisen, durch
+ *  Const-Operationen ersetzt. */
 static void sel_methods_init(void) {
   int i;
-  pmap * ldname_map = pmap_create();
+  pmap * ldname_map = pmap_create();   /* Map entitiy names to entities: to replace SymConst by Const(ent). */
   assert(entities == NULL);
   entities = eset_create();
   for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
@@ -432,7 +463,10 @@ static void callee_ana_node(ir_node * node, eset * methods) {
     entity * ent = tarval_to_entity(get_Const_tarval(node));
     assert(ent && is_method_type(get_entity_type(ent)));
     if (get_entity_visibility(ent) != visibility_external_allocated) {
-      assert(get_entity_irg(ent));
+      if (!get_entity_irg(ent)) {
+       dump_entity(ent);
+       assert(get_entity_irg(ent));
+      }
       eset_insert(methods, ent);
     } else {
       eset_insert(methods, MARK); /* free method -> unknown */
@@ -509,7 +543,7 @@ static void callee_walker(ir_node * call, void * env) {
       /* exchange(call, new_Bad());  invalid firm */
 
       ir_node *mem = get_Call_mem(call);
-      turn_into_tuple (call, pn_Call_max);
+      turn_into_tuple (call, 5 /* pn_Call_max */);
       set_Tuple_pred(call, pn_Call_M_regular       , mem);
       set_Tuple_pred(call, pn_Call_T_result        , new_Bad());
       set_Tuple_pred(call, pn_Call_P_value_res_base, new_Bad());
@@ -673,7 +707,7 @@ static void free_ana_walker(ir_node * node, eset * set) {
     for (i = get_irn_arity(node) - 1; i >= 0; --i) {
       ir_node * pred = get_irn_n(node, i);
       if (mode_is_reference(get_irn_mode(pred))) {
-       free_mark(pred, set);
+    free_mark(pred, set);
       }
     }
     break;
@@ -735,13 +769,34 @@ void cgana(int *length, entity ***free_methods) {
   DEL_ARR_F(free_meths);
 }
 
+
+
+static void destruct_walker(ir_node * node, void * env) {
+  if (get_irn_op(node) == op_Call) {
+    remove_Call_callee_arr(node);
+  }
+}
+
+void free_callee_info(ir_graph *irg) {
+  irg_walk_graph(irg, destruct_walker, NULL, NULL);
+  set_irg_callee_info_state(irg, irg_callee_info_none);
+}
+
+
 /* Optimize the address expressions passed to call nodes.
- * Alle SymConst-Operationen, die auf interne Methoden verweisen,
- * werden durch Const-Operationen ersetzt.
- * Sel Knoten deren entitaeten nicht ueberschrieben werden, werden
- * durch Const ersetzt.
- * Sel Knoten, fuer die keine Implementierung existiert, werden
- * durch Bad ersetzt. */
+ *
+ * This optimization performs the following transformations for
+ * all ir graphs:
+ * - All SymConst operations that refer to intern methods are replaced
+ *   by Const operations refering to the corresponding entity.
+ * - Sel nodes, that select entities that are not overwritten are
+ *   replaced by Const nodes refering to the selected entity.
+ * - Sel nodes, for witch no method exists at all are replaced by Bad
+ *   nodes.
+ * - Sel nodes with a pointer input that is an Alloc node are replaced
+ *   by Const nodes refering to the entity that implements the method in
+ *   the type given by the Alloc node.
+ */
 void opt_call_addrs(void) {
   sel_methods_init();
   sel_methods_dispose();