From 917134649d6fc4f0eb0b38feeee8c61b67a6d932 Mon Sep 17 00:00:00 2001 From: Michael Beck Date: Mon, 19 Jul 2004 15:31:03 +0000 Subject: [PATCH] added statistics for blocks implemented vcg dump of pattern implemented opcode->ir_op conversion [r3509] --- ir/stat/firmstat.c | 58 +++++++++-- ir/stat/firmstat.h | 27 +++-- ir/stat/pattern.c | 63 ++++++++---- ir/stat/pattern_dmp.c | 226 ++++++++++++++++++++++++++++++++++++------ ir/stat/pattern_dmp.h | 41 ++++---- 5 files changed, 331 insertions(+), 84 deletions(-) diff --git a/ir/stat/firmstat.c b/ir/stat/firmstat.c index 445a9fd89..5a6c59e70 100644 --- a/ir/stat/firmstat.c +++ b/ir/stat/firmstat.c @@ -34,15 +34,16 @@ * 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. */ diff --git a/ir/stat/firmstat.h b/ir/stat/firmstat.h index 779cb926b..e9017199c 100644 --- a/ir/stat/firmstat.h +++ b/ir/stat/firmstat.h @@ -18,6 +18,12 @@ #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) diff --git a/ir/stat/pattern.c b/ir/stat/pattern.c index 9a27807f1..b7c397c72 100644 --- a/ir/stat/pattern.c +++ b/ir/stat/pattern.c @@ -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); diff --git a/ir/stat/pattern_dmp.c b/ir/stat/pattern_dmp.c index cc23cb156..c7d61fea2 100644 --- a/ir/stat/pattern_dmp.c +++ b/ir/stat/pattern_dmp.c @@ -14,22 +14,58 @@ #endif #include +#include #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; +} diff --git a/ir/stat/pattern_dmp.h b/ir/stat/pattern_dmp.h index 9cc74735a..d270fea37 100644 --- a/ir/stat/pattern_dmp.h +++ b/ir/stat/pattern_dmp.h @@ -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_ */ -- 2.20.1