fixed various errors with exceptions + inlineing, dumping and interproc representation
authorGötz Lindenmaier <goetz@ipd.info.uni-karlsruhe.de>
Mon, 29 Sep 2003 15:17:55 +0000 (15:17 +0000)
committerGötz Lindenmaier <goetz@ipd.info.uni-karlsruhe.de>
Mon, 29 Sep 2003 15:17:55 +0000 (15:17 +0000)
added new asserstio in vrfy

[r1891]

ir/ir/ircgcons.c
ir/ir/irdump.c
ir/ir/irgopt.c
ir/ir/irnode.c
ir/ir/irnode.h
ir/ir/irvrfy.c

index be6d0f8..929e5e2 100644 (file)
@@ -498,6 +498,32 @@ static ir_node * get_except(ir_node * call) {
   return NULL;
 }
 
+/* Returns true if control flow operation exc is predecessor of end
+   block in irg.  Works also for Return nodes, not only exceptions. */
+static bool exc_branches_to_end(ir_graph *irg, ir_node *exc) {
+  int i;
+  ir_node *end = get_irg_end_block(irg);
+  for (i = get_Block_n_cfgpreds(end) -1; i >= 0; --i)
+    if (get_Block_cfgpred(end, i) == exc) return true;
+  return false;
+}
+
+/* Returns true if only caller of irg is "Unknown". */
+static bool is_outermost_graph(ir_graph *irg) {
+  irg_data_t * data = get_entity_link(get_irg_ent(irg));
+  if (data->count) {
+    return false;
+  } else if (data->open) {
+    /* Die Methode wird nur von "der" unbekannten Aufrufstelle
+     * aufgerufen. Darstellung wird für diese Methode nicht
+     * geändert. */
+  } else {
+    /* Methode kann nicht aufgerufen werden. Die Darstellung wird
+     * für diese Methode nicht geändert. Das kann nicht vorkommen,
+     * wenn zuvor "gc_irgs()" aufgerufen wurde. */
+  }
+  return true;
+}
 
 /* Grundblock der Call-Operation aufteilen. CallBegin- und Filter-Operationen
  * einfügen. Die Steuer- und Datenflussabhängigkeiten von den aufgerufenen
@@ -568,12 +594,31 @@ static void construct_call(ir_node * call) {
   /* Die interprozeduralen Steuerflussvorgänger des except_block
    * bestimmen. */
   if ((proj = get_except(call)) != NULL) {
-    except_block = create_Block(1, &proj);
-    set_nodes_Block(proj, except_block);
-    exchange(proj, new_Break());
-    set_irg_current_block(current_ir_graph, pre_block);
-    set_irn_n(except_block, 0, new_Proj(call, mode_X, 1));
-    set_irg_current_block(current_ir_graph, post_block);
+    int preds = 0;
+    bool exc_to_end = false;
+#if 1
+    if (exc_branches_to_end(current_ir_graph, proj)) {
+      /* The Call aborts the procedure if it returns with an exception.
+        If this is an outermost procedure, the normal handling of exceptions
+        will generate a Break that goes to the end block.  This is illegal
+        Frim. So directly branch to the end block with all exceptions. */
+      exc_to_end = true;
+      if (is_outermost_graph(current_ir_graph)) {
+       except_block = get_irg_end_block(current_ir_graph);
+      } else {
+       irg_data_t * data = get_entity_link(get_irg_ent(current_ir_graph));
+       except_block = get_nodes_block(data->except);
+      }
+    } else
+#endif
+      {
+      except_block = create_Block(1, &proj);
+      set_nodes_Block(proj, except_block);
+      exchange(proj, new_Break());
+      set_irg_current_block(current_ir_graph, pre_block);
+      set_irn_n(except_block, 0, new_Proj(call, mode_X, 1));
+      set_irg_current_block(current_ir_graph, post_block);
+    }
 
     /*
      * Set flag to suppress verifying placement on proper irg:
@@ -594,9 +639,24 @@ static void construct_call(ir_node * call) {
        in[i] = new_Unknown();
       }
     }
-    set_Block_cg_cfgpred_arr(except_block, n_callees, in);
-  }
 
+    preds = n_callees;
+    if (exc_to_end) {
+      /* append all existing preds of the end block to new in array.
+       * Normal access routine guarantees that with first visit we
+       * get the normal preds, and from then on the _cg_ preds.
+       * (interporcedural view is set!)
+       * Do not add the exc pred of end we are replacing! */
+      for (i = get_Block_n_cfgpreds(except_block)-1; i >= 0; --i) {
+       ir_node *pred = get_Block_cfgpred(except_block, i);
+       if (pred != proj) {
+         ARR_APP1(ir_node *, in, pred);
+         preds++;
+       }
+      }
+    }
+    set_Block_cg_cfgpred_arr(except_block, preds, in);
+  }
   set_interprocedural_view(0);
 
   /* Diesen Vorgänger in den Start-Blöcken der aufgerufenen Methoden
index 2477602..963a5bd 100644 (file)
@@ -63,7 +63,7 @@
 #define TYPE_CLASS_NODE_ATTR "color: green"
 #define TYPE_DESCRIPTION_NODE_ATTR "color: lightgreen"
 #define ENTITY_NODE_ATTR     "color: yellow"
-#define ENT_TYPE_EDGE_ATTR   "class: 3 label: \"type\" color: red"
+#define ENT_TYPE_EDGE_ATTR   "class: 3 label \"type\" color: red"
 #define ENT_OWN_EDGE_ATTR    "class: 4 label: \"owner\" color: black"
 #define METH_PAR_EDGE_ATTR   "class: 5 label: \"param %d\" color: green"
 #define METH_RES_EDGE_ATTR   "class: 6 label: \"res %d\" color: green"
@@ -352,10 +352,12 @@ static bool pred_in_wrong_graph(ir_node *n, int pos, pmap *irgmap) {
 static INLINE
 bool is_constlike_node(ir_node *n) {
   ir_op *op = get_irn_op(n);
-  return (op == op_Const || op == op_Bad || op == op_SymConst);
+  return (op == op_Const || op == op_Bad || op == op_SymConst || op == op_Unknown);
 }
 
 
+/* outputs the predecessors of n, that are constants, local.  I.e.,
+   generates a copy of the constant for each node called with. */
 static void dump_const_node_local(ir_node *n, pmap *irgmap) {
   int i;
   if (!get_opt_dump_const_local()) return;
@@ -517,7 +519,7 @@ static void print_edge_vcgattr(ir_node *from, int to) {
 
 /* dump edges to our inputs */
 static void
-dump_ir_data_edges(ir_node *n)  {
+dump_ir_data_edges(ir_node *n, pmap *irgmap)  {
   int i, visited = get_irn_visited(n);
 
   if ((get_irn_op(n) == op_End) && (!dump_keepalive))
@@ -534,9 +536,10 @@ dump_ir_data_edges(ir_node *n)  {
       fprintf (F, "edge: {sourcename: \"");
     PRINT_NODEID(n);
     fprintf (F, "\" targetname: ");
-    if ((get_opt_dump_const_local()) && is_constlike_node(pred))
+    if ((get_opt_dump_const_local()) && is_constlike_node(pred) &&
+       !pred_in_wrong_graph(n, i, irgmap))
     {
-      PRINT_CONSTID(n,pred);
+      PRINT_CONSTID(n, pred);
     }
     else
       {fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
@@ -1074,7 +1077,7 @@ static void
 dump_whole_node (ir_node *n, void* env) {
   dump_node(n, NULL);
   if (!node_floats(n)) dump_ir_block_edge(n);
-  dump_ir_data_edges(n);
+  dump_ir_data_edges(n, NULL);
 }
 
 void
@@ -1110,7 +1113,7 @@ dump_ir_blocks_nodes (ir_node *n, void *env) {
 
   if (is_no_Block(n) && get_nodes_Block(n) == block && !node_floats(n)) {
     dump_node(n, NULL);
-    dump_ir_data_edges(n);
+    dump_ir_data_edges(n, NULL);
   }
   if (get_irn_op(n) == op_Bad)
     Bad_dumped = 1;
@@ -1137,7 +1140,7 @@ dump_ir_block (ir_node *block, void *env) {
     fprintf(F, "\" status:clustered color:%s \n",
             get_Block_matured (block) ? "yellow" : "red");
     /* dump the blocks edges */
-    dump_ir_data_edges(block);
+    dump_ir_data_edges(block, NULL);
 
     /* dump the nodes that go into the block */
     irg_walk(get_irg_end(irg), dump_ir_blocks_nodes, NULL, block);
@@ -1153,14 +1156,14 @@ static void
 dump_blockless_nodes (ir_node *n, void *env) {
   if (is_no_Block(n) && get_irn_op(get_nodes_Block(n)) == op_Bad) {
     dump_node(n, NULL);
-    dump_ir_data_edges(n);
+    dump_ir_data_edges(n, NULL);
     dump_ir_block_edge(n);
     if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
     return;
   }
   if (node_floats(n)) {
     dump_node(n, NULL);
-    dump_ir_data_edges(n);
+    dump_ir_data_edges(n, NULL);
     if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
   }
 }
@@ -1426,6 +1429,7 @@ static void clear_link(ir_node * node, void * env) {
   set_irn_link(node, NULL);
 }
 
+
 static void collect_blocks_floats_cg(ir_node * node, pmap * map) {
   assert(node); assert(map);
   if (is_Block(node)
@@ -1458,15 +1462,13 @@ static void dump_cg_ir_block(ir_node * block, void * env) {
   ir_node *node;
   pmap *irgmap = (pmap *)env;
   assert(is_Block(block));
+
   fprintf(F, "graph: { title: \"");
   PRINT_NODEID(block);
   fprintf(F, "\"  label: \"");
-  fprintf (F, "%s ", get_op_name(get_irn_op(block)));
-#ifdef DEBUG_libfirm
-  fprintf (F, "%ld", get_irn_node_nr(block));
-#else
-  fprintf (F, "%p", (void*) block);
-#endif
+  dump_node_opcode(block);
+  fprintf (F, " %ld", get_irn_node_nr(block));
+
   if (exc_normal != get_Block_exc(block)) {
     fprintf (F, " (%s)", exc_to_string (get_Block_exc(block)));
   }
@@ -1475,34 +1477,36 @@ static void dump_cg_ir_block(ir_node * block, void * env) {
           get_Block_matured(block) ? "yellow" : "red");
 
   /* dump the blocks edges */
-  dump_ir_data_edges(block);
+  dump_ir_data_edges(block, irgmap);
 
   /* dump the nodes that go into the block */
   for (node = get_irn_link(block); node; node = get_irn_link(node)) {
     dump_node(node, irgmap);
-    dump_ir_data_edges(node);
+    dump_ir_data_edges(node, irgmap);
   }
 
   /* Close the vcg information for the block */
-  fprintf(F, "}\n\n");
+  fprintf(F, "}\n");
+  dump_const_node_local(block, irgmap);
+  fprintf(F, "\n");
 }
 
 static void d_cg_block_graph(ir_graph *irg, ir_node **arr, pmap *irgmap) {
   int i;
 
-  fprintf(F, "graph: { title: %p label: %s status:clustered color:white \n",
+  fprintf(F, "graph: { title: \"%p\" label: \"%s\" status:clustered color:white \n",
           (void*) irg, get_entity_name(get_irg_ent(irg)));
 
   for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
     ir_node * node = arr[i];
     if (is_Block(node)) {
-      /* Dumps the block and all the nodes in the block , which are to
+      /* Dumps the block and all the nodes in the block, which are to
         be found in Block->link. */
       dump_cg_ir_block(node, irgmap);
     } else {
       /* Nodes that are not in a Block. */
       dump_node(node, NULL);
-      dump_ir_data_edges(node);
+      dump_ir_data_edges(node, NULL);
     }
   }
   /* Close the vcg information for the irg */
@@ -1604,12 +1608,12 @@ void dump_cg_graph(ir_graph * irg) {
     for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
       ir_node * node = arr[i];
       dump_node(node, map2);
-      dump_ir_data_edges(node);
+      dump_ir_data_edges(node, NULL);
       if (is_Block(node)) {
        for (node = get_irn_link(node); node; node = get_irn_link(node)) {
          dump_node(node, map2);
          dump_ir_block_edge(node);
-         dump_ir_data_edges(node);
+         dump_ir_data_edges(node, NULL);
        }
       }
     }
index 2275d03..4cb15d2 100644 (file)
@@ -529,6 +529,8 @@ copy_node_inline (ir_node *n, void *env) {
   }
 }
 
+#include "irdump.h"
+
 void inline_method(ir_node *call, ir_graph *called_graph) {
   ir_node *pre_call;
   ir_node *post_call, *post_bl;
@@ -775,8 +777,10 @@ void inline_method(ir_node *call, ir_graph *called_graph) {
       cf_op = get_Block_cfgpred(end_bl, i);
       if (get_irn_op(cf_op) == op_Proj) {
        cf_op = get_Proj_pred(cf_op);
-       if (get_irn_op(cf_op) == op_Tuple) {
-         cf_op = get_Tuple_pred(cf_op, 1);
+       if ((get_irn_op(cf_op) == op_Tuple) && (cf_op == call)) {
+           // There are unoptimized tuples from inlineing before when no exc
+         assert(get_Proj_proj(get_Block_cfgpred(end_bl, i)) == pn_Call_X_except);
+         cf_op = get_Tuple_pred(cf_op, pn_Call_X_except);
          assert(get_irn_op(cf_op) == op_Jmp);
          break;
        }
@@ -1182,7 +1186,9 @@ static void merge_blocks(ir_node *n, void *env) {
     while (irn_not_visited(b) && (!is_Bad(new)) && (new != b)) {
       /* We would have to run gigo if new is bad, so we
         promote it directly below. */
-      assert(((b == new) || get_opt_control_flow_straightening() || get_opt_control_flow_weak_simplification()) &&
+      assert(((b == new) ||
+             get_opt_control_flow_straightening() ||
+             get_opt_control_flow_weak_simplification()) &&
             ("strange flag setting"));
       exchange (b, new);
       b = new;
@@ -1491,10 +1497,14 @@ static void walk_critical_cf_edges(ir_node *n, void *env) {
       (get_irn_arity(n) > 1)) {
     arity = get_irn_arity(n);
 
+    if (n == get_irg_end_block(current_ir_graph))
+      return;  // No use to add a block here.
+
     for (i=0; i<arity; i++) {
       pre = get_irn_n(n, i);
       /* Predecessor has multiple sucessors. Insert new flow edge */
-      if ((NULL != pre) && (op_Proj == get_irn_op(pre)) &&
+      if ((NULL != pre) &&
+         (op_Proj == get_irn_op(pre)) &&
          op_Raise != get_irn_op(skip_Proj(pre))) {
 
        /* set predecessor array for new block */
index 18822a8..deea0d8 100644 (file)
@@ -384,7 +384,7 @@ get_irn_node_nr(const ir_node *node) {
 #ifdef DEBUG_libfirm
   return node->node_nr;
 #else
-  return 0;
+  return (long)&node;
 #endif
 }
 
index 7f8b731..6e21f77 100644 (file)
@@ -150,7 +150,8 @@ INLINE void          set_irn_link          (ir_node *node, void *link);
 INLINE void         *get_irn_link          (const ir_node *node);
 
 /** Outputs a unique number for this node if libfirm is compiled for
-   debugging, (configure with --enable-debug) else returns 0. */
+   debugging, (configure with --enable-debug) else returns address
+   of node cast to long. */
 INLINE long          get_irn_node_nr(const ir_node *node);
 
 /** Returns the ir_graph this node belongs to. Only valid for
index 11ff7a2..0f852aa 100644 (file)
@@ -263,23 +263,14 @@ int irn_vrfy_irg(ir_node *n, ir_graph *irg)
       // End block may only have Return, Raise or fragile ops as preds.
       if (n == get_irg_end_block(irg))
        for (i = 0; i < get_Block_n_cfgpreds(n); ++i) {
-#if 1  // Some optimization seems to add a Jmp to the End Block??
          ir_node *pred =  skip_Proj(get_Block_cfgpred(n, i));
-         if ((get_irn_op(pred) == op_Return) ||
-             is_Bad(pred)                    ||
-             (get_irn_op(pred) == op_Raise)  ||
-             is_fragile_op(pred)               )
-           { }
-         else {
-           DDMG(irg); printf(" pred %d, ", i); DDMN(n); DDMN(pred);
-         }
-
+         if (is_Proj(pred) || get_irn_op(pred) == op_Tuple)
+           break;   // We can not test properly.  How many tuples are there?
          ASSERT_AND_RET(((get_irn_op(pred) == op_Return) ||
                          is_Bad(pred)                    ||
                          (get_irn_op(pred) == op_Raise)  ||
                          is_fragile_op(pred)               ),
                         "End Block node", 0);
-#endif
        }
       break;