Merge pull request #5714 from alexischr/update_bockbuild
[mono.git] / mono / mini / graph.c
1 /**
2  * \file
3  * Helper routines to graph various internal states of the code generator
4  *
5  * Author:
6  *   Dietmar Maurer (dietmar@ximian.com)
7  *
8  * (C) 2003 Ximian, Inc.
9  */
10
11 #include <config.h>
12 #include <mono/utils/mono-compiler.h>
13
14 #ifndef DISABLE_JIT
15
16 #include <string.h>
17 #include <mono/metadata/debug-helpers.h>
18
19 #include "mini.h"
20
21 static char *
22 convert_name (const char *str)
23 {
24         int i, j, len = strlen (str);
25         char *res = (char *)g_malloc (len * 2);
26
27         j = 0;
28         for (i = 0; i < len; i++) {
29                 char c = str [i];
30
31                 switch (c) {
32                 case '.':
33                         res [j++] = '_';
34                         break;
35                 default:
36                         res [j++] = c;
37                 }
38         }
39
40         res [j] = 0;
41
42         return res;
43 }
44
45 static void
46 dtree_emit_one_loop_level (MonoCompile *cfg, FILE *fp, MonoBasicBlock *h)
47 {
48         MonoBasicBlock *bb;
49         int i, level = 0;
50
51         if (h) {
52                 level = h->nesting;
53                 fprintf (fp, "subgraph cluster_%d {\n", h->block_num);
54                 fprintf (fp, "label=\"loop_%d\"\n", h->block_num);
55         } 
56
57         for (i = 1; i < cfg->num_bblocks; ++i) {
58                 bb = cfg->bblocks [i];
59
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);
63                         }
64                 
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);
68                         }
69                 }
70         }
71         
72         if (h) {
73                 fprintf (fp, "}\n");
74         }
75 }
76
77 static void
78 cfg_emit_one_loop_level (MonoCompile *cfg, FILE *fp, MonoBasicBlock *h)
79 {
80         MonoBasicBlock *bb;
81         int j, level = 0;
82
83         if (h) {
84                 level = h->nesting;
85                 fprintf (fp, "subgraph cluster_%d {\n", h->block_num);
86                 fprintf (fp, "label=\"loop_%d\"\n", h->block_num);
87         } 
88
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);;
94                                 break;
95                         case MONO_REGION_FINALLY:
96                                 fprintf (fp, "BB%d [color=green];\n", bb->block_num);;
97                                 break;
98                         case MONO_REGION_FAULT:
99                         case MONO_REGION_FILTER:
100                                 fprintf (fp, "BB%d [color=yellow];\n", bb->block_num);;
101                                 break;
102                         default:
103                                 break;
104                         }
105                 }
106
107                 if (!h || (g_list_find (h->loop_blocks, bb) && bb != h)) {
108
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);
112                         }
113                 
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);
118                         }
119                 }
120         }
121         
122         if (h) {
123                 fprintf (fp, "}\n");
124         }
125 }
126
127 static void
128 mono_draw_dtree (MonoCompile *cfg, FILE *fp)
129 {
130         g_assert ((cfg->comp_done & MONO_COMP_IDOM));
131
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));
135
136         fprintf (fp, "BB0 [shape=doublecircle];\n");
137         fprintf (fp, "BB1 [color=red];\n");
138
139         dtree_emit_one_loop_level (cfg, fp, NULL);
140
141         fprintf (fp, "}\n");
142 }
143
144 static void
145 mono_draw_cfg (MonoCompile *cfg, FILE *fp)
146 {
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));
150
151         fprintf (fp, "BB0 [shape=doublecircle];\n");
152         fprintf (fp, "BB1 [color=red];\n");
153
154         cfg_emit_one_loop_level (cfg, fp, NULL);
155
156         fprintf (fp, "}\n");
157 }
158
159 static void
160 mono_draw_code_cfg (MonoCompile *cfg, FILE *fp)
161 {
162         MonoBasicBlock *bb;
163                 
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));
167
168         fprintf (fp, "BB0 [shape=doublecircle];\n");
169         fprintf (fp, "BB1 [color=red];\n");
170
171         for (bb = cfg->bb_entry->next_bb; bb; bb = bb->next_bb) {
172                 MonoInst *inst;
173                 const char *color;
174
175                 if (bb == cfg->bb_exit)
176                         continue;
177
178                 if ((cfg->comp_done & MONO_COMP_REACHABILITY) && (bb->flags & BB_REACHABLE))
179                         color = "color=red,";
180                 else
181                         color = "";
182
183                 fprintf (fp, "BB%d [%sshape=record,labeljust=l,label=\"{BB%d|", bb->block_num, color, bb->block_num);
184                         
185                 MONO_BB_FOR_EACH_INS (bb, inst) {
186                         //mono_print_label (fp, inst);
187                         fprintf (fp, "\\n");                    
188                 }
189
190                 fprintf (fp, "}\"];\n");                        
191         }
192
193         cfg_emit_one_loop_level (cfg, fp, NULL);
194
195         fprintf (fp, "}\n");
196 }
197
198 void
199 mono_draw_graph (MonoCompile *cfg, MonoGraphOptions draw_options)
200 {
201         char *com;
202         const char *fn;
203         FILE *fp;
204         int _i G_GNUC_UNUSED;
205
206         fn = "/tmp/minidtree.graph";
207         fp = fopen (fn, "w+");
208         g_assert (fp);
209
210         switch (draw_options) {
211         case MONO_GRAPH_DTREE:
212                 mono_draw_dtree (cfg, fp);
213                 break;
214         case MONO_GRAPH_CFG:
215                 mono_draw_cfg (cfg, fp);
216                 break;
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);
221                 break;
222         }
223
224         fclose (fp);
225
226 #ifdef HAVE_SYSTEM
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);
229         _i = system (com);
230         g_free (com);
231 #else
232         g_assert_not_reached ();
233 #endif
234 }
235
236 #else /* !DISABLE_JIT */
237
238 MONO_EMPTY_SOURCE_FILE (graph);
239
240 #endif /* !DISABLE_JIT */
241