added two more hooks to the ir graph dumper
[libfirm] / ir / ir / irdump.c
index 329f218..722b91c 100644 (file)
@@ -41,6 +41,7 @@
 #include "callgraph.h"
 #include "irextbb_t.h"
 #include "dbginfo_t.h"
+#include "irtools.h"
 
 #include "irvrfy.h"
 
@@ -67,6 +68,141 @@ static ident *dump_file_filter_id = NULL;
 
 #define ERROR_TXT       "<ERROR>"
 
+/*******************************************************************/
+/* flags to steer output                                           */
+/*******************************************************************/
+
+/** An option to turn off edge labels */
+static int edge_label = 1;
+/** An option to turn off dumping values of constant entities */
+static int const_entities = 1;
+/** An option to dump the keep alive edges */
+static int dump_keepalive = 0;
+/** An option to dump ld_names instead of names. */
+static int dump_ld_name = 1;
+/** Compiler options to dump analysis information in dump_ir_graph */
+int dump_out_edge_flag = 0;
+int dump_dominator_information_flag = 0;
+int dump_loop_information_flag = 0;
+int dump_backedge_information_flag = 1;
+int dump_const_local = 0;
+bool opt_dump_analysed_type_info = 1;
+bool opt_dump_pointer_values_to_info = 0;  /* default off: for test compares!! */
+
+static const char *overrule_nodecolor = NULL;
+
+/** An additional edge hook. */
+static DUMP_NODE_EDGE_FUNC dump_node_edge_hook = NULL;
+
+void set_dump_node_edge_hook(DUMP_NODE_EDGE_FUNC func)
+{
+    dump_node_edge_hook = func;
+}
+
+DUMP_NODE_EDGE_FUNC get_dump_node_edge_hook(void)
+{
+    return dump_node_edge_hook;
+}
+
+
+/** The vcg node attribute hook. */
+static DUMP_IR_GRAPH_FUNC dump_ir_graph_hook = NULL;
+/** The vcg node attribute hook. */
+static DUMP_NODE_VCGATTR_FUNC dump_node_vcgattr_hook = NULL;
+/** The vcg edge attribute hook. */
+static DUMP_EDGE_VCGATTR_FUNC dump_edge_vcgattr_hook = NULL;
+
+/* set the ir graph hook */
+void set_dump_ir_graph_hook(DUMP_IR_GRAPH_FUNC hook) {
+  dump_ir_graph_hook = hook;
+}
+/* set the node attribute hook */
+void set_dump_node_vcgattr_hook(DUMP_NODE_VCGATTR_FUNC hook) {
+  dump_node_vcgattr_hook = hook;
+}
+/* set the edge attribute hook */
+void set_dump_edge_vcgattr_hook(DUMP_EDGE_VCGATTR_FUNC hook) {
+  dump_edge_vcgattr_hook = hook;
+}
+
+INLINE bool get_opt_dump_const_local(void) {
+  if (!dump_out_edge_flag && !dump_loop_information_flag)
+    return dump_const_local;
+  else
+    return false;
+}
+
+void only_dump_method_with_name(ident *name) {
+  dump_file_filter_id = name;
+}
+
+ident *get_dump_file_filter_ident(void) {
+  return dump_file_filter_id;
+}
+
+/** Returns true if dump file filter is not set, or if it is a
+ *  prefix of name. */
+int is_filtered_dump_name(ident *name) {
+  if (!dump_file_filter_id) return 1;
+  return id_is_prefix(dump_file_filter_id, name);
+}
+
+/* To turn off display of edge labels.  Edge labels often cause xvcg to
+   abort with a segmentation fault. */
+void turn_off_edge_labels(void) {
+  edge_label = 0;
+}
+
+void dump_consts_local(bool b) {
+  dump_const_local = b;
+}
+
+void dump_constant_entity_values(bool b) {
+  const_entities = b;
+}
+
+void dump_keepalive_edges(bool b) {
+  dump_keepalive = b;
+}
+
+bool get_opt_dump_keepalive_edges(void) {
+  return dump_keepalive;
+}
+
+void dump_out_edges(bool b) {
+  dump_out_edge_flag = b;
+}
+
+void dump_dominator_information(bool b) {
+  dump_dominator_information_flag = b;
+}
+
+void dump_loop_information(bool b) {
+  dump_loop_information_flag = b;
+}
+
+void dump_backedge_information(bool b) {
+  dump_backedge_information_flag = b;
+}
+
+/* Dump the information of type field specified in ana/irtypeinfo.h.
+ * If the flag is set, the type name is output in [] in the node label,
+ * else it is output as info.
+ */
+void set_opt_dump_analysed_type_info(bool b) {
+  opt_dump_analysed_type_info = b;
+}
+
+void dump_pointer_values_to_info(bool b) {
+  opt_dump_pointer_values_to_info = b;
+}
+
+void dump_ld_names(bool b) {
+  dump_ld_name = b;
+}
+
+/* -------------- some extended helper functions ----------------- */
+
 /**
  * returns the name of a mode or <ERROR> if mode is NOT a mode object.
  * in the later case, sets bad
@@ -271,7 +407,8 @@ static void *ird_get_irn_link(ir_node *n) {
  * Sets the private link field.
  */
 static void ird_set_irn_link(ir_node *n, void *x) {
-  if (!irdump_link_map) init_irdump();
+  if (!irdump_link_map)
+    init_irdump();
   pmap_insert(irdump_link_map, (void *)n, x);
 }
 
