3 * Helper routines to graph various internal states of the code generator
6 * Dietmar Maurer (dietmar@ximian.com)
8 * (C) 2003 Ximian, Inc.
12 #include <mono/utils/mono-compiler.h>
17 #include <mono/metadata/debug-helpers.h>
22 convert_name (const char *str
)
24 int i
, j
, len
= strlen (str
);
25 char *res
= (char *)g_malloc (len
* 2);
28 for (i
= 0; i
< len
; i
++) {
46 dtree_emit_one_loop_level (MonoCompile
*cfg
, FILE *fp
, MonoBasicBlock
*h
)
53 fprintf (fp
, "subgraph cluster_%d {\n", h
->block_num
);
54 fprintf (fp
, "label=\"loop_%d\"\n", h
->block_num
);
57 for (i
= 1; i
< cfg
->num_bblocks
; ++i
) {
58 bb
= cfg
->bblocks
[i
];
60 if (!h
|| (g_list_find (h
->loop_blocks
, bb
) && bb
!= h
)) {
61 if (bb
->nesting
== level
) {
62 fprintf (fp
, "BB%d -> BB%d;\n", bb
->idom
->block_num
, bb
->block_num
);
65 if (bb
->nesting
== (level
+ 1) && bb
->loop_blocks
) {
66 fprintf (fp
, "BB%d -> BB%d;\n", bb
->idom
->block_num
, bb
->block_num
);
67 dtree_emit_one_loop_level (cfg
, fp
, bb
);
78 cfg_emit_one_loop_level (MonoCompile
*cfg
, FILE *fp
, MonoBasicBlock
*h
)
85 fprintf (fp
, "subgraph cluster_%d {\n", h
->block_num
);
86 fprintf (fp
, "label=\"loop_%d\"\n", h
->block_num
);
89 for (bb
= cfg
->bb_entry
->next_bb
; bb
; bb
= bb
->next_bb
) {
90 if (bb
->region
!= -1) {
91 switch (bb
->region
& (MONO_REGION_FINALLY
|MONO_REGION_CATCH
|MONO_REGION_FAULT
|MONO_REGION_FILTER
)) {
92 case MONO_REGION_CATCH
:
93 fprintf (fp
, "BB%d [color=blue];\n", bb
->block_num
);
95 case MONO_REGION_FINALLY
:
96 fprintf (fp
, "BB%d [color=green];\n", bb
->block_num
);
98 case MONO_REGION_FAULT
:
99 case MONO_REGION_FILTER
:
100 fprintf (fp
, "BB%d [color=yellow];\n", bb
->block_num
);
107 if (!h
|| (g_list_find (h
->loop_blocks
, bb
) && bb
!= h
)) {
109 if (bb
->nesting
== level
) {
110 for (j
= 0; j
< bb
->in_count
; j
++)
111 fprintf (fp
, "BB%d -> BB%d;\n", bb
->in_bb
[j
]->block_num
, bb
->block_num
);
114 if (bb
->nesting
== (level
+ 1) && bb
->loop_blocks
) {
115 for (j
= 0; j
< bb
->in_count
; j
++)
116 fprintf (fp
, "BB%d -> BB%d;\n", bb
->in_bb
[j
]->block_num
, bb
->block_num
);
117 cfg_emit_one_loop_level (cfg
, fp
, bb
);
128 mono_draw_dtree (MonoCompile
*cfg
, FILE *fp
)
130 g_assert ((cfg
->comp_done
& MONO_COMP_IDOM
));
132 fprintf (fp
, "digraph %s {\n", convert_name (cfg
->method
->name
));
133 fprintf (fp
, "node [fontsize=12.0]\nedge [len=1,color=red]\n");
134 fprintf (fp
, "label=\"Dominator tree for %s\";\n", mono_method_full_name (cfg
->method
, TRUE
));
136 fprintf (fp
, "BB0 [shape=doublecircle];\n");
137 fprintf (fp
, "BB1 [color=red];\n");
139 dtree_emit_one_loop_level (cfg
, fp
, NULL
);
145 mono_draw_cfg (MonoCompile
*cfg
, FILE *fp
)
147 fprintf (fp
, "digraph %s {\n", convert_name (cfg
->method
->name
));
148 fprintf (fp
, "node [fontsize=12.0]\nedge [len=1,color=red]\n");
149 fprintf (fp
, "label=\"CFG for %s\";\n", mono_method_full_name (cfg
->method
, TRUE
));
151 fprintf (fp
, "BB0 [shape=doublecircle];\n");
152 fprintf (fp
, "BB1 [color=red];\n");
154 cfg_emit_one_loop_level (cfg
, fp
, NULL
);
160 mono_draw_code_cfg (MonoCompile
*cfg
, FILE *fp
)
164 fprintf (fp
, "digraph %s {\n", convert_name (cfg
->method
->name
));
165 fprintf (fp
, "node [fontsize=12.0]\nedge [len=1,color=red]\n");
166 fprintf (fp
, "label=\"CFG for %s\";\n", mono_method_full_name (cfg
->method
, TRUE
));
168 fprintf (fp
, "BB0 [shape=doublecircle];\n");
169 fprintf (fp
, "BB1 [color=red];\n");
171 for (bb
= cfg
->bb_entry
->next_bb
; bb
; bb
= bb
->next_bb
) {
175 if (bb
== cfg
->bb_exit
)
178 if ((cfg
->comp_done
& MONO_COMP_REACHABILITY
) && (bb
->flags
& BB_REACHABLE
))
179 color
= "color=red,";
183 fprintf (fp
, "BB%d [%sshape=record,labeljust=l,label=\"{BB%d|", bb
->block_num
, color
, bb
->block_num
);
185 MONO_BB_FOR_EACH_INS (bb
, inst
) {
186 //mono_print_label (fp, inst);
190 fprintf (fp
, "}\"];\n");
193 cfg_emit_one_loop_level (cfg
, fp
, NULL
);
199 mono_draw_graph (MonoCompile
*cfg
, MonoGraphOptions draw_options
)
204 int _i G_GNUC_UNUSED
;
206 fn
= "/tmp/minidtree.graph";
207 fp
= fopen (fn
, "w+");
210 switch (draw_options
) {
211 case MONO_GRAPH_DTREE
:
212 mono_draw_dtree (cfg
, fp
);
215 mono_draw_cfg (cfg
, fp
);
217 case MONO_GRAPH_CFG_CODE
:
218 case MONO_GRAPH_CFG_OPTCODE
:
219 case MONO_GRAPH_CFG_SSA
:
220 mono_draw_code_cfg (cfg
, fp
);
227 //com = g_strdup_printf ("dot %s -Tpng -o %s.png; eog %s.png", fn, fn, fn);
228 com
= g_strdup_printf ("dot %s -Tps -o %s.ps;gv %s.ps", fn
, fn
, fn
);
232 g_assert_not_reached ();
236 #else /* !DISABLE_JIT */
238 MONO_EMPTY_SOURCE_FILE (graph
);
240 #endif /* !DISABLE_JIT */