f862ab8f2ba052b3478ace9f74ed8f6761bd9200
[libfirm] / ir / ir / irdump.c
1 /* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
2 ** All rights reserved.
3 **
4 ** Authors: Martin Trapp, Christian Schaefer
5 **
6 ** irdump.h: dumping of an intermediate representation graph
7 */
8
9 # include <assert.h>
10 # include "irdump.h"
11 # include "panic.h"
12 # include <string.h>
13 # include "entity.h"
14 # include <stdlib.h>
15 # include "array.h"
16 # include "irop.h"
17 # include "tv.h"
18 # include "type_or_entity.h"
19 # include "irgwalk.h"
20 # include "typewalk.h"
21
22 #define DEFAULT_NODE_ATTR ""
23 #define BLOCK_EDGE_ATTR "class: 2 priority: 2 linestyle: dotted"
24 #define NODE2TYPE_EDGE_ATTR ""
25 #define DEFAULT_TYPE_ATTRIBUTE ""
26 #define TYPE_EDGE_ATTR ""
27
28 /* file to dump to */
29 static FILE *F;
30
31
32 /*******************************************************************/
33 /* routines to dump information about a single node                */
34 /*******************************************************************/
35
36 void
37 dump_ir_node (ir_node *n)
38 {
39   /* dump this node */
40   xfprintf (F, "node: {title: \"%p\" label: ", n);
41
42   switch (n->op->code) {  /* node label */
43   case iro_Start:
44     xfprintf (F, "\"%I\" color: blue ", n->op->name);
45     xfprintf (F, DEFAULT_NODE_ATTR);
46      break;
47   case iro_End:
48     xfprintf (F, "\"%I\" color: blue ", n->op->name);
49     xfprintf (F, DEFAULT_NODE_ATTR);
50     break;
51   case iro_Block:
52     xfprintf (F, "\"%I\" color: lightyellow ", n->op->name);
53     xfprintf (F, DEFAULT_NODE_ATTR);
54     break;
55   case iro_Phi:
56     xfprintf (F, "\"%I%I\" color: green", n->op->name, n->mode->name);
57     if (n->mode->code == irm_M)
58       xfprintf (F, DEFAULT_NODE_ATTR " color: green");
59     else
60       xfprintf (F, DEFAULT_NODE_ATTR);
61     break;
62   case iro_Const:
63     xfprintf (F, "\"%v%I\" color: yellow ", n->attr.con, n->mode->name);
64     xfprintf (F, DEFAULT_NODE_ATTR);
65     break;
66   case iro_Id:
67     xfprintf (F, "\"%I%I\" ", n->op->name, n->mode->name);
68     xfprintf (F, DEFAULT_NODE_ATTR);
69     break;
70   case iro_Proj:
71     if (n->in[1]->op->code == iro_Cmp) {
72       xfprintf (F, "\"%I%I %s\" color: yellow", n->op->name, n->mode->name,
73                 get_pnc_string(n->attr.proj));
74     } else {
75       xfprintf (F, "\"%I%I %ld\"", n->op->name, n->mode->name, n->attr.proj);
76     }
77     xfprintf (F, DEFAULT_NODE_ATTR);
78     break;
79   case iro_Conv:
80     xfprintf (F, "\"%I%I\"", n->op->name, n->mode->name);
81     xfprintf (F, DEFAULT_NODE_ATTR);
82     break;
83   case iro_Tuple:
84     xfprintf (F, "\"%I%I\"", n->op->name, n->mode->name);
85     xfprintf (F, DEFAULT_NODE_ATTR);
86     break;
87   case iro_Add:
88     xfprintf (F, "\"%I%I\"", n->op->name, n->mode->name);
89     xfprintf (F, DEFAULT_NODE_ATTR);
90     break;
91   case iro_Sub:
92     xfprintf (F, "\"%I%I\"", n->op->name, n->mode->name);
93     xfprintf (F, DEFAULT_NODE_ATTR);
94     break;
95   case iro_Mul:
96     xfprintf (F, "\"%I%I\"", n->op->name, n->mode->name);
97     xfprintf (F, DEFAULT_NODE_ATTR);
98     break;
99   case iro_Quot:
100     xfprintf (F, "\"%I%I\"", n->op->name, n->mode->name);
101     xfprintf (F, DEFAULT_NODE_ATTR);
102     break;
103   case iro_DivMod:
104     xfprintf (F, "\"%I%I\"", n->op->name, n->mode->name);
105     xfprintf (F, DEFAULT_NODE_ATTR);
106     break;
107   case iro_Div:
108     xfprintf (F, "\"%I%I\"", n->op->name, n->mode->name);
109     xfprintf (F, DEFAULT_NODE_ATTR);
110     break;
111   case iro_Mod:
112     xfprintf (F, "\"%I%I\"", n->op->name, n->mode->name);
113     xfprintf (F, DEFAULT_NODE_ATTR);
114     break;
115   case iro_And:
116     xfprintf (F, "\"%I%I\"", n->op->name, n->mode->name);
117     xfprintf (F, DEFAULT_NODE_ATTR);
118     break;
119   case iro_Or:
120     xfprintf (F, "\"%I%I\"", n->op->name, n->mode->name);
121     xfprintf (F, DEFAULT_NODE_ATTR);
122     break;
123   case iro_Eor:
124     xfprintf (F, "\"%I%I\"", n->op->name, n->mode->name);
125     xfprintf (F, DEFAULT_NODE_ATTR);
126     break;
127   case iro_Shl:
128     xfprintf (F, "\"%I%I\"", n->op->name, n->mode->name);
129     xfprintf (F, DEFAULT_NODE_ATTR);
130     break;
131   case iro_Shr:
132     xfprintf (F, "\"%I%I\"", n->op->name, n->mode->name);
133     xfprintf (F, DEFAULT_NODE_ATTR);
134     break;
135   case iro_Abs:
136     xfprintf (F, "\"%I%I\"", n->op->name, n->mode->name);
137     xfprintf (F, DEFAULT_NODE_ATTR);
138     break;
139   case iro_Cmp:
140     xfprintf (F, "\"%I%I\"", n->op->name, n->mode->name);
141     xfprintf (F, DEFAULT_NODE_ATTR);
142     break;
143   case iro_Jmp:
144     xfprintf (F, "\"%I\"", n->op->name);
145     xfprintf (F, DEFAULT_NODE_ATTR);
146     break;
147   case iro_Cond:
148     xfprintf (F, "\"%I\"", n->op->name);
149     xfprintf (F, DEFAULT_NODE_ATTR);
150     break;
151   case iro_Call:
152     xfprintf (F, "\"%I\"", n->op->name);
153     xfprintf (F, DEFAULT_NODE_ATTR);
154     break;
155   case iro_Return:
156     xfprintf (F, "\"%I\"", n->op->name);
157     xfprintf (F, DEFAULT_NODE_ATTR);
158     break;
159   case iro_Raise:
160     xfprintf (F, "\"%I%I\"", n->op->name, n->mode->name);
161     xfprintf (F, DEFAULT_NODE_ATTR);
162     break;
163   case iro_Load:
164   case iro_Store:
165     xfprintf (F, "\"%R\"", n);
166     xfprintf (F, DEFAULT_NODE_ATTR);
167     break;
168   case iro_Alloc:
169     xfprintf (F, "\"%I\" ", n->op->name);
170     xfprintf (F, DEFAULT_NODE_ATTR);
171     break;
172   case iro_Sel:
173     assert(n->attr.s.ent->kind == k_entity);
174     xfprintf (F, "\"%I ", n->op->name);
175     xfprintf (F, "%s\" ", id_to_str(n->attr.s.ent->name));
176     /*  xdoesn't work for some reason.
177         fprintf (F, "\"%I %I\" ", n->op->name, n->attr.s.ent); */
178     xfprintf (F, DEFAULT_NODE_ATTR);
179     break;
180   case iro_SymConst:
181     assert(get_kind(get_SymConst_type(n)) == k_type_class);
182     /* assert(n->attr.i.type->kind == k_type_class); */
183     assert(get_class_ident((type_class *)get_SymConst_type(n)));
184     /* assert(n->attr.i.type->clss->name); */
185     xfprintf (F, "\"%s ", id_to_str(get_class_ident((type_class *)get_SymConst_type(n))));
186     /* xfprintf (F, "\"%s ", id_to_str(n->attr.i.type->name)); */
187     /* doesn't work for some reason. */
188     /* xfprintf (F, "\"%N\" ", n->attr.i.type); */
189     switch (n->attr.i.num){
190     case type_tag:
191       xfprintf (F, "tag\" ");
192       break;
193     case size:
194       xfprintf (F, "size\" ");
195       break;
196     default:
197       assert(0);
198       break;
199     }
200     xfprintf (F, DEFAULT_NODE_ATTR);
201     break;
202   case iro_Sync:
203     xfprintf (F, "\"%I\" ", n->op->name);
204     xfprintf (F, DEFAULT_NODE_ATTR " color: green");
205     break;
206   case iro_Bad:
207     xfprintf (F, "\"%I%I\" ", n->op->name, n->mode->name);
208     xfprintf (F, DEFAULT_NODE_ATTR);
209     break;
210   default:
211     xfprintf (F, "\"%I%I\" ", n->op->name, n->mode->name);
212   }
213   xfprintf (F, "}\n");          /* footer */
214 }
215
216
217 /* dump the edge to the block this node belongs to */
218 void
219 dump_ir_block_edge(ir_node *n)  {
220   if (is_no_Block(n))
221     xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
222                 BLOCK_EDGE_ATTR "}\n", n, get_nodes_Block(n));
223 }
224
225
226 /* dump edges to our inputs */
227 void
228 dump_ir_data_edges(ir_node *n)  {
229   int i;
230
231   for (i = 0; i < get_irn_arity(n); i++) {
232     assert(get_irn_n(n, i));
233     xfprintf (F, "edge: {sourcename: \"%p\" targetname: \"%p\"",
234               n, get_irn_n(n, i));
235     fprintf (F, " label: \"%d\"", i+1);
236     fprintf (F, "}\n");
237   }
238 }
239
240 /* dumps the edges between nodes and their type or entity attributes. */
241 void dump_node2type_edges (ir_node *n, void *env)
242 {
243   assert(n);
244
245   switch (get_irn_opcode(n)) {
246   case iro_SymConst:
247     if (   (get_SymConst_kind(n) == type_tag)
248         || (get_SymConst_kind(n) == size))
249       xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
250                 NODE2TYPE_EDGE_ATTR "}\n", n, get_SymConst_type(n));
251     break;
252   case iro_Sel:
253     xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
254               NODE2TYPE_EDGE_ATTR "}\n", n, get_Sel_entity(n));
255     break;
256   case iro_Call:
257     xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
258               NODE2TYPE_EDGE_ATTR "}\n", n, get_Call_type(n));
259     break;
260   case iro_Alloc:
261     xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
262               NODE2TYPE_EDGE_ATTR "}\n", n, get_Alloc_type(n));
263     break;
264   case iro_Free:
265     printf(" in irdum\n");
266     xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
267               NODE2TYPE_EDGE_ATTR "}\n", n, get_Free_type(n));
268     break;
269   default:
270     break;
271   }
272 }
273
274
275 /* dumps a type or entity and it's edges. */
276 void
277 dump_type_info (type_or_ent *tore, void *env) {
278   int i = 0;  /* to shutup gcc */
279
280   /* dump this type or entity */
281   xfprintf (F, "node: {title: \"%p\" ", tore);
282   xfprintf (F, DEFAULT_TYPE_ATTRIBUTE);
283   xfprintf (F, "label: ");
284
285   switch (get_kind(tore)) {
286   case k_entity:
287     {
288       entity *ent = (entity *)tore;
289       xfprintf (F, "\"ent %I\"}\n", get_entity_ident(ent));
290       xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
291                 " label: \"owner\" "
292                 TYPE_EDGE_ATTR "}\n", tore, get_entity_owner(ent));
293       xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
294                 " label: \"type\" "
295                 TYPE_EDGE_ATTR "}\n", tore, get_entity_type(ent));
296     }
297     break;
298   case k_type_class:
299     {
300       type_class *type = (type_class *)tore;
301       xfprintf (F, "\"class %I\"}\n", get_class_ident(type));
302       /* edges !!!??? */
303     }
304     break;
305   case k_type_strct:
306     {
307       type_strct *type = (type_strct *)tore;
308       xfprintf (F, "\"strct %I\"}\n", get_strct_ident(type));
309       /* edges !!!??? */
310     }
311     break;
312   case k_type_method:
313     {
314       type_method *type = (type_method *)tore;
315       xfprintf (F, "\"meth %I\"}\n", get_method_ident(type));
316       for (i = 0; i < get_method_arity(type); i++)
317         xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
318                   " label: \"param %d\" " TYPE_EDGE_ATTR "}\n",
319                   tore, get_method_param_type(type, i), i);
320       for (i = 0; i < get_method_n_res(type); i++)
321         xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
322                   " label: \"res %d\" " TYPE_EDGE_ATTR "}\n",
323                   tore, get_method_res_type(type, i), i);
324     }
325     break;
326   case k_type_union:
327     {
328       type_union *type = (type_union *)tore;
329       xfprintf (F, "\"union %I\"}\n", get_union_ident(type));
330       /* edges !!!??? */
331     }
332     break;
333   case k_type_array:
334     {
335       type_array *type = (type_array *)tore;
336       xfprintf (F, "\"array %I\"}\n", get_array_ident(type));
337       xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
338                 TYPE_EDGE_ATTR "}\n", tore, get_array_element_type(type), i);
339     }
340     break;
341   case k_type_enumeration:
342     {
343       type_enumeration *type = (type_enumeration *)tore;
344       xfprintf (F, "\"enum %I\"}\n", get_enumeration_ident(type));
345     }
346     break;
347   case k_type_pointer:
348     {
349       type_pointer *type = (type_pointer *)tore;
350       xfprintf (F, "\"ptr %I\"}\n", get_pointer_ident(type));
351       xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
352                 TYPE_EDGE_ATTR "}\n", tore,
353                 get_pointer_points_to_type(type), i);
354     }
355     break;
356   case k_type_primitive:
357     {
358       type_primitive *type = (type_primitive *)tore;
359       xfprintf (F, "\"prim %I, mode %I\"}\n", get_primitive_ident(type),
360                 get_mode_ident(get_primitive_mode(type)));
361     }
362     break;
363   default:
364     break;
365   }
366
367 }
368
369 /************************************************************************/
370 /* open and close vcg file                                              */
371 /************************************************************************/
372
373 void vcg_open (ir_graph *irg, char *suffix) {
374   char *fname;  /* filename to put the vcg information in */
375   const char *cp;
376   ident *id;
377   int len;
378
379   /** open file for vcg graph */
380   id    = get_entity_ld_name (irg->ent);
381
382   len   = id_to_strlen (id);
383   cp    = id_to_str (id);
384   fname = malloc (len + 5 + strlen(suffix));
385   strcpy (fname, cp);      /* copy the filename */
386   strcat (fname, suffix);  /* append file suffix */
387   strcat (fname, ".vcg");  /* append the .vcg suffix */
388
389   F = fopen (fname, "w");  /* open file for writing */
390   if (!F) {
391     panic ("cannot open %s for writing (%m)", fname);  /* not reached */
392   }
393
394   /* print header */
395   xfprintf (F,
396             "graph: { title: \"ir graph of %s\"\n"
397             "display_edge_labels: yes\n"
398             "layoutalgorithm: mindepth\n"
399             "manhattan_edges: yes\n"
400             "port_sharing: no\n"
401             "orientation: bottom_to_top\n"
402             "classname 1: \"Data\"\n"
403             "classname 2: \"Block\"\n", cp);
404
405   xfprintf (F, "\n");           /* a separator */
406 }
407
408 void
409 vcg_close () {
410   xfprintf (F, "}\n");  /* print footer */
411   fclose (F);           /* close vcg file */
412 }
413
414
415
416 /************************************************************************/
417 /* routines to dump a graph, blocks as conventional nodes.              */
418 /************************************************************************/
419
420 void
421 dump_whole_node (ir_node *n, void* env) {
422   dump_ir_node(n);
423   dump_ir_block_edge(n);
424   dump_ir_data_edges(n);
425 }
426
427 void
428 dump_ir_graph (ir_graph *irg)
429 {
430   vcg_open (irg, "");
431
432   /* walk over the graph */
433   irg_walk(irg->end, dump_whole_node, NULL, NULL);
434
435   vcg_close();
436 }
437
438 /***********************************************************************/
439 /* the following routines dump the nodes as attached to the blocks.    */
440 /***********************************************************************/
441
442 void
443 dump_ir_blocks_nodes (ir_node *n, void *env) {
444   ir_node *block = (ir_node *)env;
445
446   if (is_no_Block(n) && get_nodes_Block(n) == block) {
447     dump_ir_node(n);
448     dump_ir_data_edges(n);
449   }
450 }
451
452
453 void
454 dump_ir_block (ir_node *block, void *env) {
455   ir_graph *irg = (ir_graph *)env;
456
457   if (get_irn_opcode(block) == iro_Block) {
458     /* This is a block. So dump the vcg information to make a block. */
459     xfprintf(F, "graph: { title: \"%p\" status:clustered color:lightyellow \n",
460              block);
461     /* dump the blocks edges */
462     dump_ir_data_edges(block);
463
464     /* dump the nodes that go into the block */
465     irg_walk(irg->end, dump_ir_blocks_nodes, NULL, block);
466
467     /* Close the vcg information for the block */
468     xfprintf(F, "}\n\n");
469   }
470 }
471
472 void
473 dump_ir_block_graph (ir_graph *irg)
474 {
475   vcg_open (irg, "");
476
477   /* walk over the blocks in the graph */
478   irg_block_walk(irg->end, dump_ir_block, NULL, irg);
479
480   vcg_close();
481 }
482
483
484 /***********************************************************************/
485 /* the following routines dump a control flow graph                    */
486 /***********************************************************************/
487
488
489 void
490 dump_block_to_cfg (ir_node *block, void *env) {
491   int i;
492   ir_node *pred;
493
494   if (get_irn_opcode(block) == iro_Block) {
495     /* This is a block. Dump a node for the block. */
496     xfprintf (F, "node: {title: \"%p\" label: \"%I\"}", block,
497               block->op->name);
498     /* Dump the edges */
499     for ( i = 0; i < get_Block_n_cfgpreds(block); i++) {
500       pred = get_nodes_Block(skip_Proj(get_Block_cfgpred(block, i)));
501       xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" }\n",
502                 block, pred);
503     }
504   }
505 }
506
507 void
508 dump_cfg (ir_graph *irg)
509 {
510   vcg_open (irg, "-cfg");
511
512   /* walk over the blocks in the graph */
513   irg_block_walk(irg->end, dump_block_to_cfg, NULL, NULL);
514
515   vcg_close();
516 }
517
518
519 /***********************************************************************/
520 /* the following routine dumps all type information                    */
521 /***********************************************************************/
522
523
524 void
525 dump_type_graph (ir_graph *irg)
526 {
527   vcg_open (irg, "-type");
528
529   /* walk over the blocks in the graph */
530   type_walk(irg, dump_type_info, NULL, NULL);
531
532   vcg_close();
533 }
534
535
536 /***********************************************************************/
537 /* dumps a graph with type information                                 */
538 /***********************************************************************/
539
540
541 void
542 dump_ir_graph_w_types (ir_graph *irg)
543 {
544   vcg_open (irg, "-all");
545
546   /* dump common ir graph */
547   /*  irg_block_walk(irg->end, dump_ir_block, NULL, irg); */
548   irg_walk(irg->end, dump_whole_node, NULL, NULL);
549   /* dump type info */
550   type_walk(irg, dump_type_info, NULL, NULL);
551   /* dump edges from graph to type info */
552   irg_walk(irg->end, dump_node2type_edges, NULL, NULL);
553
554   vcg_close();
555 }