@@ -303,21 +440,31 @@ static void clear_link(ir_node * node, void * env) {
 }
 
 /**
- * If the entity has a ld_name, returns it, else returns the name of the entity.
+ * If the entity has a ld_name, returns it if the dump_ld_name is set,
+ * else returns the name of the entity.
  */
-const char *get_ent_dump_name(entity *ent) {
+static const char *_get_ent_dump_name(entity *ent, int dump_ld_name) {
   if (!ent)
     return "<NULL entity>";
-  /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
-  if (ent->ld_name) return get_id_str(ent->ld_name);
+  if (dump_ld_name) {
+    /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
+    if (ent->ld_name) return get_id_str(ent->ld_name);
+  }
   return get_id_str(ent->name);
 }
 
+/**
+ * If the entity has a ld_name, returns it if the option dump_ld_name is set,
+ * else returns the name of the entity.
+ */
+const char *get_ent_dump_name(entity *ent) {
+  return _get_ent_dump_name(ent, dump_ld_name);
+}
+
 /* Returns the name of an IRG. */
 const char *get_irg_dump_name(ir_graph *irg) {
   /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
-  entity *ent = get_irg_entity(irg);
-  return get_ent_dump_name(ent);
+  return _get_ent_dump_name(get_irg_entity(irg), 1);
 }
 
 /**
@@ -430,121 +577,6 @@ static list_tuple *construct_extblock_lists(ir_graph *irg) {
   return lists;
 }
 
-/*******************************************************************/
-/* flags to steer output                                           */
-/*******************************************************************/
-
-/** A compiler option to turn off edge labels */
-static int edge_label = 1;
-/** A compiler option to turn off dumping values of constant entities */
-static int const_entities = 1;
-/** A compiler option to dump the keep alive edges */
-static int dump_keepalive = 0;
-/** Compiler options to dump analysis information in dump_ir_graph */
-int dump_out_edge_flag = 0;
-int dump_dominator_information_flag = 0;
-int dump_loop_information_flag = 0;
-int dump_backedge_information_flag = 1;
-int dump_const_local = 0;
-bool opt_dump_analysed_type_info = 1;
-bool opt_dump_pointer_values_to_info = 0;  /* default off: for test compares!! */
-
-static const char *overrule_nodecolor = NULL;
-
-/** An additional edge hook. */
-static DUMP_NODE_EDGE_FUNC dump_node_edge_hook = NULL;
-
-void set_dump_node_edge_hook(DUMP_NODE_EDGE_FUNC func)
-{
-    dump_node_edge_hook = func;
-}
-
-DUMP_NODE_EDGE_FUNC get_dump_node_edge_hook(void)
-{
-    return dump_node_edge_hook;
-}
-
-
-/** The vcg attribute hook. */
-static DUMP_NODE_VCGATTR_FUNC dump_node_vcgattr_hook = NULL;
-
-/* set the hook */
-void set_dump_node_vcgattr_hook(DUMP_NODE_VCGATTR_FUNC hook) {
-  dump_node_vcgattr_hook = hook;
-}
-
-INLINE bool get_opt_dump_const_local(void) {
-  if (!dump_out_edge_flag && !dump_loop_information_flag)
-    return dump_const_local;
-  else
-    return false;
-}
-
-void only_dump_method_with_name(ident *name) {
-  dump_file_filter_id = name;
-}
-
-ident *get_dump_file_filter_ident(void) {
-  return dump_file_filter_id;
-}
-
-/** Returns true if dump file filter is not set, or if it is a
- *  prefix of name. */
-int is_filtered_dump_name(ident *name) {
-  if (!dump_file_filter_id) return 1;
-  return id_is_prefix(dump_file_filter_id, name);
-}
-
-/* To turn off display of edge labels.  Edge labels offen cause xvcg to
-   abort with a segmentation fault. */
-void turn_off_edge_labels(void) {
-  edge_label = 0;
-}
-
-void dump_consts_local(bool b) {
-  dump_const_local = b;
-}
-
-void dump_constant_entity_values(bool b) {
-  const_entities = b;
-}
-
-void dump_keepalive_edges(bool b) {
-  dump_keepalive = b;
-}
-
-bool get_opt_dump_keepalive_edges(void) {
-  return dump_keepalive;
-}
-
-void dump_out_edges(bool b) {
-  dump_out_edge_flag = b;
-}
-
-void dump_dominator_information(bool b) {
-  dump_dominator_information_flag = b;
-}
-
-void dump_loop_information(bool b) {
-  dump_loop_information_flag = b;
-}
-
-void dump_backedge_information(bool b) {
-  dump_backedge_information_flag = b;
-}
-
-/* Dump the information of type field specified in ana/irtypeinfo.h.
- * If the flag is set, the type name is output in [] in the node label,
- * else it is output as info.
- */
-void set_opt_dump_analysed_type_info(bool b) {
-  opt_dump_analysed_type_info = b;
-}
-
-void dump_pointer_values_to_info(bool b) {
-  opt_dump_pointer_values_to_info = b;
-}
-
 /*-----------------------------------------------------------------*/
 /* Routines to dump information about a single ir node.            */
 /*-----------------------------------------------------------------*/
@@ -627,6 +659,9 @@ dump_node_opcode(FILE *F, ir_node *n)
   case iro_Load:
     fprintf (F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_Load_mode(n), &bad));
     break;
