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
28 #ifdef FIRM_STATISTICS
36 #include "firmstat_t.h"
37 #include "pattern_dmp.h"
39 /* dumper operations */
40 typedef void (*DUMP_NEW_PATTERN_FUNC)(pattern_dumper_t *self, counter_t *cnt);
41 typedef void (*DUMP_FINISH_PATTERN_FUNC)(pattern_dumper_t *self);
42 typedef void (*DUMP_NODE_FUNC)(pattern_dumper_t *self, unsigned id, unsigned op_code, unsigned mode_code, void *attr);
43 typedef void (*DUMP_REF_FUNC)(pattern_dumper_t *self, unsigned id);
44 typedef void (*DUMP_EDGE_FUNC)(pattern_dumper_t *self, unsigned tgt, unsigned src, unsigned pos, unsigned mode_code);
45 typedef void (*DUMP_START_CHILDREN_FUNC)(pattern_dumper_t *self, unsigned id);
46 typedef void (*DUMP_FINISH_CHILDREN_FUNC)(pattern_dumper_t *self, unsigned id);
47 typedef void (*DUMP_START_FUNC)(pattern_dumper_t *self);
48 typedef void (*DUMP_END_FUNC)(pattern_dumper_t *self);
53 struct _pattern_dumper_t {
54 DUMP_NEW_PATTERN_FUNC dump_new_pattern;
55 DUMP_FINISH_PATTERN_FUNC dump_finish_pattern;
56 DUMP_NODE_FUNC dump_node;
57 DUMP_REF_FUNC dump_ref;
58 DUMP_EDGE_FUNC dump_edge;
59 DUMP_START_CHILDREN_FUNC dump_start_children;
60 DUMP_FINISH_CHILDREN_FUNC dump_finish_children;
61 DUMP_START_FUNC dump_start;
62 DUMP_END_FUNC dump_end;
69 typedef struct _vcg_private_t {
70 FILE *f; /**< file to dump to */
71 unsigned pattern_id; /**< ID of the pattern */
72 unsigned max_pattern; /**< maximum number of pattern to be dumped */
76 * Starts a new VCG graph.
78 static void vcg_dump_start(pattern_dumper_t *self)
80 vcg_private_t *priv = self->data;
83 "graph: { title: \"Most found pattern\"\n"
84 " display_edge_labels: no\n"
85 " layoutalgorithm: mindepth\n"
86 " manhattan_edges: yes\n"
88 " orientation: bottom_to_top\n"
90 } /* vcg_dump_start */
93 * Ends a new VCG graph.
95 static void vcg_dump_end(pattern_dumper_t *self)
97 vcg_private_t *priv = self->data;
99 fprintf(priv->f, "}\n");
104 * Starts a new pattern.
106 static void vcg_dump_new_pattern(pattern_dumper_t *self, counter_t *cnt)
108 vcg_private_t *priv = self->data;
109 static unsigned nr = 0;
111 if (priv->pattern_id > priv->max_pattern)
115 " graph: { title: \"g%u\" label: \"pattern %u\" status:clustered color:yellow\n",
116 priv->pattern_id, priv->pattern_id );
118 /* add a pseudo node for the count of this pattern */
120 " node: {title: \"c%u\" label: \"cnt: %u\" color:red }\n",
121 ++nr, cnt_to_uint(cnt)
123 } /* vcg_dump_new_pattern */
126 * Finish the current pattern.
128 static void vcg_dump_finish_pattern(pattern_dumper_t *self)
130 vcg_private_t *priv = self->data;
132 if (priv->pattern_id > priv->max_pattern)
135 fprintf(priv->f, " }\n");
137 if (priv->pattern_id > 0)
138 fprintf(priv->f, " edge: { sourcename: \"g%u\" targetname: \"g%u\" linestyle:invisible}\n",
140 priv->pattern_id - 1);
143 } /* vcg_dump_finish_pattern */
148 static void vcg_dump_node(pattern_dumper_t *self, unsigned id,
149 unsigned op_code, unsigned mode_code, void *attr)
151 vcg_private_t *priv = self->data;
152 ir_op *op = stat_get_op_from_opcode(op_code);
153 ir_mode *mode = stat_mode_for_index(mode_code);
154 long l = attr ? *(long *)attr : 0;
156 if (priv->pattern_id > priv->max_pattern)
160 fprintf(priv->f, " node: {title: \"n%u_%u\" label: \"%s%s %ld n%u\" }\n",
161 priv->pattern_id, id, get_id_str(op->name), mode ? get_mode_name(mode) : "", l, id);
163 fprintf(priv->f, " node: {title: \"n%u_%u\" label: \"%s%s n%u\" }\n",
164 priv->pattern_id, id, get_id_str(op->name), mode ? get_mode_name(mode) : "", id);
166 } /* vcg_dump_node */
171 static void vcg_dump_edge(pattern_dumper_t *self, unsigned tgt, unsigned src, unsigned pos, unsigned mode_code)
173 vcg_private_t *priv = self->data;
176 if (priv->pattern_id > priv->max_pattern)
179 fprintf(priv->f, " edge: { sourcename: \"n%u_%u\" targetname: \"n%u_%u\" label: \"%u\" }\n",
180 priv->pattern_id, src,
181 priv->pattern_id, tgt,
184 } /* vcg_dump_edge */
189 static pattern_dumper_t vcg_dump = {
190 vcg_dump_new_pattern,
191 vcg_dump_finish_pattern,
203 * Starts a new pattern.
205 static void stdout_dump_new_pattern(pattern_dumper_t *self, counter_t *cnt)
207 FILE *f = self->data;
209 fprintf(f, "%8u ", cnt_to_uint(cnt));
210 } /* stdout_dump_new_pattern */
214 * Finish the current pattern.
216 static void stdout_dump_finish_pattern(pattern_dumper_t *self)
218 FILE *f = self->data;
221 } /* stdout_dump_finish_pattern */
226 static void stdout_dump_node(pattern_dumper_t *self, unsigned id, unsigned op_code, unsigned mode_code, void *attr)
228 FILE *f = self->data;
229 ir_op *op = stat_get_op_from_opcode(op_code);
230 ir_mode *mode = stat_mode_for_index(mode_code);
233 /* if (env->options & OPT_ENC_GRAPH) */
234 fprintf(f, "%u:", id);
236 fprintf(f, "%s", get_id_str(op->name));
239 fprintf(f, "%s", get_mode_name(mode));
240 } /* stdout_dump_node */
245 static void stdout_dump_ref(pattern_dumper_t *self, unsigned id)
247 FILE *f = self->data;
249 fprintf(f, "REF:%u", id);
250 } /* stdout_dump_ref */
255 static void stdout_dump_edge(pattern_dumper_t *self, unsigned tgt, unsigned src, unsigned pos, unsigned mode_code)
257 FILE *f = self->data;
265 } /* stdout_dump_edge */
268 * Start the children dumper.
270 static void stdout_start_children(pattern_dumper_t *self, unsigned id)
272 FILE *f = self->data;
276 } /* stdout_start_children */
279 * Finish the children dumper.
281 static void stdout_finish_children(pattern_dumper_t *self, unsigned id)
283 FILE *f = self->data;
287 } /* stdout_finish_children */
292 static const pattern_dumper_t stdout_dump = {
293 stdout_dump_new_pattern,
294 stdout_dump_finish_pattern,
298 stdout_start_children,
299 stdout_finish_children,
305 /* ------------------------------------ API ------------------------------------- */
308 * Starts a new pattern.
310 void pattern_dump_new_pattern(pattern_dumper_t *self, counter_t *cnt)
312 if (self->dump_new_pattern)
313 self->dump_new_pattern(self, cnt);
314 } /* pattern_dump_new_pattern */
318 * Finish the current pattern.
320 void pattern_dump_finish_pattern(pattern_dumper_t *self)
322 if (self->dump_finish_pattern)
323 self->dump_finish_pattern(self);
324 } /* pattern_dump_finish_pattern */
330 void pattern_dump_node(pattern_dumper_t *self, unsigned id, unsigned op_code, unsigned mode_code, void *attr)
333 self->dump_node(self, id, op_code, mode_code, attr);
334 } /* pattern_dump_node */
339 void pattern_dump_ref(pattern_dumper_t *self, unsigned id)
342 self->dump_ref(self, id);
343 } /* pattern_dump_ref */
348 void pattern_dump_edge(pattern_dumper_t *self, unsigned tgt, unsigned src, unsigned pos, unsigned mode_code)
351 self->dump_edge(self, tgt, src, pos, mode_code);
352 } /* pattern_dump_edge */
355 * Start the children dumper.
357 void pattern_start_children(pattern_dumper_t *self, unsigned id)
359 if (self->dump_start_children)
360 self->dump_start_children(self, id);
361 } /* pattern_start_children */
364 * Finish the the children dumper.
366 void pattern_finish_children(pattern_dumper_t *self, unsigned id)
368 if (self->dump_finish_children)
369 self->dump_finish_children(self, id);
370 } /* pattern_finish_children */
373 * Finish the the dumper.
375 void pattern_end(pattern_dumper_t *self)
378 self->dump_end(self);
384 * pattern dumper factory for text dumper
386 pattern_dumper_t *new_text_dumper(void)
388 pattern_dumper_t *res = malloc(sizeof(*res));
391 memcpy(res, &stdout_dump, sizeof(*res));
395 res->dump_start(res);
398 } /* new_text_dumper */
401 * pattern dumper factory for vcg dumper
403 pattern_dumper_t *new_vcg_dumper(const char *vcg_name, unsigned max_pattern)
405 pattern_dumper_t *res = malloc(sizeof(*res) + sizeof(vcg_private_t));
411 memcpy(res, &vcg_dump, sizeof(*res));
413 priv = (vcg_private_t *)(res + 1);
414 memset(priv, 0, sizeof(*priv));
416 f = fopen(vcg_name, "w");
418 priv->pattern_id = 0;
419 priv->max_pattern = max_pattern ? max_pattern : (unsigned)-1;
423 res->dump_start(res);
427 } /* new_vcg_dumper */
429 #endif /* FIRM_STATISTICS */