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.
15 #include <mono/metadata/debug-helpers.h>
20 convert_name (const char *str)
22 int i, j, len = strlen (str);
23 char *res = (char *)g_malloc (len * 2);
26 for (i = 0; i < len; i++) {
44 dtree_emit_one_loop_level (MonoCompile *cfg, FILE *fp, MonoBasicBlock *h)
51 fprintf (fp, "subgraph cluster_%d {\n", h->block_num);
52 fprintf (fp, "label=\"loop_%d\"\n", h->block_num);
55 for (i = 1; i < cfg->num_bblocks; ++i) {
56 bb = cfg->bblocks [i];
58 if (!h || (g_list_find (h->loop_blocks, bb) && bb != h)) {
59 if (bb->nesting == level) {
60 fprintf (fp, "BB%d -> BB%d;\n", bb->idom->block_num, bb->block_num);
63 if (bb->nesting == (level + 1) && bb->loop_blocks) {
64 fprintf (fp, "BB%d -> BB%d;\n", bb->idom->block_num, bb->block_num);
65 dtree_emit_one_loop_level (cfg, fp, bb);
76 cfg_emit_one_loop_level (MonoCompile *cfg, FILE *fp, MonoBasicBlock *h)
83 fprintf (fp, "subgraph cluster_%d {\n", h->block_num);
84 fprintf (fp, "label=\"loop_%d\"\n", h->block_num);
87 for (bb = cfg->bb_entry->next_bb; bb; bb = bb->next_bb) {
88 if (bb->region != -1) {
89 switch (bb->region & (MONO_REGION_FINALLY|MONO_REGION_CATCH|MONO_REGION_FAULT|MONO_REGION_FILTER)) {
90 case MONO_REGION_CATCH:
91 fprintf (fp, "BB%d [color=blue];\n", bb->block_num);;
93 case MONO_REGION_FINALLY:
94 fprintf (fp, "BB%d [color=green];\n", bb->block_num);;
96 case MONO_REGION_FAULT:
97 case MONO_REGION_FILTER:
98 fprintf (fp, "BB%d [color=yellow];\n", bb->block_num);;
105 if (!h || (g_list_find (h->loop_blocks, bb) && bb != h)) {
107 if (bb->nesting == level) {
108 for (j = 0; j < bb->in_count; j++)
109 fprintf (fp, "BB%d -> BB%d;\n", bb->in_bb [j]->block_num, bb->block_num);
112 if (bb->nesting == (level + 1) && bb->loop_blocks) {
113 for (j = 0; j < bb->in_count; j++)
114 fprintf (fp, "BB%d -> BB%d;\n", bb->in_bb [j]->block_num, bb->block_num);
115 cfg_emit_one_loop_level (cfg, fp, bb);
126 mono_draw_dtree (MonoCompile *cfg, FILE *fp)
128 g_assert ((cfg->comp_done & MONO_COMP_IDOM));
130 fprintf (fp, "digraph %s {\n", convert_name (cfg->method->name));
131 fprintf (fp, "node [fontsize=12.0]\nedge [len=1,color=red]\n");
132 fprintf (fp, "label=\"Dominator tree for %s\";\n", mono_method_full_name (cfg->method, TRUE));
134 fprintf (fp, "BB0 [shape=doublecircle];\n");
135 fprintf (fp, "BB1 [color=red];\n");
137 dtree_emit_one_loop_level (cfg, fp, NULL);
143 mono_draw_cfg (MonoCompile *cfg, FILE *fp)
145 fprintf (fp, "digraph %s {\n", convert_name (cfg->method->name));
146 fprintf (fp, "node [fontsize=12.0]\nedge [len=1,color=red]\n");
147 fprintf (fp, "label=\"CFG for %s\";\n", mono_method_full_name (cfg->method, TRUE));
149 fprintf (fp, "BB0 [shape=doublecircle];\n");
150 fprintf (fp, "BB1 [color=red];\n");
152 cfg_emit_one_loop_level (cfg, fp, NULL);
160 mono_print_label (FILE *fp, MonoInst *tree) {
166 arity = mono_burg_arity [tree->opcode];
168 fprintf (fp, "\\ %s%s", arity? "(": "", mono_inst_name (tree->opcode));
170 switch (tree->opcode) {
172 fprintf (fp, "[%ld]", (long)tree->inst_c0);
175 fprintf (fp, "[%lld]", (long long)tree->inst_l);
178 fprintf (fp, "[%f]", *(double*)tree->inst_p0);
181 fprintf (fp, "[%f]", *(float*)tree->inst_p0);
185 fprintf (fp, "[%d]", (int)tree->inst_c0);
188 fprintf (fp, "[0x%x(%s)]", (int)tree->inst_offset, mono_arch_regname (tree->inst_basereg));
191 fprintf (fp, "[%s]", mono_arch_regname (tree->dreg));
194 fprintf (fp, "[%s]", tree->inst_newa_class->name);
195 mono_print_label (fp, tree->inst_newa_len);
198 case OP_CALL_MEMBASE:
200 case OP_FCALL_MEMBASE:
202 case OP_LCALL_MEMBASE:
204 case OP_VCALL_MEMBASE:
206 case OP_VOIDCALL_MEMBASE: {
207 MonoCallInst *call = (MonoCallInst*)tree;
209 if (mono_method_signature (call->method)->hasthis && tree->inst_left) {
210 mono_print_label (fp, tree->inst_left);
212 fprintf (fp, "[%s]", call->method->name);
218 fprintf (fp, "[%d\\ (", (int)tree->inst_c0);
219 for (i = 0; i < tree->inst_phi_args [0]; i++) {
221 fprintf (fp, ",\\ ");
222 fprintf (fp, "%d", tree->inst_phi_args [i + 1]);
232 fprintf (fp, "[B%d]", tree->inst_target_bb->block_num);
241 case OP_VOIDCALL_REG:
242 mono_print_label (fp, tree->inst_left);
254 fprintf (fp, "[B%dB%d]", tree->inst_true_bb->block_num, tree->inst_false_bb->block_num);
255 mono_print_label (fp, tree->inst_left);
259 mono_print_label (fp, tree->inst_left);
261 mono_print_label (fp, tree->inst_right);
273 mono_draw_code_cfg (MonoCompile *cfg, FILE *fp)
277 fprintf (fp, "digraph %s {\n", convert_name (cfg->method->name));
278 fprintf (fp, "node [fontsize=12.0]\nedge [len=1,color=red]\n");
279 fprintf (fp, "label=\"CFG for %s\";\n", mono_method_full_name (cfg->method, TRUE));
281 fprintf (fp, "BB0 [shape=doublecircle];\n");
282 fprintf (fp, "BB1 [color=red];\n");
284 for (bb = cfg->bb_entry->next_bb; bb; bb = bb->next_bb) {
288 if (bb == cfg->bb_exit)
291 if ((cfg->comp_done & MONO_COMP_REACHABILITY) && (bb->flags & BB_REACHABLE))
292 color = "color=red,";
296 fprintf (fp, "BB%d [%sshape=record,labeljust=l,label=\"{BB%d|", bb->block_num, color, bb->block_num);
298 MONO_BB_FOR_EACH_INS (bb, inst) {
299 //mono_print_label (fp, inst);
303 fprintf (fp, "}\"];\n");
306 cfg_emit_one_loop_level (cfg, fp, NULL);
312 mono_draw_graph (MonoCompile *cfg, MonoGraphOptions draw_options)
317 int _i G_GNUC_UNUSED;
319 fn = "/tmp/minidtree.graph";
320 fp = fopen (fn, "w+");
323 switch (draw_options) {
324 case MONO_GRAPH_DTREE:
325 mono_draw_dtree (cfg, fp);
328 mono_draw_cfg (cfg, fp);
330 case MONO_GRAPH_CFG_CODE:
331 case MONO_GRAPH_CFG_OPTCODE:
332 case MONO_GRAPH_CFG_SSA:
333 mono_draw_code_cfg (cfg, fp);
340 //com = g_strdup_printf ("dot %s -Tpng -o %s.png; eog %s.png", fn, fn, fn);
341 com = g_strdup_printf ("dot %s -Tps -o %s.ps;gv %s.ps", fn, fn, fn);
345 g_assert_not_reached ();
349 #endif /* DISABLE_JIT */