+  case iro_Block:
+    fprintf (F, "%s%s", is_Block_dead(n) ? "Dead " : "", get_irn_opname(n));
+    break;
 
   default: {
 default_case:
@@ -856,6 +891,12 @@ handle_lut:
       }
       if (! f)
         fprintf (F, "%ld ", proj_nr);
+      if (code == iro_Cond && get_Cond_jmp_pred(pred) != COND_JMP_PRED_NONE) {
+        if (proj_nr == pn_Cond_false && get_Cond_jmp_pred(pred) == COND_JMP_PRED_FALSE)
+          fprintf(F, "PRED ");
+        if (proj_nr == pn_Cond_true && get_Cond_jmp_pred(pred) == COND_JMP_PRED_TRUE)
+          fprintf(F, "PRED ");
+      }
     }
     break;
   case iro_Filter:
@@ -1044,6 +1085,19 @@ static void dump_const_block_local(FILE *F, ir_node *n) {
     fprintf (F, "edge: { sourcename: \"");
     PRINT_NODEID(n);
     fprintf (F, "\" targetname: \""); PRINT_CONSTBLKID(n,blk);
+
+       if (dump_edge_vcgattr_hook) {
+         fprintf (F, "\" ");
+      if (dump_edge_vcgattr_hook(F, n, -1)) {
+        fprintf (F, "}\n");
+        return;
+      }
+         else {
+        fprintf (F, " " BLOCK_EDGE_ATTR "}\n");
+               return;
+         }
+    }
+
     fprintf (F, "\" "   BLOCK_EDGE_ATTR "}\n");
   }
 }
@@ -1069,7 +1123,7 @@ static void print_node_dbg_info(FILE *F, dbg_info *dbg)
   if (__dbg_info_snprint) {
     buf[0] = '\0';
     if (__dbg_info_snprint(buf, sizeof(buf), dbg) > 0)
-      fprintf (F, " info3: \"%s\"", buf);
+      fprintf (F, " info3: \"%s\"\n", buf);
   }
 }
 
@@ -1122,6 +1176,19 @@ dump_ir_block_edge(FILE *F, ir_node *n)  {
       PRINT_NODEID(n);
       fprintf (F, "\" targetname: ");
       fprintf(F, "\""); PRINT_NODEID(block); fprintf(F, "\"");
+
+         if (dump_edge_vcgattr_hook) {
+           fprintf (F, " ");
+        if (dump_edge_vcgattr_hook(F, n, -1)) {
+          fprintf (F, "}\n");
+          return;
+        }
+           else {
+          fprintf (F, " "  BLOCK_EDGE_ATTR "}\n");
+                 return;
+           }
+      }
+
       fprintf (F, " "   BLOCK_EDGE_ATTR "}\n");
     }
   }
