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