2 * graph.c: Helper routines to graph various internal states of the code generator
5 * Dietmar Maurer (dietmar@ximian.com)
7 * (C) 2003 Ximian, Inc.
11 #include <mono/utils/mono-compiler.h>
16 #include <mono/metadata/debug-helpers.h>
21 convert_name (const char *str
)
23 int i
, j
, len
= strlen (str
);
24 char *res
= (char *)g_malloc (len
* 2);
27 for (i
= 0; i
< len
; i
++) {
45 dtree_emit_one_loop_level (MonoCompile
*cfg
, FILE *fp
, MonoBasicBlock
*h
)
52 fprintf (fp
, "subgraph cluster_%d {\n", h
->block_num
);
53 fprintf (fp
, "label=\"loop_%d\"\n", h
->block_num
);
56 for (i
= 1; i
< cfg
->num_bblocks
; ++i
) {
57 bb
= cfg
->bblocks
[i
];
59 if (!h
|| (g_list_find (h
->loop_blocks
, bb
) && bb
!= h
)) {
60 if (bb
->nesting
== level
) {
61 fprintf (fp
, "BB%d -> BB%d;\n", bb
->idom
->block_num
, bb
->block_num
);
64 if (bb
->nesting
== (level
+ 1) && bb
->loop_blocks
) {
65 fprintf (fp
, "BB%d -> BB%d;\n", bb
->idom
->block_num
, bb
->block_num
);
66 dtree_emit_one_loop_level (cfg
, fp
, bb
);
77 cfg_emit_one_loop_level (MonoCompile
*cfg
, FILE *fp
, MonoBasicBlock
*h
)
84 fprintf (fp
, "subgraph cluster_%d {\n", h
->block_num
);
85 fprintf (fp
, "label=\"loop_%d\"\n", h
->block_num
);
88 for (bb
= cfg
->bb_entry
->next_bb
; bb
; bb
= bb
->next_bb
) {
89 if (bb
->region
!= -1) {
90 switch (bb
->region
& (MONO_REGION_FINALLY
|MONO_REGION_CATCH
|MONO_REGION_FAULT
|MONO_REGION_FILTER
)) {
91 case MONO_REGION_CATCH
:
92 fprintf (fp
, "BB%d [color=blue];\n", bb
->block_num
);;
94 case MONO_REGION_FINALLY
:
95 fprintf (fp
, "BB%d [color=green];\n", bb
->block_num
);;
97 case MONO_REGION_FAULT
:
98 case MONO_REGION_FILTER
:
99 fprintf (fp
, "BB%d [color=yellow];\n", bb
->block_num
);;
106 if (!h
|| (g_list_find (h
->loop_blocks
, bb
) && bb
!= h
)) {
108 if (bb
->nesting
== level
) {
109 for (j
= 0; j
< bb
->in_count
; j
++)
110 fprintf (fp
, "BB%d -> BB%d;\n", bb
->in_bb
[j
]->block_num
, bb
->block_num
);
113 if (bb
->nesting
== (level
+ 1) && bb
->loop_blocks
) {
114 for (j
= 0; j
< bb
->in_count
; j
++)
115 fprintf (fp
, "BB%d -> BB%d;\n", bb
->in_bb
[j
]->block_num
, bb
->block_num
);
116 cfg_emit_one_loop_level (cfg
, fp
, bb
);
127 mono_draw_dtree (MonoCompile
*cfg
, FILE *fp
)
129 g_assert ((cfg
->comp_done
& MONO_COMP_IDOM
));
131 fprintf (fp
, "digraph %s {\n", convert_name (cfg
->method
->name
));
132 fprintf (fp
, "node [fontsize=12.0]\nedge [len=1,color=red]\n");
133 fprintf (fp
, "label=\"Dominator tree for %s\";\n", mono_method_full_name (cfg
->method
, TRUE
));
135 fprintf (fp
, "BB0 [shape=doublecircle];\n");
136 fprintf (fp
, "BB1 [color=red];\n");
138 dtree_emit_one_loop_level (cfg
, fp
, NULL
);
144 mono_draw_cfg (MonoCompile
*cfg
, FILE *fp
)
146 fprintf (fp
, "digraph %s {\n", convert_name (cfg
->method
->name
));
147 fprintf (fp
, "node [fontsize=12.0]\nedge [len=1,color=red]\n");
148 fprintf (fp
, "label=\"CFG for %s\";\n", mono_method_full_name (cfg
->method
, TRUE
));
150 fprintf (fp
, "BB0 [shape=doublecircle];\n");
151 fprintf (fp
, "BB1 [color=red];\n");
153 cfg_emit_one_loop_level (cfg
, fp
, NULL
);
161 mono_print_label (FILE *fp
, MonoInst
*tree
) {
167 arity
= mono_burg_arity
[tree
->opcode
];
169 fprintf (fp
, "\\ %s%s", arity
? "(": "", mono_inst_name (tree
->opcode
));
171 switch (tree
->opcode
) {
173 fprintf (fp
, "[%ld]", (long)tree
->inst_c0
);
176 fprintf (fp
, "[%lld]", (long long)tree
->inst_l
);
179 fprintf (fp
, "[%f]", *(double*)tree
->inst_p0
);
182 fprintf (fp
, "[%f]", *(float*)tree
->inst_p0
);
186 fprintf (fp
, "[%d]", (int)tree
->inst_c0
);
189 fprintf (fp
, "[0x%x(%s)]", (int)tree
->inst_offset
, mono_arch_regname (tree
->inst_basereg
));
192 fprintf (fp
, "[%s]", mono_arch_regname (tree
->dreg
));
195 fprintf (fp
, "[%s]", tree
->inst_newa_class
->name
);
196 mono_print_label (fp
, tree
->inst_newa_len
);
199 case OP_CALL_MEMBASE
:
201 case OP_FCALL_MEMBASE
:
203 case OP_LCALL_MEMBASE
:
205 case OP_VCALL_MEMBASE
:
207 case OP_VOIDCALL_MEMBASE
: {
208 MonoCallInst
*call
= (MonoCallInst
*)tree
;
210 if (mono_method_signature (call
->method
)->hasthis
&& tree
->inst_left
) {
211 mono_print_label (fp
, tree
->inst_left
);
213 fprintf (fp
, "[%s]", call
->method
->name
);
219 fprintf (fp
, "[%d\\ (", (int)tree
->inst_c0
);
220 for (i
= 0; i
< tree
->inst_phi_args
[0]; i
++) {
222 fprintf (fp
, ",\\ ");
223 fprintf (fp
, "%d", tree
->inst_phi_args
[i
+ 1]);
233 fprintf (fp
, "[B%d]", tree
->inst_target_bb
->block_num
);
242 case OP_VOIDCALL_REG
:
243 mono_print_label (fp
, tree
->inst_left
);
255 fprintf (fp
, "[B%dB%d]", tree
->inst_true_bb
->block_num
, tree
->inst_false_bb
->block_num
);
256 mono_print_label (fp
, tree
->inst_left
);
260 mono_print_label (fp
, tree
->inst_left
);
262 mono_print_label (fp
, tree
->inst_right
);
274 mono_draw_code_cfg (MonoCompile
*cfg
, FILE *fp
)
278 fprintf (fp
, "digraph %s {\n", convert_name (cfg
->method
->name
));
279 fprintf (fp
, "node [fontsize=12.0]\nedge [len=1,color=red]\n");
280 fprintf (fp
, "label=\"CFG for %s\";\n", mono_method_full_name (cfg
->method
, TRUE
));
282 fprintf (fp
, "BB0 [shape=doublecircle];\n");
283 fprintf (fp
, "BB1 [color=red];\n");
285 for (bb
= cfg
->bb_entry
->next_bb
; bb
; bb
= bb
->next_bb
) {
289 if (bb
== cfg
->bb_exit
)
292 if ((cfg
->comp_done
& MONO_COMP_REACHABILITY
) && (bb
->flags
& BB_REACHABLE
))
293 color
= "color=red,";
297 fprintf (fp
, "BB%d [%sshape=record,labeljust=l,label=\"{BB%d|", bb
->block_num
, color
, bb
->block_num
);
299 MONO_BB_FOR_EACH_INS (bb
, inst
) {
300 //mono_print_label (fp, inst);
304 fprintf (fp
, "}\"];\n");
307 cfg_emit_one_loop_level (cfg
, fp
, NULL
);
313 mono_draw_graph (MonoCompile
*cfg
, MonoGraphOptions draw_options
)
318 int _i G_GNUC_UNUSED
;
320 fn
= "/tmp/minidtree.graph";
321 fp
= fopen (fn
, "w+");
324 switch (draw_options
) {
325 case MONO_GRAPH_DTREE
:
326 mono_draw_dtree (cfg
, fp
);
329 mono_draw_cfg (cfg
, fp
);
331 case MONO_GRAPH_CFG_CODE
:
332 case MONO_GRAPH_CFG_OPTCODE
:
333 case MONO_GRAPH_CFG_SSA
:
334 mono_draw_code_cfg (cfg
, fp
);
341 //com = g_strdup_printf ("dot %s -Tpng -o %s.png; eog %s.png", fn, fn, fn);
342 com
= g_strdup_printf ("dot %s -Tps -o %s.ps;gv %s.ps", fn
, fn
, fn
);
346 g_assert_not_reached ();
350 #else /* !DISABLE_JIT */
352 MONO_EMPTY_SOURCE_FILE (graph
);
354 #endif /* !DISABLE_JIT */