Fixed warnings
[libfirm] / ir / stat / pattern_dmp.c
1 /*
2  * Copyright (C) 1995-2007 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 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #include <stdio.h>
31 #ifdef HAVE_STDLIB_H
32 # include <stdlib.h>
33 #endif
34
35 #include "ident.h"
36 #include "irop_t.h"
37 #include "irmode.h"
38 #include "firmstat_t.h"
39 #include "pattern_dmp.h"
40
41 /* dumper operations */
42 typedef void (*DUMP_NEW_PATTERN_FUNC)(pattern_dumper_t *self, counter_t *cnt);
43 typedef void (*DUMP_FINISH_PATTERN_FUNC)(pattern_dumper_t *self);
44 typedef void (*DUMP_NODE_FUNC)(pattern_dumper_t *self, unsigned id, unsigned op_code, unsigned mode_code, void *attr);
45 typedef void (*DUMP_REF_FUNC)(pattern_dumper_t *self, unsigned id);
46 typedef void (*DUMP_EDGE_FUNC)(pattern_dumper_t *self, unsigned tgt, unsigned src, unsigned pos, unsigned mode_code);
47 typedef void (*DUMP_START_CHILDREN_FUNC)(pattern_dumper_t *self, unsigned id);
48 typedef void (*DUMP_FINISH_CHILDREN_FUNC)(pattern_dumper_t *self, unsigned id);
49 typedef void (*DUMP_START_FUNC)(pattern_dumper_t *self);
50 typedef void (*DUMP_END_FUNC)(pattern_dumper_t *self);
51
52 /**
53  * the pattern dumper
54  */
55 struct _pattern_dumper_t {
56         DUMP_NEW_PATTERN_FUNC      dump_new_pattern;
57         DUMP_FINISH_PATTERN_FUNC   dump_finish_pattern;
58         DUMP_NODE_FUNC             dump_node;
59         DUMP_REF_FUNC              dump_ref;
60         DUMP_EDGE_FUNC             dump_edge;
61         DUMP_START_CHILDREN_FUNC   dump_start_children;
62         DUMP_FINISH_CHILDREN_FUNC  dump_finish_children;
63         DUMP_START_FUNC            dump_start;
64         DUMP_END_FUNC              dump_end;
65         void                       *data;
66 };
67
68 /**
69  * VCG private data
70  */
71 typedef struct _vcg_private_t {
72         FILE     *f;          /**< file to dump to */
73         unsigned pattern_id;  /**< ID of the pattern */
74         unsigned max_pattern; /**< maximum number of pattern to be dumped */
75 } vcg_private_t;
76
77 /**
78  * Starts a new VCG graph.
79  */
80 static void vcg_dump_start(pattern_dumper_t *self)
81 {
82         vcg_private_t *priv = self->data;
83
84         fprintf(priv->f,
85                 "graph: { title: \"Most found pattern\"\n"
86                 "  display_edge_labels: no\n"
87                 "  layoutalgorithm: mindepth\n"
88                 "  manhattan_edges: yes\n"
89                 "  port_sharing: no\n"
90                 "  orientation: bottom_to_top\n"
91                 );
92 }  /* vcg_dump_start */
93
94 /**
95  * Ends a new VCG graph.
96  */
97 static void vcg_dump_end(pattern_dumper_t *self)
98 {
99         vcg_private_t *priv = self->data;
100
101         fprintf(priv->f, "}\n");
102         fclose(priv->f);
103 }  /* vcg_dump_end */
104
105 /**
106  * Starts a new pattern.
107  */
108 static void vcg_dump_new_pattern(pattern_dumper_t *self, counter_t *cnt)
109 {
110         vcg_private_t *priv = self->data;
111         static unsigned nr = 0;
112
113         if (priv->pattern_id > priv->max_pattern)
114                 return;
115
116         fprintf(priv->f,
117                 "  graph: { title: \"g%u\" label: \"pattern %u\" status:clustered color:yellow\n",
118                 priv->pattern_id, priv->pattern_id );
119
120         /* add a pseudo node for the count of this pattern */
121         fprintf(priv->f,
122                 "    node: {title: \"c%u\" label: \"cnt: %u\" color:red }\n",
123                 ++nr, cnt_to_uint(cnt)
124         );
125 }  /* vcg_dump_new_pattern */
126
127 /**
128  * Finish the current pattern.
129  */
130 static void vcg_dump_finish_pattern(pattern_dumper_t *self)
131 {
132         vcg_private_t *priv = self->data;
133
134         if (priv->pattern_id > priv->max_pattern)
135                 return;
136
137         fprintf(priv->f, "  }\n");
138
139         if (priv->pattern_id > 0)
140                 fprintf(priv->f, "  edge: { sourcename: \"g%u\" targetname: \"g%u\" linestyle:invisible}\n",
141                         priv->pattern_id,
142                         priv->pattern_id - 1);
143
144         ++priv->pattern_id;
145 }  /* vcg_dump_finish_pattern */
146
147 /**
148  * Dumps a node.
149  */
150 static void vcg_dump_node(pattern_dumper_t *self, unsigned id,
151     unsigned op_code, unsigned mode_code, void *attr)
152 {
153         vcg_private_t *priv = self->data;
154         ir_op *op           = stat_get_op_from_opcode(op_code);
155         ir_mode *mode       = (ir_mode *)mode_code;
156         long l              = attr ? *(long *)attr : 0;
157
158         if (priv->pattern_id > priv->max_pattern)
159                 return;
160
161         if (attr) {
162                 fprintf(priv->f, "    node: {title: \"n%u_%u\" label: \"%s%s %ld n%u\" }\n",
163                         priv->pattern_id, id, get_id_str(op->name), mode ? get_mode_name(mode) : "", l, id);
164         } else {
165                 fprintf(priv->f, "    node: {title: \"n%u_%u\" label: \"%s%s n%u\" }\n",
166                         priv->pattern_id, id, get_id_str(op->name), mode ? get_mode_name(mode) : "", id);
167         }  /* if */
168 }  /* vcg_dump_node */
169
170 /**
171  * Dumps an edge.
172  */
173 static void vcg_dump_edge(pattern_dumper_t *self, unsigned tgt, unsigned src, unsigned pos, unsigned mode_code)
174 {
175         vcg_private_t *priv = self->data;
176
177         if (priv->pattern_id > priv->max_pattern)
178                 return;
179
180         fprintf(priv->f, "    edge: { sourcename: \"n%u_%u\" targetname: \"n%u_%u\" label: \"%u\" }\n",
181                 priv->pattern_id, src,
182                 priv->pattern_id, tgt,
183                 pos
184         );
185 }  /* vcg_dump_edge */
186
187 /**
188  * The VCG dumper.
189  */
190 static pattern_dumper_t vcg_dump = {
191         vcg_dump_new_pattern,
192         vcg_dump_finish_pattern,
193         vcg_dump_node,
194         NULL,
195         vcg_dump_edge,
196         NULL,
197         NULL,
198         vcg_dump_start,
199         vcg_dump_end,
200         NULL
201 };
202
203 /**
204  * Starts a new pattern.
205  */
206 static void stdout_dump_new_pattern(pattern_dumper_t *self, counter_t *cnt)
207 {
208         FILE *f = self->data;
209
210         fprintf(f, "%8u ", cnt_to_uint(cnt));
211 }  /* stdout_dump_new_pattern */
212
213
214 /**
215  * Finish the current pattern.
216  */
217 static void stdout_dump_finish_pattern(pattern_dumper_t *self)
218 {
219         FILE *f = self->data;
220
221         fprintf(f, "\n");
222 }  /* stdout_dump_finish_pattern */
223
224 /**
225  * Dumps a node.
226  */
227 static void stdout_dump_node(pattern_dumper_t *self, unsigned id, unsigned op_code, unsigned mode_code, void *attr)
228 {
229         FILE *f       = self->data;
230         ir_op *op     = stat_get_op_from_opcode(op_code);
231         ir_mode *mode = (ir_mode *)mode_code;
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
259         if (pos > 0)
260                 fprintf(f, ", ");
261 }  /* stdout_dump_edge */
262
263 /**
264  * Start the children dumper.
265  */
266 static void stdout_start_children(pattern_dumper_t *self, unsigned id)
267 {
268         FILE *f = self->data;
269
270         fprintf(f, "(");
271 }  /* stdout_start_children */
272
273 /**
274  * Finish the children dumper.
275  */
276 static void stdout_finish_children(pattern_dumper_t *self, unsigned id)
277 {
278         FILE *f = self->data;
279
280         fprintf(f, ")");
281 }  /* stdout_finish_children */
282
283 /**
284  * The stdout dumper.
285  */
286 static const pattern_dumper_t stdout_dump = {
287         stdout_dump_new_pattern,
288         stdout_dump_finish_pattern,
289         stdout_dump_node,
290         stdout_dump_ref,
291         stdout_dump_edge,
292         stdout_start_children,
293         stdout_finish_children,
294         NULL,
295         NULL,
296         NULL
297 };
298
299 /* ------------------------------------ API ------------------------------------- */
300
301 /*
302  * Starts a new pattern.
303  */
304 void pattern_dump_new_pattern(pattern_dumper_t *self, counter_t *cnt)
305 {
306         if (self->dump_new_pattern)
307                 self->dump_new_pattern(self, cnt);
308 }  /* pattern_dump_new_pattern */
309
310
311 /*
312  * Finish the current pattern.
313  */
314 void pattern_dump_finish_pattern(pattern_dumper_t *self)
315 {
316         if (self->dump_finish_pattern)
317                 self->dump_finish_pattern(self);
318 }  /* pattern_dump_finish_pattern */
319
320
321 /*
322  * Dumps a node.
323  */
324 void pattern_dump_node(pattern_dumper_t *self, unsigned id, unsigned op_code, unsigned mode_code, void *attr)
325 {
326         if (self->dump_node)
327                 self->dump_node(self, id, op_code, mode_code, attr);
328 }  /* pattern_dump_node */
329
330 /*
331  * Dump a ref.
332  */
333 void pattern_dump_ref(pattern_dumper_t *self, unsigned id)
334 {
335         if (self->dump_ref)
336                 self->dump_ref(self, id);
337 }  /* pattern_dump_ref */
338
339 /*
340  * Dump an edge.
341  */
342 void pattern_dump_edge(pattern_dumper_t *self, unsigned tgt, unsigned src, unsigned pos, unsigned mode_code)
343 {
344         if (self->dump_edge)
345                 self->dump_edge(self, tgt, src, pos, mode_code);
346 }  /* pattern_dump_edge */
347
348 /*
349  * Start the children dumper.
350  */
351 void pattern_start_children(pattern_dumper_t *self, unsigned id)
352 {
353         if (self->dump_start_children)
354                 self->dump_start_children(self, id);
355 }  /* pattern_start_children */
356
357 /*
358  * Finish the the children dumper.
359  */
360 void pattern_finish_children(pattern_dumper_t *self, unsigned id)
361 {
362         if (self->dump_finish_children)
363                 self->dump_finish_children(self, id);
364 }  /* pattern_finish_children */
365
366 /*
367  * Finish the the dumper.
368  */
369 void pattern_end(pattern_dumper_t *self)
370 {
371         if (self->dump_end)
372                 self->dump_end(self);
373
374         free(self);
375 }  /* pattern_end */
376
377 /**
378  * pattern dumper factory for text dumper
379  */
380 pattern_dumper_t *new_text_dumper(void)
381 {
382         pattern_dumper_t *res = malloc(sizeof(*res));
383
384         if (res) {
385                 memcpy(res, &stdout_dump, sizeof(*res));
386                 res->data = stdout;
387
388                 if (res->dump_start)
389                         res->dump_start(res);
390         }  /* if */
391         return res;
392 }  /* new_text_dumper */
393
394 /**
395  * pattern dumper factory for vcg dumper
396  */
397 pattern_dumper_t *new_vcg_dumper(const char *vcg_name, unsigned max_pattern)
398 {
399         pattern_dumper_t *res = malloc(sizeof(*res) + sizeof(vcg_private_t));
400         vcg_private_t *priv;
401
402         if (res) {
403                 FILE *f;
404
405                 memcpy(res, &vcg_dump, sizeof(*res));
406
407                 priv = (vcg_private_t *)(res + 1);
408                 memset(priv, 0, sizeof(*priv));
409
410                 f = fopen(vcg_name, "w");
411                 priv->f           = f;
412                 priv->pattern_id  = 0;
413                 priv->max_pattern = max_pattern ? max_pattern : (unsigned)-1;
414                 res->data         = priv;
415
416                 if (res->dump_start)
417                         res->dump_start(res);
418         }  /* if */
419
420         return res;
421 }  /* new_vcg_dumper */