added statistics for blocks
authorMichael Beck <beck@ipd.info.uni-karlsruhe.de>
Mon, 19 Jul 2004 15:31:03 +0000 (15:31 +0000)
committerMichael Beck <beck@ipd.info.uni-karlsruhe.de>
Mon, 19 Jul 2004 15:31:03 +0000 (15:31 +0000)
implemented vcg dump of pattern
implemented opcode->ir_op conversion

[r3509]

ir/stat/firmstat.c
ir/stat/firmstat.h
ir/stat/pattern.c
ir/stat/pattern_dmp.c
ir/stat/pattern_dmp.h

index 445a9fd..5a6c59e 100644 (file)
  * just be make some things clear :-), the
  * poor man "generics"
  */
-#define HASH_MAP(type) pset_##type
+#define HASH_MAP(type) hmap_##type
 
-typedef pset pset_node_entry_t;
-typedef pset pset_graph_entry_t;
-typedef pset pset_opt_entry_t;
-typedef pset pset_block_entry_t;
+typedef pset hmap_node_entry_t;
+typedef pset hmap_graph_entry_t;
+typedef pset hmap_opt_entry_t;
+typedef pset hmap_block_entry_t;
+typedef pset hmap_ir_op;
 
 /*
- * An entry for ir_nodes
+ * An entry for ir_nodes, used in ir_graph statistics.
  */
 typedef struct _node_entry_t {
   counter_t   cnt_alive;               /**< amount of nodes in this entry */
@@ -131,6 +132,7 @@ struct _dumper_t {
 typedef struct _statistic_info_t {
   struct obstack          cnts;                        /**< obstack containing the counters */
   HASH_MAP(graph_entry_t) *irg_hash;           /**< hash map containing the counter for irgs */
+  HASH_MAP(ir_op)         *ir_op_hash;         /**< hash map containing all ir_ops (accessible by op_codes) */
   int                     recursive;           /**< flag for detecting recursive hook calls */
   int                     in_dead_node_elim;   /**< set, if dead node elimination runs */
   ir_op                   *op_Phi0;            /**< needed pseudo op */
@@ -216,6 +218,17 @@ static int block_cmp(const void *elt, const void *key)
   return e1->block_nr != e2->block_nr;
 }
 
+/**
+ * compare two elements of the ir_op hash
+ */
+static int opcode_cmp_2(const void *elt, const void *key)
+{
+  const ir_op *e1 = elt;
+  const ir_op *e2 = key;
+
+  return e1->code != e2->code;
+}
+
 /**
  * Returns the associates node_entry_t for an ir_op
  */
@@ -242,6 +255,17 @@ static node_entry_t *opcode_get_entry(const ir_op *op, pset *set)
   return pset_insert(set, elem, op->code);
 }
 
+/**
+ * Returns the associates ir_op for an opcode
+ */
+static ir_op *opcode_find_entry(opcode code, pset *set)
+{
+  ir_op key;
+
+  key.code = code;
+  return pset_find(set, &key, code);
+}
+
 /**
  * calculates a hash value for an irg
  * Addresses are typically aligned at 32bit, so we ignore the lowest bits
@@ -745,6 +769,14 @@ static dumper_t csv_dumper = {
 
 /* ---------------------------------------------------------------------- */
 
+/*
+ * helper: get an ir_op from an opcode
+ */
+ir_op *stat_get_op_from_opcode(opcode code)
+{
+  return opcode_find_entry(code, status->ir_op_hash);
+}
+
 /* initialize the statistics module. */
 void stat_init(void)
 {
@@ -769,6 +801,7 @@ void stat_init(void)
 
   /* create the hash-tables */
   status->irg_hash   = new_pset(graph_cmp, 8);
+  status->ir_op_hash = new_pset(opcode_cmp_2, 1);
 
   status->op_Phi0    = &_op_Phi0;
   status->op_PhiM    = &_op_PhiM;
@@ -777,7 +810,7 @@ void stat_init(void)
   stat_register_dumper(&csv_dumper, "firmstat.csv");
 
   /* initialize the pattern hash */
-  stat_init_pattern_history(status->enable & 0);
+  stat_init_pattern_history(status->enable);
 #undef X
 }
 
@@ -793,6 +826,8 @@ void stat_new_ir_op(const ir_op *op)
 
     /* execute for side effect :-) */
     opcode_get_entry(op, graph->opcode_hash);
+
+    pset_insert(status->ir_op_hash, op, op->code);
   }
   STAT_LEAVE;
 }
