Revert some changes which don't have proper dependencies.
[mono-project.git] / mono / dis / dis-cil.c
blobec2b518ccc03bae6ecc3cd5b1e56590d4af038c4
1 /*
2 * dis-cil.c: Disassembles CIL byte codes
4 * Author:
5 * Miguel de Icaza (miguel@ximian.com)
7 * (C) 2001 Ximian, Inc.
8 */
9 #include <config.h>
10 #include <glib.h>
11 #include <stdio.h>
12 #include <math.h>
13 #ifdef HAVE_WCHAR_H
14 #include <wchar.h>
15 #endif
16 #include "meta.h"
17 #include "get.h"
18 #include "dump.h"
19 #include "dis-cil.h"
20 #include "util.h"
21 #include "mono/metadata/opcodes.h"
22 #include "mono/metadata/class-internals.h"
23 #include "mono/utils/mono-compiler.h"
24 #include "mono/utils/mono-math.h"
26 #define CODE_INDENT g_assert (indent_level < 512); \
27 indent[indent_level*2] = ' '; \
28 indent[indent_level*2+1] = ' '; \
29 ++indent_level; \
30 indent[indent_level*2] = 0;
31 #define CODE_UNINDENT g_assert (indent_level); \
32 --indent_level; \
33 indent[indent_level*2] = 0;
35 void
36 disassemble_cil (MonoImage *m, MonoMethodHeader *mh, MonoGenericContainer *container)
38 const unsigned char *start = mh->code;
39 int size = mh->code_size;
40 const unsigned char *end = start + size;
41 const unsigned char *ptr = start;
42 const MonoOpcode *entry;
43 char indent[1024];
44 int i, j, indent_level = 0;
45 gboolean in_fault = 0;
46 const char *clause_names[] = {"catch", "filter", "finally", "", "fault"};
47 gboolean *trys = NULL;
48 indent [0] = 0;
50 #ifdef DEBUG
51 for (i = 0; i < mh->num_clauses; ++i) {
52 #define clause mh->clauses [i]
53 g_print ("/* out clause %d: from %d len=%d, handler at %d, %d */\n",
54 clause.flags, clause.try_offset, clause.try_len, clause.handler_offset, clause.handler_len);
55 #undef clause
57 #endif
59 if (mh->num_clauses) {
60 trys = (gboolean *)g_malloc0 (sizeof (gboolean) * mh->num_clauses);
61 trys [0] = 1;
62 for (i=1; i < mh->num_clauses; ++i) {
63 #define jcl mh->clauses [j]
64 #define cl mh->clauses [i]
65 trys [i] = 1;
66 for (j = 0; j < i; j++) {
67 if (cl.try_offset == jcl.try_offset && cl.try_len == jcl.try_len) {
68 trys [i] = 0;
69 break;
72 #undef jcl
73 #undef cl
77 while (ptr < end){
78 for (i = mh->num_clauses - 1; i >= 0 ; --i) {
79 if (ptr == start + mh->clauses[i].try_offset && trys [i]) {
80 fprintf (output, "\t%s.try { // %d\n", indent, i);
81 CODE_INDENT;
84 if (ptr == start + mh->clauses[i].handler_offset) {
85 if (mh->clauses[i].flags == MONO_EXCEPTION_CLAUSE_FILTER) {
86 CODE_UNINDENT;
87 fprintf (output, "\t%s} { // %d\n", indent, i);
88 } else {
89 char * klass = mh->clauses[i].flags ? g_strdup ("") :
90 dis_stringify_object_with_class (m, mh->clauses[i].data.catch_class,
91 TRUE, FALSE);
92 fprintf (output, "\t%s%s %s { // %d\n", indent,
93 clause_names [mh->clauses[i].flags], klass, i);
94 g_free (klass);
96 CODE_INDENT;
97 if (mh->clauses[i].flags == MONO_EXCEPTION_CLAUSE_FAULT)
98 in_fault = 1;
100 if (mh->clauses[i].flags == MONO_EXCEPTION_CLAUSE_FILTER && ptr == start + mh->clauses[i].data.filter_offset) {
101 fprintf (output, "\t%s%s {\n", indent, clause_names[1]);
102 CODE_INDENT;
105 fprintf (output, "\t%sIL_%04x: ", indent, (int) (ptr - start));
106 i = *ptr;
107 if (*ptr == 0xfe){
108 ptr++;
109 i = *ptr + 256;
111 entry = &mono_opcodes [i];
113 if (in_fault && entry->opval == 0xDC)
114 fprintf (output, " %s", "endfault");
115 else
116 fprintf (output, " %s ", mono_opcode_name (i));
117 ptr++;
118 switch (entry->argument){
119 case MonoInlineBrTarget: {
120 gint target = read32 (ptr);
121 fprintf (output, "IL_%04x\n", ((int) (ptr - start)) + 4 + target);
122 ptr += 4;
123 break;
126 case MonoInlineField: {
127 guint32 token = read32 (ptr);
128 char *s;
130 s = get_field (m, token, container);
131 fprintf (output, "%s", s);
132 g_free (s);
133 ptr += 4;
134 break;
137 case MonoInlineI: {
138 int value = read32 (ptr);
140 fprintf (output, "%d", value);
141 ptr += 4;
142 break;
145 case MonoInlineI8: {
146 gint64 top = read64 (ptr);
148 fprintf (output, "0x%llx", (long long) top);
149 ptr += 8;
150 break;
153 case MonoInlineMethod: {
154 guint32 token = read32 (ptr);
155 char *s;
157 s = get_method (m, token, container);
158 fprintf (output, "%s", s);
159 g_free (s);
160 ptr += 4;
161 break;
164 case MonoInlineNone:
165 break;
167 case MonoInlineR: {
168 double r;
169 readr8 (ptr, &r);
170 const int inf = mono_isinf (r);
171 if (inf == -1)
172 fprintf (output, "(00 00 00 00 00 00 f0 ff)"); /* negative infinity */
173 else if (inf == 1)
174 fprintf (output, "(00 00 00 00 00 00 f0 7f)"); /* positive infinity */
175 else if (mono_isnan (r))
176 fprintf (output, "(00 00 00 00 00 00 f8 ff)"); /* NaN */
177 else {
178 char *str = stringify_double (r);
179 fprintf (output, "%s", str);
180 g_free (str);
182 ptr += 8;
183 break;
186 case MonoInlineSig: {
187 guint32 token = read32 (ptr);
188 fprintf (output, "signature-0x%08x", token);
189 ptr += 4;
190 break;
193 case MonoInlineString: {
194 guint32 token = read32 (ptr);
195 const char *us_ptr = mono_metadata_user_string (m, token & 0xffffff);
196 int len = mono_metadata_decode_blob_size (us_ptr, (const char**)&us_ptr);
198 char *s = get_encoded_user_string_or_bytearray ((const guchar*)us_ptr, len);
201 * See section 23.1.4 on the encoding of the #US heap
203 fprintf (output, "%s", s);
204 g_free (s);
205 ptr += 4;
206 break;
209 case MonoInlineSwitch: {
210 guint32 count = read32 (ptr);
211 const unsigned char *endswitch;
212 guint32 n;
214 ptr += 4;
215 endswitch = ptr + sizeof (guint32) * count;
216 fprintf (output, count > 0 ? "(\n" : "( )");
217 CODE_INDENT;
218 for (n = 0; n < count; n++){
219 fprintf (output, "\t%sIL_%04x%s", indent,
220 (int)(endswitch-start+read32 (ptr)),
221 n == count - 1 ? ")" : ",\n");
222 ptr += 4;
224 CODE_UNINDENT;
225 break;
228 case MonoInlineTok: {
229 guint32 token = read32 (ptr);
230 char *s;
232 s = get_token (m, token, container);
233 fprintf (output, "%s", s);
234 g_free (s);
236 ptr += 4;
237 break;
240 case MonoInlineType: {
241 guint32 token = read32 (ptr);
242 char *s = get_token_type (m, token, container);
243 fprintf (output, "%s", s);
244 g_free (s);
245 ptr += 4;
246 break;
249 case MonoInlineVar: {
250 guint16 var_idx = read16 (ptr);
252 fprintf (output, "%d\n", var_idx);
253 ptr += 2;
254 break;
257 case MonoShortInlineBrTarget: {
258 signed char x = *ptr;
260 fprintf (output, "IL_%04x\n", (int)(ptr - start + 1 + x));
261 ptr++;
262 break;
265 case MonoShortInlineI: {
266 char x = *ptr;
268 fprintf (output, "0x%02x", x);
269 ptr++;
270 break;
273 case MonoShortInlineR: {
274 float f;
275 readr4 (ptr, &f);
276 const int inf = mono_isinf (f);
277 if (inf == -1)
278 fprintf (output, "(00 00 80 ff)"); /* negative infinity */
279 else if (inf == 1)
280 fprintf (output, "(00 00 80 7f)"); /* positive infinity */
281 else if (mono_isnan (f))
282 fprintf (output, "(00 00 c0 ff)"); /* NaN */
283 else {
284 char *str = stringify_double ((double) f);
285 fprintf (output, "%s", str);
286 g_free (str);
288 ptr += 4;
289 break;
292 case MonoShortInlineVar: {
293 unsigned char x = *ptr;
295 fprintf (output, "%d", (int) x);
296 ptr++;
297 break;
299 default:
300 break;
303 fprintf (output, "\n");
304 for (i = 0; i < mh->num_clauses; ++i) {
305 if (ptr == start + mh->clauses[i].try_offset + mh->clauses[i].try_len && trys [i]) {
306 CODE_UNINDENT;
307 fprintf (output, "\t%s} // end .try %d\n", indent, i);
309 if (ptr == start + mh->clauses[i].handler_offset + mh->clauses[i].handler_len) {
310 CODE_UNINDENT;
311 fprintf (output, "\t%s} // end handler %d\n", indent, i);
312 if (mh->clauses[i].flags == MONO_EXCEPTION_CLAUSE_FAULT)
313 in_fault = 0;
317 g_free (trys);