2 * This file is part of libFirm.
3 * Copyright (C) 2012 University of Karlsruhe.
8 * @brief Statistics for Firm. Dumping patterns.
19 #include "firmstat_t.h"
20 #include "pattern_dmp.h"
22 /* dumper operations */
23 typedef void (*DUMP_NEW_PATTERN_FUNC)(pattern_dumper_t *self, counter_t *cnt);
24 typedef void (*DUMP_FINISH_PATTERN_FUNC)(pattern_dumper_t *self);
25 typedef void (*DUMP_NODE_FUNC)(pattern_dumper_t *self, unsigned id, unsigned op_code, unsigned mode_code, void *attr);
26 typedef void (*DUMP_REF_FUNC)(pattern_dumper_t *self, unsigned id);
27 typedef void (*DUMP_EDGE_FUNC)(pattern_dumper_t *self, unsigned tgt, unsigned src, unsigned pos, unsigned mode_code);
28 typedef void (*DUMP_START_CHILDREN_FUNC)(pattern_dumper_t *self, unsigned id);
29 typedef void (*DUMP_FINISH_CHILDREN_FUNC)(pattern_dumper_t *self, unsigned id);
30 typedef void (*DUMP_START_FUNC)(pattern_dumper_t *self);
31 typedef void (*DUMP_END_FUNC)(pattern_dumper_t *self);
36 struct pattern_dumper_t {
37 DUMP_NEW_PATTERN_FUNC dump_new_pattern;
38 DUMP_FINISH_PATTERN_FUNC dump_finish_pattern;
39 DUMP_NODE_FUNC dump_node;
40 DUMP_REF_FUNC dump_ref;
41 DUMP_EDGE_FUNC dump_edge;
42 DUMP_START_CHILDREN_FUNC dump_start_children;
43 DUMP_FINISH_CHILDREN_FUNC dump_finish_children;
44 DUMP_START_FUNC dump_start;
45 DUMP_END_FUNC dump_end;
52 typedef struct vcg_private_t {
53 FILE *f; /**< file to dump to */
54 unsigned pattern_id; /**< ID of the pattern */
55 unsigned max_pattern; /**< maximum number of pattern to be dumped */
59 * Starts a new VCG graph.
61 static void vcg_dump_start(pattern_dumper_t *self)
63 vcg_private_t *priv = (vcg_private_t*)self->data;
66 "graph: { title: \"Most found pattern\"\n"
67 " display_edge_labels: no\n"
68 " layoutalgorithm: mindepth\n"
69 " manhattan_edges: yes\n"
71 " orientation: bottom_to_top\n"
76 * Ends a new VCG graph.
78 static void vcg_dump_end(pattern_dumper_t *self)
80 vcg_private_t *priv = (vcg_private_t*)self->data;
82 fprintf(priv->f, "}\n");
87 * Starts a new pattern.
89 static void vcg_dump_new_pattern(pattern_dumper_t *self, counter_t *cnt)
91 vcg_private_t *priv = (vcg_private_t*)self->data;
92 static unsigned nr = 0;
94 if (priv->pattern_id > priv->max_pattern)
98 " graph: { title: \"g%u\" label: \"pattern %u\" status:clustered color:yellow\n",
99 priv->pattern_id, priv->pattern_id );
101 /* add a pseudo node for the count of this pattern */
103 " node: {title: \"c%u\" label: \"cnt: %u\" color:red }\n",
104 ++nr, cnt_to_uint(cnt)
109 * Finish the current pattern.
111 static void vcg_dump_finish_pattern(pattern_dumper_t *self)
113 vcg_private_t *priv = (vcg_private_t*)self->data;
115 if (priv->pattern_id > priv->max_pattern)
118 fprintf(priv->f, " }\n");
120 if (priv->pattern_id > 0)
121 fprintf(priv->f, " edge: { sourcename: \"g%u\" targetname: \"g%u\" linestyle:invisible}\n",
123 priv->pattern_id - 1);
131 static void vcg_dump_node(pattern_dumper_t *self, unsigned id,
132 unsigned op_code, unsigned mode_code, void *attr)
134 vcg_private_t *priv = (vcg_private_t*)self->data;
135 ir_op *op = stat_get_op_from_opcode(op_code);
136 ir_mode *mode = ir_get_mode(mode_code);
137 long l = attr ? *(long *)attr : 0;
139 if (priv->pattern_id > priv->max_pattern)
143 fprintf(priv->f, " node: {title: \"n%u_%u\" label: \"%s%s %ld n%u\" }\n",
144 priv->pattern_id, id, get_id_str(op->name), mode ? get_mode_name(mode) : "", l, id);
146 fprintf(priv->f, " node: {title: \"n%u_%u\" label: \"%s%s n%u\" }\n",
147 priv->pattern_id, id, get_id_str(op->name), mode ? get_mode_name(mode) : "", id);
154 static void vcg_dump_edge(pattern_dumper_t *self, unsigned tgt, unsigned src, unsigned pos, unsigned mode_code)
156 vcg_private_t *priv = (vcg_private_t*)self->data;
159 if (priv->pattern_id > priv->max_pattern)
162 fprintf(priv->f, " edge: { sourcename: \"n%u_%u\" targetname: \"n%u_%u\" label: \"%u\" }\n",
163 priv->pattern_id, src,
164 priv->pattern_id, tgt,
172 static pattern_dumper_t vcg_dump = {
173 vcg_dump_new_pattern,
174 vcg_dump_finish_pattern,
186 * Starts a new pattern.
188 static void stdout_dump_new_pattern(pattern_dumper_t *self, counter_t *cnt)
190 FILE *f = (FILE*)self->data;
192 fprintf(f, "%8u ", cnt_to_uint(cnt));
197 * Finish the current pattern.
199 static void stdout_dump_finish_pattern(pattern_dumper_t *self)
201 FILE *f = (FILE*)self->data;
209 static void stdout_dump_node(pattern_dumper_t *self, unsigned id, unsigned op_code, unsigned mode_code, void *attr)
211 FILE *f = (FILE*)self->data;
212 ir_op *op = stat_get_op_from_opcode(op_code);
213 ir_mode *mode = ir_get_mode(mode_code);
216 /* if (env->options & OPT_ENC_GRAPH) */
217 fprintf(f, "%u:", id);
219 fprintf(f, "%s", get_id_str(op->name));
222 fprintf(f, "%s", get_mode_name(mode));
228 static void stdout_dump_ref(pattern_dumper_t *self, unsigned id)
230 FILE *f = (FILE*)self->data;
232 fprintf(f, "REF:%u", id);
238 static void stdout_dump_edge(pattern_dumper_t *self, unsigned tgt, unsigned src, unsigned pos, unsigned mode_code)
240 FILE *f = (FILE*)self->data;
251 * Start the children dumper.
253 static void stdout_start_children(pattern_dumper_t *self, unsigned id)
255 FILE *f = (FILE*)self->data;
262 * Finish the children dumper.
264 static void stdout_finish_children(pattern_dumper_t *self, unsigned id)
266 FILE *f = (FILE*)self->data;
275 static const pattern_dumper_t stdout_dump = {
276 stdout_dump_new_pattern,
277 stdout_dump_finish_pattern,
281 stdout_start_children,
282 stdout_finish_children,
288 /* ------------------------------------ API ------------------------------------- */
291 * Starts a new pattern.
293 void pattern_dump_new_pattern(pattern_dumper_t *self, counter_t *cnt)
295 if (self->dump_new_pattern)
296 self->dump_new_pattern(self, cnt);
301 * Finish the current pattern.
303 void pattern_dump_finish_pattern(pattern_dumper_t *self)
305 if (self->dump_finish_pattern)
306 self->dump_finish_pattern(self);
313 void pattern_dump_node(pattern_dumper_t *self, unsigned id, unsigned op_code, unsigned mode_code, void *attr)
316 self->dump_node(self, id, op_code, mode_code, attr);
322 void pattern_dump_ref(pattern_dumper_t *self, unsigned id)
325 self->dump_ref(self, id);
331 void pattern_dump_edge(pattern_dumper_t *self, unsigned tgt, unsigned src, unsigned pos, unsigned mode_code)
334 self->dump_edge(self, tgt, src, pos, mode_code);
338 * Start the children dumper.
340 void pattern_start_children(pattern_dumper_t *self, unsigned id)
342 if (self->dump_start_children)
343 self->dump_start_children(self, id);
347 * Finish the the children dumper.
349 void pattern_finish_children(pattern_dumper_t *self, unsigned id)
351 if (self->dump_finish_children)
352 self->dump_finish_children(self, id);
356 * Finish the the dumper.
358 void pattern_end(pattern_dumper_t *self)
361 self->dump_end(self);
367 * pattern dumper factory for text dumper
369 pattern_dumper_t *new_text_dumper(void)
371 pattern_dumper_t *res = XMALLOC(pattern_dumper_t);
377 res->dump_start(res);
382 * pattern dumper factory for vcg dumper
384 pattern_dumper_t *new_vcg_dumper(const char *vcg_name, unsigned max_pattern)
386 pattern_dumper_t *res = (pattern_dumper_t*)malloc(sizeof(*res) + sizeof(vcg_private_t));
392 memcpy(res, &vcg_dump, sizeof(*res));
394 priv = (vcg_private_t *)(res + 1);
395 memset(priv, 0, sizeof(*priv));
397 f = fopen(vcg_name, "w");
399 priv->pattern_id = 0;
400 priv->max_pattern = max_pattern ? max_pattern : (unsigned)-1;
404 res->dump_start(res);