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