c37eb0e53be4a141377903d393f377b7445821f5
[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     // xfprintf (F, "\"%I %I\" ", n->op->name, n->attr.s.ent); // GL: doesn't work for some reason.
177     xfprintf (F, DEFAULT_NODE_ATTR);
178     break;
179   case iro_SymConst:
180     assert(get_kind(get_SymConst_type(n)) == k_type_class);
181       //assert(n->attr.i.type->kind == k_type_class);
182     assert(get_class_ident((type_class *)get_SymConst_type(n)));
183     //assert(n->attr.i.type->clss->name);
184     xfprintf (F, "\"%s ", id_to_str(get_class_ident((type_class *)get_SymConst_type(n))));
185     //xfprintf (F, "\"%s ", id_to_str(n->attr.i.type->name));
186     // xfprintf (F, "\"%N\" ", n->attr.i.type);  // GL: doesn't work for some reason.
187     switch (n->attr.i.num){
188     case type_tag:
189       xfprintf (F, "tag\" ");
190       break;
191     case size:
192       xfprintf (F, "size\" ");
193       break;
194     default:
195       assert(0);
196       break;
197     }
198     xfprintf (F, DEFAULT_NODE_ATTR);
199     break;
200   case iro_Sync:
201     xfprintf (F, "\"%I\" ", n->op->name);
202     xfprintf (F, DEFAULT_NODE_ATTR " color: green");
203     break;
204   case iro_Bad:
205     xfprintf (F, "\"%I%I\" ", n->op->name, n->mode->name);
206     xfprintf (F, DEFAULT_NODE_ATTR);
207     break;
208   default:
209     xfprintf (F, "\"%I%I\" ", n->op->name, n->mode->name);
210   }
211   xfprintf (F, "}\n");          /* footer */
212 }
213
214
215 /* dump the edge to the block this node belongs to */
216 void
217 dump_ir_block_edge(ir_node *n)  {
218   if (is_no_Block(n))
219     xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
220                 BLOCK_EDGE_ATTR "}\n", n, get_nodes_Block(n));
221 }
222
223
224 /* dump edges to our inputs */
225 void
226 dump_ir_data_edges(ir_node *n)  {
227   int i;
228
229   for (i = 0; i < get_irn_arity(n); i++) {
230     assert(get_irn_n(n, i));
231     xfprintf (F, "edge: {sourcename: \"%p\" targetname: \"%p\"",
232               n, get_irn_n(n, i));
233     fprintf (F, " label: \"%d\"", i+1);
234     fprintf (F, "}\n");
235   }
236 }
237
238 /* dumps the edges between nodes and their type or entity attributes. */
239 void dump_node2type_edges (ir_node *n, void *env)
240 {
241   assert(n);
242
243   switch (get_irn_opcode(n)) {
244   case iro_SymConst:
245     if (   (get_SymConst_kind(n) == type_tag)
246         || (get_SymConst_kind(n) == size))
247       xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
248                 NODE2TYPE_EDGE_ATTR "}\n", n, get_SymConst_type(n));
249     break;
250   case iro_Sel:
251     xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
252               NODE2TYPE_EDGE_ATTR "}\n", n, get_Sel_entity(n));
253     break;
254   case iro_Call:
255     xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
256               NODE2TYPE_EDGE_ATTR "}\n", n, get_Call_type(n));
257     break;
258   case iro_Alloc:
259     xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
260               NODE2TYPE_EDGE_ATTR "}\n", n, get_Alloc_type(n));
261     break;
262   case iro_Free:
263     xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
264               NODE2TYPE_EDGE_ATTR "}\n", n, get_Free_type(n));
265     break;
266   default:
267     break;
268   }
269 }
270
271
272 /* dumps a type or entity and it's edges. */
273 void
274 dump_type_info (type_or_ent *tore, void *env) {
275   int i = 0;  /* to shutup gcc */
276
277   /* dump this type or entity */
278   xfprintf (F, "node: {title: \"%p\" ", tore);
279   xfprintf (F, DEFAULT_TYPE_ATTRIBUTE);
280   xfprintf (F, "label: ");
281
282   switch (get_kind(tore)) {
283   case k_entity:
284     {
285       entity *ent = (entity *)tore;
286       xfprintf (F, "\"ent %I\"}\n", get_entity_ident(ent));
287       xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
288                 " label: \"owner\" "
289                 TYPE_EDGE_ATTR "}\n", tore, get_entity_owner(ent));
290       xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
291                 " label: \"type\" "
292                 TYPE_EDGE_ATTR "}\n", tore, get_entity_type(ent));
293     }
294     break;
295   case k_type_class:
296     {
297       type_class *type = (type_class *)tore;
298       xfprintf (F, "\"class %I\"}\n", get_class_ident(type));
299       /* edges !!!??? */
300     }
301     break;
302   case k_type_strct:
303     {
304       type_strct *type = (type_strct *)tore;
305       xfprintf (F, "\"strct %I\"}\n", get_strct_ident(type));
306       /* edges !!!??? */
307     }
308     break;
309   case k_type_method:
310     {
311       type_method *type = (type_method *)tore;
312       xfprintf (F, "\"meth %I\"}\n", get_method_ident(type));
313       for (i = 0; i < get_method_arity(type); i++)
314         xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
315                   " label: \"param %d\" " TYPE_EDGE_ATTR "}\n",
316                   tore, get_method_param_type(type, i), i);
317       for (i = 0; i < get_method_n_res(type); i++)
318         xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
319                   " label: \"res %d\" " TYPE_EDGE_ATTR "}\n",
320                   tore, get_method_res_type(type, i), i);
321     }
322     break;
323   case k_type_union:
324     {
325       type_union *type = (type_union *)tore;
326       xfprintf (F, "\"union %I\"}\n", get_union_ident(type));
327       /* edges !!!??? */
328     }
329     break;
330   case k_type_array:
331     {
332       type_array *type = (type_array *)tore;
333       xfprintf (F, "\"array %I\"}\n", get_array_ident(type));
334       xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
335                 TYPE_EDGE_ATTR "}\n", tore, get_array_element_type(type), i);
336     }
337     break;
338   case k_type_enumeration:
339     {
340       type_enumeration *type = (type_enumeration *)tore;
341       xfprintf (F, "\"enum %I\"}\n", get_enumeration_ident(type));
342     }
343     break;
344   case k_type_pointer:
345     {
346       type_pointer *type = (type_pointer *)tore;
347       xfprintf (F, "\"ptr %I\"}\n", get_pointer_ident(type));
348       xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
349                 TYPE_EDGE_ATTR "}\n", tore,
350                 get_pointer_points_to_type(type), i);
351     }
352     break;
353   case k_type_primitive:
354     {
355       type_primitive *type = (type_primitive *)tore;
356       xfprintf (F, "\"prim %I, mode %I\"}\n", get_primitive_ident(type),
357                 get_mode_ident(get_primitive_mode(type)));
358     }
359     break;
360   default:
361     break;
362   }
363
364 }
365
366 /************************************************************************/
367 /* open and close vcg file                                              */
368 /************************************************************************/
369
370 void vcg_open (ir_graph *irg, char *suffix) {
371   char *fname;  /* filename to put the vcg information in */
372   const char *cp;
373   ident *id;
374   int len;
375
376   /** open file for vcg graph */
377   id    = get_entity_ld_name (irg->ent);
378
379   len   = id_to_strlen (id);
380   cp    = id_to_str (id);
381   fname = malloc (len + 5 + strlen(suffix));
382   strcpy (fname, cp);      /* copy the filename */
383   strcat (fname, suffix);  /* append file suffix */
384   strcat (fname, ".vcg");  /* append the .vcg suffix */
385
386   F = fopen (fname, "w");  /* open file for writing */
387   if (!F) {
388     panic ("cannot open %s for writing (%m)", fname);  /* not reached */
389   }
390
391   /* print header */
392   xfprintf (F,
393             "graph: { title: \"ir graph of %s\"\n"
394             "display_edge_labels: yes\n"
395             "layoutalgorithm: mindepth\n"
396             "manhattan_edges: yes\n"
397             "port_sharing: no\n"
398             "orientation: bottom_to_top\n"
399             "classname 1: \"Data\"\n"
400             "classname 2: \"Block\"\n", cp);
401
402   xfprintf (F, "\n");           /* a separator */
403 }
404
405 void
406 vcg_close () {
407   xfprintf (F, "}\n");  /* print footer */
408   fclose (F);           /* close vcg file */
409 }
410
411
412
413 /************************************************************************/
414 /* routines to dump a graph, blocks as conventional nodes.              */
415 /************************************************************************/
416
417 void
418 dump_whole_node (ir_node *n, void* env) {
419   dump_ir_node(n);
420   dump_ir_block_edge(n);
421   dump_ir_data_edges(n);
422 }
423
424 void
425 dump_ir_graph (ir_graph *irg)
426 {
427   vcg_open (irg, "");
428
429   /* walk over the graph */
430   irg_walk(irg->end, dump_whole_node, NULL, NULL);
431
432   vcg_close();
433 }
434
435 /***********************************************************************/
436 /* the following routines dump the nodes as attached to the blocks.    */
437 /***********************************************************************/
438
439 void
440 dump_ir_blocks_nodes (ir_node *n, void *env) {
441   ir_node *block = (ir_node *)env;
442
443   if (is_no_Block(n) && get_nodes_Block(n) == block) {
444     dump_ir_node(n);
445     dump_ir_data_edges(n);
446   }
447 }
448
449
450 void
451 dump_ir_block (ir_node *block, void *env) {
452   ir_graph *irg = (ir_graph *)env;
453
454   if (get_irn_opcode(block) == iro_Block) {
455     /* This is a block. So dump the vcg information to make a block. */
456     xfprintf(F, "graph: { title: \"%p\" status:clustered color:lightyellow \n",
457              block);
458     /* dump the blocks edges */
459     dump_ir_data_edges(block);
460
461     /* dump the nodes that go into the block */
462     irg_walk(irg->end, dump_ir_blocks_nodes, NULL, block);
463
464     /* Close the vcg information for the block */
465     xfprintf(F, "}\n\n");
466   }
467 }
468
469 void
470 dump_ir_block_graph (ir_graph *irg)
471 {
472   vcg_open (irg, "");
473
474   /* walk over the blocks in the graph */
475   irg_block_walk(irg->end, dump_ir_block, NULL, irg);
476
477   vcg_close();
478 }
479
480
481 /***********************************************************************/
482 /* the following routines dump a control flow graph                    */
483 /***********************************************************************/
484
485
486 void
487 dump_block_to_cfg (ir_node *block, void *env) {
488   int i;
489   ir_node *pred;
490
491   if (get_irn_opcode(block) == iro_Block) {
492     /* This is a block. Dump a node for the block. */
493     xfprintf (F, "node: {title: \"%p\" label: \"%I\"}", block,
494               block->op->name);
495     /* Dump the edges */
496     for ( i = 0; i < get_Block_n_cfgpreds(block); i++) {
497       pred = get_nodes_Block(skip_Proj(get_Block_cfgpred(block, i)));
498       xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" }\n",
499                 block, pred);
500     }
501   }
502 }
503
504 void
505 dump_cfg (ir_graph *irg)
506 {
507   vcg_open (irg, "-cfg");
508
509   /* walk over the blocks in the graph */
510   irg_block_walk(irg->end, dump_block_to_cfg, NULL, NULL);
511
512   vcg_close();
513 }
514
515
516 /***********************************************************************/
517 /* the following routine dumps all type information                    */
518 /***********************************************************************/
519
520
521 void
522 dump_type_graph (ir_graph *irg)
523 {
524   vcg_open (irg, "-type");
525
526   /* walk over the blocks in the graph */
527   type_walk(irg, dump_type_info, NULL, NULL);
528
529   vcg_close();
530 }
531
532
533 /***********************************************************************/
534 /* dumps a graph with type information                                 */
535 /***********************************************************************/
536
537
538 void
539 dump_ir_graph_w_types (ir_graph *irg)
540 {
541   vcg_open (irg, "-all");
542
543   /* dump common ir graph */
544   //  irg_block_walk(irg->end, dump_ir_block, NULL, irg);
545   irg_walk(irg->end, dump_whole_node, NULL, NULL);
546   /* dump type info */
547   type_walk(irg, dump_type_info, NULL, NULL);
548   /* dump edges from graph to type info */
549   irg_walk(irg->end, dump_node2type_edges, NULL, NULL);
550
551   vcg_close();
552 }