added test dumper
authorGötz Lindenmaier <goetz@ipd.info.uni-karlsruhe.de>
Thu, 2 Sep 2004 14:09:49 +0000 (14:09 +0000)
committerGötz Lindenmaier <goetz@ipd.info.uni-karlsruhe.de>
Thu, 2 Sep 2004 14:09:49 +0000 (14:09 +0000)
[r3813]

ir/ir/Makefile.in
ir/ir/irdump.c
ir/ir/irdump.h
ir/ir/irdumptxt.c [new file with mode: 0644]

index 68c5916..efbc7bd 100644 (file)
@@ -22,8 +22,8 @@ INSTALL_HEADERS = irprog.h irgraph.h irnode.h irmode.h irop.h ircons.h        \
 SOURCES = $(INSTALL_HEADERS)
 
 SOURCES +=     Makefile.in \
-               ircons.c ircons_t.h irgmod.c irgraph_t.h irnode.c iropt.c irvrfy.c \
-               irgwalk.c irgwalk_blk.c irdump.c irgopt.c irnode_t.h iropt_t.h  \
+               ircons.c ircons_t.h irgmod.c irgraph_t.h irnode.c iropt.c iropt_t.h irvrfy.c \
+               irgwalk.c irgwalk_blk.c irdump.c irdumptxt.c irgopt.c irnode_t.h        \
                irmode.c irop.c irprog.c irflag.c irflag_t.h irgraph.c \
                irmode_t.h irop_t.h irprog_t.h ircgcons.c ircgopt.c
 
index f75115d..62b2da5 100644 (file)
  */
 
 
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
 #include <string.h>
 #include <stdlib.h>
 #include <stdarg.h>
 
+#include "firm_common_t.h"
+
 #include "irnode_t.h"
 #include "irgraph_t.h"
 #include "irprog_t.h"
 #include "entity_t.h"
 #include "irop_t.h"
-#include "firm_common_t.h"
 
 #include "irdump.h"
 
@@ -113,7 +110,9 @@ SeqNo get_Block_seqno(ir_node *n);
 #endif
 
 
