2 * Copyright (C) 1995-2008 University of Karlsruhe. All right reserved.
4 * This file is part of libFirm.
6 * This file may be distributed and/or modified under the terms of the
7 * GNU General Public License version 2 as published by the Free Software
8 * Foundation and appearing in the file LICENSE.GPL included in the
9 * packaging of this file.
11 * Licensees holding valid libFirm Professional Edition licenses may use
12 * this file in accordance with the libFirm Commercial License.
13 * Agreement provided with the Software.
15 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * @brief Statistics for Firm. Dumping patterns.
23 * @author Michael Beck
30 #ifdef FIRM_STATISTICS
40 #include "firmstat_t.h"
41 #include "pattern_dmp.h"
43 /* dumper operations */
44 typedef void (*DUMP_NEW_PATTERN_FUNC)(pattern_dumper_t *self, counter_t *cnt);
45 typedef void (*DUMP_FINISH_PATTERN_FUNC)(pattern_dumper_t *self);
46 typedef void (*DUMP_NODE_FUNC)(pattern_dumper_t *self, unsigned id, unsigned op_code, unsigned mode_code, void *attr);
47 typedef void (*DUMP_REF_FUNC)(pattern_dumper_t *self, unsigned id);
48 typedef void (*DUMP_EDGE_FUNC)(pattern_dumper_t *self, unsigned tgt, unsigned src, unsigned pos, unsigned mode_code);
49 typedef void (*DUMP_START_CHILDREN_FUNC)(pattern_dumper_t *self, unsigned id);
50 typedef void (*DUMP_FINISH_CHILDREN_FUNC)(pattern_dumper_t *self, unsigned id);
51 typedef void (*DUMP_START_FUNC)(pattern_dumper_t *self);
52 typedef void (*DUMP_END_FUNC)(pattern_dumper_t *self);
57 struct _pattern_dumper_t {
58 DUMP_NEW_PATTERN_FUNC dump_new_pattern;
59 DUMP_FINISH_PATTERN_FUNC dump_finish_pattern;
60 DUMP_NODE_FUNC dump_node;
61 DUMP_REF_FUNC dump_ref;
62 DUMP_EDGE_FUNC dump_edge;
63 DUMP_START_CHILDREN_FUNC dump_start_children;
64 DUMP_FINISH_CHILDREN_FUNC dump_finish_children;
65 DUMP_START_FUNC dump_start;
66 DUMP_END_FUNC dump_end;
73 typedef struct _vcg_private_t {
74 FILE *f; /**< file to dump to */
75 unsigned pattern_id; /**< ID of the pattern */
76 unsigned max_pattern; /**< maximum number of pattern to be dumped */
80 * Starts a new VCG graph.
82 static void vcg_dump_start(pattern_dumper_t *self)
84 vcg_private_t *priv = self->data;
87 "graph: { title: \"Most found pattern\"\n"
88 " display_edge_labels: no\n"
89 " layoutalgorithm: mindepth\n"
90 " manhattan_edges: yes\n"
92 " orientation: bottom_to_top\n"
94 } /* vcg_dump_start */
97 * Ends a new VCG graph.
99 static void vcg_dump_end(pattern_dumper_t *self)
101 vcg_private_t *priv = self->data;
103 fprintf(priv->f, "}\n");
108 * Starts a new pattern.
110 static void vcg_dump_new_pattern(pattern_dumper_t *self, counter_t *cnt)
112 vcg_private_t *priv = self->data;
113 static unsigned nr = 0;
115 if (priv->pattern_id > priv->max_pattern)
119 " graph: { title: \"g%u\" label: \"pattern %u\" status:clustered color:yellow\n",
120 priv->pattern_id, priv->pattern_id );
122 /* add a pseudo node for the count of this pattern */
124 " node: {title: \"c%u\" label: \"cnt: %u\" color:red }\n",
125 ++nr, cnt_to_uint(cnt)
127 } /* vcg_dump_new_pattern */
130 * Finish the current pattern.
132 static void vcg_dump_finish_pattern(pattern_dumper_t *self)
134 vcg_private_t *priv = self->data;
136 if (priv->pattern_id > priv->max_pattern)
139 fprintf(priv->f, " }\n");
141 if (priv->pattern_id > 0)
142 fprintf(priv->f, " edge: { sourcename: \"g%u\" targetname: \"g%u\" linestyle:invisible}\n",
144 priv->pattern_id - 1);
147 } /* vcg_dump_finish_pattern */
152 static void vcg_dump_node(pattern_dumper_t *self, unsigned id,
153 unsigned op_code, unsigned mode_code, void *attr)
155 vcg_private_t *priv = self->data;
156 ir_op *op = stat_get_op_from_opcode(op_code);
157 ir_mode *mode = stat_mode_for_index(mode_code);
158 long l = attr ? *(long *)attr : 0;
160 if (priv->pattern_id > priv->max_pattern)
164 fprintf(priv->f, " node: {title: \"n%u_%u\" label: \"%s%s %ld n%u\" }\n",
165 priv->pattern_id, id, get_id_str(op->name), mode ? get_mode_name(mode) : "", l, id);
167 fprintf(priv->f, " node: {title: \"n%u_%u\" label: \"%s%s n%u\" }\n",
168 priv->pattern_id, id, get_id_str(op->name), mode ? get_mode_name(mode) : "", id);
170 } /* vcg_dump_node */
175 static void vcg_dump_edge(pattern_dumper_t *self, unsigned tgt, unsigned src, unsigned pos, unsigned mode_code)
177 vcg_private_t *priv = self->data;
180 if (priv->pattern_id > priv->max_pattern)
183 fprintf(priv->f, " edge: { sourcename: \"n%u_%u\" targetname: \"n%u_%u\" label: \"%u\" }\n",
184 priv->pattern_id, src,
185 priv->pattern_id, tgt,
188 } /* vcg_dump_edge */
193 static pattern_dumper_t vcg_dump = {
194 vcg_dump_new_pattern,
195 vcg_dump_finish_pattern,
207 * Starts a new pattern.
209 static void stdout_dump_new_pattern(pattern_dumper_t *self, counter_t *cnt)
211 FILE *f = self->data;
213 fprintf(f, "%8u ", cnt_to_uint(cnt));
214 } /* stdout_dump_new_pattern */
218 * Finish the current pattern.
220 static void stdout_dump_finish_pattern(pattern_dumper_t *self)
222 FILE *f = self->data;
225 } /* stdout_dump_finish_pattern */
230 static void stdout_dump_node(pattern_dumper_t *self, unsigned id, unsigned op_code, unsigned mode_code, void *attr)
232 FILE *f = self->data;
233 ir_op *op = stat_get_op_from_opcode(op_code);
234 ir_mode *mode = stat_mode_for_index(mode_code);
237 /* if (env->options & OPT_ENC_GRAPH) */
238 fprintf(f, "%u:", id);
240 fprintf(f, "%s", get_id_str(op->name));
243 fprintf(f, "%s", get_mode_name(mode));
244 } /* stdout_dump_node */
249 static void stdout_dump_ref(pattern_dumper_t *self, unsigned id)
251 FILE *f = self->data;
253 fprintf(f, "REF:%u", id);
254 } /* stdout_dump_ref */
259 static void stdout_dump_edge(pattern_dumper_t *self, unsigned tgt, unsigned src, unsigned pos, unsigned mode_code)
261 FILE *f = self->data;
269 } /* stdout_dump_edge */
272 * Start the children dumper.
274 static void stdout_start_children(pattern_dumper_t *self, unsigned id)
276 FILE *f = self->data;
280 } /* stdout_start_children */
283 * Finish the children dumper.
285 static void stdout_finish_children(pattern_dumper_t *self, unsigned id)
287 FILE *f = self->data;
291 } /* stdout_finish_children */
296 static const pattern_dumper_t stdout_dump = {
297 stdout_dump_new_pattern,
298 stdout_dump_finish_pattern,
302 stdout_start_children,
303 stdout_finish_children,
309 /* ------------------------------------ API ------------------------------------- */
312 * Starts a new pattern.
314 void pattern_dump_new_pattern(pattern_dumper_t *self, counter_t *cnt)
316 if (self->dump_new_pattern)
317 self->dump_new_pattern(self, cnt);
318 } /* pattern_dump_new_pattern */
322 * Finish the current pattern.
324 void pattern_dump_finish_pattern(pattern_dumper_t *self)
326 if (self->dump_finish_pattern)
327 self->dump_finish_pattern(self);
328 } /* pattern_dump_finish_pattern */
334 void pattern_dump_node(pattern_dumper_t *self, unsigned id, unsigned op_code, unsigned mode_code, void *attr)
337 self->dump_node(self, id, op_code, mode_code, attr);
338 } /* pattern_dump_node */
343 void pattern_dump_ref(pattern_dumper_t *self, unsigned id)
346 self->dump_ref(self, id);
347 } /* pattern_dump_ref */
352 void pattern_dump_edge(pattern_dumper_t *self, unsigned tgt, unsigned src, unsigned pos, unsigned mode_code)
355 self->dump_edge(self, tgt, src, pos, mode_code);
356 } /* pattern_dump_edge */
359 * Start the children dumper.
361 void pattern_start_children(pattern_dumper_t *self, unsigned id)
363 if (self->dump_start_children)
364 self->dump_start_children(self, id);
365 } /* pattern_start_children */
368 * Finish the the children dumper.
370 void pattern_finish_children(pattern_dumper_t *self, unsigned id)
372 if (self->dump_finish_children)
373 self->dump_finish_children(self, id);
374 } /* pattern_finish_children */
377 * Finish the the dumper.
379 void pattern_end(pattern_dumper_t *self)
382 self->dump_end(self);
388 * pattern dumper factory for text dumper
390 pattern_dumper_t *new_text_dumper(void)
392 pattern_dumper_t *res = malloc(sizeof(*res));
395 memcpy(res, &stdout_dump, sizeof(*res));
399 res->dump_start(res);
402 } /* new_text_dumper */
405 * pattern dumper factory for vcg dumper
407 pattern_dumper_t *new_vcg_dumper(const char *vcg_name, unsigned max_pattern)
409 pattern_dumper_t *res = malloc(sizeof(*res) + sizeof(vcg_private_t));
415 memcpy(res, &vcg_dump, sizeof(*res));
417 priv = (vcg_private_t *)(res + 1);
418 memset(priv, 0, sizeof(*priv));
420 f = fopen(vcg_name, "w");
422 priv->pattern_id = 0;
423 priv->max_pattern = max_pattern ? max_pattern : (unsigned)-1;
427 res->dump_start(res);
431 } /* new_vcg_dumper */
433 #endif /* FIRM_STATISTICS */