[sockets] Fixed reading blocking flag
[mono.git] / mono / mini / graph.c
1 /*
2  * graph.c: Helper routines to graph various internal states of the code generator
3  *
4  * Author:
5  *   Dietmar Maurer (dietmar@ximian.com)
6  *
7  * (C) 2003 Ximian, Inc.
8  */
9 #include <string.h>
10 #include <mono/metadata/debug-helpers.h>
11
12 #include "mini.h"
13
14 static char *
15 convert_name (const char *str)
16 {
17         int i, j, len = strlen (str);
18         char *res = g_malloc (len * 2);
19
20         j = 0;
21         for (i = 0; i < len; i++) {
22                 char c = str [i];
23
24                 switch (c) {
25                 case '.':
26                         res [j++] = '_';
27                         break;
28                 default:
29                         res [j++] = c;
30                 }
31         }
32
33         res [j] = 0;
34
35         return res;
36 }
37
38 static void
39 dtree_emit_one_loop_level (MonoCompile *cfg, FILE *fp, MonoBasicBlock *h)
40 {
41         MonoBasicBlock *bb;
42         int i, level = 0;
43
44         if (h) {
45                 level = h->nesting;
46                 fprintf (fp, "subgraph cluster_%d {\n", h->block_num);
47                 fprintf (fp, "label=\"loop_%d\"\n", h->block_num);
48         } 
49
50         for (i = 1; i < cfg->num_bblocks; ++i) {
51                 bb = cfg->bblocks [i];
52
53                 if (!h || (g_list_find (h->loop_blocks, bb) && bb != h)) {
54                         if (bb->nesting == level) {
55                                 fprintf (fp, "BB%d -> BB%d;\n", bb->idom->block_num, bb->block_num);
56                         }
57                 
58                         if (bb->nesting == (level + 1) && bb->loop_blocks) {
59                                 fprintf (fp, "BB%d -> BB%d;\n", bb->idom->block_num, bb->block_num);
60                                 dtree_emit_one_loop_level (cfg, fp, bb);
61                         }
62                 }
63         }
64         
65         if (h) {
66                 fprintf (fp, "}\n");
67         }
68 }
69
70 static void
71 cfg_emit_one_loop_level (MonoCompile *cfg, FILE *fp, MonoBasicBlock *h)
72 {
73         MonoBasicBlock *bb;
74         int j, level = 0;
75
76         if (h) {
77                 level = h->nesting;
78                 fprintf (fp, "subgraph cluster_%d {\n", h->block_num);
79                 fprintf (fp, "label=\"loop_%d\"\n", h->block_num);
80         } 
81
82         for (bb = cfg->bb_entry->next_bb; bb; bb = bb->next_bb) {
83                 if (bb->region != -1) {
84                         switch (bb->region & (MONO_REGION_FINALLY|MONO_REGION_CATCH|MONO_REGION_FAULT|MONO_REGION_FILTER)) {
85                         case MONO_REGION_CATCH:
86                                 fprintf (fp, "BB%d [color=blue];\n", bb->block_num);;
87                                 break;
88                         case MONO_REGION_FINALLY:
89                                 fprintf (fp, "BB%d [color=green];\n", bb->block_num);;
90                                 break;
91                         case MONO_REGION_FAULT:
92                         case MONO_REGION_FILTER:
93                                 fprintf (fp, "BB%d [color=yellow];\n", bb->block_num);;
94                                 break;
95                         default:
96                                 break;
97                         }
98                 }
99
100                 if (!h || (g_list_find (h->loop_blocks, bb) && bb != h)) {
101
102                         if (bb->nesting == level) {
103                                 for (j = 0; j < bb->in_count; j++) 
104                                         fprintf (fp, "BB%d -> BB%d;\n", bb->in_bb [j]->block_num, bb->block_num);
105                         }
106                 
107                         if (bb->nesting == (level + 1) && bb->loop_blocks) {
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);
110                                 cfg_emit_one_loop_level (cfg, fp, bb);
111                         }
112                 }
113         }
114         
115         if (h) {
116                 fprintf (fp, "}\n");
117         }
118 }
119
120 static void
121 mono_draw_dtree (MonoCompile *cfg, FILE *fp)
122 {
123         g_assert ((cfg->comp_done & MONO_COMP_IDOM));
124
125         fprintf (fp, "digraph %s {\n", convert_name (cfg->method->name));
126         fprintf (fp, "node [fontsize=12.0]\nedge [len=1,color=red]\n");
127         fprintf (fp, "label=\"Dominator tree for %s\";\n", mono_method_full_name (cfg->method, TRUE));
128
129         fprintf (fp, "BB0 [shape=doublecircle];\n");
130         fprintf (fp, "BB1 [color=red];\n");
131
132         dtree_emit_one_loop_level (cfg, fp, NULL);
133
134         fprintf (fp, "}\n");
135 }
136
137 static void
138 mono_draw_cfg (MonoCompile *cfg, FILE *fp)
139 {
140         fprintf (fp, "digraph %s {\n", convert_name (cfg->method->name));
141         fprintf (fp, "node [fontsize=12.0]\nedge [len=1,color=red]\n");
142         fprintf (fp, "label=\"CFG for %s\";\n", mono_method_full_name (cfg->method, TRUE));
143
144         fprintf (fp, "BB0 [shape=doublecircle];\n");
145         fprintf (fp, "BB1 [color=red];\n");
146
147         cfg_emit_one_loop_level (cfg, fp, NULL);
148
149         fprintf (fp, "}\n");
150 }
151
152 #if 0
153
154 static void
155 mono_print_label (FILE *fp, MonoInst *tree) {
156         int arity;
157
158         if (!tree)
159                 return;
160
161         arity = mono_burg_arity [tree->opcode];
162
163         fprintf (fp, "\\ %s%s", arity? "(": "",  mono_inst_name (tree->opcode));
164
165         switch (tree->opcode) {
166         case OP_ICONST:
167                 fprintf (fp, "[%ld]", (long)tree->inst_c0);
168                 break;
169         case OP_I8CONST:
170                 fprintf (fp, "[%lld]", (long long)tree->inst_l);
171                 break;
172         case OP_R8CONST:
173                 fprintf (fp, "[%f]", *(double*)tree->inst_p0);
174                 break;
175         case OP_R4CONST:
176                 fprintf (fp, "[%f]", *(float*)tree->inst_p0);
177                 break;
178         case OP_ARG:
179         case OP_LOCAL:
180                 fprintf (fp, "[%d]", (int)tree->inst_c0);
181                 break;
182         case OP_REGOFFSET:
183                 fprintf (fp, "[0x%x(%s)]", (int)tree->inst_offset, mono_arch_regname (tree->inst_basereg));
184                 break;
185         case OP_REGVAR:
186                 fprintf (fp, "[%s]", mono_arch_regname (tree->dreg));
187                 break;
188         case CEE_NEWARR:
189                 fprintf (fp, "[%s]",  tree->inst_newa_class->name);
190                 mono_print_label (fp, tree->inst_newa_len);
191                 break;
192         case OP_CALL:
193         case OP_CALLVIRT:
194         case OP_FCALL:
195         case OP_FCALLVIRT:
196         case OP_LCALL:
197         case OP_LCALLVIRT:
198         case OP_VCALL:
199         case OP_VCALLVIRT:
200         case OP_VOIDCALL:
201         case OP_VOIDCALLVIRT: {
202                 MonoCallInst *call = (MonoCallInst*)tree;
203                 if (call->method) {
204                         if (mono_method_signature (call->method)->hasthis && tree->inst_left) {
205                                 mono_print_label (fp, tree->inst_left);
206                         }
207                         fprintf (fp, "[%s]", call->method->name);
208                 }
209                 break;
210         }
211         case OP_PHI: {
212                 int i;
213                 fprintf (fp, "[%d\\ (", (int)tree->inst_c0);
214                 for (i = 0; i < tree->inst_phi_args [0]; i++) {
215                         if (i)
216                                 fprintf (fp, ",\\ ");
217                         fprintf (fp, "%d", tree->inst_phi_args [i + 1]);
218                 }
219                 fprintf (fp, ")]");
220                 break;
221         }
222         case OP_NOP:
223         case OP_JMP:
224         case OP_BREAK:
225                 break;
226         case OP_BR:
227                 fprintf (fp, "[B%d]", tree->inst_target_bb->block_num);
228                 break;
229         case OP_SWITCH:
230         case CEE_ISINST:
231         case CEE_CASTCLASS:
232         case OP_CALL_REG:
233         case OP_FCALL_REG:
234         case OP_LCALL_REG:
235         case OP_VCALL_REG:
236         case OP_VOIDCALL_REG:
237                 mono_print_label (fp, tree->inst_left);
238                 break;
239         case CEE_BNE_UN:
240         case CEE_BEQ:
241         case CEE_BLT:
242         case CEE_BLT_UN:
243         case CEE_BGT:
244         case CEE_BGT_UN:
245         case CEE_BGE:
246         case CEE_BGE_UN:
247         case CEE_BLE:
248         case CEE_BLE_UN:
249                 fprintf (fp, "[B%dB%d]", tree->inst_true_bb->block_num, tree->inst_false_bb->block_num);
250                 mono_print_label (fp, tree->inst_left);
251                 break;
252         default:
253                 if (arity) {
254                         mono_print_label (fp, tree->inst_left);
255                         if (arity > 1)
256                                 mono_print_label (fp, tree->inst_right);
257                 }
258                 break;
259         }
260
261         if (arity)
262                 fprintf (fp, ")");
263 }
264
265 #endif
266
267 static void
268 mono_draw_code_cfg (MonoCompile *cfg, FILE *fp)
269 {
270         MonoBasicBlock *bb;
271                 
272         fprintf (fp, "digraph %s {\n", convert_name (cfg->method->name));
273         fprintf (fp, "node [fontsize=12.0]\nedge [len=1,color=red]\n");
274         fprintf (fp, "label=\"CFG for %s\";\n", mono_method_full_name (cfg->method, TRUE));
275
276         fprintf (fp, "BB0 [shape=doublecircle];\n");
277         fprintf (fp, "BB1 [color=red];\n");
278
279         for (bb = cfg->bb_entry->next_bb; bb; bb = bb->next_bb) {
280                 MonoInst *inst;
281                 const char *color;
282
283                 if (bb == cfg->bb_exit)
284                         continue;
285
286                 if ((cfg->comp_done & MONO_COMP_REACHABILITY) && (bb->flags & BB_REACHABLE))
287                         color = "color=red,";
288                 else
289                         color = "";
290
291                 fprintf (fp, "BB%d [%sshape=record,labeljust=l,label=\"{BB%d|", bb->block_num, color, bb->block_num);
292                         
293                 MONO_BB_FOR_EACH_INS (bb, inst) {
294                         //mono_print_label (fp, inst);
295                         fprintf (fp, "\\n");                    
296                 }
297
298                 fprintf (fp, "}\"];\n");                        
299         }
300
301         cfg_emit_one_loop_level (cfg, fp, NULL);
302
303         fprintf (fp, "}\n");
304 }
305
306 void
307 mono_draw_graph (MonoCompile *cfg, MonoGraphOptions draw_options)
308 {
309         char *com;
310         const char *fn;
311         FILE *fp;
312
313         fn = "/tmp/minidtree.graph";
314         fp = fopen (fn, "w+");
315         g_assert (fp);
316
317         switch (draw_options) {
318         case MONO_GRAPH_DTREE:
319                 mono_draw_dtree (cfg, fp);
320                 break;
321         case MONO_GRAPH_CFG:
322                 mono_draw_cfg (cfg, fp);
323                 break;
324         case MONO_GRAPH_CFG_CODE:
325         case MONO_GRAPH_CFG_OPTCODE:
326         case MONO_GRAPH_CFG_SSA:
327                 mono_draw_code_cfg (cfg, fp);
328                 break;
329         }
330
331         fclose (fp);
332
333         //com = g_strdup_printf ("dot %s -Tpng -o %s.png; eog %s.png", fn, fn, fn);
334         com = g_strdup_printf ("dot %s -Tps -o %s.ps;gv %s.ps", fn, fn, fn);
335         system (com);
336         g_free (com);
337 }
338