additional graph properties added
[libfirm] / ir / ir / irdump.c
index 5f2c0d7..5ed8a48 100644 (file)
@@ -67,6 +67,129 @@ 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 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;
+}
+
+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
@@ -303,21 +426,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 +563,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.            */
 /*-----------------------------------------------------------------*/
@@ -688,6 +706,129 @@ static int dump_node_typeinfo(FILE *F, ir_node *n) {
   return bad;
 }
 
+typedef struct _pns_lookup {
+  long       nr;      /**< the proj number */
+  const char *name;   /**< the name of the Proj */
+} pns_lookup_t;
+
+typedef struct _proj_lookup {
+  opcode             code;      /**< the opcode of the Proj predecessor */
+  unsigned           num_data;  /**< number of data entries */
+  const pns_lookup_t *data;     /**< the data */
+} proj_lookup_t;
+
+#define ARR_SIZE(a)       (sizeof(a)/sizeof(a[0]))
+
+/** the lookup table for Proj(Start) names */
+static const pns_lookup_t start_lut[] = {
+#define X(a)    { pn_Start_##a, #a }
+  X(X_initial_exec),
+  X(P_frame_base),
+  X(P_globals),
+  X(T_args),
+  X(P_value_arg_base)
+#undef X
+};
+
+/** the lookup table for Proj(Cond) names */
+static const pns_lookup_t cond_lut[] = {
+#define X(a)    { pn_Cond_##a, #a }
+  X(false),
+  X(true)
+#undef X
+};
+
+/** the lookup table for Proj(Call) names */
+static const pns_lookup_t call_lut[] = {
+#define X(a)    { pn_Call_##a, #a }
+  X(M_regular),
+  X(T_result),
+  X(P_value_res_base),
+  X(X_except),
+  X(M_except)
+#undef X
+};
+
+/** the lookup table for Proj(Quot) names */
+static const pns_lookup_t quot_lut[] = {
+#define X(a)    { pn_Quot_##a, #a }
+  X(M),
+  X(X_except),
+  X(res)
+#undef X
+};
+
+/** the lookup table for Proj(DivMod) names */
+static const pns_lookup_t divmod_lut[] = {
+#define X(a)    { pn_DivMod_##a, #a }
+  X(M),
+  X(X_except),
+  X(res_div),
+  X(res_mod)
+#undef X
+};
+
+/** the lookup table for Proj(Div) names */
+static const pns_lookup_t div_lut[] = {
+#define X(a)    { pn_Div_##a, #a }
+  X(M),
+  X(X_except),
+  X(res)
+#undef X
+};
+
+/** the lookup table for Proj(Mod) names */
+static const pns_lookup_t mod_lut[] = {
+#define X(a)    { pn_Mod_##a, #a }
+  X(M),
+  X(X_except),
+  X(res)
+#undef X
+};
+
+/** the lookup table for Proj(Load) names */
+static const pns_lookup_t load_lut[] = {
+#define X(a)    { pn_Load_##a, #a }
+  X(M),
+  X(X_except),
+  X(res)
+#undef X
+};
+
+/** the lookup table for Proj(Store) names */
+static const pns_lookup_t store_lut[] = {
+#define X(a)    { pn_Store_##a, #a }
+  X(M),
+  X(X_except)
+#undef X
+};
+
+/** the lookup table for Proj(Alloc) names */
+static const pns_lookup_t alloc_lut[] = {
+#define X(a)    { pn_Alloc_##a, #a }
+  X(M),
+  X(X_except),
+  X(res)
+#undef X
+};
+
+
+/** the Proj lookup table */
+static const proj_lookup_t proj_lut[] = {
+#define E(a)  ARR_SIZE(a), a
+  { iro_Start,   E(start_lut) },
+  { iro_Cond,    E(cond_lut) },
+  { iro_Call,    E(call_lut) },
+  { iro_Quot,    E(quot_lut) },
+  { iro_DivMod,  E(divmod_lut) },
+  { iro_Div,     E(div_lut) },
+  { iro_Mod,     E(mod_lut) },
+  { iro_Load,    E(load_lut) },
+  { iro_Store,   E(store_lut) },
+  { iro_Alloc,   E(alloc_lut) }
+#undef E
+};
+
 /**
  * Dump additional node attributes of some nodes to a file F.
  */