-int my_special_flag = 0;
+/* basis for a color range for vcg */
+static int n_colors   = 0;
+static int base_color = 0;
 
 static const char *get_mode_name_ex(ir_mode *mode, int *bad)
 {
@@ -236,10 +235,6 @@ static void print_enum_item_edge(FILE *F, type *E, int item, const char *fmt, ..
 /* global and ahead declarations                                   */
 /*******************************************************************/
 
-/* A suffix to manipulate the file name. */
-
-char *dump_file_filter = "";
-
 static void dump_whole_node(ir_node *n, void *env);
 static INLINE void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg);
 
@@ -360,6 +355,8 @@ static ir_node ** construct_block_lists(ir_graph *irg) {
 /* flags to steer output                                           */
 /*******************************************************************/
 
+const char *dump_file_filter = "";
+
 /* A compiler option to turn off edge labels */
 int edge_label = 1;
 /* A compiler option to turn off dumping values of constant entities */
@@ -384,6 +381,11 @@ INLINE bool get_opt_dump_const_local(void) {
     return false;
 }
 
+void only_dump_method_with_name(ident *name) {
+  dump_file_filter = get_id_str(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) {
@@ -1338,16 +1340,20 @@ static int print_type_node(FILE *F, type *tp)
 }
 
 #define X(a)    case a: fprintf(F, #a); break
-void dump_entity_node(FILE *F, entity *ent)
+void dump_entity_node(FILE *F, entity *ent, int color)
 {
   fprintf (F, "node: {title: \"");
   PRINT_ENTID(ent); fprintf(F, "\"");
   fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
   fprintf (F, "label: ");
-  fprintf (F, "\"ent %s\" " ENTITY_NODE_ATTR , get_ent_dump_name(ent));
+  fprintf (F, "\"ent %s\" ", get_ent_dump_name(ent));
+  if (color)
+    fprintf(F, "color: %d", color);
+  else
+    fprintf (F, ENTITY_NODE_ATTR);
   fprintf (F, "\n info1: \"");
 
-  dump_entity_to_file(F, ent);
+  dump_entity_to_file(F, ent, dump_verbosity_max);
 
   fprintf(F, "\"\n}\n");
 }
@@ -1382,7 +1388,7 @@ dump_type_info(type_or_ent *tore, void *env) {
       entity *ent = (entity *)tore;
       ir_node *value;
       /* The node */
-      dump_entity_node(F, ent);
+      dump_entity_node(F, ent, 0);
       /* The Edges */
       /* skip this to reduce graph.  Member edge of type is parallel to this edge. *
       fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
@@ -1511,7 +1517,7 @@ dump_class_hierarchy_node (type_or_ent *tore, void *ctx) {
     if (!is_method_type(get_entity_type(ent))) break;  /* GL */
     if (env->dump_ent && is_class_type(get_entity_owner(ent))) {
       /* The node */
-      dump_entity_node(F, ent);
+      dump_entity_node(F, ent, 0);
       /* The edges */
       print_type_ent_edge(F,get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
       for(i = 0; i < get_entity_n_overwrites(ent); i++)
@@ -1684,6 +1690,39 @@ dump_vcg_header(FILE *F, const char *name, const char *orientation) {
        "infoname 2: \"Verification errors\"\n",
        name, label, orientation);
 
+  /* don't use all, the range is too whith/black. */
+  n_colors   = 18;
+  base_color = 105;
+  fprintf (F,
+       "colorentry 100:    0   0    0\n"
+       "colorentry 101:   20   0    0\n"
+       "colorentry 102:   40   0    0\n"
+       "colorentry 103:   60   0    0\n"
+       "colorentry 104:   80   0    0\n"
+       "colorentry 105:  100   0    0\n"
+       "colorentry 106:  120   0    0\n"
+       "colorentry 107:  140   0    0\n"
+       "colorentry 108:  150   0    0\n"
+       "colorentry 109:  180   0    0\n"
+       "colorentry 110:  200   0    0\n"
+       "colorentry 111:  220   0    0\n"
+       "colorentry 112:  240   0    0\n"
+       "colorentry 113:  255   0    0\n"
+       "colorentry 113:  255  20   20\n"
+       "colorentry 114:  255  40   40\n"
+       "colorentry 115:  255  60   60\n"
+       "colorentry 116:  255  80   80\n"
+       "colorentry 117:  255 100  100\n"
+       "colorentry 118:  255 120  120\n"
+       "colorentry 119:  255 140  140\n"
+       "colorentry 120:  255 150  150\n"
+       "colorentry 121:  255 180  180\n"
+       "colorentry 122:  255 200  200\n"
+       "colorentry 123:  255 220  220\n"
+       "colorentry 124:  255 240  240\n"
+       "colorentry 125:  255 250  250\n"
+          );
+
   fprintf (F, "\n");        /* a separator */
 }
 
@@ -1804,7 +1843,7 @@ dump_ir_graph (ir_graph *irg, const char *suffix )
   char *suffix1;
   rem = current_ir_graph;
 
-  if(strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter))!=0) return;
+  if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0) return;
   current_ir_graph = irg;
   if (interprocedural_view) suffix1 = "-pure-ip";
   else                      suffix1 = "-pure";
@@ -2001,13 +2040,51 @@ dump_cfg (ir_graph *irg, const char *suffix)
   current_ir_graph = rem;
 }
 
+static int weight_overall(int rec, int loop) {
+  return 2*rec + loop;
+}
+
+static int compute_color (int my, int max) {
+  int color;
+  if (!max) {
+    color = 0;
+  } else {
+    /* if small, scale to the full color range. */
+    if (max < n_colors)
+      my = my * (n_colors/max);
+
+    int step = 1 + (max / n_colors);
+
+    color = my/step;
+  }
+  return base_color + n_colors - color;
+}
+
+static int get_entity_color(entity *ent) {
+  assert(get_entity_irg(ent));
+  ir_graph *irg = get_entity_irg(ent);
+
+  int rec_depth     = get_irg_recursion_depth(irg);
+  int loop_depth    = get_irg_loop_depth(irg);
+  int overall_depth = weight_overall(rec_depth, loop_depth);
+
+  int max_rec_depth     = irp->max_callgraph_recursion_depth;
+  int max_loop_depth    = irp->max_callgraph_loop_depth;
+  int max_overall_depth = weight_overall(max_rec_depth, max_loop_depth);
+
+  int my_rec_color     = compute_color(rec_depth, max_rec_depth);
+  int my_loop_color    = compute_color(loop_depth, max_loop_depth);
+  int my_overall_color = compute_color(overall_depth, max_overall_depth);;
+
+  return my_overall_color;
+}
+
 void dump_callgraph(const char *suffix) {
   FILE *F;
   int i, n_irgs = get_irp_n_irgs();
   int rem = edge_label;
   edge_label = 1;
-
-  my_special_flag = 1;
+  //ident *prefix = new_id_from_str("java/");
 
   F = vcg_open_name("Callgraph", suffix);
   dump_vcg_header(F, "Callgraph", NULL);
@@ -2017,19 +2094,22 @@ void dump_callgraph(const char *suffix) {
     entity *ent = get_irg_entity(irg);
     int j, n_callees = get_irg_n_callees(irg);
 
-    dump_entity_node(F, ent);
+    /* Do not dump runtime system. */
+    //if (id_is_prefix(prefix, get_entity_ld_ident(ent))) continue;
+
+    dump_entity_node(F, ent, get_entity_color(ent));
     for (j = 0; j < n_callees; ++j) {
       entity *c = get_irg_entity(get_irg_callee(irg, j));
+      //if (id_is_prefix(prefix, get_entity_ld_ident(c))) continue;
       int be = is_irg_callee_backedge(irg, j);
       char *attr;
       attr = (be) ?
-        "label:\"recursion %d\" color:red" :
-        "label:\"calls %d\"";
-      print_ent_ent_edge(F, ent, c, be, attr, get_irg_callee_loop_depth(irg, j));
+        "label:\"recursion %d\" color: %d" :
+        "label:\"calls %d\" color: %d";
+      print_ent_ent_edge(F, ent, c, be, attr, get_irg_callee_loop_depth(irg, j), get_entity_color(ent));
     }
   }
 
-  my_special_flag = 0;
   edge_label = rem;
   vcg_close(F);
 }
@@ -2247,7 +2327,7 @@ void dump_loop_tree(ir_graph *irg, const char *suffix)
   current_ir_graph = rem;
 }
 
