identifiers starting with _ are reserved; remove this bad practice
[libfirm] / ir / stat / pattern_dmp.c
1 /*
2  * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
3  *
4  * This file is part of libFirm.
5  *
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.
10  *
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.
14  *
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
17  * PURPOSE.
18  */
19
20 /**
21  * @file
22  * @brief   Statistics for Firm. Dumping patterns.
23  * @author  Michael Beck
24  * @version $Id$
25  */
26 #include "config.h"
27
28 #ifdef FIRM_STATISTICS
29
30 #include <stdio.h>
31 #include <stdlib.h>
32
33 #include "ident.h"
34 #include "irop_t.h"
35 #include "irmode.h"
36 #include "firmstat_t.h"
37 #include "pattern_dmp.h"
38
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);
49
50 /**
51  * the pattern dumper
52  */
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;
63         void                       *data;
64 };
65
66 /**
67  * VCG private data
68  */
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 */
73 } vcg_private_t;
74
75 /**
76  * Starts a new VCG graph.
77  */
78 static void vcg_dump_start(pattern_dumper_t *self)
79 {
80         vcg_private_t *priv = self->data;
81
82         fprintf(priv->f,
83                 "graph: { title: \"Most found pattern\"\n"
84                 "  display_edge_labels: no\n"
85                 "  layoutalgorithm: mindepth\n"
86                 "  manhattan_edges: yes\n"
87                 "  port_sharing: no\n"
88                 "  orientation: bottom_to_top\n"
89                 );
90 }  /* vcg_dump_start */
91
92 /**
93  * Ends a new VCG graph.
94  */
95 static void vcg_dump_end(pattern_dumper_t *self)
96 {
97         vcg_private_t *priv = self->data;
98
99         fprintf(priv->f, "}\n");
100         fclose(priv->f);
101 }  /* vcg_dump_end */
102
103 /**
104  * Starts a new pattern.
105  */
106 static void vcg_dump_new_pattern(pattern_dumper_t *self, counter_t *cnt)
107 {
108         vcg_private_t *priv = self->data;
109         static unsigned nr = 0;
110
111         if (priv->pattern_id > priv->max_pattern)
112                 return;
113
114         fprintf(priv->f,
115                 "  graph: { title: \"g%u\" label: \"pattern %u\" status:clustered color:yellow\n",
116                 priv->pattern_id, priv->pattern_id );
117
118         /* add a pseudo node for the count of this pattern */
119         fprintf(priv->f,
120                 "    node: {title: \"c%u\" label: \"cnt: %u\" color:red }\n",
121                 ++nr, cnt_to_uint(cnt)
122         );
123 }  /* vcg_dump_new_pattern */
124
125 /**
126  * Finish the current pattern.
127  */
128 static void vcg_dump_finish_pattern(pattern_dumper_t *self)
129 {
130         vcg_private_t *priv = self->data;
131
132         if (priv->pattern_id > priv->max_pattern)
133                 return;
134
135         fprintf(priv->f, "  }\n");
136
137         if (priv->pattern_id > 0)
138                 fprintf(priv->f, "  edge: { sourcename: \"g%u\" targetname: \"g%u\" linestyle:invisible}\n",
139                         priv->pattern_id,
140                         priv->pattern_id - 1);
141
142         ++priv->pattern_id;
143 }  /* vcg_dump_finish_pattern */
144
145 /**
146  * Dumps a node.
147  */
148 static void vcg_dump_node(pattern_dumper_t *self, unsigned id,
149     unsigned op_code, unsigned mode_code, void *attr)
150 {
151         vcg_private_t *priv = self->data;
152         ir_op *op           = stat_get_op_from_opcode(op_code);
153         ir_mode *mode       = get_irp_mode(mode_code);
154         long l              = attr ? *(long *)attr : 0;
155
156         if (priv->pattern_id > priv->max_pattern)
157                 return;
158
159         if (attr) {
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);
162         } else {
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);
165         }  /* if */
166 }  /* vcg_dump_node */
167
168 /**
169  * Dumps an edge.
170  */
171 static void vcg_dump_edge(pattern_dumper_t *self, unsigned tgt, unsigned src, unsigned pos, unsigned mode_code)
172 {
173         vcg_private_t *priv = self->data;
174         (void) mode_code;
175
176         if (priv->pattern_id > priv->max_pattern)
177                 return;
178
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,
182                 pos
183         );
184 }  /* vcg_dump_edge */
185
186 /**
187  * The VCG dumper.
188  */
189 static pattern_dumper_t vcg_dump = {
190         vcg_dump_new_pattern,
191         vcg_dump_finish_pattern,
192         vcg_dump_node,
193         NULL,
194         vcg_dump_edge,
195         NULL,
196         NULL,
197         vcg_dump_start,
198         vcg_dump_end,
199         NULL
200 };
201
202 /**
203  * Starts a new pattern.
204  */
205 static void stdout_dump_new_pattern(pattern_dumper_t *self, counter_t *cnt)
206 {
207         FILE *f = self->data;
208
209         fprintf(f, "%8u ", cnt_to_uint(cnt));
210 }  /* stdout_dump_new_pattern */
211
212
213 /**
214  * Finish the current pattern.
215  */
216 static void stdout_dump_finish_pattern(pattern_dumper_t *self)
217 {
218         FILE *f = self->data;
219
220         fprintf(f, "\n");
221 }  /* stdout_dump_finish_pattern */
222
223 /**
224  * Dumps a node.
225  */
226 static void stdout_dump_node(pattern_dumper_t *self, unsigned id, unsigned op_code, unsigned mode_code, void *attr)
227 {
228         FILE *f       = self->data;
229         ir_op *op     = stat_get_op_from_opcode(op_code);
230         ir_mode *mode = get_irp_mode(mode_code);
231         (void) attr;
232
233         /* if (env->options & OPT_ENC_GRAPH) */
234         fprintf(f, "%u:", id);
235
236         fprintf(f, "%s", get_id_str(op->name));
237
238         if (mode)
239                 fprintf(f, "%s", get_mode_name(mode));
240 }  /* stdout_dump_node */
241
242 /**
243  * Dump a ref
244  */
245 static void stdout_dump_ref(pattern_dumper_t *self, unsigned id)
246 {
247         FILE *f = self->data;
248
249         fprintf(f, "REF:%u", id);
250 }  /* stdout_dump_ref */
251
252 /**
253  * Dump an edge.
254  */
255 static void stdout_dump_edge(pattern_dumper_t *self, unsigned tgt, unsigned src, unsigned pos, unsigned mode_code)
256 {
257         FILE *f = self->data;
258         (void) tgt;
259         (void) src;
260         (void) pos;
261         (void) mode_code;
262
263         if (pos > 0)
264                 fprintf(f, ", ");
265 }  /* stdout_dump_edge */
266
267 /**
268  * Start the children dumper.
269  */
270 static void stdout_start_children(pattern_dumper_t *self, unsigned id)
271 {
272         FILE *f = self->data;
273         (void) id;
274
275         fprintf(f, "(");
276 }  /* stdout_start_children */
277
278 /**
279  * Finish the children dumper.
280  */
281 static void stdout_finish_children(pattern_dumper_t *self, unsigned id)
282 {
283         FILE *f = self->data;
284         (void) id;
285
286         fprintf(f, ")");
287 }  /* stdout_finish_children */
288
289 /**
290  * The stdout dumper.
291  */
292 static const pattern_dumper_t stdout_dump = {
293         stdout_dump_new_pattern,
294         stdout_dump_finish_pattern,
295         stdout_dump_node,
296         stdout_dump_ref,
297         stdout_dump_edge,
298         stdout_start_children,
299         stdout_finish_children,
300         NULL,
301         NULL,
302         NULL
303 };
304
305 /* ------------------------------------ API ------------------------------------- */
306
307 /*
308  * Starts a new pattern.
309  */
310 void pattern_dump_new_pattern(pattern_dumper_t *self, counter_t *cnt)
311 {
312         if (self->dump_new_pattern)
313                 self->dump_new_pattern(self, cnt);
314 }  /* pattern_dump_new_pattern */
315
316
317 /*
318  * Finish the current pattern.
319  */
320 void pattern_dump_finish_pattern(pattern_dumper_t *self)
321 {
322         if (self->dump_finish_pattern)
323                 self->dump_finish_pattern(self);
324 }  /* pattern_dump_finish_pattern */
325
326
327 /*
328  * Dumps a node.
329  */
330 void pattern_dump_node(pattern_dumper_t *self, unsigned id, unsigned op_code, unsigned mode_code, void *attr)
331 {
332         if (self->dump_node)
333                 self->dump_node(self, id, op_code, mode_code, attr);
334 }  /* pattern_dump_node */
335
336 /*
337  * Dump a ref.
338  */
339 void pattern_dump_ref(pattern_dumper_t *self, unsigned id)
340 {
341         if (self->dump_ref)
342                 self->dump_ref(self, id);
343 }  /* pattern_dump_ref */
344
345 /*
346  * Dump an edge.
347  */
348 void pattern_dump_edge(pattern_dumper_t *self, unsigned tgt, unsigned src, unsigned pos, unsigned mode_code)
349 {
350         if (self->dump_edge)
351                 self->dump_edge(self, tgt, src, pos, mode_code);
352 }  /* pattern_dump_edge */
353
354 /*
355  * Start the children dumper.
356  */
357 void pattern_start_children(pattern_dumper_t *self, unsigned id)
358 {
359         if (self->dump_start_children)
360                 self->dump_start_children(self, id);
361 }  /* pattern_start_children */
362
363 /*
364  * Finish the the children dumper.
365  */
366 void pattern_finish_children(pattern_dumper_t *self, unsigned id)
367 {
368         if (self->dump_finish_children)
369                 self->dump_finish_children(self, id);
370 }  /* pattern_finish_children */
371
372 /*
373  * Finish the the dumper.
374  */
375 void pattern_end(pattern_dumper_t *self)
376 {
377         if (self->dump_end)
378                 self->dump_end(self);
379
380         free(self);
381 }  /* pattern_end */
382
383 /**
384  * pattern dumper factory for text dumper
385  */
386 pattern_dumper_t *new_text_dumper(void)
387 {
388         pattern_dumper_t *res = malloc(sizeof(*res));
389
390         if (res) {
391                 memcpy(res, &stdout_dump, sizeof(*res));
392                 res->data = stdout;
393
394                 if (res->dump_start)
395                         res->dump_start(res);
396         }  /* if */
397         return res;
398 }  /* new_text_dumper */
399
400 /**
401  * pattern dumper factory for vcg dumper
402  */
403 pattern_dumper_t *new_vcg_dumper(const char *vcg_name, unsigned max_pattern)
404 {
405         pattern_dumper_t *res = malloc(sizeof(*res) + sizeof(vcg_private_t));
406         vcg_private_t *priv;
407
408         if (res) {
409                 FILE *f;
410
411                 memcpy(res, &vcg_dump, sizeof(*res));
412
413                 priv = (vcg_private_t *)(res + 1);
414                 memset(priv, 0, sizeof(*priv));
415
416                 f = fopen(vcg_name, "w");
417                 priv->f           = f;
418                 priv->pattern_id  = 0;
419                 priv->max_pattern = max_pattern ? max_pattern : (unsigned)-1;
420                 res->data         = priv;
421
422                 if (res->dump_start)
423                         res->dump_start(res);
424         }  /* if */
425
426         return res;
427 }  /* new_vcg_dumper */
428
429 #endif /* FIRM_STATISTICS */