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
15 # include "irnode_t.h"
16 # include "irgraph_t.h"
21 # include "entity_t.h"
26 # include "type_or_entity.h"
28 # include "typewalk.h"
32 /* Attributes of nodes */
33 #define DEFAULT_NODE_ATTR ""
34 #define DEFAULT_TYPE_ATTRIBUTE ""
36 /* Attributes of edges between Firm nodes */
37 #define BLOCK_EDGE_ATTR "class: 2 priority: 2 linestyle: dotted"
38 #define CF_EDGE_ATTR "color: red"
39 #define MEM_EDGE_ATTR "color: blue"
40 #define DOMINATOR_EDGE_ATTR "color: red"
42 /* Attributes of edges between Firm nodes and type/entity nodes */
43 #define NODE2TYPE_EDGE_ATTR "class: 2 priority: 2 linestyle: dotted"
45 /* Attributes of edges in type/entity graphs. */
46 #define TYPE_METH_NODE_ATTR "color: lightyellow"
47 #define TYPE_CLASS_NODE_ATTR "color: green"
48 #define ENTITY_NODE_ATTR "color: yellow"
49 #define ENT_TYPE_EDGE_ATTR "class: 3 label: \"type\" color: red"
50 #define ENT_OWN_EDGE_ATTR "class: 4 label: \"owner\" color: black"
51 #define METH_PAR_EDGE_ATTR "class: 5 label: \"param %d\" color: green"
52 #define METH_RES_EDGE_ATTR "class: 6 label: \"res %d\" color: green"
53 #define TYPE_SUPER_EDGE_ATTR "class: 7 label: \"supertype\" color: blue"
54 #define UNION_EDGE_ATTR "class: 8 label: \"component\" color: blue"
55 #define PTR_PTS_TO_EDGE_ATTR "class: 9 label: \"points to\" color:green"
56 #define ARR_ELT_TYPE_EDGE_ATTR "class: 10 label: \"arr elt tp\" color:green"
57 #define ARR_ENT_EDGE_ATTR "class: 10 label: \"arr ent\" color: green"
58 #define ENT_OVERWRITES_EDGE_ATTR "class: 11 label: \"overwrites\" color:red"
59 #define ENT_VALUE_EDGE_ATTR "label: \"value "
60 #define ENT_CORR_EDGE_ATTR "label: \"value %d corresponds to \" "
61 #define TYPE_MEMBER_EDGE_ATTR "class: 12 label: \"member\" color:blue"
64 #if DEBUG_libfirm && NODEID_AS_LABEL
65 #define PRINT_NODEID(X) fprintf(F, "%d", get_irn_node_nr(X))
67 #define PRINT_NODEID(X) fprintf(F, "%p", X)
73 /* A compiler option to turn off edge labels */
75 /* A compiler option to turn off dumping values of constant entities */
76 int const_entities = 1;
77 /* A compiler option to dump the keep alive edges */
78 int dump_keepalive = 0;
79 /* A compiler option to dump the out edges in dump_ir_graph */
80 int dump_out_edge_flag = 0;
81 int dump_dominator_information_flag = 0;
83 /* A global variable to record output of the Bad node. */
87 void dump_ir_blocks_nodes (ir_node *n, void *env);
88 void dump_whole_node (ir_node *n, void* env);
90 /*******************************************************************/
91 /* routines to dump information about a single node */
92 /*******************************************************************/
97 dump_node_opcode (ir_node *n)
101 if (n->op->code == iro_Const) {
102 xfprintf (F, "%v", n->attr.con);
105 } else if (n->op->code == iro_SymConst) {
106 if (get_SymConst_kind(n) == linkage_ptr_info) {
107 /* don't use get_SymConst_ptr_info as it mangles the name. */
108 xfprintf (F, "SymC %I", n->attr.i.tori.ptrinfo);
110 assert(get_kind(get_SymConst_type(n)) == k_type);
111 assert(get_type_ident(get_SymConst_type(n)));
112 xfprintf (F, "SymC %I ", get_type_ident(get_SymConst_type(n)));
113 if (get_SymConst_kind == type_tag)
116 xfprintf (F, "size");
120 xfprintf (F, "%I", get_irn_opident(n));
125 dump_node_mode (ir_node *n)
127 switch (n->op->code) {
144 xfprintf (F, "%I", get_mode_ident(n->mode));
151 dump_node_nodeattr (ir_node *n)
153 switch (n->op->code) {
155 if (n->in[1]->op->code == iro_Cmp) {
156 xfprintf (F, "%s", get_pnc_string(n->attr.proj));
158 xfprintf (F, "%ld", n->attr.proj);
162 assert(get_kind(get_Sel_entity(n)) == k_entity);
163 xfprintf (F, "%I", get_entity_ident(get_Sel_entity(n)));
170 dump_node_vcgattr (ir_node *n)
172 switch (n->op->code) {
175 xfprintf (F, "color: blue");
178 xfprintf (F, "color: lightyellow");
181 xfprintf (F, "color: green");
186 xfprintf (F, "color: yellow");
189 xfprintf (F, DEFAULT_NODE_ATTR);
194 dump_node (ir_node *n) {
197 xfprintf (F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
202 dump_node_nodeattr(n);
204 xfprintf (F, " %ld", get_irn_node_nr(n));
207 dump_node_vcgattr(n);
212 dump_ir_node (ir_node *n)
215 fprintf (F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: ");
217 switch (n->op->code) { /* node label */
219 xfprintf (F, "\"%I\" color: blue ", get_irn_opident(n));
220 xfprintf (F, DEFAULT_NODE_ATTR);
223 xfprintf (F, "\"%I\" color: blue ", get_irn_opident(n));
224 xfprintf (F, DEFAULT_NODE_ATTR);
227 xfprintf (F, "\"%I\" color: lightyellow ", get_irn_opident(n));
228 xfprintf (F, DEFAULT_NODE_ATTR);
231 xfprintf (F, "\"%I%I\" color: green", get_irn_opident(n), get_irn_modeident(n));
232 if (get_irn_modecode(n) == irm_M)
233 xfprintf (F, DEFAULT_NODE_ATTR " color: green");
235 xfprintf (F, DEFAULT_NODE_ATTR);
238 xfprintf (F, "\"%v%I\" color: yellow ", n->attr.con, get_irn_modeident(n));
239 xfprintf (F, DEFAULT_NODE_ATTR);
242 xfprintf (F, "\"%I%I\" ", get_irn_opident(n), get_irn_modeident(n));
243 xfprintf (F, DEFAULT_NODE_ATTR);
246 if (n->in[1]->op->code == iro_Cmp) {
247 xfprintf (F, "\"%I%I %s\" color: yellow", get_irn_opident(n), get_irn_modeident(n),
248 get_pnc_string(n->attr.proj));
250 xfprintf (F, "\"%I%I %ld\"", get_irn_opident(n), get_irn_modeident(n), n->attr.proj);
252 xfprintf (F, DEFAULT_NODE_ATTR);
255 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
256 xfprintf (F, DEFAULT_NODE_ATTR);
259 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
260 xfprintf (F, DEFAULT_NODE_ATTR);
263 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
264 xfprintf (F, DEFAULT_NODE_ATTR);
267 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
268 xfprintf (F, DEFAULT_NODE_ATTR);
271 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
272 xfprintf (F, DEFAULT_NODE_ATTR);
275 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
276 xfprintf (F, DEFAULT_NODE_ATTR);
279 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
280 xfprintf (F, DEFAULT_NODE_ATTR);
283 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
284 xfprintf (F, DEFAULT_NODE_ATTR);
287 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
288 xfprintf (F, DEFAULT_NODE_ATTR);
291 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
292 xfprintf (F, DEFAULT_NODE_ATTR);
295 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
296 xfprintf (F, DEFAULT_NODE_ATTR);
299 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
300 xfprintf (F, DEFAULT_NODE_ATTR);
303 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
304 xfprintf (F, DEFAULT_NODE_ATTR);
307 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
308 xfprintf (F, DEFAULT_NODE_ATTR);
311 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
312 xfprintf (F, DEFAULT_NODE_ATTR);
315 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
316 xfprintf (F, DEFAULT_NODE_ATTR);
319 xfprintf (F, "\"%I\"", get_irn_opident(n));
320 xfprintf (F, DEFAULT_NODE_ATTR);
323 xfprintf (F, "\"%I\"", get_irn_opident(n));
324 xfprintf (F, DEFAULT_NODE_ATTR);
327 xfprintf (F, "\"%I\"", get_irn_opident(n));
328 xfprintf (F, DEFAULT_NODE_ATTR);
331 xfprintf (F, "\"%I\"", get_irn_opident(n));
332 xfprintf (F, DEFAULT_NODE_ATTR);
335 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
336 xfprintf (F, DEFAULT_NODE_ATTR);
340 xfprintf (F, "\"%R\"", n);
341 xfprintf (F, DEFAULT_NODE_ATTR);
344 xfprintf (F, "\"%I\" ", get_irn_opident(n));
345 xfprintf (F, DEFAULT_NODE_ATTR);
348 assert(get_kind(get_Sel_entity(n)) == k_entity);
349 xfprintf (F, "\"%I ", get_irn_opident(n));
350 xfprintf (F, "%I", get_entity_ident(get_Sel_entity(n)));
351 xfprintf (F, DEFAULT_NODE_ATTR);
354 assert(get_kind(get_SymConst_type(n)) == k_type);
355 assert(get_type_ident(get_SymConst_type(n)));
356 xfprintf (F, "\"%s ", get_type_name(get_SymConst_type(n)));
357 switch (n->attr.i.num){
359 xfprintf (F, "tag\" ");
362 xfprintf (F, "size\" ");
368 xfprintf (F, DEFAULT_NODE_ATTR);
371 xfprintf (F, "\"%I\" ", get_irn_opident(n));
372 xfprintf (F, DEFAULT_NODE_ATTR " color: green");
375 xfprintf (F, "\"%I%I\" ", get_irn_opident(n), get_irn_modeident(n));
376 xfprintf (F, DEFAULT_NODE_ATTR);
379 xfprintf (F, "\"%I%I\" ", get_irn_opident(n), get_irn_modeident(n));
381 xfprintf (F, "}\n"); /* footer */
385 /* dump the edge to the block this node belongs to */
387 dump_ir_block_edge(ir_node *n) {
388 if (is_no_Block(n)) {
389 xfprintf (F, "edge: { sourcename: \"");
391 xfprintf (F, "\" targetname: \"");
392 PRINT_NODEID(get_nodes_Block(n));
393 xfprintf (F, "\" " BLOCK_EDGE_ATTR "}\n");
397 void print_edge_vcgattr(ir_node *from, int to) {
400 switch (get_irn_opcode(from)) {
402 xfprintf (F, CF_EDGE_ATTR);
404 case iro_Start: break;
407 case iro_Cond: break;
410 if (to == 0) xfprintf (F, MEM_EDGE_ATTR);
412 case iro_Const: break;
413 case iro_SymConst:break;
416 if (to == 0) xfprintf (F, MEM_EDGE_ATTR);
420 case iro_Minus: break;
426 if (to == 0) xfprintf (F, MEM_EDGE_ATTR);
434 case iro_Shrs: break;
437 case iro_Conv: break;
439 if (get_irn_modecode(from) == irm_M) xfprintf (F, MEM_EDGE_ATTR);
445 if (to == 0) xfprintf (F, MEM_EDGE_ATTR);
448 xfprintf (F, MEM_EDGE_ATTR);
450 case iro_Tuple: break;
452 switch (get_irn_modecode(from)) {
454 xfprintf (F, CF_EDGE_ATTR);
457 xfprintf (F, MEM_EDGE_ATTR);
468 /* dump edges to our inputs */
470 dump_ir_data_edges(ir_node *n) {
473 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
476 for (i = 0; i < get_irn_arity(n); i++) {
477 assert(get_irn_n(n, i));
478 fprintf (F, "edge: {sourcename: \"");
480 fprintf (F, "\" targetname: \"");
481 PRINT_NODEID(get_irn_n(n, i));
483 fprintf (F, " label: \"%d\" ", i);
484 print_edge_vcgattr(n, i);
491 dump_out_edge (ir_node *n, void* env) {
493 for (i = 0; i < get_irn_n_outs(n); i++) {
494 assert(get_irn_out(n, i));
495 fprintf (F, "edge: {sourcename: \"");
497 fprintf (F, "\" targetname: \"");
498 PRINT_NODEID(get_irn_out(n, i));
499 fprintf (F, "\" color: red linestyle: dashed");
505 /* dumps the edges between nodes and their type or entity attributes. */
506 void dump_node2type_edges (ir_node *n, void *env)
510 switch (get_irn_opcode(n)) {
512 /* @@@ some consts have an entity */
515 if ( (get_SymConst_kind(n) == type_tag)
516 || (get_SymConst_kind(n) == size)) {
517 xfprintf (F, "edge: { sourcename: \"");
519 fprintf (F, "\" targetname: \"%p\" "
520 NODE2TYPE_EDGE_ATTR "}\n", get_SymConst_type(n));
524 xfprintf (F, "edge: { sourcename: \"");
526 fprintf (F, "\" targetname: \"%p\" "
527 NODE2TYPE_EDGE_ATTR "}\n", get_Sel_entity(n));
530 xfprintf (F, "edge: { sourcename: \"");
532 fprintf (F, "\" targetname: \"%p\" "
533 NODE2TYPE_EDGE_ATTR "}\n", get_Call_type(n));
536 xfprintf (F, "edge: { sourcename: \"");
538 fprintf (F, "\" targetname: \"%p\" "
539 NODE2TYPE_EDGE_ATTR "}\n", get_Alloc_type(n));
542 xfprintf (F, "edge: { sourcename: \"");
544 fprintf (F, "\" targetname: \"%p\" "
545 NODE2TYPE_EDGE_ATTR "}\n", get_Free_type(n));
553 void dump_const_expression(ir_node *value) {
554 ir_graph *rem = current_ir_graph;
555 current_ir_graph = get_const_code_irg();
556 irg_walk(value, dump_ir_blocks_nodes, NULL, get_nodes_Block(value));
557 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
558 current_ir_graph = rem;
562 void print_type_info(type *tp) {
563 if (get_type_state(tp) == layout_undefined) {
564 xfprintf(F, "state: layout_undefined\n");
566 xfprintf(F, "state: layout_fixed,\n");
568 if (get_type_mode(tp))
569 xfprintf(F, "mode: %s,\n", get_mode_name(get_type_mode(tp)));
570 xfprintf(F, "size: %dB,\n", get_type_size(tp));
574 void print_typespecific_info(type *tp) {
575 switch (get_type_tpop_code(tp)) {
578 xfprintf (F, " " TYPE_CLASS_NODE_ATTR);
582 xfprintf (F, " " TYPE_METH_NODE_ATTR);
593 case tpo_enumeration:
606 void print_type_node(type *tp) {
607 xfprintf (F, "node: {title: \"%p\" ", tp);
608 xfprintf (F, "label: \"%I %I\"", get_type_tpop_nameid(tp), get_type_ident(tp));
609 xfprintf (F, "info1: \"");
612 print_typespecific_info(tp);
616 /* dumps a type or entity and it's edges. */
618 dump_type_info (type_or_ent *tore, void *env) {
619 int i = 0; /* to shutup gcc */
621 /* dump this type or entity */
623 switch (get_kind(tore)) {
626 entity *ent = (entity *)tore;
629 xfprintf (F, "node: {title: \"%p\" ", tore);
630 xfprintf (F, DEFAULT_TYPE_ATTRIBUTE);
631 xfprintf (F, "label: ");
632 xfprintf (F, "\"ent %I\" " ENTITY_NODE_ATTR , get_entity_ident(ent));
633 if(dynamic_allocated == get_entity_allocation(ent))
634 xfprintf (F, " info1:\"dynamic allocated\n");
636 xfprintf (F, " info1:\"static allocated\n");
637 switch (get_entity_visibility(ent)) {
638 case local: fprintf (F, "local\n"); break;
639 case external_visible: fprintf (F, "external_visible\n"); break;
640 case external_allocated: fprintf (F, "external_allocate\n");break;
642 switch (get_entity_variability(ent)) {
643 case uninitialized: fprintf (F, "uninitialized");break;
644 case initialized: fprintf (F, "initialized"); break;
645 case part_constant: fprintf (F, "part_constant");break;
646 case constant: fprintf (F, "constant"); break;
648 if (is_method_type(get_entity_type(ent)))
649 xfprintf (F, "\n irg = %p ", get_entity_irg(ent));
650 xfprintf(F, "\"}\n");
652 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
653 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
654 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
655 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
656 ENT_TYPE_EDGE_ATTR "}\n", ent, get_entity_type(ent));
657 for(i = 0; i < get_entity_n_overwrites(ent); i++)
658 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
659 ENT_OVERWRITES_EDGE_ATTR "}\n", ent, get_entity_overwrites(ent, i));
660 /* attached subgraphs */
661 if (const_entities && (get_entity_variability(ent) != uninitialized)) {
662 if (is_atomic_entity(ent)) {
663 value = get_atomic_ent_value(ent);
664 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"", ent);
666 fprintf(F, "\" " ENT_VALUE_EDGE_ATTR "\"}\n");
667 dump_const_expression(value);
669 if (is_compound_entity(ent)) {
670 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
671 value = get_compound_ent_value(ent, i);
672 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"", ent);
674 fprintf(F, "\" " ENT_VALUE_EDGE_ATTR " %d \"}\n", i);
675 dump_const_expression(value);
676 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
677 ENT_CORR_EDGE_ATTR "}\n", ent,
678 get_compound_ent_value_member(ent, i), i);
685 type *tp = (type *)tore;
687 /* and now the edges */
688 switch (get_type_tpop_code(tp)) {
691 for (i=0; i < get_class_n_supertype(tp); i++)
692 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
693 TYPE_SUPER_EDGE_ATTR "}\n",
694 tp, get_class_supertype(tp, i));
695 for (i=0; i < get_class_n_member(tp); i++)
696 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
697 TYPE_MEMBER_EDGE_ATTR "}\n",
698 tp, get_class_member(tp, i));
702 for (i=0; i < get_struct_n_member(tp); i++)
703 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
704 TYPE_MEMBER_EDGE_ATTR "}\n",
705 tp, get_struct_member(tp, i));
709 for (i = 0; i < get_method_n_params(tp); i++)
710 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
711 METH_PAR_EDGE_ATTR "}\n",
712 tp, get_method_param_type(tp, i), i);
713 for (i = 0; i < get_method_n_res(tp); i++)
714 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
715 METH_RES_EDGE_ATTR "}\n",
716 tp, get_method_res_type(tp, i), i);
720 for (i = 0; i < get_union_n_members(tp); i++)
721 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
722 "label: \"\"f" UNION_EDGE_ATTR "}\n",
723 tp, get_union_member(tp, i));
727 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
728 ARR_ELT_TYPE_EDGE_ATTR "}\n", tp, get_array_element_type(tp), i);
729 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
730 ARR_ENT_EDGE_ATTR "}\n", tp, get_array_element_entity(tp), i);
732 case tpo_enumeration:
737 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
738 PTR_PTS_TO_EDGE_ATTR "}\n", tp,
739 get_pointer_points_to_type(tp), i);
747 break; /* case k_type */
750 printf(" *** irdump, %s(l.%i), faulty type.\n", __FUNCTION__, __LINE__);
752 } /* switch kind_or_entity */
755 /************************************************************************/
756 /* open and close vcg file */
757 /************************************************************************/
759 void vcg_open (ir_graph *irg, char *suffix) {
760 char *fname; /* filename to put the vcg information in */
767 /** open file for vcg graph */
768 ent = get_irg_ent(irg);
769 id = ent->ld_name ? ent->ld_name : ent->name;
770 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
771 len = id_to_strlen (id);
773 fname = malloc (len + 5 + strlen(suffix));
774 strncpy (fname, cp, len); /* copy the filename */
776 strcat (fname, suffix); /* append file suffix */
778 fname = malloc (len + 5 + strlen(suffix));
779 strncpy (fname, cp, len); /* copy the filename */
780 fname[len] = '\0'; /* ensure string termination */
781 /*strcpy (fname, cp); * copy the filename *
782 this produces wrong, too long strings in conjuction with the
783 jocca frontend. The \0 seems to be missing. */
784 strcat (fname, suffix); /* append file suffix */
785 strcat (fname, ".vcg"); /* append the .vcg suffix */
786 F = fopen (fname, "w"); /* open file for writing */
788 panic ("cannot open %s for writing (%m)", fname); /* not reached */
792 strcpy(label, "yes");
794 strcpy (label, "no");
799 "graph: { title: \"ir graph of %s\"\n"
800 "display_edge_labels: %s\n"
801 "layoutalgorithm: mindepth\n"
802 "manhattan_edges: yes\n"
804 "orientation: bottom_to_top\n"
805 "classname 1: \"Data\"\n"
806 "classname 2: \"Block\"\n"
807 "classname 3: \"Entity type\""
808 "classname 4: \"Entity owner\""
809 "classname 5: \"Method Param\""
810 "classname 6: \"Method Res\""
811 "classname 7: \"Super\""
812 "classname 8: \"Union\""
813 "classname 9: \"Points-to\""
814 "classname 10: \"Array Element Type\""
815 "classname 11: \"Overwrites\""
816 "classname 12: \"Member\""
819 xfprintf (F, "\n"); /* a separator */
822 void vcg_open_name (const char *name) {
823 char *fname; /* filename to put the vcg information in */
827 /** open file for vcg graph */
829 fname = malloc (len + 5);
830 strcpy (fname, name); /* copy the filename */
831 strcat (fname, ".vcg"); /* append the .vcg suffix */
832 F = fopen (fname, "w"); /* open file for writing */
834 panic ("cannot open %s for writing (%m)", fname); /* not reached */
838 strcpy(label, "yes");
840 strcpy (label, "no");
845 "graph: { title: \"ir graph of %s\"\n"
846 "display_edge_labels: %s\n"
847 "layoutalgorithm: mindepth\n"
848 "manhattan_edges: yes\n"
850 "orientation: bottom_to_top\n"
851 "classname 1: \"Data\"\n"
852 "classname 2: \"Block\"\n"
853 "classname 3: \"Entity type\"\n"
854 "classname 4: \"Entity owner\"\n"
855 "classname 5: \"Method Param\"\n"
856 "classname 6: \"Method Res\"\n"
857 "classname 7: \"Super\"\n"
858 "classname 8: \"Union\"\n"
859 "classname 9: \"Points-to\"\n"
860 "classname 10: \"Array Element Type\"\n"
861 "classname 11: \"Overwrites\"\n"
862 "classname 12: \"Member\"\n"
865 xfprintf (F, "\n"); /* a separator */
870 xfprintf (F, "}\n"); /* print footer */
871 fclose (F); /* close vcg file */
874 /************************************************************************/
875 /* routines to dump a graph, blocks as conventional nodes. */
876 /************************************************************************/
879 dump_whole_node (ir_node *n, void* env) {
881 if (!node_floats(n)) dump_ir_block_edge(n);
882 dump_ir_data_edges(n);
886 dump_ir_graph (ir_graph *irg)
889 rem = current_ir_graph;
890 current_ir_graph = irg;
894 /* walk over the graph */
895 irg_walk(irg->end, dump_whole_node, NULL, NULL);
897 /* dump the out edges in a separate walk */
898 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != no_outs)) {
899 irg_out_walk(irg->start, dump_out_edge, NULL, NULL);
904 current_ir_graph = rem;
907 /***********************************************************************/
908 /* the following routines dump the nodes as attached to the blocks. */
909 /***********************************************************************/
911 int node_floats(ir_node *n) {
913 return ((get_op_pinned(get_irn_op(n)) == floats) &&
914 (get_irg_pinned(current_ir_graph) == floats));
918 dump_ir_blocks_nodes (ir_node *n, void *env) {
919 ir_node *block = (ir_node *)env;
921 if (is_no_Block(n) && get_nodes_Block(n) == block && !node_floats(n)) {
923 dump_ir_data_edges(n);
925 if (get_irn_op(n) == op_Bad)
930 dump_ir_block (ir_node *block, void *env) {
931 ir_graph *irg = (ir_graph *)env;
933 if (get_irn_opcode(block) == iro_Block) {
935 /* This is a block. So dump the vcg information to make a block. */
936 xfprintf(F, "graph: { title: \""); PRINT_NODEID(block); fprintf(F, "\" label: \"");
938 xfprintf (F, "%ld", get_irn_node_nr(block));
940 xfprintf (F, "%I", block->op->name);
942 xfprintf(F, "\" status:clustered color:%s \n",
943 get_Block_matured (block) ? "yellow" : "red");
944 /* dump the blocks edges */
945 dump_ir_data_edges(block);
947 /* dump the nodes that go into the block */
948 irg_walk(irg->end, dump_ir_blocks_nodes, NULL, block);
950 /* Close the vcg information for the block */
951 xfprintf(F, "}\n\n");
957 dump_blockless_nodes (ir_node *n, void *env) {
958 if (is_no_Block(n) && get_irn_op(get_nodes_Block(n)) == op_Bad) {
960 dump_ir_data_edges(n);
961 dump_ir_block_edge(n);
962 if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
965 if (node_floats(n)) {
967 dump_ir_data_edges(n);
968 if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
972 void dump_ir_block_graph_2 (ir_graph *irg)
975 /* walk over the blocks in the graph */
976 irg_block_walk(irg->end, dump_ir_block, NULL, irg);
978 /* dump all nodes that are not in a Block */
979 irg_walk(irg->end, dump_blockless_nodes, NULL, NULL);
981 /* dump the Bad node */
983 dump_node(get_irg_bad(irg));
987 dump_ir_block_graph (ir_graph *irg)
990 rem = current_ir_graph;
991 current_ir_graph = irg;
995 dump_ir_block_graph_2 (irg);
998 current_ir_graph = rem;
1002 /***********************************************************************/
1003 /* the following routines dump a control flow graph */
1004 /***********************************************************************/
1008 dump_block_to_cfg (ir_node *block, void *env) {
1012 if (get_irn_opcode(block) == iro_Block) {
1013 /* This is a block. Dump a node for the block. */
1014 xfprintf (F, "node: {title:\""); PRINT_NODEID(block);
1015 xfprintf (F, "\" label: \"%I ", block->op->name); PRINT_NODEID(block);
1016 xfprintf (F, "\" ");
1017 if (dump_dominator_information_flag)
1018 xfprintf(F, "info1:\"dom depth %d\"", get_Block_dom_depth(block));
1019 xfprintf (F, "}\n");
1020 /* Dump the edges */
1021 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
1022 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
1023 pred = get_nodes_Block(skip_Proj(get_Block_cfgpred(block, i)));
1024 xfprintf (F, "edge: { sourcename: \"");
1025 PRINT_NODEID(block);
1026 fprintf (F, "\" targetname: \"");
1028 fprintf (F, "\" }\n");
1031 /* Dump dominator edge */
1032 if (dump_dominator_information_flag && get_Block_idom(block)) {
1033 pred = get_Block_idom(block);
1034 xfprintf (F, "edge: { sourcename: \"");
1035 PRINT_NODEID(block);
1036 fprintf (F, "\" targetname: \"");
1038 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
1044 dump_cfg (ir_graph *irg)
1046 int rem = dump_dominator_information_flag;
1047 vcg_open (irg, "-cfg");
1049 if (get_irg_dom_state(irg) != dom_consistent)
1050 dump_dominator_information_flag = 0;
1052 /* walk over the blocks in the graph */
1053 irg_block_walk(irg->end, dump_block_to_cfg, NULL, NULL);
1055 dump_dominator_information_flag = rem;
1060 /***********************************************************************/
1061 /* the following routine dumps all type information reachable from an */
1063 /***********************************************************************/
1067 dump_type_graph (ir_graph *irg)
1070 rem = current_ir_graph;
1071 current_ir_graph = irg;
1073 vcg_open (irg, "-type");
1075 /* walk over the blocks in the graph */
1076 type_walk_irg(irg, dump_type_info, NULL, NULL);
1077 /* The walker for the const code can be called several times for the
1078 same (sub) experssion. So that no nodes are dumped several times
1079 we decrease the visited flag of the corresponding graph after each
1080 walk. So now increase it finally. */
1081 inc_irg_visited(get_const_code_irg());
1084 current_ir_graph = rem;
1087 /***********************************************************************/
1088 /* the following routine dumps all type information */
1089 /***********************************************************************/
1093 dump_all_types (void)
1095 vcg_open_name ("All_types");
1096 type_walk(dump_type_info, NULL, NULL);
1097 inc_irg_visited(get_const_code_irg());
1101 /***********************************************************************/
1102 /* dumps a graph with type information */
1103 /***********************************************************************/
1107 dump_ir_graph_w_types (ir_graph *irg)
1110 rem = current_ir_graph;
1111 current_ir_graph = irg;
1113 vcg_open (irg, "-all");
1115 /* dump common ir graph */
1116 irg_walk(irg->end, dump_whole_node, NULL, NULL);
1117 /* dump type info */
1118 type_walk_irg(irg, dump_type_info, NULL, NULL);
1119 inc_irg_visited(get_const_code_irg());
1120 /* dump edges from graph to type info */
1121 irg_walk(irg->end, dump_node2type_edges, NULL, NULL);
1124 current_ir_graph = rem;
1128 dump_ir_block_graph_w_types (ir_graph *irg)
1131 rem = current_ir_graph;
1132 current_ir_graph = irg;
1134 vcg_open (irg, "-all");
1136 /* dump common blocked ir graph */
1137 dump_ir_block_graph_2(irg);
1138 /* dump type info */
1139 type_walk_irg(irg, dump_type_info, NULL, NULL);
1140 inc_irg_visited(get_const_code_irg());
1141 /* dump edges from graph to type info */
1142 irg_walk(irg->end, dump_node2type_edges, NULL, NULL);
1145 current_ir_graph = rem;
1148 /***********************************************************************/
1149 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
1151 /* dump_ir_block_graph */
1153 /* dump_type_graph */
1154 /* dump_ir_graph_w_types */
1155 /***********************************************************************/
1156 void dump_all_ir_graphs (void dump_graph(ir_graph*)) {
1158 for (i=0; i < get_irp_n_irgs(); i++) {
1159 dump_graph(get_irp_irg(i));
1164 /* To turn off display of edge labels. Edge labels offen cause xvcg to
1165 abort with a segmentation fault. */
1166 void turn_off_edge_labels() {
1170 void turn_off_constant_entity_values() {
1174 void dump_keepalive_edges() {
1178 void dump_out_edges() {
1179 dump_out_edge_flag = 1;
1182 void dump_dominator_information() {
1183 dump_dominator_information_flag = 1;