@@ -1155,6 +1222,10 @@ static void
 print_edge_vcgattr(FILE *F, ir_node *from, int to) {
   assert(from);
 
+  if (dump_edge_vcgattr_hook)
+       if (dump_edge_vcgattr_hook(F, from, to))
+               return;
+
   if (dump_backedge_information_flag && is_backedge(from, to))
     fprintf (F, BACK_EDGE_ATTR);
 
@@ -1361,6 +1432,8 @@ static void dump_const_expression(FILE *F, ir_node *value) {
 static void
 dump_whole_block(FILE *F, ir_node *block) {
   ir_node *node;
+  const char *color = "yellow";
+
   assert(is_Block(block));
 
   fprintf(F, "graph: { title: \"");
@@ -1371,8 +1444,17 @@ dump_whole_block(FILE *F, ir_node *block) {
   if (get_opt_dump_abstvals())
     fprintf (F, " seqno: %d", (int)get_Block_seqno(block));
 #endif
-  fprintf(F, "\" status:clustered color:%s \n",
-       get_Block_matured(block) ? "yellow" : "red");
+
+  /* colorize blocks */
+  if (! get_Block_matured(block))
+    color = "red";
+  if (is_Block_dead(block))
+    color = "orange";
+
+  fprintf(F, "\" status:clustered color:%s \n", color);
+
+  /* ycomp can show attributs for blocks, VCG parses but ignores them */
+  dump_node_info(F, block);
 
   /* dump the blocks edges */
   dump_ir_data_edges(F, block);
@@ -1451,7 +1533,7 @@ dump_extblock_graph(FILE *F, ir_graph *irg) {
   compute_extbb(irg);
   for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
     ir_extblk *extbb = arr[i];
-    ir_node *leader = extbb->blks[0];
+    ir_node *leader = get_extbb_leader(extbb);
     int j;
 
     fprintf(F, "graph: { title: \"");
@@ -1613,8 +1695,7 @@ static void print_typespecific_vcgattr(FILE *F, type *tp) {
 }
 
 
-/* Why not dump_type_node as the others? */
-static int print_type_node(FILE *F, type *tp)
+int dump_type_node(FILE *F, type *tp)
 {
   int bad = 0;
 
@@ -1628,17 +1709,14 @@ static int print_type_node(FILE *F, type *tp)
 #else
   dump_type_to_file(F, tp, dump_verbosity_max);
 #endif
-  fprintf (F, "\"");
+  fprintf (F, "\"\n");
+  print_node_dbg_info(F, get_type_dbg_info(tp));
   print_typespecific_vcgattr(F, tp);
   fprintf (F, "}\n");
 
   return bad;
 }
 
-int dump_type_node(FILE *F, type *tp) {
-  return print_type_node(F, tp);
-}
-
 
 #define X(a)    case a: fprintf(F, #a); break
 void dump_entity_node(FILE *F, entity *ent, int color)
@@ -1656,7 +1734,9 @@ void dump_entity_node(FILE *F, entity *ent, int color)
 
   dump_entity_to_file(F, ent, dump_verbosity_entattrs | dump_verbosity_entconsts);
 
-  fprintf(F, "\"\n}\n");
+  fprintf(F, "\"\n");
+  print_node_dbg_info(F, get_entity_dbg_info(ent));
+  fprintf(F, "}\n");
 }
 #undef X
 
@@ -1729,7 +1809,7 @@ dump_type_info(type_or_ent *tore, void *env) {
   case k_type:
     {
       type *tp = (type *)tore;
-      print_type_node(F, tp);
+      dump_type_node(F, tp);
       /* and now the edges */
       switch (get_type_tpop_code(tp)) {
       case tpo_class:
@@ -1831,7 +1911,7 @@ dump_class_hierarchy_node (type_or_ent *tore, void *ctx) {
       if (tp == get_glob_type()) break;
       switch (get_type_tpop_code(tp)) {
         case tpo_class: {
-          print_type_node(F, tp);
+          dump_type_node(F, tp);
           /* and now the edges */
           for (i=0; i < get_class_n_supertypes(tp); i++)
           {
@@ -1879,7 +1959,7 @@ static INLINE void dump_loop_info(FILE *F, ir_loop *loop) {
   fprintf (F, " info1: \"");
   fprintf (F, " loop nr: %d", get_loop_loop_nr(loop));
 #if DEBUG_libfirm   /* GL @@@ debug analyses */
-  fprintf (F, "\n The loop was analyzed %d times.", (int)get_loop_link(loop));
+  fprintf (F, "\n The loop was analyzed %d times.", PTR_TO_INT(get_loop_link(loop)));
 #endif
   fprintf (F, "\"");
 }
@@ -1950,7 +2030,7 @@ void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg) {
 /**
  * dumps the VCG header
  */
-INLINE void dump_vcg_header(FILE *F, const char *name, const char *orientation) {
+void dump_vcg_header(FILE *F, const char *name, const char *orientation) {
   char *label;
 
   if (edge_label) {
@@ -2078,7 +2158,7 @@ FILE *vcg_open (ir_graph *irg, const char * suffix1, const char *suffix2) {
 /**
  * open a vcg file
  *
- * @param irg     The graph to be dumped
+ * @param name    prefix file name
  * @param suffix  filename suffix
  */
 FILE *vcg_open_name (const char *name, const char *suffix) {
@@ -2089,7 +2169,7 @@ FILE *vcg_open_name (const char *name, const char *suffix) {
   if (!suffix) suffix = "";
 
   /** open file for vcg graph */
-  fname = malloc (len * 2 + 5 + strlen(suffix));
+  fname = xmalloc(len * 2 + 5 + strlen(suffix));
   /* strcpy (fname, name);*/    /* copy the filename */
   j = 0;
   for (i = 0; i < len; ++i) {  /* replace '/' in the name: escape by @. */
@@ -2159,6 +2239,11 @@ dump_ir_graph (ir_graph *irg, const char *suffix )
   f = vcg_open(irg, suffix, suffix1);
   dump_vcg_header(f, get_irg_dump_name(irg), NULL);
 
+  /* call the dump graph hook */
+  if (dump_ir_graph_hook)
+    if (dump_ir_graph_hook(f, irg))
+      return;
+
   /* walk over the graph */
   /* dump_whole_node must be called in post visiting predecessors */
   irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
@@ -2267,12 +2352,16 @@ dump_ir_graph_w_types (ir_graph *irg, const char *suffix)
   FILE *f;
   ir_graph *rem = current_ir_graph;
   char *suffix1;
+  int rem_dump_const_local;
 
   /* if a filter is set, dump only the irg's that match the filter */
   if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
     return;
 
   current_ir_graph = irg;
+  rem_dump_const_local = dump_const_local;
+  /* dumping types does not work with local nodes */
+  dump_const_local = 0;
 
   if (get_interprocedural_view()) suffix1 = "-pure-wtypes-ip";
   else                            suffix1 = "-pure-wtypes";
@@ -2288,6 +2377,7 @@ dump_ir_graph_w_types (ir_graph *irg, const char *suffix)
   irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
 
   vcg_close(f);
+  dump_const_local = rem_dump_const_local;
   current_ir_graph = rem;
 }
 
@@ -2298,11 +2388,16 @@ dump_ir_block_graph_w_types (ir_graph *irg, const char *suffix)
   int i;
   char *suffix1;
   ir_graph *rem = current_ir_graph;
+  int rem_dump_const_local;
 
   /* if a filter is set, dump only the irg's that match the filter */
   if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
     return;
 
+  rem_dump_const_local = dump_const_local;
+  /* dumping types does not work with local nodes */
+  dump_const_local = 0;
+
   if (get_interprocedural_view()) suffix1 = "-wtypes-ip";
   else                            suffix1 = "-wtypes";
   f = vcg_open(irg, suffix, suffix1);
@@ -2327,8 +2422,9 @@ dump_ir_block_graph_w_types (ir_graph *irg, const char *suffix)
   /* dump edges from graph to type info */
   irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
 
-  current_ir_graph = rem;
   vcg_close(f);
+  dump_const_local = rem_dump_const_local;
+  current_ir_graph = rem;
 }
 
 /*---------------------------------------------------------------------*/
@@ -2338,7 +2434,7 @@ dump_ir_block_graph_w_types (ir_graph *irg, const char *suffix)
 static void
 dump_block_to_cfg(ir_node *block, void *env) {
   FILE *F = env;
-  int i, fl;
+  int i, fl = 0;
   ir_node *pred;
 
   if (is_Block(block)) {