-void dump_callgraph_loop_tree(char *suffix) {
+void dump_callgraph_loop_tree(const char *suffix) {
   FILE *F;
   F = vcg_open_name("Callgraph_looptree", suffix);
   dump_vcg_header(F, "callgraph looptree", "top_to_bottom");
index d19bda5..8d92ad4 100644 (file)
 # include "irloop.h"
 
 
-/** Set this to the name (not the ld_name) of the method to be dumped. */
-extern char *dump_file_filter;
+/* **************************************************************************** */
+/*                                 GRAPH DUMPERS                                */
+/* **************************************************************************** */
 
-/**
- *  Dump a firm graph.
+/** Dump a firm graph.
  *
  *  @param irg  The firm graph to be dumped.
  *
@@ -59,10 +59,8 @@ extern char *dump_file_filter;
  * @see turn_off_edge_labels()
  */
 void dump_ir_graph (ir_graph *irg, const char *suffix);
-#define dump_cg_graph dump_ir_graph
 
-/**
- *  Dump a firm graph without explicit block nodes.
+/** Dump a firm graph without explicit block nodes.
  *
  *  @param irg   The firm graph to be dumped.
  *
@@ -79,14 +77,12 @@ void dump_ir_graph (ir_graph *irg, const char *suffix);
  * @see turn_off_edge_labels()
  */
 void dump_ir_block_graph (ir_graph *irg, const char *suffix);
-#define dump_cg_block_graph dump_ir_block_graph
 
 /** Dumps all graphs in interprocedural view to a file named All_graphs.vcg.
  */
 void dump_all_cg_block_graph(const char *suffix);
 
-/**
- *  Dumps a firm graph and  all the type information needed for Calls,
+/** Dumps a firm graph and  all the type information needed for Calls,
  *  Sels, ... in this graph.
  *
  *  @param irg   The firm graph to be dumped with its type information.
@@ -102,8 +98,7 @@ void dump_all_cg_block_graph(const char *suffix);
  */
 void dump_ir_graph_w_types (ir_graph *irg, const char *suffix);
 
-/**
- *  Dumps a firm graph and  all the type information needed for Calls,
+/** Dumps a firm graph and  all the type information needed for Calls,
  *  Sels, ... in this graph.
  *
  *  @param irg   The firm graph to be dumped with its type information.
@@ -120,15 +115,13 @@ void dump_ir_graph_w_types (ir_graph *irg, const char *suffix);
  */
 void dump_ir_block_graph_w_types (ir_graph *irg, const char *suffix);
 
-/**
- *   The type of a walker function that is called for each graph.
+/** The type of a walker function that is called for each graph.
  *
- *   @param irg   current visited graph
+ *  @param irg   current visited graph
  */
 typedef void dump_graph_func(ir_graph *irg, const char *suffix);
 
-/**
- *   A walker that calls a dumper for each graph.
+/**  A walker that calls a dumper for each graph.
  *
  *   @param dump_graph    The dumper to be used for dumping.
  *
@@ -148,8 +141,7 @@ typedef void dump_graph_func(ir_graph *irg, const char *suffix);
 void dump_all_ir_graphs (dump_graph_func *dump_graph, const char *suffix);
 
 
-/**
- *   Dump the control flow graph of a procedure.
+/**  Dump the control flow graph of a procedure.
  *
  *   @param irg  The firm graph whose CFG shall be dumped.
  *
@@ -166,12 +158,21 @@ void dump_all_ir_graphs (dump_graph_func *dump_graph, const char *suffix);
 void dump_cfg (ir_graph *irg, const char *suffix);
 
 
+/* **************************************************************************** */
+/*                              CALLGRAPH DUMPERS                               */
+/* **************************************************************************** */
+
+
 /** Dump the call graph.
  *
  * Dumps the callgraph to a file "Callgraph"<suffix>".vcg".
  */
 void dump_callgraph(const char *suffix);
 
+/* **************************************************************************** */
+/*                              TYPEGRAPH DUMPERS                               */
+/* **************************************************************************** */
+
 /**
  *  Dumps all the type information needed for Calls, Sels, ... in this graph.
  *  Does not dump the graph!
@@ -188,8 +189,7 @@ void dump_callgraph(const char *suffix);
  */
 void dump_type_graph (ir_graph *irg, const char *suffix);
 
-/**
- *   Dumps all type information.
+/**  Dumps all type information.
  *
  *   @return
  *      A file containing all type information for the program in standard
@@ -203,8 +203,7 @@ void dump_type_graph (ir_graph *irg, const char *suffix);
  */
 void dump_all_types (const char *suffix);
 
-/**
- *   Dumps the class hierarchy with or without entities.
+/**  Dumps the class hierarchy with or without entities.
  *
  *   @param entities    Flag whether to dump the entities.
  *
@@ -221,6 +220,9 @@ void dump_all_types (const char *suffix);
  */
 void dump_class_hierarchy (bool entities, const char *suffix);
 
+/* **************************************************************************** */
+/*                              LOOPTREE DUMPERS                                */
+/* **************************************************************************** */
 
 /**
  * Dump a standalone loop tree, which contains the loop nodes and the firm nodes
@@ -236,8 +238,8 @@ void dump_class_hierarchy (bool entities, const char *suffix);
 void dump_loop_tree(ir_graph *irg, const char *suffix);
 
 /** Dumps the firm nodes in the sub-loop-tree of loop to a graph.
- *  Dumps the loop nodes if dump_loop_information() is set.
  *
+ *  Dumps the loop nodes if dump_loop_information() is set.
  *  The name of the file is loop_<loop_nr><suffix>.vcg.
  *
  *  @arg loop    Dump the loop tree for this loop.
@@ -252,7 +254,90 @@ void dump_loop (ir_loop *l, const char *suffix);
  *
  *  @arg suffix  Suffix to filename.
  */
-void dump_callgraph_loop_tree(char *suffix);
+void dump_callgraph_loop_tree(const char *suffix);
+
+
+/* **************************************************************************** */
+/*                                TEXT DUMPERS                                  */
+/* **************************************************************************** */
+
+/** Verbosity for text dumpers */
+typedef enum {
+  dump_verbosity_onlynames         = 0x00000001,   /**< only dump type names. turns off all other
+                                                     flags up to 0x00010000. */
+  dump_verbosity_fields            = 0x00000002,   /**< dump types and fields (like a type declaration) */
+  dump_verbosity_methods           = 0x00000004,   /**< dump types and methods (like a type declaration) */
+  dump_verbosity_typeattrs         = 0x00000008,   /**< dump all type attributes */
+  dump_verbosity_entattrs          = 0x00000010,   /**< dump all entity attributes */
+  dump_verbosity_entconsts         = 0x00000020,   /**< dump entity constants */
+
+  dump_verbosity_noClassTypes      = 0x00001000,   /**< dump no class       types */
+  dump_verbosity_noStructTypes     = 0x00002000,   /**< dump no struct      types */
+  dump_verbosity_noUnionTypes      = 0x00004000,   /**< dump no union       types */
+  dump_verbosity_noArrayTypes      = 0x00008000,   /**< dump no array       types */
+  dump_verbosity_noPointerTypes    = 0x00010000,   /**< dump no pointer     types */
+  dump_verbosity_noMethodTypes     = 0x00020000,   /**< dump no method      types */
+  dump_verbosity_noPrimitiveTypes  = 0x00040000,   /**< dump no primitive   types */
+  dump_verbosity_noEnumerationTypes= 0x00080000,   /**< dump no enumeration types */
+
+  dump_verbosity_onlyClassTypes     = 0x000FE000,  /**< dump only class     types */
+  dump_verbosity_onlyStructTypes    = 0x000FD000,  /**< dump only struct    types */
+  dump_verbosity_onlyUnionTypes     = 0x000FB000,  /**< dump only union     types */
+  dump_verbosity_onlyArrayTypes     = 0x000F8000,  /**< dump only array     types */
+  dump_verbosity_onlyPointerTypes   = 0x000EF000,  /**< dump only pointer   types */
+  dump_verbosity_onlyMethodTypes    = 0x000DF000,  /**< dump only method    types */
+  dump_verbosity_onlyPrimitiveTypes = 0x000BF000,  /**< dump only primitive types */
+  dump_verbosity_onlyEnumerationTypes=0x0008F000,  /**< dump only enumeration types */
+
+  dump_verbosity_max               = 0x48888888,   /**< turn on all verbosity. */
+} dump_verbosity;
+
+
+/** Write the entity and all its attributes to the passed file.
+ *  */
+void    dump_entity_to_file (FILE *F, entity *ent, unsigned verbosity);
+
+/** Write the entity and all its attributes to the stdout.
+ *
+ *  Calls dump_entity_to_file().  */
+void    dump_entity (entity *ent);
+
+/** Write the type and all its attributes to the file passed.
+ * */
+void    dump_type_to_file (FILE *f, type *tp, unsigned verbosity);
+
+/** Write the type and all its attributes to stdout.
+ *  */
+void    dump_type (type *tp);
+
+
+/** Dump type information as text.
+ *
+ *  Often type graphs are unhandy in their vcg representation.  The text
+ *  dumper represents the information for a single type more compact, but
+ *  the relations between the types only implicitly.
+ *  Dumps only 'real' types, i.e., those in the type list.  Does not dump
+ *  the global type nor frame types or the like.
+ *
+ *  The file name is the program name (get_irp_name()), or 'TextTypes'
+ *  if the program name is not set appended by <suffix>-types.txt.
+ */
+void dump_types_as_text(unsigned verbosity, const char *suffix);
+
+/* **************************************************************************** */
+/*                                    FLAGS                                     */
+/* **************************************************************************** */
+
+/** Output a selected graph.
+ *
+ *  All graph dumpers check this name.  If the name is != "" and
+ *  not a prefix of the graph to be dumped, the dumper does not
+ *  dump the graph.
+ *
+ *  @param name The prefix of the name (not the ld_name) of the method
+ *              entity to be dumped.
+ */
+void only_dump_method_with_name(ident *name);
 
 /**  Sets the vcg flag "display_edge_labels" to no.
  *
@@ -263,7 +348,7 @@ void turn_off_edge_labels(void);
 
 /**
  *  If set to true constants will be replicated for every use. In non
- *  blocked view edges from constant to block are scipped.  Vcg then
+ *  blocked view edges from constant to block are skipped.  Vcg then
  *  layouts the graphs more compact, this makes them better readable.
  *  The flag is automatically and temporarily set to false if other
  *  edges are dumped, as outs, loop, ...
@@ -277,35 +362,33 @@ void dump_consts_local(bool b);
  */
 bool get_opt_dump_const_local(void);
 
-/**
- *   Turns off dumping the values of constant entities. Makes type graphs
+/**  Turns off dumping the values of constant entities. Makes type graphs
  *   better readable.
  */
 void turn_off_constant_entity_values(void);
 
-/**
- *   Turns on dumping the edges from the End node to nodes to be kept
- *   alive
+/**  Turns on dumping the edges from the End node to nodes to be kept
+ *   alive.
  */
 void dump_keepalive_edges(bool b);
 bool get_opt_dump_keepalive_edges(void);
 
-/**
- *   Turns on dumping the out edges starting from the Start block in
- *   dump_ir_graph.  To test the consistency of the out datastructure.
+/** Turns on dumping the out edges starting from the Start block in
+ *  dump_ir_graph.
+ *
+ *  To test the consistency of the out datastructure.
  */
 void dump_out_edges(void);
 
-/**
- *   If this flag is set the dumper dumps edges to immediate dominator in cfg.
+/** If this flag is set the dumper dumps edges to immediate dominator in cfg.
  */
 void dump_dominator_information(void);
 
-/**
- *   If this flag is set the dumper dumps loop nodes and edges from
- *   these nodes to the contained ir nodes.
- *   Can be turned off with dont_dump_loop_information().
- *   If the loops are interprocedural nodes can be missing.
+/** If this flag is set the dumper dumps loop nodes and edges from
+ *  these nodes to the contained ir nodes.
+ *
+ *  Can be turned off with dont_dump_loop_information().
+ *  If the loops are interprocedural nodes can be missing.
  */
 void dump_loop_information(void);
 
@@ -314,23 +397,24 @@ void dump_loop_information(void);
  */
 void dont_dump_loop_information(void);
 
-/**
- * If set and backedge info is computed, backedges are dumped dashed
- * and as vcg 'backedge' construct.  Default: set.
+/** If set and backedge info is computed, backedges are dumped dashed
+ *  and as vcg 'backedge' construct.
+ *
+ *  Default: set.
  */
 void dump_backedge_information(bool b);
 
-/**
- *  Dump the information of type field specified in ana/irtypeinfo.h.
+/** 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 dump_analysed_type_info(bool b);
 
-/**
- * Write the address of a node into the vcg info.
- * This is off per default for automatic comparisons of
- * vcg graphs -- these will differ in the pointer values!
+/** Write the address of a node into the vcg info.
+ *
+ *  This is off per default for automatic comparisons of
+ *  vcg graphs -- these will differ in the pointer values!
  */
 void dump_pointer_values_to_info(bool b);
 
diff --git a/ir/ir/irdumptxt.c b/ir/ir/irdumptxt.c
new file mode 100644 (file)
index 0000000..39be89f
--- /dev/null
@@ -0,0 +1,294 @@
+/*
+ * Project:     libFIRM
+ * File name:   ir/ir/irdump.c
+ * Purpose:     Write vcg representation of firm to file.
+ * Author:      Martin Trapp, Christian Schaefer
+ * Modified by: Goetz Lindenmaier, Hubert Schmidt
+ * Created:
+ * CVS-ID:      $Id$
+ * Copyright:   (c) 1998-2003 Universität Karlsruhe
+ * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+#include "irdump.h"
+
+#include "firm_common_t.h"
+
+#include "irgraph_t.h"
+#include "irprog_t.h"
+#include "entity_t.h"
+
+int dump_node_opcode(FILE *F, ir_node *n); /* from irdump.c */
+
+
+
+#define X(a)    case a: fprintf(F, #a); break
+void    dump_entity_to_file_prefix (FILE *F, entity *ent, char *prefix, unsigned verbosity) {
+  int i, j;
+  assert(ent && ent->kind == k_entity);
+  type *owner = get_entity_owner(ent);
+  type *type  = get_entity_type(ent);
+
+  if (verbosity & dump_verbosity_onlynames) {
+    fprintf(F, "%sentity %s (%ld)\n", prefix, get_entity_name(ent), get_entity_nr(ent));
+    return;
+  }
+
+  if (verbosity & dump_verbosity_entattrs) {
+    fprintf(F, "%sentity %s (%ld)\n", prefix, get_entity_name(ent), get_entity_nr(ent));
+    fprintf(F, "%s  type:  %s (%ld)\n", prefix, get_type_name(type),  get_type_nr(type));
+    fprintf(F, "%s  owner: %s (%ld)\n", prefix, get_type_name(owner), get_type_nr(owner));
+
+    if (is_class_type(get_entity_owner(ent))) {
+      if (get_entity_n_overwrites(ent) > 0) {
+       fprintf(F, "%s  overwrites:\n", prefix);
+       for (i = 0; i < get_entity_n_overwrites(ent); ++i) {
+         entity *ov = get_entity_overwrites(ent, i);
+         fprintf(F, "%s    %d: %s of class %s\n", prefix, i, get_entity_name(ov),
+                 get_type_name(get_entity_owner(ov)));
+       }
+      } else {
+       fprintf(F, "%s  Does not overwrite other entities. \n", prefix);
+      }
+      if (get_entity_n_overwrittenby(ent) > 0) {
+       fprintf(F, "%s  overwritten by:\n", prefix);
+       for (i = 0; i < get_entity_n_overwrittenby(ent); ++i) {
+         entity *ov = get_entity_overwrittenby(ent, i);
+         fprintf(F, "%s    %d: %s of class %s\n", prefix, i, get_entity_name(ov),
+                 get_type_name(get_entity_owner(ov)));
+       }
+      } else {
+       fprintf(F, "%s  Is not overwriten by other entities. \n", prefix);
+      }
+    }
+
+    fprintf(F, "%s  allocation:  ", prefix);
+    switch (get_entity_allocation(ent)) {
+      X(allocation_dynamic);
+      X(allocation_automatic);
+      X(allocation_static);
+      X(allocation_parameter);
+    }
+
+    fprintf(F, "\n%s  visibility:  ", prefix);
+    switch (get_entity_visibility(ent)) {
+      X(visibility_local);
+      X(visibility_external_visible);
+      X(visibility_external_allocated);
+    }
+
+    fprintf(F, "\n%s  variability: ", prefix);
+    switch (get_entity_variability(ent)) {
+      X(variability_uninitialized);
+      X(variability_initialized);
+      X(variability_part_constant);
+      X(variability_constant);
+    }
+    fprintf(F, "\n");
+  } else {  /* no entityattrs */
+    fprintf(F, "%s(%3d) %*s: %s", prefix,
+           get_entity_offset_bits(ent), -40, get_type_name(get_entity_type(ent)), get_entity_name(ent));
+    if (is_method_type(get_entity_type(ent))) fprintf(F, "(...)");
+    fprintf(F, "\n");
+  }
+
+  if (verbosity & dump_verbosity_entconsts) {
+    if (get_entity_variability(ent) != variability_uninitialized) {
+      if (is_atomic_entity(ent)) {
+       fprintf(F, "%s  atomic value: ", prefix);
+       dump_node_opcode(F, get_atomic_ent_value(ent));
+      } else {
+       fprintf(F, "%s  compound values:", prefix);
+       for (i = 0; i < get_compound_ent_n_values(ent); ++i) {
+         compound_graph_path *path = get_compound_ent_value_path(ent, i);
+         entity *ent0 = get_compound_graph_path_node(path, 0);
+         fprintf(F, "\n%s    %3d ", prefix, get_entity_offset_bits(ent0));
+         if (get_type_state(type) == layout_fixed)
+           fprintf(F, "(%3d) ",   get_compound_ent_value_offset_bits(ent, i));
+         fprintf(F, "%s", get_entity_name(ent0));
+         for (j = 0; j < get_compound_graph_path_length(path); ++j) {
+           entity *node = get_compound_graph_path_node(path, j);
+           fprintf(F, ".%s", get_entity_name(node));
+           if (is_array_type(get_entity_owner(node)))
+             fprintf(F, "[%d]", get_compound_graph_path_array_index(path, j));
+         }
+         fprintf(F, "\t = ");
+         dump_node_opcode(F, get_compound_ent_value(ent, i));
+       }
+      }
+      fprintf(F, "\n");
+    }
+  }
+
+
+  if (verbosity & dump_verbosity_entattrs) {
+    fprintf(F, "%s  volatility:  ", prefix);
+    switch (get_entity_volatility(ent)) {
+      X(volatility_non_volatile);
+      X(volatility_is_volatile);
+    }
+
+    fprintf(F, "\n%s  peculiarity: %s", prefix, get_peculiarity_string(get_entity_peculiarity(ent)));
+    fprintf(F, "\n%s  ld_name: %s", prefix, ent->ld_name ? get_entity_ld_name(ent) : "no yet set");
+    fprintf(F, "\n%s  offset:  %d", prefix, get_entity_offset_bits(ent));
+    if (is_method_type(get_entity_type(ent))) {
+      if (get_entity_irg(ent))   /* can be null */ {
+       fprintf(F, "\n%s  irg = %ld", prefix, get_irg_graph_nr(get_entity_irg(ent)));
+       if (get_irp_callgraph_state() == irp_callgraph_and_calltree_consistent) {
+         fprintf(F, "\n%s    recursion depth %d", prefix, get_irg_recursion_depth(get_entity_irg(ent)));
+         fprintf(F, "\n%s    loop depth      %d", prefix, get_irg_loop_depth(get_entity_irg(ent)));
+       }
+      } else {
+       fprintf(F, "\n%s  irg = NULL", prefix);
+      }
+    }
+    fprintf(F, "\n");
+  }
+}
+#undef X
+
+void    dump_entity_to_file (FILE *F, entity *ent, unsigned verbosity) {
+  dump_entity_to_file_prefix (F, ent, "", verbosity);
+  fprintf(F, "\n");
+}
+
+void dump_entity (entity *ent) {
+  dump_entity_to_file(stdout, ent, dump_verbosity_max);
+}
+
+void dump_type_to_file (FILE *F, type *tp, dump_verbosity verbosity) {
+  int i;
+
+  if ((is_class_type(tp))       && (verbosity & dump_verbosity_noClassTypes)) return;
+  if ((is_struct_type(tp))      && (verbosity & dump_verbosity_noStructTypes)) return;
+  if ((is_union_type(tp))       && (verbosity & dump_verbosity_noUnionTypes)) return;
+  if ((is_array_type(tp))       && (verbosity & dump_verbosity_noArrayTypes)) return;
+  if ((is_pointer_type(tp))     && (verbosity & dump_verbosity_noPointerTypes)) return;
+  if ((is_method_type(tp))      && (verbosity & dump_verbosity_noMethodTypes)) return;
+  if ((is_primitive_type(tp))   && (verbosity & dump_verbosity_noPrimitiveTypes)) return;
+  if ((is_enumeration_type(tp)) && (verbosity & dump_verbosity_noEnumerationTypes)) return;
+
+  fprintf(F, "%s type %s (%ld)", get_tpop_name(get_type_tpop(tp)), get_type_name(tp), get_type_nr(tp));
+  if (verbosity & dump_verbosity_onlynames) { fprintf(F, "\n"); return; }
+
+  switch (get_type_tpop_code(tp)) {
+
+  case tpo_class:
+    if ((verbosity & dump_verbosity_methods) || (verbosity & dump_verbosity_fields)) {
+      fprintf(F, "\n  members: \n");
+    }
+    for (i = 0; i < get_class_n_members(tp); ++i) {
+      entity *mem = get_class_member(tp, i);
+      if (((verbosity & dump_verbosity_methods) &&  is_method_type(get_entity_type(mem))) ||
+         ((verbosity & dump_verbosity_fields)  && !is_method_type(get_entity_type(mem)))   ) {
+       dump_entity_to_file_prefix(F, mem, "    ", verbosity);
+      }
+    }
+    if (verbosity & dump_verbosity_typeattrs) {
+      fprintf(F, "  supertypes: ");
+      for (i = 0; i < get_class_n_supertypes(tp); ++i) {
+       type *stp = get_class_supertype(tp, i);
+       fprintf(F, "\n    %s", get_type_name(stp));
+      }
+      fprintf(F, "\n  subtypes: ");
+      for (i = 0; i < get_class_n_subtypes(tp); ++i) {
+       type *stp = get_class_subtype(tp, i);
+       fprintf(F, "\n    %s", get_type_name(stp));
+      }
+
+      fprintf(F, "\n  peculiarity: %s", get_peculiarity_string(get_class_peculiarity(tp)));
+    }
+    break;
+
+  case tpo_union:
+  case tpo_struct:
+    if (verbosity & dump_verbosity_fields) fprintf(F, "\n  members: ");
+    for (i = 0; i < get_compound_n_members(tp); ++i) {
+      entity *mem = get_compound_member(tp, i);
+      if (verbosity & dump_verbosity_fields) {
+       dump_entity_to_file_prefix(F, mem, "    ", verbosity);
+      }
+    }
+    break;
+
+  case tpo_pointer: {
+    if (verbosity & dump_verbosity_typeattrs) {
+      type *tt = get_pointer_points_to_type(tp);
+      fprintf(F, "\n  points to %s (%ld)", get_type_name(tt), get_type_nr(tt));
+    }
+
+  } break;
+
+  default:
+    if (verbosity & dump_verbosity_typeattrs) {
+      fprintf(F, ": details not implemented\n");
+    }
+  }
+  fprintf(F, "\n\n");
+}
+
+void dump_type(type *tp) {
+  dump_type_to_file (stdout, tp, dump_verbosity_max);
+}
+
+
+
+static FILE *text_open (const char *basename, const char * suffix1, const char *suffix2) {
+  FILE *F;
+  int len = strlen(basename), i, j;
+  char *fname;  /* filename to put the vcg information in */
+
+  if (!basename) assert(basename);
+  if (!suffix1) suffix1 = "";
+  if (!suffix2) suffix2 = "";
+
+  /* open file for vcg graph */
+  fname = malloc (strlen(basename)*2 + strlen(suffix1) + strlen(suffix2) + 5); /* *2: space for excapes. */
+
+  j = 0;
+  for (i = 0; i < len; ++i) {  /* replase '/' in the name: escape by @. */
+    if (basename[i] == '/') {
+      fname[j] = '@'; j++; fname[j] = '1'; j++;
+    } else if (basename[i] == '@') {
+      fname[j] = '@'; j++; fname[j] = '2'; j++;
+    } else {
+      fname[j] = basename[i]; j++;
+    }
+  }
+  fname[j] = '\0';
+  strcat (fname, suffix1);  /* append file suffix */
+  strcat (fname, suffix2);  /* append file suffix */
+  strcat (fname, ".txt");   /* append the .txt suffix */
+
+  F = fopen (fname, "w");   /* open file for writing */
+  if (!F) {
+    assert(0);
+  }
+  free(fname);
+
+  return F;
+}
+
+void dump_types_as_text(unsigned verbosity, const char *suffix) {
+  const char *basename;
+  FILE *F;
+  int i, n_types = get_irp_n_types();
+
+  if (get_irp_prog_ident() == new_id_from_str("no_name_set")) {
+    basename = "TextTypes";
+  } else {
+    basename = get_irp_prog_name();
+  }
+  F = text_open (basename, suffix, "-types");
+
+  for (i = 0; i < n_types; ++i) {
+    type *t = get_irp_type(i);
+    dump_type_to_file(F, t, verbosity);
+  }
+
+  fclose (F);
+}