[netcore] Implement missing Bmi1/Bmi2 intrinsics (#16919)
[mono-project.git] / mono / mini / graph.c
blob39d7bdec76e74eb493947c431f5ec3f441b6e12b
1 /**
2 * \file
3 * Helper routines to graph various internal states of the code generator
5 * Author:
6 * Dietmar Maurer (dietmar@ximian.com)
8 * (C) 2003 Ximian, Inc.
9 */
11 #include <config.h>
12 #include <mono/utils/mono-compiler.h>
14 #ifndef DISABLE_JIT
16 #include <string.h>
17 #include <mono/metadata/debug-helpers.h>
19 #include "mini.h"
21 static char *
22 convert_name (const char *str)
24 int i, j, len = strlen (str);
25 char *res = (char *)g_malloc (len * 2);
27 j = 0;
28 for (i = 0; i < len; i++) {
29 char c = str [i];
31 switch (c) {
32 case '.':
33 res [j++] = '_';
34 break;
35 default:
36 res [j++] = c;
40 res [j] = 0;
42 return res;
45 static void
46 dtree_emit_one_loop_level (MonoCompile *cfg, FILE *fp, MonoBasicBlock *h)
48 MonoBasicBlock *bb;
49 int i, level = 0;
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);
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);
72 if (h) {
73 fprintf (fp, "}\n");
77 static void
78 cfg_emit_one_loop_level (MonoCompile *cfg, FILE *fp, MonoBasicBlock *h)
80 MonoBasicBlock *bb;
81 int j, level = 0;
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);
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;
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);
122 if (h) {
123 fprintf (fp, "}\n");
127 static void
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);
141 fprintf (fp, "}\n");
144 static void
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);
156 fprintf (fp, "}\n");
159 static void
160 mono_draw_code_cfg (MonoCompile *cfg, FILE *fp)
162 MonoBasicBlock *bb;
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) {
172 MonoInst *inst;
173 const char *color;
175 if (bb == cfg->bb_exit)
176 continue;
178 if ((cfg->comp_done & MONO_COMP_REACHABILITY) && (bb->flags & BB_REACHABLE))
179 color = "color=red,";
180 else
181 color = "";
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);
187 fprintf (fp, "\\n");
190 fprintf (fp, "}\"];\n");
193 cfg_emit_one_loop_level (cfg, fp, NULL);
195 fprintf (fp, "}\n");
198 void
199 mono_draw_graph (MonoCompile *cfg, MonoGraphOptions draw_options)
201 char *com;
202 const char *fn;
203 FILE *fp;
204 int _i G_GNUC_UNUSED;
206 fn = "/tmp/minidtree.graph";
207 fp = fopen (fn, "w+");
208 g_assert (fp);
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;
224 fclose (fp);
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
236 #else /* !DISABLE_JIT */
238 MONO_EMPTY_SOURCE_FILE (graph);
240 #endif /* !DISABLE_JIT */