@@ -921,6 +956,15 @@ void stat_irg_walk(ir_graph *irg, void *pre, void *post)
   STAT_LEAVE;
 }
 
+/*
+ * A walk over a graph in block-wise order is initiated. Do not count walks from statistic code.
+ */
+void stat_irg_walk_blkwise(ir_graph *irg, void *pre, void *post)
+{
+  /* for now, do NOT differentiate between blockwise and normal */
+  stat_irg_walk(irg, pre, post);
+}
+
 /*
  * A walk over the graph's blocks is initiated. Do not count walks from statistic code.
  */
index 779cb92..e901719 100644 (file)
 #include "irnode.h"
 #include "irgraph.h"
 
+/**
+ * Finish the statistics.
+ * Never called from libFirm should be called from user.
+ */
+void stat_finish(void);
+
 #ifdef FIRM_STATISTICS
 
 typedef enum {
@@ -41,11 +47,6 @@ typedef enum {
  */
 void stat_init(void);
 
-/**
- * Finish the statistics.
- */
-void stat_finish(void);
-
 /**
  * A new IR op is registered.
  */
@@ -81,6 +82,11 @@ void stat_free_graph(ir_graph *irg);
  */
 void stat_irg_walk(ir_graph *irg, void *pre, void *post);
 
+/**
+ * A walk over a graph in block-wise order is initiated
+ */
+void stat_irg_walk_blkwise(ir_graph *irg, void *pre, void *post);
+
 /**
  * A walk over the graph's blocks is initiated
  */
@@ -119,10 +125,18 @@ void stat_dead_node_elim_start(ir_graph *irg);
  */
 void stat_dead_node_elim_stop(ir_graph *irg);
 
+/**
+ * helper: get an ir_op from an opcode
+ *
+ * @param code  the opcode
+ *
+ * @return  The associated ir_op or NULL if the opcode could not be found.
+ */
+ir_op *stat_get_op_from_opcode(opcode code);
+
 #else
 
 #define stat_init()
-#define stat_finish()
 #define stat_new_ir_op(op)
 #define stat_free_ir_op(op)
 #define stat_new_node(node)
@@ -130,6 +144,7 @@ void stat_dead_node_elim_stop(ir_graph *irg);
 #define stat_new_graph(irg, ent)
 #define stat_free_graph(irg)
 #define stat_irg_walk(irg, pre, post)
+#define stat_irg_walk_blkwise(irg, pre, post)
 #define stat_irg_block_walk(irg, node, pre, post)
 #define stat_merge_nodes(new_node_array, new_num_entries, old_node_array, old_num_entries, opt)
 #define stat_lower(node)
index 9a27807..b7c397c 100644 (file)
@@ -45,6 +45,7 @@ enum vlc_code_t {
   VLC_32BIT      = 0xF0,       /**< 40 bit code, carrying 32 bits payload */
 
   VLC_TAG_FIRST  = 0xF1,       /**< first possible tag value */
+  VLC_TAG_ICONST = 0xFB,       /**< encodes an integer constant */
   VLC_TAG_EMPTY  = 0xFC,       /**< encodes an empty entity */
   VLC_TAG_OPTION = 0xFD,       /**< options exists */
   VLC_TAG_REF    = 0xFE,       /**< special tag, next code is an ID */
@@ -64,8 +65,9 @@ typedef struct _pattern_entry_t {
  * current options
  */
 enum options_t {
-  OPT_WITH_MODE = 0x00000001,  /**< use modes */
-  OPT_ENC_GRAPH = 0x00000002,  /**< encode graphs, not terms */
+  OPT_WITH_MODE   = 0x00000001,        /**< use modes */
+  OPT_ENC_GRAPH   = 0x00000002,        /**< encode graphs, not terms */
+  OPT_WITH_ICONST = 0x00000004, /**< encode integer constants */
 };
 
 
@@ -320,11 +322,7 @@ static void _encode_node(ir_node *node, int max_depth, codec_env_t *env)
   set_entry *s_entry;
   int i, preds;
 
-#if 0
   opcode code = get_irn_opcode(node);
-#else
-  ir_op *code = get_irn_op(node);
-#endif
 
   /* insert the node into our ID map */
   entry.addr = node;
@@ -347,6 +345,7 @@ static void _encode_node(ir_node *node, int max_depth, codec_env_t *env)
 
   put_code(env->buf, (unsigned)code);
 
+  /* do we need the mode ? */
   if (env->options & OPT_WITH_MODE) {
     ir_mode *mode = get_irn_mode(node);
 
@@ -356,6 +355,20 @@ static void _encode_node(ir_node *node, int max_depth, codec_env_t *env)
       put_tag(env->buf, VLC_TAG_EMPTY);
   }
 
+  /* do we need integer constants */
+  if (env->options & OPT_WITH_ICONST) {
+    if (code == iro_Const) {
+      tarval *tv = get_Const_tarval(node);
+
+      if (tarval_is_long(tv)) {
+       long v = tarval_to_long(tv);
+
+       put_tag(env->buf, VLC_TAG_ICONST);
+       put_code(env->buf, v);
+      }
+    }
+  }
+
   --max_depth;
 
   if (max_depth <= 0) {
@@ -410,6 +423,8 @@ static void _decode_node(unsigned parent, int position, codec_env_t *env)
   unsigned code;
   unsigned op_code;
   unsigned mode_code = 0;
+  long iconst;
+  int have_iconst = 0;
 
   code = next_tag(env->buf);
   if (code == VLC_TAG_REF) { /* it's a REF */
@@ -435,13 +450,18 @@ static void _decode_node(unsigned parent, int position, codec_env_t *env)
     }
   }
 
+  if (next_tag(env->buf) == VLC_TAG_ICONST) {
+    iconst      = get_code(env->buf);
+    have_iconst = 1;
+  }
+
   /* dump the edge */
   if (parent)
       pattern_dump_edge(env->dmp, env->curr_id, parent, position);
 
   /* dump the node */
   parent = env->curr_id;
-  pattern_dump_node(env->dmp, parent, op_code, mode_code);
+  pattern_dump_node(env->dmp, parent, op_code, mode_code, have_iconst ? &iconst : NULL);
 
   /* ok, we have a new ID */
   ++env->curr_id;
@@ -465,7 +485,7 @@ static void _decode_node(unsigned parent, int position, codec_env_t *env)
 /**
  * decode an IR-node
  */
-static void decode_node(BYTE *b, unsigned len)
+static void decode_node(BYTE *b, unsigned len, pattern_dumper_t *dump)
 {
   codec_env_t env;
   CODE_BUFFER buf;
@@ -475,7 +495,7 @@ static void decode_node(BYTE *b, unsigned len)
 
   env.buf     = &buf;
   env.curr_id = 1;     /* 0 is used for special purpose */
-  env.dmp     = &stdout_dump;
+  env.dmp     = dump;
 
   /* decode options */
   code = next_tag(&buf);
@@ -542,11 +562,13 @@ static void calc_nodes_pattern(ir_node *node, void *ctx)
 }
 
 /**
+ * output the collected pattern
  */
 static void pattern_output(void)
 {
-  pattern_entry_t *entry;
-  pattern_entry_t **pattern_arr;
+  pattern_entry_t  *entry;
+  pattern_entry_t  **pattern_arr;
+  pattern_dumper_t *dump;
   int i, count = pset_count(status->pattern_hash);
 
   printf("\n%d pattern detected\n", count);
@@ -554,6 +576,9 @@ static void pattern_output(void)
   if (count <= 0)
     return;
 
+  /* creates a dumper */
+  dump = new_vcg_dumper("pattern.vcg", 100);
+
   pattern_arr = xmalloc(sizeof(*pattern_arr) * count);
   for (i = 0, entry = pset_first(status->pattern_hash);
        entry && i < count;
@@ -571,10 +596,14 @@ static void pattern_output(void)
     if (entry->count.cnt[0] < status->bound)
       continue;
 
-    printf("%8d\t", entry->count.cnt[0]);
-    decode_node(entry->buf, entry->len);
-    printf("\n");
+    /* dump a pattern */
+    pattern_dump_new_pattern(dump, &entry->count);
+    decode_node(entry->buf, entry->len, dump);
+    pattern_dump_finish_pattern(dump);
   }
+
+  /* destroy it */
+  pattern_end(dump);
 }
 
 /*
@@ -591,7 +620,7 @@ void stat_calc_pattern_history(ir_graph *irg)
   if (irg == get_const_code_irg())
     return;
 
-  env.max_depth = 4;
+  env.max_depth = 5;
   irg_walk_graph(irg, calc_nodes_pattern, NULL, &env);
 }
 
@@ -604,8 +633,8 @@ void stat_init_pattern_history(int enable)
   if (! enable)
     return;
 
-  status->bound   = 3;
-  status->options = OPT_WITH_MODE | OPT_ENC_GRAPH;
+  status->bound   = 10;
+  status->options = OPT_WITH_MODE | OPT_ENC_GRAPH | OPT_WITH_ICONST;
 
   obstack_init(&status->obst);
 
index cc23cb1..c7d61fe 100644 (file)
 #endif
 
 #include <stdio.h>
+#include <stdlib.h>
 
 #include "ident.h"
 #include "irop_t.h"
 #include "irmode.h"
+#include "firmstat.h"
 #include "pattern_dmp.h"
 
-FILE *f;
+/* dumper operations */
+typedef void (*DUMP_NEW_PATTERN_FUNC)(pattern_dumper_t *self, counter_t *cnt);
+typedef void (*DUMP_FINISH_PATTERN_FUNC)(pattern_dumper_t *self);
+typedef void (*DUMP_NODE_FUNC)(pattern_dumper_t *self, unsigned id, unsigned op_code, unsigned mode_code, void *attr);
+typedef void (*DUMP_REF_FUNC)(pattern_dumper_t *self, unsigned id);
+typedef void (*DUMP_EDGE_FUNC)(pattern_dumper_t *self, unsigned id, unsigned parent, unsigned position);
+typedef void (*DUMP_START_CHILDREN_FUNC)(pattern_dumper_t *self, unsigned id);
+typedef void (*DUMP_FINISH_CHILDREN_FUNC)(pattern_dumper_t *self, unsigned id);
+typedef void (*DUMP_START_FUNC)(pattern_dumper_t *self);
+typedef void (*DUMP_END_FUNC)(pattern_dumper_t *self);
+
+/**
+ * the pattern dumper
+ */
+struct _pattern_dumper_t {
+  DUMP_NEW_PATTERN_FUNC      dump_new_pattern;
+  DUMP_FINISH_PATTERN_FUNC   dump_finish_pattern;
+  DUMP_NODE_FUNC             dump_node;
+  DUMP_REF_FUNC              dump_ref;
+  DUMP_EDGE_FUNC             dump_edge;
+  DUMP_START_CHILDREN_FUNC   dump_start_children;
+  DUMP_FINISH_CHILDREN_FUNC  dump_finish_children;
+  DUMP_START_FUNC            dump_start;
+  DUMP_END_FUNC              dump_end;
+  void                       *data;
+};
+
+/**
+ * VCG private data
+ */
+typedef struct _vcg_private_t {
+  FILE     *f;                 /**< file to dump to */
+  unsigned pattern_id;         /**< ID of the pattern */
+  unsigned max_pattern;                /**< maximum number of pattern to be dumped */
+} vcg_private_t;
 
 /**
  * starts a new VCG graph
  */
 static void vcg_dump_start(pattern_dumper_t *self)
 {
-  f = fopen("firmpattern.vcg", "w");
+  vcg_private_t *priv = self->data;
 
-  fprintf(f,
+  fprintf(priv->f,
     "graph: { title: \"Most found pattern\"\n"
     "  display_edge_labels: no\n"
     "  layoutalgorithm: mindepth\n"
@@ -44,8 +80,10 @@ static void vcg_dump_start(pattern_dumper_t *self)
  */
 static void vcg_dump_end(pattern_dumper_t *self)
 {
-  fprintf(f, "}\n");
-  fclose(f);
+  vcg_private_t *priv = self->data;
+
+  fprintf(priv->f, "}\n");
+  fclose(priv->f);
 }
 
 /*
@@ -53,10 +91,21 @@ static void vcg_dump_end(pattern_dumper_t *self)
  */
 static void vcg_dump_new_pattern(pattern_dumper_t *self, counter_t *cnt)
 {
-  fprintf(f,
-    "  graph: { title: \"pattern cnt %u\"\n", cnt->cnt[0]
-  );
+  vcg_private_t *priv = self->data;
+  static unsigned nr = 0;
+
+  if (priv->pattern_id > priv->max_pattern)
+    return;
 
+  fprintf(priv->f,
+    "  graph: { title: \"g%u\" label: \"pattern %u\" status:clustered color:yellow\n",
+    priv->pattern_id, priv->pattern_id );
+
+  /** add a pseudo node */
+  fprintf(priv->f,
+    "     node: {title: \"c%u\" label: \"cnt: %u\" color:red }\n",
+    ++nr, cnt->cnt[0]
+  );
 }
 
 /**
@@ -64,29 +113,64 @@ static void vcg_dump_new_pattern(pattern_dumper_t *self, counter_t *cnt)
  */
 static void vcg_dump_finish_pattern(pattern_dumper_t *self)
 {
-  fprintf(f, "  }\n");
-}
+  vcg_private_t *priv = self->data;
+
+  if (priv->pattern_id > priv->max_pattern)
+    return;
+
+  fprintf(priv->f, "  }\n");
 
+  if (priv->pattern_id > 0)
+    fprintf(priv->f, "  edge: { sourcename: \"g%u\" targetname: \"g%u\"}\n",
+      priv->pattern_id,
+      priv->pattern_id - 1);
 
+  ++priv->pattern_id;
+}
+
+/**
+ * Dumps a node
+ */
 static void vcg_dump_node(pattern_dumper_t *self, unsigned id,
-    unsigned op_code, unsigned mode_code)
+    unsigned op_code, unsigned mode_code, void *attr)
 {
-  ir_op *op     = (ir_op *)op_code;
-  ir_mode *mode = (ir_mode *)mode_code;
-
-  fprintf(f, "    node: {title: \"n%u\" label: \"%s%s n%u\" }\n",
-    id, get_id_str(op->name), mode ? get_mode_name(mode) : "", id);
+  vcg_private_t *priv = self->data;
+  ir_op *op           = stat_get_op_from_opcode(op_code);
+  ir_mode *mode       = (ir_mode *)mode_code;
+  long l              = attr ? *(long *)attr : 0;
+
+  if (priv->pattern_id > priv->max_pattern)
+    return;
+
+  if (attr) {
+    fprintf(priv->f, "    node: {title: \"n%u_%u\" label: \"%s%s %ld n%u\" }\n",
+      priv->pattern_id, id, get_id_str(op->name), mode ? get_mode_name(mode) : "", l, id);
+  }
+  else {
+    fprintf(priv->f, "    node: {title: \"n%u_%u\" label: \"%s%s n%u\" }\n",
+      priv->pattern_id, id, get_id_str(op->name), mode ? get_mode_name(mode) : "", id);
+  }
 }
 
+/**
+ * Dumps an edge.
+ */
 static void vcg_dump_edge(pattern_dumper_t *self, unsigned id, unsigned parent, unsigned position)
 {
-  fprintf(f, "    edge: { sourcename: \"n%u\" targetname: \"n%u\"}\n", parent, id);
+  vcg_private_t *priv = self->data;
+
+  if (priv->pattern_id > priv->max_pattern)
+    return;
+
+  fprintf(priv->f, "    edge: { sourcename: \"n%u_%u\" targetname: \"n%u_%u\"}\n",
+      priv->pattern_id, parent,
+      priv->pattern_id, id);
 }
 
 /**
  * The VCG dumper.
  */
-pattern_dumper_t vcg_dump = {
+static pattern_dumper_t vcg_dump = {
   vcg_dump_new_pattern,
   vcg_dump_finish_pattern,
   vcg_dump_node,
@@ -94,6 +178,9 @@ pattern_dumper_t vcg_dump = {
   vcg_dump_edge,
   NULL,
   NULL,
+  vcg_dump_start,
+  vcg_dump_end,
+  NULL
 };
 
 /**
@@ -101,33 +188,38 @@ pattern_dumper_t vcg_dump = {
  */
 static void stdout_dump_new_pattern(pattern_dumper_t *self, counter_t *cnt)
 {
-  printf("%8u ", cnt->cnt[0]);
+  FILE *f = self->data;
+
+  fprintf(f, "%8u ", cnt->cnt[0]);
 }
 
 
-/*
+/**
  * Finishes current pattern
  */
 static void stdout_dump_finish_pattern(pattern_dumper_t *self)
 {
-  printf("\n");
+  FILE *f = self->data;
+
+  fprintf(f, "\n");
 }
 
 /**
  * Dumps a node
  */
-static void stdout_dump_node(pattern_dumper_t *self, unsigned id, unsigned op_code, unsigned mode_code)
+static void stdout_dump_node(pattern_dumper_t *self, unsigned id, unsigned op_code, unsigned mode_code, void *attr)
 {
-  ir_op *op     = (ir_op *)op_code;
+  FILE *f       = self->data;
+  ir_op *op     = stat_get_op_from_opcode(op_code);
   ir_mode *mode = (ir_mode *)mode_code;
 
   /* if (env->options & OPT_ENC_GRAPH) */
-    printf("%u:", id);
+    fprintf(f, "%u:", id);
 
-  printf("%s", get_id_str(op->name));
+  fprintf(f, "%s", get_id_str(op->name));
 
   if (mode)
-    printf("%s", get_mode_name(mode));
+    fprintf(f, "%s", get_mode_name(mode));
 }
 
 /**
@@ -135,7 +227,9 @@ static void stdout_dump_node(pattern_dumper_t *self, unsigned id, unsigned op_co
  */
 static void stdout_dump_ref(pattern_dumper_t *self, unsigned id)
 {
-  printf("REF:%u", id);
+  FILE *f = self->data;
+
+  fprintf(f, "REF:%u", id);
 }
 
 /**
@@ -143,8 +237,10 @@ static void stdout_dump_ref(pattern_dumper_t *self, unsigned id)
  */
 static void stdout_dump_edge(pattern_dumper_t *self, unsigned id, unsigned parent, unsigned position)
 {
+  FILE *f = self->data;
+
   if (position > 0)
-    printf(", ");
+    fprintf(f, ", ");
 }
 
 /**
@@ -152,7 +248,9 @@ static void stdout_dump_edge(pattern_dumper_t *self, unsigned id, unsigned paren
  */
 static void stdout_start_children(pattern_dumper_t *self, unsigned id)
 {
-  printf("(");
+  FILE *f = self->data;
+
+  fprintf(f, "(");
 }
 
 /**
@@ -160,13 +258,15 @@ static void stdout_start_children(pattern_dumper_t *self, unsigned id)
  */
 static void stdout_finish_children(pattern_dumper_t *self, unsigned id)
 {
-  printf(")");
+  FILE *f = self->data;
+
+  fprintf(f, ")");
 }
 
 /**
  * The stdout dumper.
  */
-pattern_dumper_t stdout_dump = {
+static const pattern_dumper_t stdout_dump = {
   stdout_dump_new_pattern,
   stdout_dump_finish_pattern,
   stdout_dump_node,
@@ -174,6 +274,9 @@ pattern_dumper_t stdout_dump = {
   stdout_dump_edge,
   stdout_start_children,
   stdout_finish_children,
+  NULL,
+  NULL,
+  NULL
 };
 
 /* ------------------------------------ API ------------------------------------- */
@@ -201,10 +304,10 @@ void pattern_dump_finish_pattern(pattern_dumper_t *self)
 /*
  * Dumps a node
  */
-void pattern_dump_node(pattern_dumper_t *self, unsigned id, unsigned op_code, unsigned mode_code)
+void pattern_dump_node(pattern_dumper_t *self, unsigned id, unsigned op_code, unsigned mode_code, void *attr)
 {
   if (self->dump_node)
-    self->dump_node(self, id, op_code, mode_code);
+    self->dump_node(self, id, op_code, mode_code, attr);
 }
 
 /*
@@ -242,3 +345,60 @@ void pattern_finish_children(pattern_dumper_t *self, unsigned id)
   if (self->dump_finish_children)
     self->dump_finish_children(self, id);
 }
+
+/*
+ * finishes the dumper
+ */
+void pattern_end(pattern_dumper_t *self)
+{
+  if (self->dump_end)
+    self->dump_end(self);
+
+  free(self);
+}
+
+/**
+ * pattern dumper factory for text dumper
+ */
+pattern_dumper_t *new_text_dumper(void)
+{
+  pattern_dumper_t *res = malloc(sizeof(*res));
+
+  if (res) {
+    memcpy(res, &stdout_dump, sizeof(*res));
+    res->data = stdout;
+
+    if (res->dump_start)
+      res->dump_start(res);
+  }
+  return res;
+}
+
+/**
+ * pattern dumper factory for vcg dumper
+ */
+pattern_dumper_t *new_vcg_dumper(const char *vcg_name, unsigned max_pattern)
+{
+  pattern_dumper_t *res = malloc(sizeof(*res) + sizeof(vcg_private_t));
+  vcg_private_t *priv;
+
+  if (res) {
+    FILE *f;
+
+    memcpy(res, &vcg_dump, sizeof(*res));
+
+    priv = (vcg_private_t *)(res + 1);
+    memset(priv, 0, sizeof(*priv));
+
+    f = fopen(vcg_name, "w");
+    priv->f           = f;
+    priv->pattern_id  = 0;
+    priv->max_pattern = max_pattern ? max_pattern : (unsigned)-1;
+    res->data         = priv;
+
+    if (res->dump_start)
+      res->dump_start(res);
+  }
+
+  return res;
+}
index 9cc7473..d270fea 100644 (file)
@@ -4,25 +4,6 @@
 #include "counter.h"
 
 typedef struct _pattern_dumper_t pattern_dumper_t;
-typedef void (*DUMP_NEW_PATTERN_FUNC)(pattern_dumper_t *self, counter_t *cnt);
-typedef void (*DUMP_FINISH_PATTERN_FUNC)(pattern_dumper_t *self);
-typedef void (*DUMP_NODE_FUNC)(pattern_dumper_t *self, unsigned id, unsigned op_code, unsigned mode_code);
-typedef void (*DUMP_REF_FUNC)(pattern_dumper_t *self, unsigned id);
-typedef void (*DUMP_EDGE_FUNC)(pattern_dumper_t *self, unsigned id, unsigned parent, unsigned position);
-typedef void (*DUMP_START_CHILDREN_FUNC)(pattern_dumper_t *self, unsigned id);
-typedef void (*DUMP_FINISH_CHILDREN_FUNC)(pattern_dumper_t *self, unsigned id);
-
-struct _pattern_dumper_t {
-  DUMP_NEW_PATTERN_FUNC      dump_new_pattern;
-  DUMP_FINISH_PATTERN_FUNC   dump_finish_pattern;
-  DUMP_NODE_FUNC             dump_node;
-  DUMP_REF_FUNC              dump_ref;
-  DUMP_EDGE_FUNC             dump_edge;
-  DUMP_START_CHILDREN_FUNC   dump_start_children;
-  DUMP_FINISH_CHILDREN_FUNC  dump_finish_children;
-};
-
-extern pattern_dumper_t vcg_dump, stdout_dump;
 
 /**
  * starts a new pattern
@@ -37,7 +18,7 @@ void pattern_dump_finish_pattern(pattern_dumper_t *self);
 /**
  * Dumps a node
  */
-void pattern_dump_node(pattern_dumper_t *self, unsigned id, unsigned op_code, unsigned mode_code);
+void pattern_dump_node(pattern_dumper_t *self, unsigned id, unsigned op_code, unsigned mode_code, void *attr);
 
 /**
  * Dump a ref
@@ -55,8 +36,26 @@ void pattern_dump_edge(pattern_dumper_t *self, unsigned id, unsigned parent, uns
 void pattern_start_children(pattern_dumper_t *self, unsigned id);
 
 /**
- * finishes childred  dumper
+ * finishes childred dumper
  */
 void pattern_finish_children(pattern_dumper_t *self, unsigned id);
 
+/**
+ * finishes dumper, destroyes the dumper object
+ */
+void pattern_end(pattern_dumper_t *self);
+
+/**
+ * pattern dumper factory for text dumper
+ */
+pattern_dumper_t *new_text_dumper(void);
+
+/**
+ * pattern dumper factory for vcg dumper
+ *
+ * @param vcg_name    name of the VCG file
+ * @param max_pattern maximum number of pattern to be dumped
+ */
+pattern_dumper_t *new_vcg_dumper(const char *vcg_name, unsigned max_pattern);
+
 #endif /* _PATTERN_DMP_H_ */