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)
70 /* A suffix to manipulate the file name. */
71 char *dump_file_suffix = NULL;
76 /* A compiler option to turn off edge labels */
78 /* A compiler option to turn off dumping values of constant entities */
79 int const_entities = 1;
80 /* A compiler option to dump the keep alive edges */
81 int dump_keepalive = 0;
82 /* A compiler option to dump the out edges in dump_ir_graph */
83 int dump_out_edge_flag = 0;
84 int dump_dominator_information_flag = 0;
86 /* A global variable to record output of the Bad node. */
90 void dump_ir_blocks_nodes (ir_node *n, void *env);
91 void dump_whole_node (ir_node *n, void* env);
93 /*******************************************************************/
94 /* routines to dump information about a single node */
95 /*******************************************************************/
100 dump_node_opcode (ir_node *n)
104 if (n->op->code == iro_Const) {
105 xfprintf (F, "%v", n->attr.con);
108 } else if (n->op->code == iro_SymConst) {
109 if (get_SymConst_kind(n) == linkage_ptr_info) {
110 /* don't use get_SymConst_ptr_info as it mangles the name. */
111 xfprintf (F, "SymC %I", n->attr.i.tori.ptrinfo);
113 assert(get_kind(get_SymConst_type(n)) == k_type);
114 assert(get_type_ident(get_SymConst_type(n)));
115 xfprintf (F, "SymC %I ", get_type_ident(get_SymConst_type(n)));
116 if (get_SymConst_kind == type_tag)
119 xfprintf (F, "size");
123 xfprintf (F, "%I", get_irn_opident(n));
128 dump_node_mode (ir_node *n)
130 switch (n->op->code) {
147 xfprintf (F, "%I", get_mode_ident(n->mode));
154 dump_node_nodeattr (ir_node *n)
156 switch (n->op->code) {
158 if (n->in[1]->op->code == iro_Cmp) {
159 xfprintf (F, "%s", get_pnc_string(n->attr.proj));
161 xfprintf (F, "%ld", n->attr.proj);
165 assert(get_kind(get_Sel_entity(n)) == k_entity);
166 xfprintf (F, "%I", get_entity_ident(get_Sel_entity(n)));
173 dump_node_vcgattr (ir_node *n)
175 switch (n->op->code) {
178 xfprintf (F, "color: blue");
181 xfprintf (F, "color: lightyellow");
184 xfprintf (F, "color: green");
189 xfprintf (F, "color: yellow");
192 xfprintf (F, DEFAULT_NODE_ATTR);
197 dump_node (ir_node *n) {
200 xfprintf (F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
205 dump_node_nodeattr(n);
207 xfprintf (F, " %ld", get_irn_node_nr(n));
210 dump_node_vcgattr(n);
215 dump_ir_node (ir_node *n)
218 fprintf (F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: ");
220 switch (n->op->code) { /* node label */
222 xfprintf (F, "\"%I\" color: blue ", get_irn_opident(n));
223 xfprintf (F, DEFAULT_NODE_ATTR);
226 xfprintf (F, "\"%I\" color: blue ", get_irn_opident(n));
227 xfprintf (F, DEFAULT_NODE_ATTR);
230 xfprintf (F, "\"%I\" color: lightyellow ", get_irn_opident(n));
231 xfprintf (F, DEFAULT_NODE_ATTR);
234 xfprintf (F, "\"%I%I\" color: green", get_irn_opident(n), get_irn_modeident(n));
235 if (get_irn_modecode(n) == irm_M)
236 xfprintf (F, DEFAULT_NODE_ATTR " color: green");
238 xfprintf (F, DEFAULT_NODE_ATTR);
241 xfprintf (F, "\"%v%I\" color: yellow ", n->attr.con, get_irn_modeident(n));
242 xfprintf (F, DEFAULT_NODE_ATTR);
245 xfprintf (F, "\"%I%I\" ", get_irn_opident(n), get_irn_modeident(n));
246 xfprintf (F, DEFAULT_NODE_ATTR);
249 if (n->in[1]->op->code == iro_Cmp) {
250 xfprintf (F, "\"%I%I %s\" color: yellow", get_irn_opident(n), get_irn_modeident(n),
251 get_pnc_string(n->attr.proj));
253 xfprintf (F, "\"%I%I %ld\"", get_irn_opident(n), get_irn_modeident(n), n->attr.proj);
255 xfprintf (F, DEFAULT_NODE_ATTR);
258 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
259 xfprintf (F, DEFAULT_NODE_ATTR);
262 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
263 xfprintf (F, DEFAULT_NODE_ATTR);
266 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
267 xfprintf (F, DEFAULT_NODE_ATTR);
270 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
271 xfprintf (F, DEFAULT_NODE_ATTR);
274 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
275 xfprintf (F, DEFAULT_NODE_ATTR);
278 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
279 xfprintf (F, DEFAULT_NODE_ATTR);
282 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
283 xfprintf (F, DEFAULT_NODE_ATTR);
286 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
287 xfprintf (F, DEFAULT_NODE_ATTR);
290 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
291 xfprintf (F, DEFAULT_NODE_ATTR);
294 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
295 xfprintf (F, DEFAULT_NODE_ATTR);
298 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
299 xfprintf (F, DEFAULT_NODE_ATTR);
302 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
303 xfprintf (F, DEFAULT_NODE_ATTR);
306 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
307 xfprintf (F, DEFAULT_NODE_ATTR);
310 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
311 xfprintf (F, DEFAULT_NODE_ATTR);
314 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
315 xfprintf (F, DEFAULT_NODE_ATTR);
318 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
319 xfprintf (F, DEFAULT_NODE_ATTR);
322 xfprintf (F, "\"%I\"", get_irn_opident(n));
323 xfprintf (F, DEFAULT_NODE_ATTR);
326 xfprintf (F, "\"%I\"", get_irn_opident(n));
327 xfprintf (F, DEFAULT_NODE_ATTR);
330 xfprintf (F, "\"%I\"", get_irn_opident(n));
331 xfprintf (F, DEFAULT_NODE_ATTR);
334 xfprintf (F, "\"%I\"", get_irn_opident(n));
335 xfprintf (F, DEFAULT_NODE_ATTR);
338 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
339 xfprintf (F, DEFAULT_NODE_ATTR);
343 xfprintf (F, "\"%R\"", n);
344 xfprintf (F, DEFAULT_NODE_ATTR);
347 xfprintf (F, "\"%I\" ", get_irn_opident(n));
348 xfprintf (F, DEFAULT_NODE_ATTR);
351 assert(get_kind(get_Sel_entity(n)) == k_entity);
352 xfprintf (F, "\"%I ", get_irn_opident(n));
353 xfprintf (F, "%I", get_entity_ident(get_Sel_entity(n)));
354 xfprintf (F, DEFAULT_NODE_ATTR);
357 assert(get_kind(get_SymConst_type(n)) == k_type);
358 assert(get_type_ident(get_SymConst_type(n)));
359 xfprintf (F, "\"%s ", get_type_name(get_SymConst_type(n)));
360 switch (n->attr.i.num){
362 xfprintf (F, "tag\" ");
365 xfprintf (F, "size\" ");
371 xfprintf (F, DEFAULT_NODE_ATTR);
374 xfprintf (F, "\"%I\" ", get_irn_opident(n));
375 xfprintf (F, DEFAULT_NODE_ATTR " color: green");
378 xfprintf (F, "\"%I%I\" ", get_irn_opident(n), get_irn_modeident(n));
379 xfprintf (F, DEFAULT_NODE_ATTR);
382 xfprintf (F, "\"%I%I\" ", get_irn_opident(n), get_irn_modeident(n));
384 xfprintf (F, "}\n"); /* footer */
388 /* dump the edge to the block this node belongs to */
390 dump_ir_block_edge(ir_node *n) {
391 if (is_no_Block(n)) {
392 xfprintf (F, "edge: { sourcename: \"");
394 xfprintf (F, "\" targetname: \"");
395 PRINT_NODEID(get_nodes_Block(n));
396 xfprintf (F, "\" " BLOCK_EDGE_ATTR "}\n");
400 void print_edge_vcgattr(ir_node *from, int to) {
403 switch (get_irn_opcode(from)) {
405 xfprintf (F, CF_EDGE_ATTR);
407 case iro_Start: break;
410 case iro_Cond: break;
413 if (to == 0) xfprintf (F, MEM_EDGE_ATTR);
415 case iro_Const: break;
416 case iro_SymConst:break;
419 if (to == 0) xfprintf (F, MEM_EDGE_ATTR);
423 case iro_Minus: break;
429 if (to == 0) xfprintf (F, MEM_EDGE_ATTR);
437 case iro_Shrs: break;
440 case iro_Conv: break;
442 if (get_irn_modecode(from) == irm_M) xfprintf (F, MEM_EDGE_ATTR);
448 if (to == 0) xfprintf (F, MEM_EDGE_ATTR);
451 xfprintf (F, MEM_EDGE_ATTR);
453 case iro_Tuple: break;
455 switch (get_irn_modecode(from)) {
457 xfprintf (F, CF_EDGE_ATTR);
460 xfprintf (F, MEM_EDGE_ATTR);
471 /* dump edges to our inputs */
473 dump_ir_data_edges(ir_node *n) {
476 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
479 for (i = 0; i < get_irn_arity(n); i++) {
480 assert(get_irn_n(n, i));
481 fprintf (F, "edge: {sourcename: \"");
483 fprintf (F, "\" targetname: \"");
484 PRINT_NODEID(get_irn_n(n, i));
486 fprintf (F, " label: \"%d\" ", i);
487 print_edge_vcgattr(n, i);
494 dump_out_edge (ir_node *n, void* env) {
496 for (i = 0; i < get_irn_n_outs(n); i++) {
497 assert(get_irn_out(n, i));
498 fprintf (F, "edge: {sourcename: \"");
500 fprintf (F, "\" targetname: \"");
501 PRINT_NODEID(get_irn_out(n, i));
502 fprintf (F, "\" color: red linestyle: dashed");
508 /* dumps the edges between nodes and their type or entity attributes. */
509 void dump_node2type_edges (ir_node *n, void *env)
513 switch (get_irn_opcode(n)) {
515 /* @@@ some consts have an entity */
518 if ( (get_SymConst_kind(n) == type_tag)
519 || (get_SymConst_kind(n) == size)) {
520 xfprintf (F, "edge: { sourcename: \"");
522 fprintf (F, "\" targetname: \"%p\" "
523 NODE2TYPE_EDGE_ATTR "}\n", get_SymConst_type(n));
527 xfprintf (F, "edge: { sourcename: \"");
529 fprintf (F, "\" targetname: \"%p\" "
530 NODE2TYPE_EDGE_ATTR "}\n", get_Sel_entity(n));
533 xfprintf (F, "edge: { sourcename: \"");
535 fprintf (F, "\" targetname: \"%p\" "
536 NODE2TYPE_EDGE_ATTR "}\n", get_Call_type(n));
539 xfprintf (F, "edge: { sourcename: \"");
541 fprintf (F, "\" targetname: \"%p\" "
542 NODE2TYPE_EDGE_ATTR "}\n", get_Alloc_type(n));
545 xfprintf (F, "edge: { sourcename: \"");
547 fprintf (F, "\" targetname: \"%p\" "
548 NODE2TYPE_EDGE_ATTR "}\n", get_Free_type(n));
556 void dump_const_expression(ir_node *value) {
557 ir_graph *rem = current_ir_graph;
558 current_ir_graph = get_const_code_irg();
559 irg_walk(value, dump_ir_blocks_nodes, NULL, get_nodes_Block(value));
560 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
561 current_ir_graph = rem;
565 void print_type_info(type *tp) {
566 if (get_type_state(tp) == layout_undefined) {
567 xfprintf(F, "state: layout_undefined\n");
569 xfprintf(F, "state: layout_fixed,\n");
571 if (get_type_mode(tp))
572 xfprintf(F, "mode: %s,\n", get_mode_name(get_type_mode(tp)));
573 xfprintf(F, "size: %dB,\n", get_type_size(tp));
577 void print_typespecific_info(type *tp) {
578 switch (get_type_tpop_code(tp)) {
581 xfprintf (F, " " TYPE_CLASS_NODE_ATTR);
585 xfprintf (F, " " TYPE_METH_NODE_ATTR);
596 case tpo_enumeration:
609 void print_type_node(type *tp) {
610 xfprintf (F, "node: {title: \"%p\" ", tp);
611 xfprintf (F, "label: \"%I %I\"", get_type_tpop_nameid(tp), get_type_ident(tp));
612 xfprintf (F, "info1: \"");
615 print_typespecific_info(tp);
619 /* dumps a type or entity and it's edges. */
621 dump_type_info (type_or_ent *tore, void *env) {
622 int i = 0; /* to shutup gcc */
624 /* dump this type or entity */
626 switch (get_kind(tore)) {
629 entity *ent = (entity *)tore;
632 xfprintf (F, "node: {title: \"%p\" ", tore);
633 xfprintf (F, DEFAULT_TYPE_ATTRIBUTE);
634 xfprintf (F, "label: ");
635 xfprintf (F, "\"ent %I\" " ENTITY_NODE_ATTR , get_entity_ident(ent));
636 if(dynamic_allocated == get_entity_allocation(ent))
637 xfprintf (F, " info1:\"dynamic allocated\n");
639 xfprintf (F, " info1:\"static allocated\n");
640 switch (get_entity_visibility(ent)) {
641 case local: fprintf (F, "local\n"); break;
642 case external_visible: fprintf (F, "external_visible\n"); break;
643 case external_allocated: fprintf (F, "external_allocate\n");break;
645 switch (get_entity_variability(ent)) {
646 case uninitialized: fprintf (F, "uninitialized");break;
647 case initialized: fprintf (F, "initialized"); break;
648 case part_constant: fprintf (F, "part_constant");break;
649 case constant: fprintf (F, "constant"); break;
651 if (is_method_type(get_entity_type(ent)))
652 xfprintf (F, "\n irg = %p ", get_entity_irg(ent));
653 xfprintf(F, "\"}\n");
655 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
656 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
657 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
658 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
659 ENT_TYPE_EDGE_ATTR "}\n", ent, get_entity_type(ent));
660 for(i = 0; i < get_entity_n_overwrites(ent); i++)
661 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
662 ENT_OVERWRITES_EDGE_ATTR "}\n", ent, get_entity_overwrites(ent, i));
663 /* attached subgraphs */
664 if (const_entities && (get_entity_variability(ent) != uninitialized)) {
665 if (is_atomic_entity(ent)) {
666 value = get_atomic_ent_value(ent);
667 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"", ent);
669 fprintf(F, "\" " ENT_VALUE_EDGE_ATTR "\"}\n");
670 dump_const_expression(value);
672 if (is_compound_entity(ent)) {
673 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
674 value = get_compound_ent_value(ent, i);
675 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"", ent);
677 fprintf(F, "\" " ENT_VALUE_EDGE_ATTR " %d \"}\n", i);
678 dump_const_expression(value);
679 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
680 ENT_CORR_EDGE_ATTR "}\n", ent,
681 get_compound_ent_value_member(ent, i), i);
688 type *tp = (type *)tore;
690 /* and now the edges */
691 switch (get_type_tpop_code(tp)) {
694 for (i=0; i < get_class_n_supertype(tp); i++)
695 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
696 TYPE_SUPER_EDGE_ATTR "}\n",
697 tp, get_class_supertype(tp, i));
698 for (i=0; i < get_class_n_member(tp); i++)
699 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
700 TYPE_MEMBER_EDGE_ATTR "}\n",
701 tp, get_class_member(tp, i));
705 for (i=0; i < get_struct_n_member(tp); i++)
706 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
707 TYPE_MEMBER_EDGE_ATTR "}\n",
708 tp, get_struct_member(tp, i));
712 for (i = 0; i < get_method_n_params(tp); i++)
713 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
714 METH_PAR_EDGE_ATTR "}\n",
715 tp, get_method_param_type(tp, i), i);
716 for (i = 0; i < get_method_n_res(tp); i++)
717 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
718 METH_RES_EDGE_ATTR "}\n",
719 tp, get_method_res_type(tp, i), i);
723 for (i = 0; i < get_union_n_members(tp); i++)
724 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
725 "label: \"\"f" UNION_EDGE_ATTR "}\n",
726 tp, get_union_member(tp, i));
730 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
731 ARR_ELT_TYPE_EDGE_ATTR "}\n", tp, get_array_element_type(tp), i);
732 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
733 ARR_ENT_EDGE_ATTR "}\n", tp, get_array_element_entity(tp), i);
735 case tpo_enumeration:
740 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
741 PTR_PTS_TO_EDGE_ATTR "}\n", tp,
742 get_pointer_points_to_type(tp), i);
750 break; /* case k_type */
753 printf(" *** irdump, %s(l.%i), faulty type.\n", __FUNCTION__, __LINE__);
755 } /* switch kind_or_entity */
758 /************************************************************************/
759 /* open and close vcg file */
760 /************************************************************************/
762 void vcg_open (ir_graph *irg, char *suffix) {
763 char *fname; /* filename to put the vcg information in */
770 /** open file for vcg graph */
771 ent = get_irg_ent(irg);
772 id = ent->ld_name ? ent->ld_name : ent->name;
773 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
774 len = id_to_strlen (id);
776 if (dump_file_suffix)
777 fname = malloc (len + 5 + strlen(suffix) + strlen(dump_file_suffix));
779 fname = malloc (len + 5 + strlen(suffix));
780 strncpy (fname, cp, len); /* copy the filename */
782 if (dump_file_suffix) strcat (fname, dump_file_suffix); /* append file suffix */
783 strcat (fname, suffix); /* append file suffix */
784 strcat (fname, ".vcg"); /* append the .vcg suffix */
785 F = fopen (fname, "w"); /* open file for writing */
787 panic ("cannot open %s for writing (%m)", fname); /* not reached */
791 strcpy(label, "yes");
793 strcpy (label, "no");
798 "graph: { title: \"ir graph of %s\"\n"
799 "display_edge_labels: %s\n"
800 "layoutalgorithm: mindepth\n"
801 "manhattan_edges: yes\n"
803 "orientation: bottom_to_top\n"
804 "classname 1: \"Data\"\n"
805 "classname 2: \"Block\"\n"
806 "classname 3: \"Entity type\""
807 "classname 4: \"Entity owner\""
808 "classname 5: \"Method Param\""
809 "classname 6: \"Method Res\""
810 "classname 7: \"Super\""
811 "classname 8: \"Union\""
812 "classname 9: \"Points-to\""
813 "classname 10: \"Array Element Type\""
814 "classname 11: \"Overwrites\""
815 "classname 12: \"Member\""
818 xfprintf (F, "\n"); /* a separator */
821 void vcg_open_name (const char *name) {
822 char *fname; /* filename to put the vcg information in */
826 /** open file for vcg graph */
828 fname = malloc (len + 5);
829 strcpy (fname, name); /* copy the filename */
830 strcat (fname, ".vcg"); /* append the .vcg suffix */
831 F = fopen (fname, "w"); /* open file for writing */
833 panic ("cannot open %s for writing (%m)", fname); /* not reached */
837 strcpy(label, "yes");
839 strcpy (label, "no");
844 "graph: { title: \"ir graph of %s\"\n"
845 "display_edge_labels: %s\n"
846 "layoutalgorithm: mindepth\n"
847 "manhattan_edges: yes\n"
849 "orientation: bottom_to_top\n"
850 "classname 1: \"Data\"\n"
851 "classname 2: \"Block\"\n"
852 "classname 3: \"Entity type\"\n"
853 "classname 4: \"Entity owner\"\n"
854 "classname 5: \"Method Param\"\n"
855 "classname 6: \"Method Res\"\n"
856 "classname 7: \"Super\"\n"
857 "classname 8: \"Union\"\n"
858 "classname 9: \"Points-to\"\n"
859 "classname 10: \"Array Element Type\"\n"
860 "classname 11: \"Overwrites\"\n"
861 "classname 12: \"Member\"\n"
864 xfprintf (F, "\n"); /* a separator */
869 xfprintf (F, "}\n"); /* print footer */
870 fclose (F); /* close vcg file */
873 /************************************************************************/
874 /* routines to dump a graph, blocks as conventional nodes. */
875 /************************************************************************/
878 dump_whole_node (ir_node *n, void* env) {
880 if (!node_floats(n)) dump_ir_block_edge(n);
881 dump_ir_data_edges(n);
885 dump_ir_graph (ir_graph *irg)
888 rem = current_ir_graph;
889 current_ir_graph = irg;
893 /* walk over the graph */
894 irg_walk(irg->end, dump_whole_node, NULL, NULL);
896 /* dump the out edges in a separate walk */
897 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != no_outs)) {
898 irg_out_walk(irg->start, dump_out_edge, NULL, NULL);
903 current_ir_graph = rem;
906 /***********************************************************************/
907 /* the following routines dump the nodes as attached to the blocks. */
908 /***********************************************************************/
910 int node_floats(ir_node *n) {
912 return ((get_op_pinned(get_irn_op(n)) == floats) &&
913 (get_irg_pinned(current_ir_graph) == floats));
917 dump_ir_blocks_nodes (ir_node *n, void *env) {
918 ir_node *block = (ir_node *)env;
920 if (is_no_Block(n) && get_nodes_Block(n) == block && !node_floats(n)) {
922 dump_ir_data_edges(n);
924 if (get_irn_op(n) == op_Bad)
929 dump_ir_block (ir_node *block, void *env) {
930 ir_graph *irg = (ir_graph *)env;
932 if (get_irn_opcode(block) == iro_Block) {
934 /* This is a block. So dump the vcg information to make a block. */
935 xfprintf(F, "graph: { title: \""); PRINT_NODEID(block); fprintf(F, "\" label: \"");
937 xfprintf (F, "%ld", get_irn_node_nr(block));
939 xfprintf (F, "%I", block->op->name);
941 xfprintf(F, "\" status:clustered color:%s \n",
942 get_Block_matured (block) ? "yellow" : "red");
943 /* dump the blocks edges */
944 dump_ir_data_edges(block);
946 /* dump the nodes that go into the block */
947 irg_walk(irg->end, dump_ir_blocks_nodes, NULL, block);
949 /* Close the vcg information for the block */
950 xfprintf(F, "}\n\n");
956 dump_blockless_nodes (ir_node *n, void *env) {
957 if (is_no_Block(n) && get_irn_op(get_nodes_Block(n)) == op_Bad) {
959 dump_ir_data_edges(n);
960 dump_ir_block_edge(n);
961 if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
964 if (node_floats(n)) {
966 dump_ir_data_edges(n);
967 if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
971 void dump_ir_block_graph_2 (ir_graph *irg)
974 /* walk over the blocks in the graph */
975 irg_block_walk(irg->end, dump_ir_block, NULL, irg);
977 /* dump all nodes that are not in a Block */
978 irg_walk(irg->end, dump_blockless_nodes, NULL, NULL);
980 /* dump the Bad node */
982 dump_node(get_irg_bad(irg));
986 dump_ir_block_graph (ir_graph *irg)
989 rem = current_ir_graph;
990 current_ir_graph = irg;
994 dump_ir_block_graph_2 (irg);
997 current_ir_graph = rem;
1001 /***********************************************************************/
1002 /* the following routines dump a control flow graph */
1003 /***********************************************************************/
1007 dump_block_to_cfg (ir_node *block, void *env) {
1011 if (get_irn_opcode(block) == iro_Block) {
1012 /* This is a block. Dump a node for the block. */
1013 xfprintf (F, "node: {title:\""); PRINT_NODEID(block);
1014 xfprintf (F, "\" label: \"%I ", block->op->name); PRINT_NODEID(block);
1015 xfprintf (F, "\" ");
1016 if (dump_dominator_information_flag)
1017 xfprintf(F, "info1:\"dom depth %d\"", get_Block_dom_depth(block));
1018 xfprintf (F, "}\n");
1019 /* Dump the edges */
1020 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
1021 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
1022 pred = get_nodes_Block(skip_Proj(get_Block_cfgpred(block, i)));
1023 xfprintf (F, "edge: { sourcename: \"");
1024 PRINT_NODEID(block);
1025 fprintf (F, "\" targetname: \"");
1027 fprintf (F, "\" }\n");
1030 /* Dump dominator edge */
1031 if (dump_dominator_information_flag && get_Block_idom(block)) {
1032 pred = get_Block_idom(block);
1033 xfprintf (F, "edge: { sourcename: \"");
1034 PRINT_NODEID(block);
1035 fprintf (F, "\" targetname: \"");
1037 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
1043 dump_cfg (ir_graph *irg)
1045 int rem = dump_dominator_information_flag;
1046 vcg_open (irg, "-cfg");
1048 if (get_irg_dom_state(irg) != dom_consistent)
1049 dump_dominator_information_flag = 0;
1051 /* walk over the blocks in the graph */
1052 irg_block_walk(irg->end, dump_block_to_cfg, NULL, NULL);
1054 dump_dominator_information_flag = rem;
1059 /***********************************************************************/
1060 /* the following routine dumps all type information reachable from an */
1062 /***********************************************************************/
1066 dump_type_graph (ir_graph *irg)
1069 rem = current_ir_graph;
1070 current_ir_graph = irg;
1072 vcg_open (irg, "-type");
1074 /* walk over the blocks in the graph */
1075 type_walk_irg(irg, dump_type_info, NULL, NULL);
1076 /* The walker for the const code can be called several times for the
1077 same (sub) experssion. So that no nodes are dumped several times
1078 we decrease the visited flag of the corresponding graph after each
1079 walk. So now increase it finally. */
1080 inc_irg_visited(get_const_code_irg());
1083 current_ir_graph = rem;
1086 /***********************************************************************/
1087 /* the following routine dumps all type information */
1088 /***********************************************************************/
1092 dump_all_types (void)
1094 vcg_open_name ("All_types");
1095 type_walk(dump_type_info, NULL, NULL);
1096 inc_irg_visited(get_const_code_irg());
1100 /***********************************************************************/
1101 /* dumps a graph with type information */
1102 /***********************************************************************/
1106 dump_ir_graph_w_types (ir_graph *irg)
1109 rem = current_ir_graph;
1110 current_ir_graph = irg;
1112 vcg_open (irg, "-all");
1114 /* dump common ir graph */
1115 irg_walk(irg->end, dump_whole_node, NULL, NULL);
1116 /* dump type info */
1117 type_walk_irg(irg, dump_type_info, NULL, NULL);
1118 inc_irg_visited(get_const_code_irg());
1119 /* dump edges from graph to type info */
1120 irg_walk(irg->end, dump_node2type_edges, NULL, NULL);
1123 current_ir_graph = rem;
1127 dump_ir_block_graph_w_types (ir_graph *irg)
1130 rem = current_ir_graph;
1131 current_ir_graph = irg;
1133 vcg_open (irg, "-all");
1135 /* dump common blocked ir graph */
1136 dump_ir_block_graph_2(irg);
1137 /* dump type info */
1138 type_walk_irg(irg, dump_type_info, NULL, NULL);
1139 inc_irg_visited(get_const_code_irg());
1140 /* dump edges from graph to type info */
1141 irg_walk(irg->end, dump_node2type_edges, NULL, NULL);
1144 current_ir_graph = rem;
1147 /***********************************************************************/
1148 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
1150 /* dump_ir_block_graph */
1152 /* dump_type_graph */
1153 /* dump_ir_graph_w_types */
1154 /***********************************************************************/
1155 void dump_all_ir_graphs (void dump_graph(ir_graph*)) {
1157 for (i=0; i < get_irp_n_irgs(); i++) {
1158 dump_graph(get_irp_irg(i));
1163 /* To turn off display of edge labels. Edge labels offen cause xvcg to
1164 abort with a segmentation fault. */
1165 void turn_off_edge_labels() {
1169 void turn_off_constant_entity_values() {
1173 void dump_keepalive_edges() {
1177 void dump_out_edges() {
1178 dump_out_edge_flag = 1;
1181 void dump_dominator_information() {
1182 dump_dominator_information_flag = 1;