@@ -696,6 +837,8 @@ dump_node_nodeattr(FILE *F, ir_node *n)
 {
   int bad = 0;
   ir_node *pred;
+  opcode code;
+  long proj_nr;
 
   switch (get_irn_opcode(n)) {
   case iro_Start:
@@ -703,30 +846,45 @@ dump_node_nodeattr(FILE *F, ir_node *n)
       fprintf (F, "%s ", get_ent_dump_name(get_irg_entity(current_ir_graph)));
     }
     break;
+
   case iro_Proj:
-    pred = get_Proj_pred(n);
+    pred    = get_Proj_pred(n);
+    proj_nr = get_Proj_proj(n);
+handle_lut:
+    code    = get_irn_opcode(pred);
 
-    if (get_irn_opcode(pred) == iro_Cmp)
+    if (code == iro_Cmp)
       fprintf (F, "%s ", get_pnc_string(get_Proj_proj(n)));
-    else if (get_irn_opcode(pred) == iro_Start) {
-      switch (get_Proj_proj(n)) {
-      case pn_Start_P_frame_base:
-        fprintf (F, "FrameBase "); break;
-      case pn_Start_P_globals:
-        fprintf (F, "GlobalBase "); break;
-      case pn_Start_P_value_arg_base:
-        fprintf (F, "ValueBase "); break;
-      default:
-        fprintf (F, "%ld ", get_Proj_proj(n));
+    else if (code == iro_Proj && get_irn_opcode(get_Proj_pred(pred)) == iro_Start)
+      fprintf (F, "Arg %ld ", proj_nr);
+    else {
+      unsigned i, j, f = 0;
+
+      for (i = 0; i < ARR_SIZE(proj_lut); ++i) {
+        if (code == proj_lut[i].code) {
+          for (j = 0; j < proj_lut[i].num_data; ++j) {
+            if (proj_nr == proj_lut[i].data[j].nr) {
+              fprintf (F, "%s ", proj_lut[i].data[j].name);
+              f = 1;
+              break;
+            }
+          }
+          break;
+        }
       }
+      if (! f)
+        fprintf (F, "%ld ", proj_nr);
     }
-    else if (get_irn_opcode(pred) == iro_Proj && get_irn_opcode(get_Proj_pred(pred)) == iro_Start)
-      fprintf (F, "Arg %ld ", get_Proj_proj(n));
-    else
-      fprintf (F, "%ld ", get_Proj_proj(n));
     break;
   case iro_Filter:
-    fprintf (F, "%ld ", get_Filter_proj(n));
+    proj_nr = get_Filter_proj(n);
+    if (! get_interprocedural_view()) {
+      /* it's a Proj' */
+      pred    = get_Filter_pred(n);
+      goto handle_lut;
+    }
+    else
+      fprintf (F, "%ld ", proj_nr);
     break;
   case iro_Sel:
     fprintf (F, "%s ", get_ent_dump_name(get_Sel_entity(n)));
@@ -929,7 +1087,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);
   }
 }
 
@@ -1473,8 +1631,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;
 
@@ -1488,17 +1645,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)
@@ -1516,7 +1670,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
 
@@ -1589,7 +1745,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:
@@ -1691,7 +1847,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++)
           {
@@ -1810,7 +1966,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) {
@@ -1938,7 +2094,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) {
@@ -1949,7 +2105,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 @. */
@@ -2127,12 +2283,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";
@@ -2148,6 +2308,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;
 }
 
@@ -2158,11 +2319,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);
@@ -2187,8 +2353,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;
 }
 
 /*---------------------------------------------------------------------*/
@@ -2198,7 +2365,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)) {