1 /* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
2 ** All rights reserved.
4 ** Authors: Martin Trapp, Christian Schaefer
6 ** irdump.h: dumping of an intermediate representation graph
13 # include "irnode_t.h"
14 # include "irgraph_t.h"
24 # include "type_or_entity.h"
26 # include "typewalk.h"
28 /* Attributes of nodes */
29 #define DEFAULT_NODE_ATTR ""
30 #define DEFAULT_TYPE_ATTRIBUTE ""
32 /* Attributes of edges between Firm nodes */
33 #define BLOCK_EDGE_ATTR "class: 2 priority: 2 linestyle: dotted"
34 #define CF_EDGE_ATTR "color: red"
35 #define MEM_EDGE_ATTR "color: blue"
37 /* Attributes of edges between Firm nodes and type/entity nodes */
38 #define NODE2TYPE_EDGE_ATTR ""
40 /* Attributes of edges in type/entity graphs. */
41 #define TYPE_METH_NODE_ATTR "color: lightyellow"
42 #define TYPE_CLASS_NODE_ATTR "color: green"
43 #define ENTITY_NODE_ATTR "color: yellow"
44 #define ENT_TYPE_EDGE_ATTR "label: \"type\" color: red"
45 #define ENT_OWN_EDGE_ATTR "label: \"owner\" color: black"
46 #define METH_PAR_EDGE_ATTR "label: \"param %d\" color: green"
47 #define METH_RES_EDGE_ATTR "label: \"res %d\" color: green"
48 #define TYPE_SUPER_EDGE_ATTR "label: \"supertype\" color: blue"
49 #define PTR_PTS_TO_EDGE_ATTR "label: \"points to\" color:green"
50 #define ARR_ELT_TYPE_EDGE_ATTR "label: \"arr elt\" color:green"
52 #define PRINT_NODEID(X) fprintf(F, "%p", X)
58 /*******************************************************************/
59 /* routines to dump information about a single node */
60 /*******************************************************************/
65 dump_node_opcode (ir_node *n)
68 if (n->op->code == iro_Const) {
69 xfprintf (F, "%v", n->attr.con);
71 } else if (n->op->code == iro_SymConst) {
72 if (get_SymConst_kind(n) == linkage_ptr_info) {
73 xfprintf (F, "%I", get_SymConst_ptrinfo(n));
75 assert(get_kind(get_SymConst_type(n)) == k_type_class);
76 assert(get_class_ident((type_class *)get_SymConst_type(n)));
77 xfprintf (F, "%s ", id_to_str(get_class_ident((type_class *)get_SymConst_type(n))));
78 if (get_SymConst_kind == type_tag)
85 xfprintf (F, "%I", get_irn_opident(n));
90 dump_node_mode (ir_node *n)
92 switch (n->op->code) {
109 xfprintf (F, "%I", get_mode_ident(n->mode));
116 dump_node_nodeattr (ir_node *n)
118 switch (n->op->code) {
120 if (n->in[1]->op->code == iro_Cmp) {
121 xfprintf (F, "%s", get_pnc_string(n->attr.proj));
123 xfprintf (F, "%ld", n->attr.proj);
127 assert(get_kind(get_Sel_entity(n)) == k_entity);
128 xfprintf (F, "%s", id_to_str(get_entity_ident(get_Sel_entity(n))));
135 dump_node_vcgattr (ir_node *n)
137 switch (n->op->code) {
140 xfprintf (F, "color: blue");
143 xfprintf (F, "color: lightyellow");
146 xfprintf (F, "color: green");
151 xfprintf (F, "color: yellow");
154 xfprintf (F, DEFAULT_NODE_ATTR);
159 dump_node (ir_node *n) {
162 xfprintf (F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
167 dump_node_nodeattr(n);
169 xfprintf (F, " %ld", get_irn_node_nr(n));
172 dump_node_vcgattr(n);
177 dump_ir_node (ir_node *n)
180 fprintf (F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: ");
182 switch (n->op->code) { /* node label */
184 xfprintf (F, "\"%I\" color: blue ", get_irn_opident(n));
185 xfprintf (F, DEFAULT_NODE_ATTR);
188 xfprintf (F, "\"%I\" color: blue ", get_irn_opident(n));
189 xfprintf (F, DEFAULT_NODE_ATTR);
192 xfprintf (F, "\"%I\" color: lightyellow ", get_irn_opident(n));
193 xfprintf (F, DEFAULT_NODE_ATTR);
196 xfprintf (F, "\"%I%I\" color: green", get_irn_opident(n), get_irn_modeident(n));
197 if (get_irn_modecode(n) == irm_M)
198 xfprintf (F, DEFAULT_NODE_ATTR " color: green");
200 xfprintf (F, DEFAULT_NODE_ATTR);
203 xfprintf (F, "\"%v%I\" color: yellow ", n->attr.con, get_irn_modeident(n));
204 xfprintf (F, DEFAULT_NODE_ATTR);
207 xfprintf (F, "\"%I%I\" ", get_irn_opident(n), get_irn_modeident(n));
208 xfprintf (F, DEFAULT_NODE_ATTR);
211 if (n->in[1]->op->code == iro_Cmp) {
212 xfprintf (F, "\"%I%I %s\" color: yellow", get_irn_opident(n), get_irn_modeident(n),
213 get_pnc_string(n->attr.proj));
215 xfprintf (F, "\"%I%I %ld\"", get_irn_opident(n), get_irn_modeident(n), n->attr.proj);
217 xfprintf (F, DEFAULT_NODE_ATTR);
220 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
221 xfprintf (F, DEFAULT_NODE_ATTR);
224 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
225 xfprintf (F, DEFAULT_NODE_ATTR);
228 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
229 xfprintf (F, DEFAULT_NODE_ATTR);
232 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
233 xfprintf (F, DEFAULT_NODE_ATTR);
236 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
237 xfprintf (F, DEFAULT_NODE_ATTR);
240 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
241 xfprintf (F, DEFAULT_NODE_ATTR);
244 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
245 xfprintf (F, DEFAULT_NODE_ATTR);
248 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
249 xfprintf (F, DEFAULT_NODE_ATTR);
252 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
253 xfprintf (F, DEFAULT_NODE_ATTR);
256 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
257 xfprintf (F, DEFAULT_NODE_ATTR);
260 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
261 xfprintf (F, DEFAULT_NODE_ATTR);
264 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
265 xfprintf (F, DEFAULT_NODE_ATTR);
268 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
269 xfprintf (F, DEFAULT_NODE_ATTR);
272 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
273 xfprintf (F, DEFAULT_NODE_ATTR);
276 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
277 xfprintf (F, DEFAULT_NODE_ATTR);
280 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
281 xfprintf (F, DEFAULT_NODE_ATTR);
284 xfprintf (F, "\"%I\"", get_irn_opident(n));
285 xfprintf (F, DEFAULT_NODE_ATTR);
288 xfprintf (F, "\"%I\"", get_irn_opident(n));
289 xfprintf (F, DEFAULT_NODE_ATTR);
292 xfprintf (F, "\"%I\"", get_irn_opident(n));
293 xfprintf (F, DEFAULT_NODE_ATTR);
296 xfprintf (F, "\"%I\"", get_irn_opident(n));
297 xfprintf (F, DEFAULT_NODE_ATTR);
300 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
301 xfprintf (F, DEFAULT_NODE_ATTR);
305 xfprintf (F, "\"%R\"", n);
306 xfprintf (F, DEFAULT_NODE_ATTR);
309 xfprintf (F, "\"%I\" ", get_irn_opident(n));
310 xfprintf (F, DEFAULT_NODE_ATTR);
313 assert(get_kind(get_Sel_entity(n)) == k_entity);
314 xfprintf (F, "\"%I ", get_irn_opident(n));
315 xfprintf (F, "%s", id_to_str(get_entity_ident(get_Sel_entity(n))));
316 xfprintf (F, DEFAULT_NODE_ATTR);
319 assert(get_kind(get_SymConst_type(n)) == k_type_class);
320 assert(get_class_ident((type_class *)get_SymConst_type(n)));
321 xfprintf (F, "\"%s ",
322 id_to_str(get_class_ident((type_class *)get_SymConst_type(n))));
323 switch (n->attr.i.num){
325 xfprintf (F, "tag\" ");
328 xfprintf (F, "size\" ");
334 xfprintf (F, DEFAULT_NODE_ATTR);
337 xfprintf (F, "\"%I\" ", get_irn_opident(n));
338 xfprintf (F, DEFAULT_NODE_ATTR " color: green");
341 xfprintf (F, "\"%I%I\" ", get_irn_opident(n), get_irn_modeident(n));
342 xfprintf (F, DEFAULT_NODE_ATTR);
345 xfprintf (F, "\"%I%I\" ", get_irn_opident(n), get_irn_modeident(n));
347 xfprintf (F, "}\n"); /* footer */
351 /* dump the edge to the block this node belongs to */
353 dump_ir_block_edge(ir_node *n) {
355 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
356 BLOCK_EDGE_ATTR "}\n", n, get_nodes_Block(n));
359 void print_edge_vcgattr(ir_node *from, int to) {
362 switch (get_irn_opcode(from)) {
364 xfprintf (F, CF_EDGE_ATTR);
366 case iro_Start: break;
369 case iro_Cond: break;
372 if (to == 0) xfprintf (F, MEM_EDGE_ATTR);
374 case iro_Const: break;
375 case iro_SymConst:break;
378 if (to == 0) xfprintf (F, MEM_EDGE_ATTR);
382 case iro_Minus: break;
388 if (to == 0) xfprintf (F, MEM_EDGE_ATTR);
396 case iro_Shrs: break;
399 case iro_Conv: break;
401 if (get_irn_modecode(from) == irm_M) xfprintf (F, MEM_EDGE_ATTR);
407 if (to == 0) xfprintf (F, MEM_EDGE_ATTR);
410 xfprintf (F, MEM_EDGE_ATTR);
412 case iro_Tuple: break;
414 switch (get_irn_modecode(from)) {
416 xfprintf (F, CF_EDGE_ATTR);
419 xfprintf (F, MEM_EDGE_ATTR);
430 /* dump edges to our inputs */
432 dump_ir_data_edges(ir_node *n) {
435 for (i = 0; i < get_irn_arity(n); i++) {
436 assert(get_irn_n(n, i));
437 xfprintf (F, "edge: {sourcename: \"%p\" targetname: \"%p\"",
439 fprintf (F, " label: \"%d\" ", i+1);
440 print_edge_vcgattr(n, i);
445 /* dumps the edges between nodes and their type or entity attributes. */
446 void dump_node2type_edges (ir_node *n, void *env)
450 switch (get_irn_opcode(n)) {
452 if ( (get_SymConst_kind(n) == type_tag)
453 || (get_SymConst_kind(n) == size))
454 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
455 NODE2TYPE_EDGE_ATTR "}\n", n, get_SymConst_type(n));
458 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
459 NODE2TYPE_EDGE_ATTR "}\n", n, get_Sel_entity(n));
462 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
463 NODE2TYPE_EDGE_ATTR "}\n", n, get_Call_type(n));
466 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
467 NODE2TYPE_EDGE_ATTR "}\n", n, get_Alloc_type(n));
470 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
471 NODE2TYPE_EDGE_ATTR "}\n", n, get_Free_type(n));
479 /* dumps a type or entity and it's edges. */
481 dump_type_info (type_or_ent *tore, void *env) {
482 int i = 0; /* to shutup gcc */
484 /* dump this type or entity */
485 xfprintf (F, "node: {title: \"%p\" ", tore);
486 xfprintf (F, DEFAULT_TYPE_ATTRIBUTE);
487 xfprintf (F, "label: ");
489 switch (get_kind(tore)) {
492 entity *ent = (entity *)tore;
493 xfprintf (F, "\"ent %I\" " ENTITY_NODE_ATTR "}\n", get_entity_ident(ent));
494 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
495 ENT_OWN_EDGE_ATTR "}\n", tore, get_entity_owner(ent));
496 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
497 ENT_TYPE_EDGE_ATTR "}\n", tore, get_entity_type(ent));
501 type_class *type = (type_class *)tore;
502 xfprintf (F, "\"class %I\" " TYPE_CLASS_NODE_ATTR "}\n", get_class_ident(type));
503 for (i=0; i < get_class_n_supertype(type); i++)
504 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
505 TYPE_SUPER_EDGE_ATTR "}\n",
506 type, get_class_supertype(type, i));
510 type_strct *type = (type_strct *)tore;
511 xfprintf (F, "\"strct %I\"}\n", get_strct_ident(type));
516 type_method *type = (type_method *)tore;
517 xfprintf (F, "\"meth %I\" " TYPE_METH_NODE_ATTR "}\n", get_method_ident(type));
518 for (i = 0; i < get_method_arity(type); i++)
519 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
520 METH_PAR_EDGE_ATTR "}\n",
521 tore, get_method_param_type(type, i), i);
522 for (i = 0; i < get_method_n_res(type); i++)
523 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
524 METH_RES_EDGE_ATTR "}\n",
525 tore, get_method_res_type(type, i), i);
529 type_union *type = (type_union *)tore;
530 xfprintf (F, "\"union %I\"}\n", get_union_ident(type));
535 type_array *type = (type_array *)tore;
536 xfprintf (F, "\"array %I\"}\n", get_array_ident(type));
537 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
538 ARR_ELT_TYPE_EDGE_ATTR "}\n", tore, get_array_element_type(type), i);
541 case k_type_enumeration:
543 type_enumeration *type = (type_enumeration *)tore;
544 xfprintf (F, "\"enum %I\"}\n", get_enumeration_ident(type));
548 type_pointer *type = (type_pointer *)tore;
549 xfprintf (F, "\"ptr %I\"}\n", get_pointer_ident(type));
550 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
551 PTR_PTS_TO_EDGE_ATTR "}\n", tore,
552 get_pointer_points_to_type(type), i);
554 case k_type_primitive:
556 type_primitive *type = (type_primitive *)tore;
557 xfprintf (F, "\"prim %I, mode %I\"}\n", get_primitive_ident(type),
558 get_mode_ident(get_primitive_mode(type)));
562 xfprintf (F, "\" faulty type \"}\n");
563 printf(" *** irdump, %s(l.%i), faulty type.\n", __FUNCTION__, __LINE__);
568 /************************************************************************/
569 /* open and close vcg file */
570 /************************************************************************/
572 void vcg_open (ir_graph *irg, char *suffix) {
573 char *fname; /* filename to put the vcg information in */
578 /** open file for vcg graph */
579 id = get_entity_ld_name (get_irg_ent(irg));
580 len = id_to_strlen (id);
583 fname = malloc (len + 5 + strlen(suffix));
584 strncpy (fname, cp, len); /* copy the filename */
586 strcat (fname, suffix); /* append file suffix */
588 fname = malloc (len + 5 + strlen(suffix));
589 strncpy (fname, cp, len); /* copy the filename */
590 fname[len] = '\0'; /* ensure string termination */
591 /*strcpy (fname, cp); * copy the filename *
592 this produces wrong, too long strings in conjuction with the
593 jocca frontend. The \0 seems to be missing. */
594 strcat (fname, suffix); /* append file suffix */
595 strcat (fname, ".vcg"); /* append the .vcg suffix */
596 F = fopen (fname, "w"); /* open file for writing */
598 panic ("cannot open %s for writing (%m)", fname); /* not reached */
603 "graph: { title: \"ir graph of %s\"\n"
604 "display_edge_labels: yes\n"
605 "layoutalgorithm: mindepth\n"
606 "manhattan_edges: yes\n"
608 "orientation: bottom_to_top\n"
609 "classname 1: \"Data\"\n"
610 "classname 2: \"Block\"\n", cp);
612 xfprintf (F, "\n"); /* a separator */
615 void vcg_open_name (const char *name) {
616 char *fname; /* filename to put the vcg information in */
619 /** open file for vcg graph */
621 fname = malloc (len + 5);
622 strcpy (fname, name); /* copy the filename */
623 strcat (fname, ".vcg"); /* append the .vcg suffix */
624 F = fopen (fname, "w"); /* open file for writing */
626 panic ("cannot open %s for writing (%m)", fname); /* not reached */
631 "graph: { title: \"ir graph of %s\"\n"
632 "display_edge_labels: yes\n"
633 "layoutalgorithm: mindepth\n"
634 "manhattan_edges: yes\n"
636 "orientation: bottom_to_top\n"
637 "classname 1: \"Data\"\n"
638 "classname 2: \"Block\"\n", name);
640 xfprintf (F, "\n"); /* a separator */
645 xfprintf (F, "}\n"); /* print footer */
646 fclose (F); /* close vcg file */
649 /************************************************************************/
650 /* routines to dump a graph, blocks as conventional nodes. */
651 /************************************************************************/
654 dump_whole_node (ir_node *n, void* env) {
656 dump_ir_block_edge(n);
657 dump_ir_data_edges(n);
661 dump_ir_graph (ir_graph *irg)
664 rem = current_ir_graph;
665 current_ir_graph = irg;
669 /* walk over the graph */
670 irg_walk(irg->end, dump_whole_node, NULL, NULL);
674 current_ir_graph = rem;
677 /***********************************************************************/
678 /* the following routines dump the nodes as attached to the blocks. */
679 /***********************************************************************/
682 dump_ir_blocks_nodes (ir_node *n, void *env) {
683 ir_node *block = (ir_node *)env;
685 if (is_no_Block(n) && get_nodes_Block(n) == block) {
687 dump_ir_data_edges(n);
692 dump_ir_block (ir_node *block, void *env) {
693 ir_graph *irg = (ir_graph *)env;
695 if (get_irn_opcode(block) == iro_Block) {
697 /* This is a block. So dump the vcg information to make a block. */
698 xfprintf(F, "graph: { title: \""); PRINT_NODEID(block); fprintf(F, "\" label: \"");
700 xfprintf (F, "%ld", get_irn_node_nr(block));
702 xfprintf (F, "%I", block->op->name);
704 xfprintf(F, "\" status:clustered color:lightyellow \n");
705 /* dump the blocks edges */
706 dump_ir_data_edges(block);
708 /* dump the nodes that go into the block */
709 irg_walk(irg->end, dump_ir_blocks_nodes, NULL, block);
711 /* Close the vcg information for the block */
712 xfprintf(F, "}\n\n");
717 dump_ir_block_graph (ir_graph *irg)
720 rem = current_ir_graph;
721 current_ir_graph = irg;
725 /* walk over the blocks in the graph */
726 irg_block_walk(irg->end, dump_ir_block, NULL, irg);
729 current_ir_graph = rem;
733 /***********************************************************************/
734 /* the following routines dump a control flow graph */
735 /***********************************************************************/
739 dump_block_to_cfg (ir_node *block, void *env) {
743 if (get_irn_opcode(block) == iro_Block) {
744 /* This is a block. Dump a node for the block. */
745 xfprintf (F, "node: {title: \"%p\" label: \"%I\"}", block,
748 for ( i = 0; i < get_Block_n_cfgpreds(block); i++) {
749 pred = get_nodes_Block(skip_Proj(get_Block_cfgpred(block, i)));
750 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" }\n",
757 dump_cfg (ir_graph *irg)
759 vcg_open (irg, "-cfg");
761 /* walk over the blocks in the graph */
762 irg_block_walk(irg->end, dump_block_to_cfg, NULL, NULL);
768 /***********************************************************************/
769 /* the following routine dumps all type information reachable from an */
771 /***********************************************************************/
775 dump_type_graph (ir_graph *irg)
778 rem = current_ir_graph;
779 current_ir_graph = irg;
781 vcg_open (irg, "-type");
783 /* walk over the blocks in the graph */
784 type_walk_irg(irg, dump_type_info, NULL, NULL);
787 current_ir_graph = rem;
790 /***********************************************************************/
791 /* the following routine dumps all type information */
792 /***********************************************************************/
796 dump_all_types (void)
798 vcg_open_name ("All_types");
799 type_walk(dump_type_info, NULL, NULL);
803 /***********************************************************************/
804 /* dumps a graph with type information */
805 /***********************************************************************/
809 dump_ir_graph_w_types (ir_graph *irg)
812 rem = current_ir_graph;
813 current_ir_graph = irg;
815 vcg_open (irg, "-all");
817 /* dump common ir graph */
818 /* irg_block_walk(irg->end, dump_ir_block, NULL, irg); */
819 irg_walk(irg->end, dump_whole_node, NULL, NULL);
821 type_walk_irg(irg, dump_type_info, NULL, NULL);
822 /* dump edges from graph to type info */
823 irg_walk(irg->end, dump_node2type_edges, NULL, NULL);
826 current_ir_graph = rem;
829 /***********************************************************************/
830 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
832 /* dump_ir_block_graph */
834 /* dump_type_graph */
835 /* dump_ir_graph_w_types */
836 /***********************************************************************/
837 void dump_all_ir_graphs (void dump_graph(ir_graph*)) {
839 for (i=0; i < get_irp_n_irgs(); i++) {
840 dump_graph(get_irp_irg(i));